langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java
changeset 42416 1cfad0990b99
parent 37848 3c8ff4204d2d
child 42819 4ce83e629dc1
equal deleted inserted replaced
42415:85388bae723d 42416:1cfad0990b99
  1867      *  A change listener can be attached to an inference variable, to receive notifications
  1867      *  A change listener can be attached to an inference variable, to receive notifications
  1868      *  whenever the bounds of an inference variable change.
  1868      *  whenever the bounds of an inference variable change.
  1869      */
  1869      */
  1870     public static class UndetVar extends DelegatedType {
  1870     public static class UndetVar extends DelegatedType {
  1871 
  1871 
       
  1872         enum Kind {
       
  1873             NORMAL,
       
  1874             CAPTURED,
       
  1875             THROWS;
       
  1876         }
       
  1877 
  1872         /** Inference variable change listener. The listener method is called
  1878         /** Inference variable change listener. The listener method is called
  1873          *  whenever a change to the inference variable's bounds occurs
  1879          *  whenever a change to the inference variable's bounds occurs
  1874          */
  1880          */
  1875         public interface UndetVarListener {
  1881         public interface UndetVarListener {
  1876             /** called when some inference variable bounds (of given kinds ibs) change */
  1882             /** called when some inference variable bounds (of given kinds ibs) change */
  1927         public int declaredCount;
  1933         public int declaredCount;
  1928 
  1934 
  1929         /** inference variable's change listener */
  1935         /** inference variable's change listener */
  1930         public UndetVarListener listener = null;
  1936         public UndetVarListener listener = null;
  1931 
  1937 
       
  1938         Kind kind;
       
  1939 
  1932         @Override
  1940         @Override
  1933         public <R,S> R accept(Type.Visitor<R,S> v, S s) {
  1941         public <R,S> R accept(Type.Visitor<R,S> v, S s) {
  1934             return v.visitUndetVar(this, s);
  1942             return v.visitUndetVar(this, s);
  1935         }
  1943         }
  1936 
  1944 
  1937         public UndetVar(TypeVar origin, UndetVarListener listener, Types types) {
  1945         public UndetVar(TypeVar origin, UndetVarListener listener, Types types) {
  1938             // This is a synthesized internal type, so we cannot annotate it.
  1946             // This is a synthesized internal type, so we cannot annotate it.
  1939             super(UNDETVAR, origin);
  1947             super(UNDETVAR, origin);
       
  1948             this.kind = origin.isCaptured() ?
       
  1949                     Kind.CAPTURED :
       
  1950                     Kind.NORMAL;
  1940             this.listener = listener;
  1951             this.listener = listener;
  1941             bounds = new EnumMap<>(InferenceBound.class);
  1952             bounds = new EnumMap<>(InferenceBound.class);
  1942             List<Type> declaredBounds = types.getBounds(origin);
  1953             List<Type> declaredBounds = types.getBounds(origin);
  1943             declaredCount = declaredBounds.length();
  1954             declaredCount = declaredBounds.length();
  1944             bounds.put(InferenceBound.UPPER, List.nil());
  1955             bounds.put(InferenceBound.UPPER, List.nil());
  1946             bounds.put(InferenceBound.EQ, List.nil());
  1957             bounds.put(InferenceBound.EQ, List.nil());
  1947             for (Type t : declaredBounds.reverse()) {
  1958             for (Type t : declaredBounds.reverse()) {
  1948                 //add bound works in reverse order
  1959                 //add bound works in reverse order
  1949                 addBound(InferenceBound.UPPER, t, types, true);
  1960                 addBound(InferenceBound.UPPER, t, types, true);
  1950             }
  1961             }
       
  1962             if (origin.isCaptured() && !origin.lower.hasTag(BOT)) {
       
  1963                 //add lower bound if needed
       
  1964                 addBound(InferenceBound.LOWER, origin.lower, types, true);
       
  1965             }
  1951         }
  1966         }
  1952 
  1967 
  1953         @DefinedBy(Api.LANGUAGE_MODEL)
  1968         @DefinedBy(Api.LANGUAGE_MODEL)
  1954         public String toString() {
  1969         public String toString() {
  1955             StringBuilder sb = new StringBuilder();
  1970             StringBuilder sb = new StringBuilder();
  1973                 if (aboundList.size() > 0) {
  1988                 if (aboundList.size() > 0) {
  1974                     result += bound + " = " + aboundList + '\n';
  1989                     result += bound + " = " + aboundList + '\n';
  1975                 }
  1990                 }
  1976             }
  1991             }
  1977             return result;
  1992             return result;
       
  1993         }
       
  1994 
       
  1995         public void setThrow() {
       
  1996             if (this.kind == Kind.CAPTURED) {
       
  1997                 //invalid state transition
       
  1998                 throw new IllegalStateException();
       
  1999             }
       
  2000             this.kind = Kind.THROWS;
  1978         }
  2001         }
  1979 
  2002 
  1980         /**
  2003         /**
  1981          * Returns a new copy of this undet var.
  2004          * Returns a new copy of this undet var.
  1982          */
  2005          */
  2060         /** add a bound of a given kind - this might trigger listener notification */
  2083         /** add a bound of a given kind - this might trigger listener notification */
  2061         public final void addBound(InferenceBound ib, Type bound, Types types) {
  2084         public final void addBound(InferenceBound ib, Type bound, Types types) {
  2062             addBound(ib, bound, types, false);
  2085             addBound(ib, bound, types, false);
  2063         }
  2086         }
  2064 
  2087 
  2065         protected void addBound(InferenceBound ib, Type bound, Types types, boolean update) {
  2088         @SuppressWarnings("fallthrough")
  2066             Type bound2 = bound.map(toTypeVarMap).baseType();
  2089         private void addBound(InferenceBound ib, Type bound, Types types, boolean update) {
  2067             List<Type> prevBounds = bounds.get(ib);
  2090             if (kind == Kind.CAPTURED && !update) {
  2068             if (bound == qtype) return;
  2091                 //Captured inference variables bounds must not be updated during incorporation,
  2069             for (Type b : prevBounds) {
  2092                 //except when some inference variable (beta) has been instantiated in the
  2070                 //check for redundancy - use strict version of isSameType on tvars
  2093                 //right-hand-side of a 'C<alpha> = capture(C<? extends/super beta>) constraint.
  2071                 //(as the standard version will lead to false positives w.r.t. clones ivars)
  2094                 if (bound.hasTag(UNDETVAR) && !((UndetVar)bound).isCaptured()) {
  2072                 if (types.isSameType(b, bound2, true)) return;
  2095                     //If the new incoming bound is itself a (regular) inference variable,
  2073             }
  2096                     //then we are allowed to propagate this inference variable bounds to it.
  2074             bounds.put(ib, prevBounds.prepend(bound2));
  2097                     ((UndetVar)bound).addBound(ib.complement(), this, types, false);
  2075             notifyBoundChange(ib, bound2, false);
  2098                 }
       
  2099             } else {
       
  2100                 Type bound2 = bound.map(toTypeVarMap).baseType();
       
  2101                 List<Type> prevBounds = bounds.get(ib);
       
  2102                 if (bound == qtype) return;
       
  2103                 for (Type b : prevBounds) {
       
  2104                     //check for redundancy - use strict version of isSameType on tvars
       
  2105                     //(as the standard version will lead to false positives w.r.t. clones ivars)
       
  2106                     if (types.isSameType(b, bound2, true)) return;
       
  2107                 }
       
  2108                 bounds.put(ib, prevBounds.prepend(bound2));
       
  2109                 notifyBoundChange(ib, bound2, false);
       
  2110             }
  2076         }
  2111         }
  2077         //where
  2112         //where
  2078             TypeMapping<Void> toTypeVarMap = new TypeMapping<Void>() {
  2113             TypeMapping<Void> toTypeVarMap = new TypeMapping<Void>() {
  2079                 @Override
  2114                 @Override
  2080                 public Type visitUndetVar(UndetVar uv, Void _unused) {
  2115                 public Type visitUndetVar(UndetVar uv, Void _unused) {
  2126             if (listener != null) {
  2161             if (listener != null) {
  2127                 listener.varBoundChanged(this, ib, bound, update);
  2162                 listener.varBoundChanged(this, ib, bound, update);
  2128             }
  2163             }
  2129         }
  2164         }
  2130 
  2165 
  2131         public boolean isCaptured() {
  2166         public final boolean isCaptured() {
  2132             return false;
  2167             return kind == Kind.CAPTURED;
  2133         }
  2168         }
  2134     }
  2169 
  2135 
  2170         public final boolean isThrows() {
  2136     /**
  2171             return kind == Kind.THROWS;
  2137      * This class is used to represent synthetic captured inference variables
       
  2138      * that can be generated during nested generic method calls. The only difference
       
  2139      * between these inference variables and ordinary ones is that captured inference
       
  2140      * variables cannot get new bounds through incorporation.
       
  2141      */
       
  2142     public static class CapturedUndetVar extends UndetVar {
       
  2143 
       
  2144         public CapturedUndetVar(CapturedType origin, UndetVarListener listener, Types types) {
       
  2145             super(origin, listener, types);
       
  2146             if (!origin.lower.hasTag(BOT)) {
       
  2147                 addBound(InferenceBound.LOWER, origin.lower, types, true);
       
  2148             }
       
  2149         }
       
  2150 
       
  2151         @Override
       
  2152         public void addBound(InferenceBound ib, Type bound, Types types, boolean update) {
       
  2153             if (update) {
       
  2154                 //only change bounds if request comes from substBounds
       
  2155                 super.addBound(ib, bound, types, update);
       
  2156             }
       
  2157             else if (bound.hasTag(UNDETVAR) && !((UndetVar) bound).isCaptured()) {
       
  2158                 ((UndetVar) bound).addBound(ib.complement(), this, types, false);
       
  2159             }
       
  2160         }
       
  2161 
       
  2162         @Override
       
  2163         public boolean isCaptured() {
       
  2164             return true;
       
  2165         }
       
  2166 
       
  2167         public UndetVar dup(Types types) {
       
  2168             UndetVar uv2 = new CapturedUndetVar((CapturedType)qtype, listener, types);
       
  2169             dupTo(uv2, types);
       
  2170             return uv2;
       
  2171         }
  2172         }
  2172     }
  2173     }
  2173 
  2174 
  2174     /** Represents NONE.
  2175     /** Represents NONE.
  2175      */
  2176      */