73 * If you write code that depends on this, you do so at your own risk. |
73 * If you write code that depends on this, you do so at your own risk. |
74 * This code and its internal interfaces are subject to change or |
74 * This code and its internal interfaces are subject to change or |
75 * deletion without notice.</b> |
75 * deletion without notice.</b> |
76 */ |
76 */ |
77 public class Types { |
77 public class Types { |
78 protected static final Context.Key<Types> typesKey = |
78 protected static final Context.Key<Types> typesKey = new Context.Key<>(); |
79 new Context.Key<Types>(); |
|
80 |
79 |
81 final Symtab syms; |
80 final Symtab syms; |
82 final JavacMessages messages; |
81 final JavacMessages messages; |
83 final Names names; |
82 final Names names; |
84 final boolean allowBoxing; |
83 final boolean allowBoxing; |
245 if (t.tsym == sym) |
244 if (t.tsym == sym) |
246 return t; |
245 return t; |
247 Type base = asSuper(sym.type, t.tsym); |
246 Type base = asSuper(sym.type, t.tsym); |
248 if (base == null) |
247 if (base == null) |
249 return null; |
248 return null; |
250 ListBuffer<Type> from = new ListBuffer<Type>(); |
249 ListBuffer<Type> from = new ListBuffer<>(); |
251 ListBuffer<Type> to = new ListBuffer<Type>(); |
250 ListBuffer<Type> to = new ListBuffer<>(); |
252 try { |
251 try { |
253 adapt(base, t, from, to); |
252 adapt(base, t, from, to); |
254 } catch (AdaptFailure ex) { |
253 } catch (AdaptFailure ex) { |
255 return null; |
254 return null; |
256 } |
255 } |
257 Type res = subst(sym.type, from.toList(), to.toList()); |
256 Type res = subst(sym.type, from.toList(), to.toList()); |
258 if (!isSubtype(res, t)) |
257 if (!isSubtype(res, t)) |
259 return null; |
258 return null; |
260 ListBuffer<Type> openVars = new ListBuffer<Type>(); |
259 ListBuffer<Type> openVars = new ListBuffer<>(); |
261 for (List<Type> l = sym.type.allparams(); |
260 for (List<Type> l = sym.type.allparams(); |
262 l.nonEmpty(); l = l.tail) |
261 l.nonEmpty(); l = l.tail) |
263 if (res.contains(l.head) && !t.contains(l.head)) |
262 if (res.contains(l.head) && !t.contains(l.head)) |
264 openVars.append(l.head); |
263 openVars.append(l.head); |
265 if (openVars.nonEmpty()) { |
264 if (openVars.nonEmpty()) { |
267 // The subtype of a raw type is raw |
266 // The subtype of a raw type is raw |
268 res = erasure(res); |
267 res = erasure(res); |
269 } else { |
268 } else { |
270 // Unbound type arguments default to ? |
269 // Unbound type arguments default to ? |
271 List<Type> opens = openVars.toList(); |
270 List<Type> opens = openVars.toList(); |
272 ListBuffer<Type> qs = new ListBuffer<Type>(); |
271 ListBuffer<Type> qs = new ListBuffer<>(); |
273 for (List<Type> iter = opens; iter.nonEmpty(); iter = iter.tail) { |
272 for (List<Type> iter = opens; iter.nonEmpty(); iter = iter.tail) { |
274 qs.append(new WildcardType(syms.objectType, BoundKind.UNBOUND, syms.boundClass, (TypeVar) iter.head.unannotatedType())); |
273 qs.append(new WildcardType(syms.objectType, BoundKind.UNBOUND, syms.boundClass, (TypeVar) iter.head.unannotatedType())); |
275 } |
274 } |
276 res = subst(res, opens, qs.toList()); |
275 res = subst(res, opens, qs.toList()); |
277 } |
276 } |
345 * A cache that keeps track of function descriptors associated with given |
344 * A cache that keeps track of function descriptors associated with given |
346 * functional interfaces. |
345 * functional interfaces. |
347 */ |
346 */ |
348 class DescriptorCache { |
347 class DescriptorCache { |
349 |
348 |
350 private WeakHashMap<TypeSymbol, Entry> _map = new WeakHashMap<TypeSymbol, Entry>(); |
349 private WeakHashMap<TypeSymbol, Entry> _map = new WeakHashMap<>(); |
351 |
350 |
352 class FunctionDescriptor { |
351 class FunctionDescriptor { |
353 Symbol descSym; |
352 Symbol descSym; |
354 |
353 |
355 FunctionDescriptor(Symbol descSym) { |
354 FunctionDescriptor(Symbol descSym) { |
725 return sym.kind == Kinds.MTH && |
724 return sym.kind == Kinds.MTH && |
726 (sym.flags() & (ABSTRACT | DEFAULT)) == ABSTRACT && |
725 (sym.flags() & (ABSTRACT | DEFAULT)) == ABSTRACT && |
727 !overridesObjectMethod(origin, sym) && |
726 !overridesObjectMethod(origin, sym) && |
728 (interfaceCandidates(origin.type, (MethodSymbol)sym).head.flags() & DEFAULT) == 0; |
727 (interfaceCandidates(origin.type, (MethodSymbol)sym).head.flags() & DEFAULT) == 0; |
729 } |
728 } |
730 }; |
729 } |
731 |
730 |
732 // <editor-fold defaultstate="collapsed" desc="isSubtype"> |
731 // <editor-fold defaultstate="collapsed" desc="isSubtype"> |
733 /** |
732 /** |
734 * Is t an unchecked subtype of s? |
733 * Is t an unchecked subtype of s? |
735 */ |
734 */ |
862 default: |
861 default: |
863 throw new AssertionError("isSubtype " + t.getTag()); |
862 throw new AssertionError("isSubtype " + t.getTag()); |
864 } |
863 } |
865 } |
864 } |
866 |
865 |
867 private Set<TypePair> cache = new HashSet<TypePair>(); |
866 private Set<TypePair> cache = new HashSet<>(); |
868 |
867 |
869 private boolean containsTypeRecursive(Type t, Type s) { |
868 private boolean containsTypeRecursive(Type t, Type s) { |
870 TypePair pair = new TypePair(t, s); |
869 TypePair pair = new TypePair(t, s); |
871 if (cache.add(pair)) { |
870 if (cache.add(pair)) { |
872 try { |
871 try { |
1142 |
1141 |
1143 if (t.isCompound() && s.isCompound()) { |
1142 if (t.isCompound() && s.isCompound()) { |
1144 if (!visit(supertype(t), supertype(s))) |
1143 if (!visit(supertype(t), supertype(s))) |
1145 return false; |
1144 return false; |
1146 |
1145 |
1147 HashSet<UniqueType> set = new HashSet<UniqueType>(); |
1146 HashSet<UniqueType> set = new HashSet<>(); |
1148 for (Type x : interfaces(t)) |
1147 for (Type x : interfaces(t)) |
1149 set.add(new UniqueType(x.unannotatedType(), Types.this)); |
1148 set.add(new UniqueType(x.unannotatedType(), Types.this)); |
1150 for (Type x : interfaces(s)) { |
1149 for (Type x : interfaces(s)) { |
1151 if (!set.remove(new UniqueType(x.unannotatedType(), Types.this))) |
1150 if (!set.remove(new UniqueType(x.unannotatedType(), Types.this))) |
1152 return false; |
1151 return false; |
1230 } |
1229 } |
1231 @Override |
1230 @Override |
1232 protected boolean containsTypes(List<Type> ts1, List<Type> ts2) { |
1231 protected boolean containsTypes(List<Type> ts1, List<Type> ts2) { |
1233 return containsTypeEquivalent(ts1, ts2); |
1232 return containsTypeEquivalent(ts1, ts2); |
1234 } |
1233 } |
1235 }; |
1234 } |
1236 |
1235 |
1237 /** |
1236 /** |
1238 * Strict type-equality relation - type variables are considered |
1237 * Strict type-equality relation - type variables are considered |
1239 * equals if they share the same object identity. |
1238 * equals if they share the same object identity. |
1240 */ |
1239 */ |
1241 TypeRelation isSameTypeStrict = new SameTypeVisitor() { |
1240 TypeRelation isSameTypeStrict = new SameTypeVisitor() { |
1242 @Override |
1241 @Override |
1705 return disjointType.visit(t, s); |
1704 return disjointType.visit(t, s); |
1706 } |
1705 } |
1707 // where |
1706 // where |
1708 private TypeRelation disjointType = new TypeRelation() { |
1707 private TypeRelation disjointType = new TypeRelation() { |
1709 |
1708 |
1710 private Set<TypePair> cache = new HashSet<TypePair>(); |
1709 private Set<TypePair> cache = new HashSet<>(); |
1711 |
1710 |
1712 @Override |
1711 @Override |
1713 public Boolean visitType(Type t, Type s) { |
1712 public Boolean visitType(Type t, Type s) { |
1714 if (s.hasTag(WILDCARD)) |
1713 if (s.hasTag(WILDCARD)) |
1715 return visit(s, t); |
1714 return visit(s, t); |
2444 return false; |
2443 return false; |
2445 } |
2444 } |
2446 // </editor-fold> |
2445 // </editor-fold> |
2447 |
2446 |
2448 // <editor-fold defaultstate="collapsed" desc="isDerivedRaw"> |
2447 // <editor-fold defaultstate="collapsed" desc="isDerivedRaw"> |
2449 Map<Type,Boolean> isDerivedRawCache = new HashMap<Type,Boolean>(); |
2448 Map<Type,Boolean> isDerivedRawCache = new HashMap<>(); |
2450 |
2449 |
2451 public boolean isDerivedRaw(Type t) { |
2450 public boolean isDerivedRaw(Type t) { |
2452 Boolean result = isDerivedRawCache.get(t); |
2451 Boolean result = isDerivedRawCache.get(t); |
2453 if (result == null) { |
2452 if (result == null) { |
2454 result = isDerivedRawInternal(t); |
2453 result = isDerivedRawInternal(t); |
2606 } |
2605 } |
2607 |
2606 |
2608 // <editor-fold defaultstate="collapsed" desc="Determining method implementation in given site"> |
2607 // <editor-fold defaultstate="collapsed" desc="Determining method implementation in given site"> |
2609 class ImplementationCache { |
2608 class ImplementationCache { |
2610 |
2609 |
2611 private WeakHashMap<MethodSymbol, SoftReference<Map<TypeSymbol, Entry>>> _map = |
2610 private WeakHashMap<MethodSymbol, SoftReference<Map<TypeSymbol, Entry>>> _map = new WeakHashMap<>(); |
2612 new WeakHashMap<MethodSymbol, SoftReference<Map<TypeSymbol, Entry>>>(); |
|
2613 |
2611 |
2614 class Entry { |
2612 class Entry { |
2615 final MethodSymbol cachedImpl; |
2613 final MethodSymbol cachedImpl; |
2616 final Filter<Symbol> implFilter; |
2614 final Filter<Symbol> implFilter; |
2617 final boolean checkResult; |
2615 final boolean checkResult; |
2636 |
2634 |
2637 MethodSymbol get(MethodSymbol ms, TypeSymbol origin, boolean checkResult, Filter<Symbol> implFilter) { |
2635 MethodSymbol get(MethodSymbol ms, TypeSymbol origin, boolean checkResult, Filter<Symbol> implFilter) { |
2638 SoftReference<Map<TypeSymbol, Entry>> ref_cache = _map.get(ms); |
2636 SoftReference<Map<TypeSymbol, Entry>> ref_cache = _map.get(ms); |
2639 Map<TypeSymbol, Entry> cache = ref_cache != null ? ref_cache.get() : null; |
2637 Map<TypeSymbol, Entry> cache = ref_cache != null ? ref_cache.get() : null; |
2640 if (cache == null) { |
2638 if (cache == null) { |
2641 cache = new HashMap<TypeSymbol, Entry>(); |
2639 cache = new HashMap<>(); |
2642 _map.put(ms, new SoftReference<Map<TypeSymbol, Entry>>(cache)); |
2640 _map.put(ms, new SoftReference<>(cache)); |
2643 } |
2641 } |
2644 Entry e = cache.get(origin); |
2642 Entry e = cache.get(origin); |
2645 CompoundScope members = membersClosure(origin.type, true); |
2643 CompoundScope members = membersClosure(origin.type, true); |
2646 if (e == null || |
2644 if (e == null || |
2647 !e.matches(implFilter, checkResult, members.getMark())) { |
2645 !e.matches(implFilter, checkResult, members.getMark())) { |
2679 // </editor-fold> |
2677 // </editor-fold> |
2680 |
2678 |
2681 // <editor-fold defaultstate="collapsed" desc="compute transitive closure of all members in given site"> |
2679 // <editor-fold defaultstate="collapsed" desc="compute transitive closure of all members in given site"> |
2682 class MembersClosureCache extends SimpleVisitor<CompoundScope, Boolean> { |
2680 class MembersClosureCache extends SimpleVisitor<CompoundScope, Boolean> { |
2683 |
2681 |
2684 private WeakHashMap<TypeSymbol, Entry> _map = |
2682 private WeakHashMap<TypeSymbol, Entry> _map = new WeakHashMap<>(); |
2685 new WeakHashMap<TypeSymbol, Entry>(); |
|
2686 |
2683 |
2687 class Entry { |
2684 class Entry { |
2688 final boolean skipInterfaces; |
2685 final boolean skipInterfaces; |
2689 final CompoundScope compoundScope; |
2686 final CompoundScope compoundScope; |
2690 |
2687 |
2798 s.name == msym.name && |
2795 s.name == msym.name && |
2799 (s.flags() & SYNTHETIC) == 0 && |
2796 (s.flags() & SYNTHETIC) == 0 && |
2800 s.isInheritedIn(site.tsym, Types.this) && |
2797 s.isInheritedIn(site.tsym, Types.this) && |
2801 overrideEquivalent(memberType(site, s), memberType(site, msym)); |
2798 overrideEquivalent(memberType(site, s), memberType(site, msym)); |
2802 } |
2799 } |
2803 }; |
2800 } |
2804 // </editor-fold> |
2801 // </editor-fold> |
2805 |
2802 |
2806 /** |
2803 /** |
2807 * Does t have the same arguments as s? It is assumed that both |
2804 * Does t have the same arguments as s? It is assumed that both |
2808 * types are (possibly polymorphic) method types. Monomorphic |
2805 * types are (possibly polymorphic) method types. Monomorphic |
3299 * <p>A closure is a list of all the supertypes and interfaces of |
3296 * <p>A closure is a list of all the supertypes and interfaces of |
3300 * a class or interface type, ordered by ClassSymbol.precedes |
3297 * a class or interface type, ordered by ClassSymbol.precedes |
3301 * (that is, subclasses come first, arbitrary but fixed |
3298 * (that is, subclasses come first, arbitrary but fixed |
3302 * otherwise). |
3299 * otherwise). |
3303 */ |
3300 */ |
3304 private Map<Type,List<Type>> closureCache = new HashMap<Type,List<Type>>(); |
3301 private Map<Type,List<Type>> closureCache = new HashMap<>(); |
3305 |
3302 |
3306 /** |
3303 /** |
3307 * Returns the closure of a class or interface type. |
3304 * Returns the closure of a class or interface type. |
3308 */ |
3305 */ |
3309 public List<Type> closure(Type t) { |
3306 public List<Type> closure(Type t) { |
3402 TypePair typePair = (TypePair)obj; |
3399 TypePair typePair = (TypePair)obj; |
3403 return isSameType(t1, typePair.t1) |
3400 return isSameType(t1, typePair.t1) |
3404 && isSameType(t2, typePair.t2); |
3401 && isSameType(t2, typePair.t2); |
3405 } |
3402 } |
3406 } |
3403 } |
3407 Set<TypePair> mergeCache = new HashSet<TypePair>(); |
3404 Set<TypePair> mergeCache = new HashSet<>(); |
3408 private Type merge(Type c1, Type c2) { |
3405 private Type merge(Type c1, Type c2) { |
3409 ClassType class1 = (ClassType) c1; |
3406 ClassType class1 = (ClassType) c1; |
3410 List<Type> act1 = class1.getTypeArguments(); |
3407 List<Type> act1 = class1.getTypeArguments(); |
3411 ClassType class2 = (ClassType) c2; |
3408 ClassType class2 = (ClassType) c2; |
3412 List<Type> act2 = class2.getTypeArguments(); |
3409 List<Type> act2 = class2.getTypeArguments(); |
3413 ListBuffer<Type> merged = new ListBuffer<Type>(); |
3410 ListBuffer<Type> merged = new ListBuffer<>(); |
3414 List<Type> typarams = class1.tsym.type.getTypeArguments(); |
3411 List<Type> typarams = class1.tsym.type.getTypeArguments(); |
3415 |
3412 |
3416 while (act1.nonEmpty() && act2.nonEmpty() && typarams.nonEmpty()) { |
3413 while (act1.nonEmpty() && act2.nonEmpty() && typarams.nonEmpty()) { |
3417 if (containsType(act1.head, act2.head)) { |
3414 if (containsType(act1.head, act2.head)) { |
3418 merged.append(act1.head); |
3415 merged.append(act1.head); |
4088 Map<Symbol,Type> mapping; |
4085 Map<Symbol,Type> mapping; |
4089 |
4086 |
4090 Adapter(ListBuffer<Type> from, ListBuffer<Type> to) { |
4087 Adapter(ListBuffer<Type> from, ListBuffer<Type> to) { |
4091 this.from = from; |
4088 this.from = from; |
4092 this.to = to; |
4089 this.to = to; |
4093 mapping = new HashMap<Symbol,Type>(); |
4090 mapping = new HashMap<>(); |
4094 } |
4091 } |
4095 |
4092 |
4096 public void adapt(Type source, Type target) throws AdaptFailure { |
4093 public void adapt(Type source, Type target) throws AdaptFailure { |
4097 visit(source, target); |
4094 visit(source, target); |
4098 List<Type> fromList = from.toList(); |
4095 List<Type> fromList = from.toList(); |
4157 @Override |
4154 @Override |
4158 public Void visitType(Type source, Type target) { |
4155 public Void visitType(Type source, Type target) { |
4159 return null; |
4156 return null; |
4160 } |
4157 } |
4161 |
4158 |
4162 private Set<TypePair> cache = new HashSet<TypePair>(); |
4159 private Set<TypePair> cache = new HashSet<>(); |
4163 |
4160 |
4164 private void adaptRecursive(Type source, Type target) { |
4161 private void adaptRecursive(Type source, Type target) { |
4165 TypePair pair = new TypePair(source, target); |
4162 TypePair pair = new TypePair(source, target); |
4166 if (cache.add(pair)) { |
4163 if (cache.add(pair)) { |
4167 try { |
4164 try { |
4231 this.rewriteTypeVars = rewriteTypeVars; |
4228 this.rewriteTypeVars = rewriteTypeVars; |
4232 } |
4229 } |
4233 |
4230 |
4234 @Override |
4231 @Override |
4235 public Type visitClassType(ClassType t, Void s) { |
4232 public Type visitClassType(ClassType t, Void s) { |
4236 ListBuffer<Type> rewritten = new ListBuffer<Type>(); |
4233 ListBuffer<Type> rewritten = new ListBuffer<>(); |
4237 boolean changed = false; |
4234 boolean changed = false; |
4238 for (Type arg : t.allparams()) { |
4235 for (Type arg : t.allparams()) { |
4239 Type bound = visit(arg); |
4236 Type bound = visit(arg); |
4240 if (arg != bound) { |
4237 if (arg != bound) { |
4241 changed = true; |
4238 changed = true; |