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(); |
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 */ |