Types.java revision 2897:524255b0bec0
1219019Sgabor/* 2219019Sgabor * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. 3219019Sgabor * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4219019Sgabor * 5219019Sgabor * This code is free software; you can redistribute it and/or modify it 6219019Sgabor * under the terms of the GNU General Public License version 2 only, as 7219019Sgabor * published by the Free Software Foundation. Oracle designates this 8219019Sgabor * particular file as subject to the "Classpath" exception as provided 9219019Sgabor * by Oracle in the LICENSE file that accompanied this code. 10219019Sgabor * 11219019Sgabor * This code is distributed in the hope that it will be useful, but WITHOUT 12219019Sgabor * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13219019Sgabor * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14219019Sgabor * version 2 for more details (a copy is included in the LICENSE file that 15219019Sgabor * accompanied this code). 16219019Sgabor * 17219019Sgabor * You should have received a copy of the GNU General Public License version 18219019Sgabor * 2 along with this work; if not, write to the Free Software Foundation, 19219019Sgabor * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20219019Sgabor * 21219019Sgabor * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22219019Sgabor * or visit www.oracle.com if you need additional information or have any 23219019Sgabor * questions. 24219019Sgabor */ 25219019Sgabor 26219019Sgaborpackage com.sun.tools.javac.code; 27219019Sgabor 28219019Sgaborimport java.lang.ref.SoftReference; 29219019Sgaborimport java.util.HashSet; 30219019Sgaborimport java.util.HashMap; 31219019Sgaborimport java.util.Locale; 32219019Sgaborimport java.util.Map; 33219019Sgaborimport java.util.Set; 34219019Sgaborimport java.util.WeakHashMap; 35219019Sgaborimport java.util.function.BiPredicate; 36219019Sgaborimport java.util.stream.Collector; 37219019Sgabor 38219019Sgaborimport javax.tools.JavaFileObject; 39219019Sgabor 40219019Sgaborimport com.sun.tools.javac.code.Attribute.RetentionPolicy; 41219019Sgaborimport com.sun.tools.javac.code.Lint.LintCategory; 42219019Sgaborimport com.sun.tools.javac.code.Type.UndetVar.InferenceBound; 43219019Sgaborimport com.sun.tools.javac.code.TypeMetadata.Entry.Kind; 44219019Sgaborimport com.sun.tools.javac.comp.AttrContext; 45219019Sgaborimport com.sun.tools.javac.comp.Check; 46219019Sgaborimport com.sun.tools.javac.comp.Enter; 47219019Sgaborimport com.sun.tools.javac.comp.Env; 48219019Sgaborimport com.sun.tools.javac.util.*; 49219019Sgabor 50219019Sgaborimport static com.sun.tools.javac.code.BoundKind.*; 51219019Sgaborimport static com.sun.tools.javac.code.Flags.*; 52219019Sgaborimport static com.sun.tools.javac.code.Kinds.Kind.*; 53219019Sgaborimport static com.sun.tools.javac.code.Scope.*; 54219019Sgaborimport static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE; 55219019Sgaborimport static com.sun.tools.javac.code.Symbol.*; 56219019Sgaborimport static com.sun.tools.javac.code.Type.*; 57219019Sgaborimport static com.sun.tools.javac.code.TypeTag.*; 58219019Sgaborimport static com.sun.tools.javac.jvm.ClassFile.externalize; 59219019Sgabor 60219019Sgabor/** 61219019Sgabor * Utility class containing various operations on types. 62219019Sgabor * 63219019Sgabor * <p>Unless other names are more illustrative, the following naming 64219019Sgabor * conventions should be observed in this file: 65219019Sgabor * 66219019Sgabor * <dl> 67219019Sgabor * <dt>t</dt> 68219019Sgabor * <dd>If the first argument to an operation is a type, it should be named t.</dd> 69219019Sgabor * <dt>s</dt> 70219019Sgabor * <dd>Similarly, if the second argument to an operation is a type, it should be named s.</dd> 71219019Sgabor * <dt>ts</dt> 72219019Sgabor * <dd>If an operations takes a list of types, the first should be named ts.</dd> 73219019Sgabor * <dt>ss</dt> 74219019Sgabor * <dd>A second list of types should be named ss.</dd> 75219019Sgabor * </dl> 76219019Sgabor * 77219019Sgabor * <p><b>This is NOT part of any supported API. 78219019Sgabor * If you write code that depends on this, you do so at your own risk. 79219019Sgabor * This code and its internal interfaces are subject to change or 80219019Sgabor * deletion without notice.</b> 81219019Sgabor */ 82219019Sgaborpublic class Types { 83219019Sgabor protected static final Context.Key<Types> typesKey = new Context.Key<>(); 84219019Sgabor 85219019Sgabor final Symtab syms; 86219019Sgabor final JavacMessages messages; 87219019Sgabor final Names names; 88219019Sgabor final boolean allowObjectToPrimitiveCast; 89219019Sgabor final boolean allowDefaultMethods; 90219019Sgabor final Check chk; 91219019Sgabor final Enter enter; 92219019Sgabor JCDiagnostic.Factory diags; 93219019Sgabor List<Warner> warnStack = List.nil(); 94219019Sgabor final Name capturedName; 95219019Sgabor private final FunctionDescriptorLookupError functionDescriptorLookupError; 96219019Sgabor 97219019Sgabor public final Warner noWarnings; 98219019Sgabor 99219019Sgabor // <editor-fold defaultstate="collapsed" desc="Instantiating"> 100219019Sgabor public static Types instance(Context context) { 101219019Sgabor Types instance = context.get(typesKey); 102219019Sgabor if (instance == null) 103219019Sgabor instance = new Types(context); 104219019Sgabor return instance; 105219019Sgabor } 106219019Sgabor 107219019Sgabor protected Types(Context context) { 108219019Sgabor context.put(typesKey, this); 109219019Sgabor syms = Symtab.instance(context); 110219019Sgabor names = Names.instance(context); 111219019Sgabor Source source = Source.instance(context); 112219019Sgabor allowObjectToPrimitiveCast = source.allowObjectToPrimitiveCast(); 113219019Sgabor allowDefaultMethods = source.allowDefaultMethods(); 114219019Sgabor chk = Check.instance(context); 115219019Sgabor enter = Enter.instance(context); 116219019Sgabor capturedName = names.fromString("<captured wildcard>"); 117219019Sgabor messages = JavacMessages.instance(context); 118219019Sgabor diags = JCDiagnostic.Factory.instance(context); 119219019Sgabor functionDescriptorLookupError = new FunctionDescriptorLookupError(); 120219019Sgabor noWarnings = new Warner(null); 121219019Sgabor } 122219019Sgabor // </editor-fold> 123219019Sgabor 124219019Sgabor // <editor-fold defaultstate="collapsed" desc="bounds"> 125219019Sgabor /** 126219019Sgabor * Get a wildcard's upper bound, returning non-wildcards unchanged. 127219019Sgabor * @param t a type argument, either a wildcard or a type 128219019Sgabor */ 129219019Sgabor public Type wildUpperBound(Type t) { 130219019Sgabor if (t.hasTag(WILDCARD)) { 131219019Sgabor WildcardType w = (WildcardType) t; 132219019Sgabor if (w.isSuperBound()) 133219019Sgabor return w.bound == null ? syms.objectType : w.bound.bound; 134219019Sgabor else 135219019Sgabor return wildUpperBound(w.type); 136219019Sgabor } 137219019Sgabor else return t; 138219019Sgabor } 139219019Sgabor 140219019Sgabor /** 141219019Sgabor * Get a capture variable's upper bound, returning other types unchanged. 142219019Sgabor * @param t a type 143219019Sgabor */ 144219019Sgabor public Type cvarUpperBound(Type t) { 145219019Sgabor if (t.hasTag(TYPEVAR)) { 146219019Sgabor TypeVar v = (TypeVar) t; 147219019Sgabor return v.isCaptured() ? cvarUpperBound(v.bound) : v; 148219019Sgabor } 149219019Sgabor else return t; 150219019Sgabor } 151219019Sgabor 152219019Sgabor /** 153219019Sgabor * Get a wildcard's lower bound, returning non-wildcards unchanged. 154219019Sgabor * @param t a type argument, either a wildcard or a type 155219019Sgabor */ 156219019Sgabor public Type wildLowerBound(Type t) { 157219019Sgabor if (t.hasTag(WILDCARD)) { 158219019Sgabor WildcardType w = (WildcardType) t; 159219019Sgabor return w.isExtendsBound() ? syms.botType : wildLowerBound(w.type); 160219019Sgabor } 161219019Sgabor else return t; 162219019Sgabor } 163219019Sgabor 164219019Sgabor /** 165219019Sgabor * Get a capture variable's lower bound, returning other types unchanged. 166219019Sgabor * @param t a type 167219019Sgabor */ 168219019Sgabor public Type cvarLowerBound(Type t) { 169219019Sgabor if (t.hasTag(TYPEVAR) && ((TypeVar) t).isCaptured()) { 170219019Sgabor return cvarLowerBound(t.getLowerBound()); 171219019Sgabor } 172219019Sgabor else return t; 173219019Sgabor } 174219019Sgabor 175219019Sgabor /** 176219019Sgabor * Recursively skip type-variables until a class/array type is found; capture conversion is then 177219019Sgabor * (optionally) applied to the resulting type. This is useful for i.e. computing a site that is 178219019Sgabor * suitable for a method lookup. 179219019Sgabor */ 180219019Sgabor public Type skipTypeVars(Type site, boolean capture) { 181219019Sgabor while (site.hasTag(TYPEVAR)) { 182219019Sgabor site = site.getUpperBound(); 183219019Sgabor } 184219019Sgabor return capture ? capture(site) : site; 185219019Sgabor } 186219019Sgabor // </editor-fold> 187219019Sgabor 188219019Sgabor // <editor-fold defaultstate="collapsed" desc="isUnbounded"> 189219019Sgabor /** 190219019Sgabor * Checks that all the arguments to a class are unbounded 191219019Sgabor * wildcards or something else that doesn't make any restrictions 192219019Sgabor * on the arguments. If a class isUnbounded, a raw super- or 193219019Sgabor * subclass can be cast to it without a warning. 194219019Sgabor * @param t a type 195219019Sgabor * @return true iff the given type is unbounded or raw 196219019Sgabor */ 197219019Sgabor public boolean isUnbounded(Type t) { 198219019Sgabor return isUnbounded.visit(t); 199219019Sgabor } 200219019Sgabor // where 201219019Sgabor private final UnaryVisitor<Boolean> isUnbounded = new UnaryVisitor<Boolean>() { 202219019Sgabor 203219019Sgabor public Boolean visitType(Type t, Void ignored) { 204219019Sgabor return true; 205219019Sgabor } 206219019Sgabor 207219019Sgabor @Override 208219019Sgabor public Boolean visitClassType(ClassType t, Void ignored) { 209219019Sgabor List<Type> parms = t.tsym.type.allparams(); 210219019Sgabor List<Type> args = t.allparams(); 211219019Sgabor while (parms.nonEmpty()) { 212219019Sgabor WildcardType unb = new WildcardType(syms.objectType, 213219019Sgabor BoundKind.UNBOUND, 214219019Sgabor syms.boundClass, 215219019Sgabor (TypeVar)parms.head); 216219019Sgabor if (!containsType(args.head, unb)) 217219019Sgabor return false; 218219019Sgabor parms = parms.tail; 219219019Sgabor args = args.tail; 220219019Sgabor } 221219019Sgabor return true; 222219019Sgabor } 223219019Sgabor }; 224219019Sgabor // </editor-fold> 225219019Sgabor 226219019Sgabor // <editor-fold defaultstate="collapsed" desc="asSub"> 227219019Sgabor /** 228219019Sgabor * Return the least specific subtype of t that starts with symbol 229219019Sgabor * sym. If none exists, return null. The least specific subtype 230219019Sgabor * is determined as follows: 231219019Sgabor * 232219019Sgabor * <p>If there is exactly one parameterized instance of sym that is a 233219019Sgabor * subtype of t, that parameterized instance is returned.<br> 234219019Sgabor * Otherwise, if the plain type or raw type `sym' is a subtype of 235219019Sgabor * type t, the type `sym' itself is returned. Otherwise, null is 236219019Sgabor * returned. 237219019Sgabor */ 238219019Sgabor public Type asSub(Type t, Symbol sym) { 239219019Sgabor return asSub.visit(t, sym); 240219019Sgabor } 241219019Sgabor // where 242219019Sgabor private final SimpleVisitor<Type,Symbol> asSub = new SimpleVisitor<Type,Symbol>() { 243219019Sgabor 244219019Sgabor public Type visitType(Type t, Symbol sym) { 245219019Sgabor return null; 246219019Sgabor } 247219019Sgabor 248219019Sgabor @Override 249219019Sgabor public Type visitClassType(ClassType t, Symbol sym) { 250219019Sgabor if (t.tsym == sym) 251219019Sgabor return t; 252219019Sgabor Type base = asSuper(sym.type, t.tsym); 253219019Sgabor if (base == null) 254219019Sgabor return null; 255219019Sgabor ListBuffer<Type> from = new ListBuffer<>(); 256219019Sgabor ListBuffer<Type> to = new ListBuffer<>(); 257219019Sgabor try { 258219019Sgabor adapt(base, t, from, to); 259219019Sgabor } catch (AdaptFailure ex) { 260219019Sgabor return null; 261219019Sgabor } 262219019Sgabor Type res = subst(sym.type, from.toList(), to.toList()); 263219019Sgabor if (!isSubtype(res, t)) 264219019Sgabor return null; 265219019Sgabor ListBuffer<Type> openVars = new ListBuffer<>(); 266219019Sgabor for (List<Type> l = sym.type.allparams(); 267219019Sgabor l.nonEmpty(); l = l.tail) 268219019Sgabor if (res.contains(l.head) && !t.contains(l.head)) 269219019Sgabor openVars.append(l.head); 270219019Sgabor if (openVars.nonEmpty()) { 271219019Sgabor if (t.isRaw()) { 272219019Sgabor // The subtype of a raw type is raw 273219019Sgabor res = erasure(res); 274219019Sgabor } else { 275219019Sgabor // Unbound type arguments default to ? 276219019Sgabor List<Type> opens = openVars.toList(); 277219019Sgabor ListBuffer<Type> qs = new ListBuffer<>(); 278219019Sgabor for (List<Type> iter = opens; iter.nonEmpty(); iter = iter.tail) { 279219019Sgabor qs.append(new WildcardType(syms.objectType, BoundKind.UNBOUND, 280219019Sgabor syms.boundClass, (TypeVar) iter.head)); 281219019Sgabor } 282219019Sgabor res = subst(res, opens, qs.toList()); 283219019Sgabor } 284219019Sgabor } 285219019Sgabor return res; 286219019Sgabor } 287219019Sgabor 288219019Sgabor @Override 289219019Sgabor public Type visitErrorType(ErrorType t, Symbol sym) { 290219019Sgabor return t; 291219019Sgabor } 292219019Sgabor }; 293219019Sgabor // </editor-fold> 294219019Sgabor 295219019Sgabor // <editor-fold defaultstate="collapsed" desc="isConvertible"> 296219019Sgabor /** 297219019Sgabor * Is t a subtype of or convertible via boxing/unboxing 298219019Sgabor * conversion to s? 299219019Sgabor */ 300219019Sgabor public boolean isConvertible(Type t, Type s, Warner warn) { 301219019Sgabor if (t.hasTag(ERROR)) { 302219019Sgabor return true; 303219019Sgabor } 304219019Sgabor boolean tPrimitive = t.isPrimitive(); 305219019Sgabor boolean sPrimitive = s.isPrimitive(); 306219019Sgabor if (tPrimitive == sPrimitive) { 307219019Sgabor return isSubtypeUnchecked(t, s, warn); 308219019Sgabor } 309219019Sgabor return tPrimitive 310219019Sgabor ? isSubtype(boxedClass(t).type, s) 311219019Sgabor : isSubtype(unboxedType(t), s); 312219019Sgabor } 313219019Sgabor 314219019Sgabor /** 315219019Sgabor * Is t a subtype of or convertible via boxing/unboxing 316219019Sgabor * conversions to s? 317219019Sgabor */ 318219019Sgabor public boolean isConvertible(Type t, Type s) { 319219019Sgabor return isConvertible(t, s, noWarnings); 320219019Sgabor } 321219019Sgabor // </editor-fold> 322219019Sgabor 323219019Sgabor // <editor-fold defaultstate="collapsed" desc="findSam"> 324219019Sgabor 325219019Sgabor /** 326219019Sgabor * Exception used to report a function descriptor lookup failure. The exception 327219019Sgabor * wraps a diagnostic that can be used to generate more details error 328219019Sgabor * messages. 329219019Sgabor */ 330219019Sgabor public static class FunctionDescriptorLookupError extends RuntimeException { 331219019Sgabor private static final long serialVersionUID = 0; 332219019Sgabor 333219019Sgabor JCDiagnostic diagnostic; 334219019Sgabor 335219019Sgabor FunctionDescriptorLookupError() { 336219019Sgabor this.diagnostic = null; 337219019Sgabor } 338219019Sgabor 339219019Sgabor FunctionDescriptorLookupError setMessage(JCDiagnostic diag) { 340219019Sgabor this.diagnostic = diag; 341219019Sgabor return this; 342219019Sgabor } 343219019Sgabor 344219019Sgabor public JCDiagnostic getDiagnostic() { 345219019Sgabor return diagnostic; 346219019Sgabor } 347219019Sgabor } 348219019Sgabor 349219019Sgabor /** 350219019Sgabor * A cache that keeps track of function descriptors associated with given 351219019Sgabor * functional interfaces. 352219019Sgabor */ 353219019Sgabor class DescriptorCache { 354219019Sgabor 355219019Sgabor private WeakHashMap<TypeSymbol, Entry> _map = new WeakHashMap<>(); 356219019Sgabor 357219019Sgabor class FunctionDescriptor { 358219019Sgabor Symbol descSym; 359219019Sgabor 360219019Sgabor FunctionDescriptor(Symbol descSym) { 361219019Sgabor this.descSym = descSym; 362219019Sgabor } 363219019Sgabor 364219019Sgabor public Symbol getSymbol() { 365219019Sgabor return descSym; 366219019Sgabor } 367219019Sgabor 368219019Sgabor public Type getType(Type site) { 369219019Sgabor site = removeWildcards(site); 370219019Sgabor if (!chk.checkValidGenericType(site)) { 371219019Sgabor //if the inferred functional interface type is not well-formed, 372219019Sgabor //or if it's not a subtype of the original target, issue an error 373219019Sgabor throw failure(diags.fragment("no.suitable.functional.intf.inst", site)); 374219019Sgabor } 375219019Sgabor return memberType(site, descSym); 376219019Sgabor } 377219019Sgabor } 378219019Sgabor 379219019Sgabor class Entry { 380219019Sgabor final FunctionDescriptor cachedDescRes; 381219019Sgabor final int prevMark; 382219019Sgabor 383219019Sgabor public Entry(FunctionDescriptor cachedDescRes, 384219019Sgabor int prevMark) { 385219019Sgabor this.cachedDescRes = cachedDescRes; 386219019Sgabor this.prevMark = prevMark; 387219019Sgabor } 388219019Sgabor 389219019Sgabor boolean matches(int mark) { 390219019Sgabor return this.prevMark == mark; 391219019Sgabor } 392219019Sgabor } 393219019Sgabor 394219019Sgabor FunctionDescriptor get(TypeSymbol origin) throws FunctionDescriptorLookupError { 395219019Sgabor Entry e = _map.get(origin); 396219019Sgabor CompoundScope members = membersClosure(origin.type, false); 397219019Sgabor if (e == null || 398219019Sgabor !e.matches(members.getMark())) { 399219019Sgabor FunctionDescriptor descRes = findDescriptorInternal(origin, members); 400219019Sgabor _map.put(origin, new Entry(descRes, members.getMark())); 401219019Sgabor return descRes; 402219019Sgabor } 403219019Sgabor else { 404219019Sgabor return e.cachedDescRes; 405219019Sgabor } 406219019Sgabor } 407219019Sgabor 408219019Sgabor /** 409219019Sgabor * Compute the function descriptor associated with a given functional interface 410219019Sgabor */ 411219019Sgabor public FunctionDescriptor findDescriptorInternal(TypeSymbol origin, 412219019Sgabor CompoundScope membersCache) throws FunctionDescriptorLookupError { 413219019Sgabor if (!origin.isInterface() || (origin.flags() & ANNOTATION) != 0) { 414219019Sgabor //t must be an interface 415219019Sgabor throw failure("not.a.functional.intf", origin); 416219019Sgabor } 417219019Sgabor 418219019Sgabor final ListBuffer<Symbol> abstracts = new ListBuffer<>(); 419219019Sgabor for (Symbol sym : membersCache.getSymbols(new DescriptorFilter(origin))) { 420219019Sgabor Type mtype = memberType(origin.type, sym); 421219019Sgabor if (abstracts.isEmpty() || 422219019Sgabor (sym.name == abstracts.first().name && 423219019Sgabor overrideEquivalent(mtype, memberType(origin.type, abstracts.first())))) { 424219019Sgabor abstracts.append(sym); 425219019Sgabor } else { 426219019Sgabor //the target method(s) should be the only abstract members of t 427219019Sgabor throw failure("not.a.functional.intf.1", origin, 428219019Sgabor diags.fragment("incompatible.abstracts", Kinds.kindName(origin), origin)); 429219019Sgabor } 430219019Sgabor } 431219019Sgabor if (abstracts.isEmpty()) { 432219019Sgabor //t must define a suitable non-generic method 433219019Sgabor throw failure("not.a.functional.intf.1", origin, 434219019Sgabor diags.fragment("no.abstracts", Kinds.kindName(origin), origin)); 435219019Sgabor } else if (abstracts.size() == 1) { 436219019Sgabor return new FunctionDescriptor(abstracts.first()); 437219019Sgabor } else { // size > 1 438219019Sgabor FunctionDescriptor descRes = mergeDescriptors(origin, abstracts.toList()); 439219019Sgabor if (descRes == null) { 440219019Sgabor //we can get here if the functional interface is ill-formed 441219019Sgabor ListBuffer<JCDiagnostic> descriptors = new ListBuffer<>(); 442219019Sgabor for (Symbol desc : abstracts) { 443219019Sgabor String key = desc.type.getThrownTypes().nonEmpty() ? 444219019Sgabor "descriptor.throws" : "descriptor"; 445219019Sgabor descriptors.append(diags.fragment(key, desc.name, 446219019Sgabor desc.type.getParameterTypes(), 447219019Sgabor desc.type.getReturnType(), 448219019Sgabor desc.type.getThrownTypes())); 449219019Sgabor } 450219019Sgabor JCDiagnostic.MultilineDiagnostic incompatibleDescriptors = 451219019Sgabor new JCDiagnostic.MultilineDiagnostic(diags.fragment("incompatible.descs.in.functional.intf", 452219019Sgabor Kinds.kindName(origin), origin), descriptors.toList()); 453219019Sgabor throw failure(incompatibleDescriptors); 454219019Sgabor } 455219019Sgabor return descRes; 456219019Sgabor } 457219019Sgabor } 458219019Sgabor 459219019Sgabor /** 460219019Sgabor * Compute a synthetic type for the target descriptor given a list 461219019Sgabor * of override-equivalent methods in the functional interface type. 462219019Sgabor * The resulting method type is a method type that is override-equivalent 463219019Sgabor * and return-type substitutable with each method in the original list. 464219019Sgabor */ 465219019Sgabor private FunctionDescriptor mergeDescriptors(TypeSymbol origin, List<Symbol> methodSyms) { 466219019Sgabor //pick argument types - simply take the signature that is a 467219019Sgabor //subsignature of all other signatures in the list (as per JLS 8.4.2) 468219019Sgabor List<Symbol> mostSpecific = List.nil(); 469219019Sgabor outer: for (Symbol msym1 : methodSyms) { 470219019Sgabor Type mt1 = memberType(origin.type, msym1); 471219019Sgabor for (Symbol msym2 : methodSyms) { 472219019Sgabor Type mt2 = memberType(origin.type, msym2); 473219019Sgabor if (!isSubSignature(mt1, mt2)) { 474219019Sgabor continue outer; 475219019Sgabor } 476219019Sgabor } 477219019Sgabor mostSpecific = mostSpecific.prepend(msym1); 478219019Sgabor } 479219019Sgabor if (mostSpecific.isEmpty()) { 480219019Sgabor return null; 481219019Sgabor } 482219019Sgabor 483219019Sgabor 484219019Sgabor //pick return types - this is done in two phases: (i) first, the most 485219019Sgabor //specific return type is chosen using strict subtyping; if this fails, 486219019Sgabor //a second attempt is made using return type substitutability (see JLS 8.4.5) 487219019Sgabor boolean phase2 = false; 488219019Sgabor Symbol bestSoFar = null; 489219019Sgabor while (bestSoFar == null) { 490219019Sgabor outer: for (Symbol msym1 : mostSpecific) { 491219019Sgabor Type mt1 = memberType(origin.type, msym1); 492219019Sgabor for (Symbol msym2 : methodSyms) { 493219019Sgabor Type mt2 = memberType(origin.type, msym2); 494219019Sgabor if (phase2 ? 495219019Sgabor !returnTypeSubstitutable(mt1, mt2) : 496219019Sgabor !isSubtypeInternal(mt1.getReturnType(), mt2.getReturnType())) { 497219019Sgabor continue outer; 498219019Sgabor } 499219019Sgabor } 500219019Sgabor bestSoFar = msym1; 501219019Sgabor } 502219019Sgabor if (phase2) { 503219019Sgabor break; 504219019Sgabor } else { 505219019Sgabor phase2 = true; 506219019Sgabor } 507219019Sgabor } 508219019Sgabor if (bestSoFar == null) return null; 509219019Sgabor 510219019Sgabor //merge thrown types - form the intersection of all the thrown types in 511219019Sgabor //all the signatures in the list 512219019Sgabor boolean toErase = !bestSoFar.type.hasTag(FORALL); 513219019Sgabor List<Type> thrown = null; 514219019Sgabor Type mt1 = memberType(origin.type, bestSoFar); 515219019Sgabor for (Symbol msym2 : methodSyms) { 516219019Sgabor Type mt2 = memberType(origin.type, msym2); 517219019Sgabor List<Type> thrown_mt2 = mt2.getThrownTypes(); 518219019Sgabor if (toErase) { 519219019Sgabor thrown_mt2 = erasure(thrown_mt2); 520219019Sgabor } else { 521219019Sgabor /* If bestSoFar is generic then all the methods are generic. 522219019Sgabor * The opposite is not true: a non generic method can override 523219019Sgabor * a generic method (raw override) so it's safe to cast mt1 and 524219019Sgabor * mt2 to ForAll. 525219019Sgabor */ 526219019Sgabor ForAll fa1 = (ForAll)mt1; 527219019Sgabor ForAll fa2 = (ForAll)mt2; 528219019Sgabor thrown_mt2 = subst(thrown_mt2, fa2.tvars, fa1.tvars); 529219019Sgabor } 530219019Sgabor thrown = (thrown == null) ? 531219019Sgabor thrown_mt2 : 532219019Sgabor chk.intersect(thrown_mt2, thrown); 533219019Sgabor } 534219019Sgabor 535219019Sgabor final List<Type> thrown1 = thrown; 536219019Sgabor return new FunctionDescriptor(bestSoFar) { 537219019Sgabor @Override 538219019Sgabor public Type getType(Type origin) { 539219019Sgabor Type mt = memberType(origin, getSymbol()); 540219019Sgabor return createMethodTypeWithThrown(mt, thrown1); 541219019Sgabor } 542219019Sgabor }; 543219019Sgabor } 544219019Sgabor 545219019Sgabor boolean isSubtypeInternal(Type s, Type t) { 546219019Sgabor return (s.isPrimitive() && t.isPrimitive()) ? 547219019Sgabor isSameType(t, s) : 548219019Sgabor isSubtype(s, t); 549219019Sgabor } 550219019Sgabor 551219019Sgabor FunctionDescriptorLookupError failure(String msg, Object... args) { 552219019Sgabor return failure(diags.fragment(msg, args)); 553219019Sgabor } 554219019Sgabor 555219019Sgabor FunctionDescriptorLookupError failure(JCDiagnostic diag) { 556219019Sgabor return functionDescriptorLookupError.setMessage(diag); 557219019Sgabor } 558219019Sgabor } 559219019Sgabor 560219019Sgabor private DescriptorCache descCache = new DescriptorCache(); 561219019Sgabor 562219019Sgabor /** 563219019Sgabor * Find the method descriptor associated to this class symbol - if the 564219019Sgabor * symbol 'origin' is not a functional interface, an exception is thrown. 565219019Sgabor */ 566219019Sgabor public Symbol findDescriptorSymbol(TypeSymbol origin) throws FunctionDescriptorLookupError { 567219019Sgabor return descCache.get(origin).getSymbol(); 568219019Sgabor } 569219019Sgabor 570219019Sgabor /** 571219019Sgabor * Find the type of the method descriptor associated to this class symbol - 572219019Sgabor * if the symbol 'origin' is not a functional interface, an exception is thrown. 573219019Sgabor */ 574219019Sgabor public Type findDescriptorType(Type origin) throws FunctionDescriptorLookupError { 575219019Sgabor return descCache.get(origin.tsym).getType(origin); 576219019Sgabor } 577219019Sgabor 578219019Sgabor /** 579219019Sgabor * Is given type a functional interface? 580219019Sgabor */ 581219019Sgabor public boolean isFunctionalInterface(TypeSymbol tsym) { 582219019Sgabor try { 583219019Sgabor findDescriptorSymbol(tsym); 584219019Sgabor return true; 585219019Sgabor } catch (FunctionDescriptorLookupError ex) { 586219019Sgabor return false; 587219019Sgabor } 588219019Sgabor } 589219019Sgabor 590219019Sgabor public boolean isFunctionalInterface(Type site) { 591219019Sgabor try { 592219019Sgabor findDescriptorType(site); 593219019Sgabor return true; 594219019Sgabor } catch (FunctionDescriptorLookupError ex) { 595219019Sgabor return false; 596219019Sgabor } 597219019Sgabor } 598219019Sgabor 599219019Sgabor public Type removeWildcards(Type site) { 600219019Sgabor Type capturedSite = capture(site); 601219019Sgabor if (capturedSite != site) { 602219019Sgabor Type formalInterface = site.tsym.type; 603219019Sgabor ListBuffer<Type> typeargs = new ListBuffer<>(); 604219019Sgabor List<Type> actualTypeargs = site.getTypeArguments(); 605219019Sgabor List<Type> capturedTypeargs = capturedSite.getTypeArguments(); 606219019Sgabor //simply replace the wildcards with its bound 607219019Sgabor for (Type t : formalInterface.getTypeArguments()) { 608219019Sgabor if (actualTypeargs.head.hasTag(WILDCARD)) { 609219019Sgabor WildcardType wt = (WildcardType)actualTypeargs.head; 610219019Sgabor Type bound; 611219019Sgabor switch (wt.kind) { 612219019Sgabor case EXTENDS: 613219019Sgabor case UNBOUND: 614219019Sgabor CapturedType capVar = (CapturedType)capturedTypeargs.head; 615219019Sgabor //use declared bound if it doesn't depend on formal type-args 616219019Sgabor bound = capVar.bound.containsAny(capturedSite.getTypeArguments()) ? 617219019Sgabor wt.type : capVar.bound; 618219019Sgabor break; 619219019Sgabor default: 620219019Sgabor bound = wt.type; 621219019Sgabor } 622219019Sgabor typeargs.append(bound); 623219019Sgabor } else { 624219019Sgabor typeargs.append(actualTypeargs.head); 625219019Sgabor } 626219019Sgabor actualTypeargs = actualTypeargs.tail; 627219019Sgabor capturedTypeargs = capturedTypeargs.tail; 628219019Sgabor } 629219019Sgabor return subst(formalInterface, formalInterface.getTypeArguments(), typeargs.toList()); 630219019Sgabor } else { 631219019Sgabor return site; 632219019Sgabor } 633219019Sgabor } 634219019Sgabor 635219019Sgabor /** 636219019Sgabor * Create a symbol for a class that implements a given functional interface 637219019Sgabor * and overrides its functional descriptor. This routine is used for two 638219019Sgabor * main purposes: (i) checking well-formedness of a functional interface; 639219019Sgabor * (ii) perform functional interface bridge calculation. 640219019Sgabor */ 641219019Sgabor public ClassSymbol makeFunctionalInterfaceClass(Env<AttrContext> env, Name name, List<Type> targets, long cflags) { 642219019Sgabor if (targets.isEmpty()) { 643219019Sgabor return null; 644219019Sgabor } 645219019Sgabor Symbol descSym = findDescriptorSymbol(targets.head.tsym); 646219019Sgabor Type descType = findDescriptorType(targets.head); 647219019Sgabor ClassSymbol csym = new ClassSymbol(cflags, name, env.enclClass.sym.outermostClass()); 648219019Sgabor csym.completer = Completer.NULL_COMPLETER; 649219019Sgabor csym.members_field = WriteableScope.create(csym); 650219019Sgabor MethodSymbol instDescSym = new MethodSymbol(descSym.flags(), descSym.name, descType, csym); 651219019Sgabor csym.members_field.enter(instDescSym); 652219019Sgabor Type.ClassType ctype = new Type.ClassType(Type.noType, List.<Type>nil(), csym); 653219019Sgabor ctype.supertype_field = syms.objectType; 654219019Sgabor ctype.interfaces_field = targets; 655219019Sgabor csym.type = ctype; 656219019Sgabor csym.sourcefile = ((ClassSymbol)csym.owner).sourcefile; 657219019Sgabor return csym; 658219019Sgabor } 659219019Sgabor 660219019Sgabor /** 661219019Sgabor * Find the minimal set of methods that are overridden by the functional 662219019Sgabor * descriptor in 'origin'. All returned methods are assumed to have different 663219019Sgabor * erased signatures. 664219019Sgabor */ 665219019Sgabor public List<Symbol> functionalInterfaceBridges(TypeSymbol origin) { 666219019Sgabor Assert.check(isFunctionalInterface(origin)); 667219019Sgabor Symbol descSym = findDescriptorSymbol(origin); 668219019Sgabor CompoundScope members = membersClosure(origin.type, false); 669219019Sgabor ListBuffer<Symbol> overridden = new ListBuffer<>(); 670219019Sgabor outer: for (Symbol m2 : members.getSymbolsByName(descSym.name, bridgeFilter)) { 671219019Sgabor if (m2 == descSym) continue; 672219019Sgabor else if (descSym.overrides(m2, origin, Types.this, false)) { 673219019Sgabor for (Symbol m3 : overridden) { 674219019Sgabor if (isSameType(m3.erasure(Types.this), m2.erasure(Types.this)) || 675219019Sgabor (m3.overrides(m2, origin, Types.this, false) && 676219019Sgabor (pendingBridges((ClassSymbol)origin, m3.enclClass()) || 677219019Sgabor (((MethodSymbol)m2).binaryImplementation((ClassSymbol)m3.owner, Types.this) != null)))) { 678219019Sgabor continue outer; 679219019Sgabor } 680219019Sgabor } 681219019Sgabor overridden.add(m2); 682219019Sgabor } 683219019Sgabor } 684219019Sgabor return overridden.toList(); 685219019Sgabor } 686219019Sgabor //where 687219019Sgabor private Filter<Symbol> bridgeFilter = new Filter<Symbol>() { 688219019Sgabor public boolean accepts(Symbol t) { 689219019Sgabor return t.kind == MTH && 690219019Sgabor t.name != names.init && 691219019Sgabor t.name != names.clinit && 692219019Sgabor (t.flags() & SYNTHETIC) == 0; 693219019Sgabor } 694219019Sgabor }; 695219019Sgabor private boolean pendingBridges(ClassSymbol origin, TypeSymbol s) { 696219019Sgabor //a symbol will be completed from a classfile if (a) symbol has 697219019Sgabor //an associated file object with CLASS kind and (b) the symbol has 698219019Sgabor //not been entered 699219019Sgabor if (origin.classfile != null && 700219019Sgabor origin.classfile.getKind() == JavaFileObject.Kind.CLASS && 701219019Sgabor enter.getEnv(origin) == null) { 702219019Sgabor return false; 703219019Sgabor } 704219019Sgabor if (origin == s) { 705219019Sgabor return true; 706219019Sgabor } 707219019Sgabor for (Type t : interfaces(origin.type)) { 708219019Sgabor if (pendingBridges((ClassSymbol)t.tsym, s)) { 709219019Sgabor return true; 710219019Sgabor } 711219019Sgabor } 712219019Sgabor return false; 713219019Sgabor } 714219019Sgabor // </editor-fold> 715219019Sgabor 716219019Sgabor /** 717219019Sgabor * Scope filter used to skip methods that should be ignored (such as methods 718219019Sgabor * overridden by j.l.Object) during function interface conversion interface check 719219019Sgabor */ 720219019Sgabor class DescriptorFilter implements Filter<Symbol> { 721219019Sgabor 722219019Sgabor TypeSymbol origin; 723219019Sgabor 724219019Sgabor DescriptorFilter(TypeSymbol origin) { 725219019Sgabor this.origin = origin; 726219019Sgabor } 727219019Sgabor 728219019Sgabor @Override 729219019Sgabor public boolean accepts(Symbol sym) { 730219019Sgabor return sym.kind == MTH && 731219019Sgabor (sym.flags() & (ABSTRACT | DEFAULT)) == ABSTRACT && 732219019Sgabor !overridesObjectMethod(origin, sym) && 733219019Sgabor (interfaceCandidates(origin.type, (MethodSymbol)sym).head.flags() & DEFAULT) == 0; 734219019Sgabor } 735219019Sgabor } 736219019Sgabor 737219019Sgabor // <editor-fold defaultstate="collapsed" desc="isSubtype"> 738219019Sgabor /** 739219019Sgabor * Is t an unchecked subtype of s? 740219019Sgabor */ 741219019Sgabor public boolean isSubtypeUnchecked(Type t, Type s) { 742219019Sgabor return isSubtypeUnchecked(t, s, noWarnings); 743219019Sgabor } 744219019Sgabor /** 745219019Sgabor * Is t an unchecked subtype of s? 746219019Sgabor */ 747219019Sgabor public boolean isSubtypeUnchecked(Type t, Type s, Warner warn) { 748219019Sgabor boolean result = isSubtypeUncheckedInternal(t, s, warn); 749219019Sgabor if (result) { 750219019Sgabor checkUnsafeVarargsConversion(t, s, warn); 751219019Sgabor } 752219019Sgabor return result; 753219019Sgabor } 754219019Sgabor //where 755219019Sgabor private boolean isSubtypeUncheckedInternal(Type t, Type s, Warner warn) { 756219019Sgabor if (t.hasTag(ARRAY) && s.hasTag(ARRAY)) { 757219019Sgabor if (((ArrayType)t).elemtype.isPrimitive()) { 758219019Sgabor return isSameType(elemtype(t), elemtype(s)); 759219019Sgabor } else { 760219019Sgabor return isSubtypeUnchecked(elemtype(t), elemtype(s), warn); 761219019Sgabor } 762219019Sgabor } else if (isSubtype(t, s)) { 763219019Sgabor return true; 764219019Sgabor } else if (t.hasTag(TYPEVAR)) { 765219019Sgabor return isSubtypeUnchecked(t.getUpperBound(), s, warn); 766219019Sgabor } else if (!s.isRaw()) { 767219019Sgabor Type t2 = asSuper(t, s.tsym); 768219019Sgabor if (t2 != null && t2.isRaw()) { 769219019Sgabor if (isReifiable(s)) { 770219019Sgabor warn.silentWarn(LintCategory.UNCHECKED); 771219019Sgabor } else { 772219019Sgabor warn.warn(LintCategory.UNCHECKED); 773219019Sgabor } 774219019Sgabor return true; 775219019Sgabor } 776219019Sgabor } 777219019Sgabor return false; 778219019Sgabor } 779219019Sgabor 780219019Sgabor private void checkUnsafeVarargsConversion(Type t, Type s, Warner warn) { 781219019Sgabor if (!t.hasTag(ARRAY) || isReifiable(t)) { 782219019Sgabor return; 783219019Sgabor } 784219019Sgabor ArrayType from = (ArrayType)t; 785219019Sgabor boolean shouldWarn = false; 786219019Sgabor switch (s.getTag()) { 787219019Sgabor case ARRAY: 788219019Sgabor ArrayType to = (ArrayType)s; 789219019Sgabor shouldWarn = from.isVarargs() && 790219019Sgabor !to.isVarargs() && 791219019Sgabor !isReifiable(from); 792219019Sgabor break; 793219019Sgabor case CLASS: 794219019Sgabor shouldWarn = from.isVarargs(); 795219019Sgabor break; 796219019Sgabor } 797219019Sgabor if (shouldWarn) { 798219019Sgabor warn.warn(LintCategory.VARARGS); 799219019Sgabor } 800219019Sgabor } 801219019Sgabor 802219019Sgabor /** 803219019Sgabor * Is t a subtype of s?<br> 804219019Sgabor * (not defined for Method and ForAll types) 805219019Sgabor */ 806219019Sgabor final public boolean isSubtype(Type t, Type s) { 807219019Sgabor return isSubtype(t, s, true); 808219019Sgabor } 809219019Sgabor final public boolean isSubtypeNoCapture(Type t, Type s) { 810219019Sgabor return isSubtype(t, s, false); 811219019Sgabor } 812219019Sgabor public boolean isSubtype(Type t, Type s, boolean capture) { 813219019Sgabor if (t.equalsIgnoreMetadata(s)) 814219019Sgabor return true; 815219019Sgabor if (s.isPartial()) 816219019Sgabor return isSuperType(s, t); 817219019Sgabor 818219019Sgabor if (s.isCompound()) { 819219019Sgabor for (Type s2 : interfaces(s).prepend(supertype(s))) { 820219019Sgabor if (!isSubtype(t, s2, capture)) 821219019Sgabor return false; 822219019Sgabor } 823219019Sgabor return true; 824219019Sgabor } 825219019Sgabor 826219019Sgabor // Generally, if 's' is a lower-bounded type variable, recur on lower bound; but 827219019Sgabor // for inference variables and intersections, we need to keep 's' 828219019Sgabor // (see JLS 4.10.2 for intersections and 18.2.3 for inference vars) 829219019Sgabor if (!t.hasTag(UNDETVAR) && !t.isCompound()) { 830219019Sgabor // TODO: JDK-8039198, bounds checking sometimes passes in a wildcard as s 831219019Sgabor Type lower = cvarLowerBound(wildLowerBound(s)); 832219019Sgabor if (s != lower && !lower.hasTag(BOT)) 833219019Sgabor return isSubtype(capture ? capture(t) : t, lower, false); 834219019Sgabor } 835219019Sgabor 836219019Sgabor return isSubtype.visit(capture ? capture(t) : t, s); 837219019Sgabor } 838219019Sgabor // where 839219019Sgabor private TypeRelation isSubtype = new TypeRelation() 840219019Sgabor { 841219019Sgabor @Override 842219019Sgabor public Boolean visitType(Type t, Type s) { 843219019Sgabor switch (t.getTag()) { 844219019Sgabor case BYTE: 845219019Sgabor return (!s.hasTag(CHAR) && t.getTag().isSubRangeOf(s.getTag())); 846219019Sgabor case CHAR: 847219019Sgabor return (!s.hasTag(SHORT) && t.getTag().isSubRangeOf(s.getTag())); 848219019Sgabor case SHORT: case INT: case LONG: 849219019Sgabor case FLOAT: case DOUBLE: 850219019Sgabor return t.getTag().isSubRangeOf(s.getTag()); 851219019Sgabor case BOOLEAN: case VOID: 852219019Sgabor return t.hasTag(s.getTag()); 853219019Sgabor case TYPEVAR: 854219019Sgabor return isSubtypeNoCapture(t.getUpperBound(), s); 855219019Sgabor case BOT: 856219019Sgabor return 857219019Sgabor s.hasTag(BOT) || s.hasTag(CLASS) || 858219019Sgabor s.hasTag(ARRAY) || s.hasTag(TYPEVAR); 859219019Sgabor case WILDCARD: //we shouldn't be here - avoids crash (see 7034495) 860219019Sgabor case NONE: 861219019Sgabor return false; 862219019Sgabor default: 863219019Sgabor throw new AssertionError("isSubtype " + t.getTag()); 864219019Sgabor } 865219019Sgabor } 866219019Sgabor 867219019Sgabor private Set<TypePair> cache = new HashSet<>(); 868219019Sgabor 869219019Sgabor private boolean containsTypeRecursive(Type t, Type s) { 870219019Sgabor TypePair pair = new TypePair(t, s); 871219019Sgabor if (cache.add(pair)) { 872219019Sgabor try { 873219019Sgabor return containsType(t.getTypeArguments(), 874219019Sgabor s.getTypeArguments()); 875219019Sgabor } finally { 876219019Sgabor cache.remove(pair); 877219019Sgabor } 878219019Sgabor } else { 879219019Sgabor return containsType(t.getTypeArguments(), 880219019Sgabor rewriteSupers(s).getTypeArguments()); 881219019Sgabor } 882219019Sgabor } 883219019Sgabor 884219019Sgabor private Type rewriteSupers(Type t) { 885219019Sgabor if (!t.isParameterized()) 886219019Sgabor return t; 887219019Sgabor ListBuffer<Type> from = new ListBuffer<>(); 888219019Sgabor ListBuffer<Type> to = new ListBuffer<>(); 889219019Sgabor adaptSelf(t, from, to); 890219019Sgabor if (from.isEmpty()) 891219019Sgabor return t; 892219019Sgabor ListBuffer<Type> rewrite = new ListBuffer<>(); 893219019Sgabor boolean changed = false; 894219019Sgabor for (Type orig : to.toList()) { 895219019Sgabor Type s = rewriteSupers(orig); 896219019Sgabor if (s.isSuperBound() && !s.isExtendsBound()) { 897219019Sgabor s = new WildcardType(syms.objectType, 898219019Sgabor BoundKind.UNBOUND, 899219019Sgabor syms.boundClass, 900219019Sgabor s.getMetadata()); 901219019Sgabor changed = true; 902219019Sgabor } else if (s != orig) { 903219019Sgabor s = new WildcardType(wildUpperBound(s), 904219019Sgabor BoundKind.EXTENDS, 905219019Sgabor syms.boundClass, 906219019Sgabor s.getMetadata()); 907219019Sgabor changed = true; 908219019Sgabor } 909219019Sgabor rewrite.append(s); 910219019Sgabor } 911219019Sgabor if (changed) 912219019Sgabor return subst(t.tsym.type, from.toList(), rewrite.toList()); 913219019Sgabor else 914219019Sgabor return t; 915219019Sgabor } 916219019Sgabor 917219019Sgabor @Override 918219019Sgabor public Boolean visitClassType(ClassType t, Type s) { 919219019Sgabor Type sup = asSuper(t, s.tsym); 920219019Sgabor if (sup == null) return false; 921219019Sgabor // If t is an intersection, sup might not be a class type 922219019Sgabor if (!sup.hasTag(CLASS)) return isSubtypeNoCapture(sup, s); 923219019Sgabor return sup.tsym == s.tsym 924219019Sgabor // Check type variable containment 925219019Sgabor && (!s.isParameterized() || containsTypeRecursive(s, sup)) 926219019Sgabor && isSubtypeNoCapture(sup.getEnclosingType(), 927219019Sgabor s.getEnclosingType()); 928219019Sgabor } 929219019Sgabor 930219019Sgabor @Override 931219019Sgabor public Boolean visitArrayType(ArrayType t, Type s) { 932219019Sgabor if (s.hasTag(ARRAY)) { 933219019Sgabor if (t.elemtype.isPrimitive()) 934219019Sgabor return isSameType(t.elemtype, elemtype(s)); 935219019Sgabor else 936219019Sgabor return isSubtypeNoCapture(t.elemtype, elemtype(s)); 937219019Sgabor } 938219019Sgabor 939219019Sgabor if (s.hasTag(CLASS)) { 940219019Sgabor Name sname = s.tsym.getQualifiedName(); 941219019Sgabor return sname == names.java_lang_Object 942219019Sgabor || sname == names.java_lang_Cloneable 943219019Sgabor || sname == names.java_io_Serializable; 944219019Sgabor } 945219019Sgabor 946219019Sgabor return false; 947219019Sgabor } 948219019Sgabor 949219019Sgabor @Override 950219019Sgabor public Boolean visitUndetVar(UndetVar t, Type s) { 951219019Sgabor //todo: test against origin needed? or replace with substitution? 952219019Sgabor if (t == s || t.qtype == s || s.hasTag(ERROR) || s.hasTag(UNKNOWN)) { 953219019Sgabor return true; 954219019Sgabor } else if (s.hasTag(BOT)) { 955219019Sgabor //if 's' is 'null' there's no instantiated type U for which 956219019Sgabor //U <: s (but 'null' itself, which is not a valid type) 957219019Sgabor return false; 958219019Sgabor } 959219019Sgabor 960219019Sgabor t.addBound(InferenceBound.UPPER, s, Types.this); 961219019Sgabor return true; 962219019Sgabor } 963219019Sgabor 964219019Sgabor @Override 965219019Sgabor public Boolean visitErrorType(ErrorType t, Type s) { 966219019Sgabor return true; 967219019Sgabor } 968219019Sgabor }; 969219019Sgabor 970219019Sgabor /** 971219019Sgabor * Is t a subtype of every type in given list `ts'?<br> 972219019Sgabor * (not defined for Method and ForAll types)<br> 973219019Sgabor * Allows unchecked conversions. 974219019Sgabor */ 975219019Sgabor public boolean isSubtypeUnchecked(Type t, List<Type> ts, Warner warn) { 976219019Sgabor for (List<Type> l = ts; l.nonEmpty(); l = l.tail) 977219019Sgabor if (!isSubtypeUnchecked(t, l.head, warn)) 978219019Sgabor return false; 979219019Sgabor return true; 980219019Sgabor } 981219019Sgabor 982219019Sgabor /** 983219019Sgabor * Are corresponding elements of ts subtypes of ss? If lists are 984219019Sgabor * of different length, return false. 985219019Sgabor */ 986219019Sgabor public boolean isSubtypes(List<Type> ts, List<Type> ss) { 987219019Sgabor while (ts.tail != null && ss.tail != null 988219019Sgabor /*inlined: ts.nonEmpty() && ss.nonEmpty()*/ && 989219019Sgabor isSubtype(ts.head, ss.head)) { 990219019Sgabor ts = ts.tail; 991219019Sgabor ss = ss.tail; 992219019Sgabor } 993219019Sgabor return ts.tail == null && ss.tail == null; 994219019Sgabor /*inlined: ts.isEmpty() && ss.isEmpty();*/ 995219019Sgabor } 996219019Sgabor 997219019Sgabor /** 998219019Sgabor * Are corresponding elements of ts subtypes of ss, allowing 999219019Sgabor * unchecked conversions? If lists are of different length, 1000219019Sgabor * return false. 1001219019Sgabor **/ 1002219019Sgabor public boolean isSubtypesUnchecked(List<Type> ts, List<Type> ss, Warner warn) { 1003219019Sgabor while (ts.tail != null && ss.tail != null 1004219019Sgabor /*inlined: ts.nonEmpty() && ss.nonEmpty()*/ && 1005219019Sgabor isSubtypeUnchecked(ts.head, ss.head, warn)) { 1006219019Sgabor ts = ts.tail; 1007219019Sgabor ss = ss.tail; 1008219019Sgabor } 1009219019Sgabor return ts.tail == null && ss.tail == null; 1010219019Sgabor /*inlined: ts.isEmpty() && ss.isEmpty();*/ 1011219019Sgabor } 1012219019Sgabor // </editor-fold> 1013219019Sgabor 1014219019Sgabor // <editor-fold defaultstate="collapsed" desc="isSuperType"> 1015219019Sgabor /** 1016219019Sgabor * Is t a supertype of s? 1017219019Sgabor */ 1018219019Sgabor public boolean isSuperType(Type t, Type s) { 1019219019Sgabor switch (t.getTag()) { 1020219019Sgabor case ERROR: 1021219019Sgabor return true; 1022219019Sgabor case UNDETVAR: { 1023219019Sgabor UndetVar undet = (UndetVar)t; 1024219019Sgabor if (t == s || 1025219019Sgabor undet.qtype == s || 1026219019Sgabor s.hasTag(ERROR) || 1027219019Sgabor s.hasTag(BOT)) { 1028219019Sgabor return true; 1029219019Sgabor } 1030219019Sgabor undet.addBound(InferenceBound.LOWER, s, this); 1031219019Sgabor return true; 1032219019Sgabor } 1033219019Sgabor default: 1034219019Sgabor return isSubtype(s, t); 1035219019Sgabor } 1036219019Sgabor } 1037219019Sgabor // </editor-fold> 1038219019Sgabor 1039219019Sgabor // <editor-fold defaultstate="collapsed" desc="isSameType"> 1040219019Sgabor /** 1041219019Sgabor * Are corresponding elements of the lists the same type? If 1042219019Sgabor * lists are of different length, return false. 1043219019Sgabor */ 1044219019Sgabor public boolean isSameTypes(List<Type> ts, List<Type> ss) { 1045219019Sgabor return isSameTypes(ts, ss, false); 1046219019Sgabor } 1047219019Sgabor public boolean isSameTypes(List<Type> ts, List<Type> ss, boolean strict) { 1048219019Sgabor while (ts.tail != null && ss.tail != null 1049219019Sgabor /*inlined: ts.nonEmpty() && ss.nonEmpty()*/ && 1050219019Sgabor isSameType(ts.head, ss.head, strict)) { 1051219019Sgabor ts = ts.tail; 1052219019Sgabor ss = ss.tail; 1053219019Sgabor } 1054219019Sgabor return ts.tail == null && ss.tail == null; 1055219019Sgabor /*inlined: ts.isEmpty() && ss.isEmpty();*/ 1056219019Sgabor } 1057219019Sgabor 1058219019Sgabor /** 1059219019Sgabor * A polymorphic signature method (JLS SE 7, 8.4.1) is a method that 1060219019Sgabor * (i) is declared in the java.lang.invoke.MethodHandle class, (ii) takes 1061219019Sgabor * a single variable arity parameter (iii) whose declared type is Object[], 1062219019Sgabor * (iv) has a return type of Object and (v) is native. 1063219019Sgabor */ 1064219019Sgabor public boolean isSignaturePolymorphic(MethodSymbol msym) { 1065219019Sgabor List<Type> argtypes = msym.type.getParameterTypes(); 1066219019Sgabor return (msym.flags_field & NATIVE) != 0 && 1067219019Sgabor msym.owner == syms.methodHandleType.tsym && 1068219019Sgabor argtypes.tail.tail == null && 1069219019Sgabor argtypes.head.hasTag(TypeTag.ARRAY) && 1070219019Sgabor msym.type.getReturnType().tsym == syms.objectType.tsym && 1071219019Sgabor ((ArrayType)argtypes.head).elemtype.tsym == syms.objectType.tsym; 1072219019Sgabor } 1073219019Sgabor 1074219019Sgabor /** 1075219019Sgabor * Is t the same type as s? 1076219019Sgabor */ 1077219019Sgabor public boolean isSameType(Type t, Type s) { 1078219019Sgabor return isSameType(t, s, false); 1079219019Sgabor } 1080219019Sgabor public boolean isSameType(Type t, Type s, boolean strict) { 1081219019Sgabor return strict ? 1082219019Sgabor isSameTypeStrict.visit(t, s) : 1083219019Sgabor isSameTypeLoose.visit(t, s); 1084219019Sgabor } 1085219019Sgabor // where 1086219019Sgabor abstract class SameTypeVisitor extends TypeRelation { 1087219019Sgabor 1088219019Sgabor public Boolean visitType(Type t, Type s) { 1089219019Sgabor if (t.equalsIgnoreMetadata(s)) 1090219019Sgabor return true; 1091219019Sgabor 1092219019Sgabor if (s.isPartial()) 1093219019Sgabor return visit(s, t); 1094219019Sgabor 1095219019Sgabor switch (t.getTag()) { 1096219019Sgabor case BYTE: case CHAR: case SHORT: case INT: case LONG: case FLOAT: 1097219019Sgabor case DOUBLE: case BOOLEAN: case VOID: case BOT: case NONE: 1098219019Sgabor return t.hasTag(s.getTag()); 1099219019Sgabor case TYPEVAR: { 1100219019Sgabor if (s.hasTag(TYPEVAR)) { 1101219019Sgabor //type-substitution does not preserve type-var types 1102219019Sgabor //check that type var symbols and bounds are indeed the same 1103219019Sgabor return sameTypeVars((TypeVar)t, (TypeVar)s); 1104219019Sgabor } 1105219019Sgabor else { 1106219019Sgabor //special case for s == ? super X, where upper(s) = u 1107219019Sgabor //check that u == t, where u has been set by Type.withTypeVar 1108219019Sgabor return s.isSuperBound() && 1109219019Sgabor !s.isExtendsBound() && 1110219019Sgabor visit(t, wildUpperBound(s)); 1111219019Sgabor } 1112219019Sgabor } 1113219019Sgabor default: 1114219019Sgabor throw new AssertionError("isSameType " + t.getTag()); 1115219019Sgabor } 1116219019Sgabor } 1117219019Sgabor 1118219019Sgabor abstract boolean sameTypeVars(TypeVar tv1, TypeVar tv2); 1119219019Sgabor 1120219019Sgabor @Override 1121219019Sgabor public Boolean visitWildcardType(WildcardType t, Type s) { 1122219019Sgabor if (s.isPartial()) 1123219019Sgabor return visit(s, t); 1124219019Sgabor else 1125219019Sgabor return false; 1126219019Sgabor } 1127219019Sgabor 1128219019Sgabor @Override 1129219019Sgabor public Boolean visitClassType(ClassType t, Type s) { 1130219019Sgabor if (t == s) 1131219019Sgabor return true; 1132219019Sgabor 1133219019Sgabor if (s.isPartial()) 1134219019Sgabor return visit(s, t); 1135219019Sgabor 1136219019Sgabor if (s.isSuperBound() && !s.isExtendsBound()) 1137219019Sgabor return visit(t, wildUpperBound(s)) && visit(t, wildLowerBound(s)); 1138219019Sgabor 1139219019Sgabor if (t.isCompound() && s.isCompound()) { 1140219019Sgabor if (!visit(supertype(t), supertype(s))) 1141219019Sgabor return false; 1142219019Sgabor 1143219019Sgabor HashSet<UniqueType> set = new HashSet<>(); 1144219019Sgabor for (Type x : interfaces(t)) 1145219019Sgabor set.add(new UniqueType(x, Types.this)); 1146219019Sgabor for (Type x : interfaces(s)) { 1147219019Sgabor if (!set.remove(new UniqueType(x, Types.this))) 1148219019Sgabor return false; 1149219019Sgabor } 1150219019Sgabor return (set.isEmpty()); 1151219019Sgabor } 1152219019Sgabor return t.tsym == s.tsym 1153219019Sgabor && visit(t.getEnclosingType(), s.getEnclosingType()) 1154219019Sgabor && containsTypes(t.getTypeArguments(), s.getTypeArguments()); 1155219019Sgabor } 1156219019Sgabor 1157219019Sgabor abstract protected boolean containsTypes(List<Type> ts1, List<Type> ts2); 1158219019Sgabor 1159219019Sgabor @Override 1160219019Sgabor public Boolean visitArrayType(ArrayType t, Type s) { 1161219019Sgabor if (t == s) 1162219019Sgabor return true; 1163219019Sgabor 1164219019Sgabor if (s.isPartial()) 1165219019Sgabor return visit(s, t); 1166219019Sgabor 1167219019Sgabor return s.hasTag(ARRAY) 1168219019Sgabor && containsTypeEquivalent(t.elemtype, elemtype(s)); 1169219019Sgabor } 1170219019Sgabor 1171219019Sgabor @Override 1172219019Sgabor public Boolean visitMethodType(MethodType t, Type s) { 1173219019Sgabor // isSameType for methods does not take thrown 1174219019Sgabor // exceptions into account! 1175219019Sgabor return hasSameArgs(t, s) && visit(t.getReturnType(), s.getReturnType()); 1176219019Sgabor } 1177219019Sgabor 1178219019Sgabor @Override 1179219019Sgabor public Boolean visitPackageType(PackageType t, Type s) { 1180219019Sgabor return t == s; 1181219019Sgabor } 1182219019Sgabor 1183219019Sgabor @Override 1184219019Sgabor public Boolean visitForAll(ForAll t, Type s) { 1185219019Sgabor if (!s.hasTag(FORALL)) { 1186219019Sgabor return false; 1187219019Sgabor } 1188219019Sgabor 1189219019Sgabor ForAll forAll = (ForAll)s; 1190219019Sgabor return hasSameBounds(t, forAll) 1191219019Sgabor && visit(t.qtype, subst(forAll.qtype, forAll.tvars, t.tvars)); 1192219019Sgabor } 1193219019Sgabor 1194219019Sgabor @Override 1195219019Sgabor public Boolean visitUndetVar(UndetVar t, Type s) { 1196219019Sgabor if (s.hasTag(WILDCARD)) { 1197219019Sgabor // FIXME, this might be leftovers from before capture conversion 1198219019Sgabor return false; 1199219019Sgabor } 1200219019Sgabor 1201219019Sgabor if (t == s || t.qtype == s || s.hasTag(ERROR) || s.hasTag(UNKNOWN)) { 1202219019Sgabor return true; 1203219019Sgabor } 1204219019Sgabor 1205219019Sgabor t.addBound(InferenceBound.EQ, s, Types.this); 1206219019Sgabor 1207219019Sgabor return true; 1208219019Sgabor } 1209219019Sgabor 1210219019Sgabor @Override 1211219019Sgabor public Boolean visitErrorType(ErrorType t, Type s) { 1212219019Sgabor return true; 1213219019Sgabor } 1214219019Sgabor } 1215219019Sgabor 1216219019Sgabor /** 1217219019Sgabor * Standard type-equality relation - type variables are considered 1218219019Sgabor * equals if they share the same type symbol. 1219219019Sgabor */ 1220219019Sgabor TypeRelation isSameTypeLoose = new LooseSameTypeVisitor(); 1221219019Sgabor 1222219019Sgabor private class LooseSameTypeVisitor extends SameTypeVisitor { 1223219019Sgabor 1224219019Sgabor /** cache of the type-variable pairs being (recursively) tested. */ 1225219019Sgabor private Set<TypePair> cache = new HashSet<>(); 1226219019Sgabor 1227219019Sgabor @Override 1228219019Sgabor boolean sameTypeVars(TypeVar tv1, TypeVar tv2) { 1229219019Sgabor return tv1.tsym == tv2.tsym && checkSameBounds(tv1, tv2); 1230219019Sgabor } 1231219019Sgabor @Override 1232219019Sgabor protected boolean containsTypes(List<Type> ts1, List<Type> ts2) { 1233219019Sgabor return containsTypeEquivalent(ts1, ts2); 1234219019Sgabor } 1235219019Sgabor 1236219019Sgabor /** 1237219019Sgabor * Since type-variable bounds can be recursive, we need to protect against 1238219019Sgabor * infinite loops - where the same bounds are checked over and over recursively. 1239219019Sgabor */ 1240219019Sgabor private boolean checkSameBounds(TypeVar tv1, TypeVar tv2) { 1241219019Sgabor TypePair p = new TypePair(tv1, tv2, true); 1242219019Sgabor if (cache.add(p)) { 1243219019Sgabor try { 1244219019Sgabor return visit(tv1.getUpperBound(), tv2.getUpperBound()); 1245219019Sgabor } finally { 1246219019Sgabor cache.remove(p); 1247219019Sgabor } 1248219019Sgabor } else { 1249219019Sgabor return false; 1250219019Sgabor } 1251219019Sgabor } 1252219019Sgabor }; 1253219019Sgabor 1254219019Sgabor /** 1255219019Sgabor * Strict type-equality relation - type variables are considered 1256219019Sgabor * equals if they share the same object identity. 1257219019Sgabor */ 1258219019Sgabor TypeRelation isSameTypeStrict = new SameTypeVisitor() { 1259219019Sgabor @Override 1260219019Sgabor boolean sameTypeVars(TypeVar tv1, TypeVar tv2) { 1261219019Sgabor return tv1 == tv2; 1262219019Sgabor } 1263219019Sgabor @Override 1264219019Sgabor protected boolean containsTypes(List<Type> ts1, List<Type> ts2) { 1265219019Sgabor return isSameTypes(ts1, ts2, true); 1266219019Sgabor } 1267219019Sgabor 1268219019Sgabor @Override 1269219019Sgabor public Boolean visitWildcardType(WildcardType t, Type s) { 1270219019Sgabor if (!s.hasTag(WILDCARD)) { 1271219019Sgabor return false; 1272219019Sgabor } else { 1273219019Sgabor WildcardType t2 = (WildcardType)s; 1274219019Sgabor return t.kind == t2.kind && 1275219019Sgabor isSameType(t.type, t2.type, true); 1276219019Sgabor } 1277219019Sgabor } 1278219019Sgabor }; 1279219019Sgabor 1280219019Sgabor // </editor-fold> 1281219019Sgabor 1282219019Sgabor // <editor-fold defaultstate="collapsed" desc="Contains Type"> 1283219019Sgabor public boolean containedBy(Type t, Type s) { 1284219019Sgabor switch (t.getTag()) { 1285219019Sgabor case UNDETVAR: 1286219019Sgabor if (s.hasTag(WILDCARD)) { 1287219019Sgabor UndetVar undetvar = (UndetVar)t; 1288219019Sgabor WildcardType wt = (WildcardType)s; 1289219019Sgabor switch(wt.kind) { 1290219019Sgabor case UNBOUND: 1291219019Sgabor break; 1292219019Sgabor case EXTENDS: { 1293219019Sgabor Type bound = wildUpperBound(s); 1294219019Sgabor undetvar.addBound(InferenceBound.UPPER, bound, this); 1295219019Sgabor break; 1296219019Sgabor } 1297219019Sgabor case SUPER: { 1298219019Sgabor Type bound = wildLowerBound(s); 1299219019Sgabor undetvar.addBound(InferenceBound.LOWER, bound, this); 1300219019Sgabor break; 1301219019Sgabor } 1302219019Sgabor } 1303219019Sgabor return true; 1304219019Sgabor } else { 1305219019Sgabor return isSameType(t, s); 1306219019Sgabor } 1307219019Sgabor case ERROR: 1308219019Sgabor return true; 1309219019Sgabor default: 1310219019Sgabor return containsType(s, t); 1311219019Sgabor } 1312219019Sgabor } 1313219019Sgabor 1314219019Sgabor boolean containsType(List<Type> ts, List<Type> ss) { 1315219019Sgabor while (ts.nonEmpty() && ss.nonEmpty() 1316219019Sgabor && containsType(ts.head, ss.head)) { 1317219019Sgabor ts = ts.tail; 1318219019Sgabor ss = ss.tail; 1319219019Sgabor } 1320219019Sgabor return ts.isEmpty() && ss.isEmpty(); 1321219019Sgabor } 1322219019Sgabor 1323219019Sgabor /** 1324219019Sgabor * Check if t contains s. 1325219019Sgabor * 1326219019Sgabor * <p>T contains S if: 1327219019Sgabor * 1328219019Sgabor * <p>{@code L(T) <: L(S) && U(S) <: U(T)} 1329219019Sgabor * 1330219019Sgabor * <p>This relation is only used by ClassType.isSubtype(), that 1331219019Sgabor * is, 1332219019Sgabor * 1333219019Sgabor * <p>{@code C<S> <: C<T> if T contains S.} 1334219019Sgabor * 1335219019Sgabor * <p>Because of F-bounds, this relation can lead to infinite 1336219019Sgabor * recursion. Thus we must somehow break that recursion. Notice 1337219019Sgabor * that containsType() is only called from ClassType.isSubtype(). 1338219019Sgabor * Since the arguments have already been checked against their 1339219019Sgabor * bounds, we know: 1340219019Sgabor * 1341219019Sgabor * <p>{@code U(S) <: U(T) if T is "super" bound (U(T) *is* the bound)} 1342219019Sgabor * 1343219019Sgabor * <p>{@code L(T) <: L(S) if T is "extends" bound (L(T) is bottom)} 1344219019Sgabor * 1345219019Sgabor * @param t a type 1346219019Sgabor * @param s a type 1347219019Sgabor */ 1348219019Sgabor public boolean containsType(Type t, Type s) { 1349219019Sgabor return containsType.visit(t, s); 1350219019Sgabor } 1351219019Sgabor // where 1352219019Sgabor private TypeRelation containsType = new TypeRelation() { 1353219019Sgabor 1354219019Sgabor public Boolean visitType(Type t, Type s) { 1355219019Sgabor if (s.isPartial()) 1356219019Sgabor return containedBy(s, t); 1357219019Sgabor else 1358219019Sgabor return isSameType(t, s); 1359219019Sgabor } 1360219019Sgabor 1361219019Sgabor// void debugContainsType(WildcardType t, Type s) { 1362219019Sgabor// System.err.println(); 1363219019Sgabor// System.err.format(" does %s contain %s?%n", t, s); 1364219019Sgabor// System.err.format(" %s U(%s) <: U(%s) %s = %s%n", 1365219019Sgabor// wildUpperBound(s), s, t, wildUpperBound(t), 1366219019Sgabor// t.isSuperBound() 1367219019Sgabor// || isSubtypeNoCapture(wildUpperBound(s), wildUpperBound(t))); 1368219019Sgabor// System.err.format(" %s L(%s) <: L(%s) %s = %s%n", 1369219019Sgabor// wildLowerBound(t), t, s, wildLowerBound(s), 1370219019Sgabor// t.isExtendsBound() 1371219019Sgabor// || isSubtypeNoCapture(wildLowerBound(t), wildLowerBound(s))); 1372219019Sgabor// System.err.println(); 1373219019Sgabor// } 1374219019Sgabor 1375219019Sgabor @Override 1376219019Sgabor public Boolean visitWildcardType(WildcardType t, Type s) { 1377219019Sgabor if (s.isPartial()) 1378219019Sgabor return containedBy(s, t); 1379219019Sgabor else { 1380219019Sgabor// debugContainsType(t, s); 1381219019Sgabor return isSameWildcard(t, s) 1382219019Sgabor || isCaptureOf(s, t) 1383219019Sgabor || ((t.isExtendsBound() || isSubtypeNoCapture(wildLowerBound(t), wildLowerBound(s))) && 1384219019Sgabor (t.isSuperBound() || isSubtypeNoCapture(wildUpperBound(s), wildUpperBound(t)))); 1385219019Sgabor } 1386219019Sgabor } 1387219019Sgabor 1388219019Sgabor @Override 1389219019Sgabor public Boolean visitUndetVar(UndetVar t, Type s) { 1390219019Sgabor if (!s.hasTag(WILDCARD)) { 1391219019Sgabor return isSameType(t, s); 1392219019Sgabor } else { 1393219019Sgabor return false; 1394219019Sgabor } 1395219019Sgabor } 1396219019Sgabor 1397219019Sgabor @Override 1398219019Sgabor public Boolean visitErrorType(ErrorType t, Type s) { 1399219019Sgabor return true; 1400219019Sgabor } 1401219019Sgabor }; 1402219019Sgabor 1403219019Sgabor public boolean isCaptureOf(Type s, WildcardType t) { 1404219019Sgabor if (!s.hasTag(TYPEVAR) || !((TypeVar)s).isCaptured()) 1405219019Sgabor return false; 1406219019Sgabor return isSameWildcard(t, ((CapturedType)s).wildcard); 1407219019Sgabor } 1408219019Sgabor 1409219019Sgabor public boolean isSameWildcard(WildcardType t, Type s) { 1410219019Sgabor if (!s.hasTag(WILDCARD)) 1411219019Sgabor return false; 1412219019Sgabor WildcardType w = (WildcardType)s; 1413219019Sgabor return w.kind == t.kind && w.type == t.type; 1414219019Sgabor } 1415219019Sgabor 1416219019Sgabor public boolean containsTypeEquivalent(List<Type> ts, List<Type> ss) { 1417219019Sgabor while (ts.nonEmpty() && ss.nonEmpty() 1418219019Sgabor && containsTypeEquivalent(ts.head, ss.head)) { 1419219019Sgabor ts = ts.tail; 1420219019Sgabor ss = ss.tail; 1421219019Sgabor } 1422219019Sgabor return ts.isEmpty() && ss.isEmpty(); 1423219019Sgabor } 1424219019Sgabor // </editor-fold> 1425219019Sgabor 1426219019Sgabor // <editor-fold defaultstate="collapsed" desc="isCastable"> 1427219019Sgabor public boolean isCastable(Type t, Type s) { 1428219019Sgabor return isCastable(t, s, noWarnings); 1429219019Sgabor } 1430219019Sgabor 1431219019Sgabor /** 1432219019Sgabor * Is t is castable to s?<br> 1433219019Sgabor * s is assumed to be an erased type.<br> 1434219019Sgabor * (not defined for Method and ForAll types). 1435219019Sgabor */ 1436219019Sgabor public boolean isCastable(Type t, Type s, Warner warn) { 1437219019Sgabor if (t == s) 1438219019Sgabor return true; 1439219019Sgabor 1440219019Sgabor if (t.isPrimitive() != s.isPrimitive()) 1441219019Sgabor return (isConvertible(t, s, warn) 1442219019Sgabor || (allowObjectToPrimitiveCast && 1443219019Sgabor s.isPrimitive() && 1444219019Sgabor isSubtype(boxedClass(s).type, t))); 1445219019Sgabor if (warn != warnStack.head) { 1446219019Sgabor try { 1447219019Sgabor warnStack = warnStack.prepend(warn); 1448219019Sgabor checkUnsafeVarargsConversion(t, s, warn); 1449219019Sgabor return isCastable.visit(t,s); 1450219019Sgabor } finally { 1451219019Sgabor warnStack = warnStack.tail; 1452219019Sgabor } 1453219019Sgabor } else { 1454219019Sgabor return isCastable.visit(t,s); 1455219019Sgabor } 1456219019Sgabor } 1457219019Sgabor // where 1458219019Sgabor private TypeRelation isCastable = new TypeRelation() { 1459219019Sgabor 1460219019Sgabor public Boolean visitType(Type t, Type s) { 1461219019Sgabor if (s.hasTag(ERROR)) 1462219019Sgabor return true; 1463219019Sgabor 1464219019Sgabor switch (t.getTag()) { 1465219019Sgabor case BYTE: case CHAR: case SHORT: case INT: case LONG: case FLOAT: 1466219019Sgabor case DOUBLE: 1467219019Sgabor return s.isNumeric(); 1468219019Sgabor case BOOLEAN: 1469219019Sgabor return s.hasTag(BOOLEAN); 1470219019Sgabor case VOID: 1471219019Sgabor return false; 1472219019Sgabor case BOT: 1473219019Sgabor return isSubtype(t, s); 1474219019Sgabor default: 1475219019Sgabor throw new AssertionError(); 1476219019Sgabor } 1477219019Sgabor } 1478219019Sgabor 1479219019Sgabor @Override 1480219019Sgabor public Boolean visitWildcardType(WildcardType t, Type s) { 1481219019Sgabor return isCastable(wildUpperBound(t), s, warnStack.head); 1482219019Sgabor } 1483219019Sgabor 1484219019Sgabor @Override 1485219019Sgabor public Boolean visitClassType(ClassType t, Type s) { 1486219019Sgabor if (s.hasTag(ERROR) || s.hasTag(BOT)) 1487219019Sgabor return true; 1488219019Sgabor 1489219019Sgabor if (s.hasTag(TYPEVAR)) { 1490219019Sgabor if (isCastable(t, s.getUpperBound(), noWarnings)) { 1491219019Sgabor warnStack.head.warn(LintCategory.UNCHECKED); 1492219019Sgabor return true; 1493219019Sgabor } else { 1494219019Sgabor return false; 1495219019Sgabor } 1496219019Sgabor } 1497219019Sgabor 1498219019Sgabor if (t.isIntersection() || s.isIntersection()) { 1499219019Sgabor return !t.isIntersection() ? 1500219019Sgabor visitIntersectionType((IntersectionClassType)s, t, true) : 1501219019Sgabor visitIntersectionType((IntersectionClassType)t, s, false); 1502219019Sgabor } 1503219019Sgabor 1504219019Sgabor if (s.hasTag(CLASS) || s.hasTag(ARRAY)) { 1505219019Sgabor boolean upcast; 1506219019Sgabor if ((upcast = isSubtype(erasure(t), erasure(s))) 1507219019Sgabor || isSubtype(erasure(s), erasure(t))) { 1508219019Sgabor if (!upcast && s.hasTag(ARRAY)) { 1509219019Sgabor if (!isReifiable(s)) 1510219019Sgabor warnStack.head.warn(LintCategory.UNCHECKED); 1511219019Sgabor return true; 1512219019Sgabor } else if (s.isRaw()) { 1513219019Sgabor return true; 1514219019Sgabor } else if (t.isRaw()) { 1515219019Sgabor if (!isUnbounded(s)) 1516219019Sgabor warnStack.head.warn(LintCategory.UNCHECKED); 1517219019Sgabor return true; 1518219019Sgabor } 1519219019Sgabor // Assume |a| <: |b| 1520219019Sgabor final Type a = upcast ? t : s; 1521219019Sgabor final Type b = upcast ? s : t; 1522219019Sgabor final boolean HIGH = true; 1523219019Sgabor final boolean LOW = false; 1524219019Sgabor final boolean DONT_REWRITE_TYPEVARS = false; 1525219019Sgabor Type aHigh = rewriteQuantifiers(a, HIGH, DONT_REWRITE_TYPEVARS); 1526219019Sgabor Type aLow = rewriteQuantifiers(a, LOW, DONT_REWRITE_TYPEVARS); 1527219019Sgabor Type bHigh = rewriteQuantifiers(b, HIGH, DONT_REWRITE_TYPEVARS); 1528219019Sgabor Type bLow = rewriteQuantifiers(b, LOW, DONT_REWRITE_TYPEVARS); 1529219019Sgabor Type lowSub = asSub(bLow, aLow.tsym); 1530219019Sgabor Type highSub = (lowSub == null) ? null : asSub(bHigh, aHigh.tsym); 1531219019Sgabor if (highSub == null) { 1532219019Sgabor final boolean REWRITE_TYPEVARS = true; 1533219019Sgabor aHigh = rewriteQuantifiers(a, HIGH, REWRITE_TYPEVARS); 1534219019Sgabor aLow = rewriteQuantifiers(a, LOW, REWRITE_TYPEVARS); 1535219019Sgabor bHigh = rewriteQuantifiers(b, HIGH, REWRITE_TYPEVARS); 1536219019Sgabor bLow = rewriteQuantifiers(b, LOW, REWRITE_TYPEVARS); 1537219019Sgabor lowSub = asSub(bLow, aLow.tsym); 1538219019Sgabor highSub = (lowSub == null) ? null : asSub(bHigh, aHigh.tsym); 1539219019Sgabor } 1540219019Sgabor if (highSub != null) { 1541219019Sgabor if (!(a.tsym == highSub.tsym && a.tsym == lowSub.tsym)) { 1542219019Sgabor Assert.error(a.tsym + " != " + highSub.tsym + " != " + lowSub.tsym); 1543219019Sgabor } 1544219019Sgabor if (!disjointTypes(aHigh.allparams(), highSub.allparams()) 1545219019Sgabor && !disjointTypes(aHigh.allparams(), lowSub.allparams()) 1546219019Sgabor && !disjointTypes(aLow.allparams(), highSub.allparams()) 1547219019Sgabor && !disjointTypes(aLow.allparams(), lowSub.allparams())) { 1548219019Sgabor if (upcast ? giveWarning(a, b) : 1549219019Sgabor giveWarning(b, a)) 1550219019Sgabor warnStack.head.warn(LintCategory.UNCHECKED); 1551219019Sgabor return true; 1552219019Sgabor } 1553219019Sgabor } 1554219019Sgabor if (isReifiable(s)) 1555219019Sgabor return isSubtypeUnchecked(a, b); 1556219019Sgabor else 1557219019Sgabor return isSubtypeUnchecked(a, b, warnStack.head); 1558219019Sgabor } 1559219019Sgabor 1560219019Sgabor // Sidecast 1561219019Sgabor if (s.hasTag(CLASS)) { 1562219019Sgabor if ((s.tsym.flags() & INTERFACE) != 0) { 1563219019Sgabor return ((t.tsym.flags() & FINAL) == 0) 1564219019Sgabor ? sideCast(t, s, warnStack.head) 1565219019Sgabor : sideCastFinal(t, s, warnStack.head); 1566219019Sgabor } else if ((t.tsym.flags() & INTERFACE) != 0) { 1567219019Sgabor return ((s.tsym.flags() & FINAL) == 0) 1568219019Sgabor ? sideCast(t, s, warnStack.head) 1569219019Sgabor : sideCastFinal(t, s, warnStack.head); 1570219019Sgabor } else { 1571219019Sgabor // unrelated class types 1572219019Sgabor return false; 1573219019Sgabor } 1574219019Sgabor } 1575219019Sgabor } 1576219019Sgabor return false; 1577219019Sgabor } 1578219019Sgabor 1579219019Sgabor boolean visitIntersectionType(IntersectionClassType ict, Type s, boolean reverse) { 1580219019Sgabor Warner warn = noWarnings; 1581219019Sgabor for (Type c : ict.getComponents()) { 1582219019Sgabor warn.clear(); 1583219019Sgabor if (reverse ? !isCastable(s, c, warn) : !isCastable(c, s, warn)) 1584219019Sgabor return false; 1585219019Sgabor } 1586219019Sgabor if (warn.hasLint(LintCategory.UNCHECKED)) 1587219019Sgabor warnStack.head.warn(LintCategory.UNCHECKED); 1588219019Sgabor return true; 1589219019Sgabor } 1590219019Sgabor 1591219019Sgabor @Override 1592219019Sgabor public Boolean visitArrayType(ArrayType t, Type s) { 1593219019Sgabor switch (s.getTag()) { 1594219019Sgabor case ERROR: 1595219019Sgabor case BOT: 1596219019Sgabor return true; 1597219019Sgabor case TYPEVAR: 1598219019Sgabor if (isCastable(s, t, noWarnings)) { 1599219019Sgabor warnStack.head.warn(LintCategory.UNCHECKED); 1600219019Sgabor return true; 1601219019Sgabor } else { 1602219019Sgabor return false; 1603219019Sgabor } 1604219019Sgabor case CLASS: 1605219019Sgabor return isSubtype(t, s); 1606219019Sgabor case ARRAY: 1607219019Sgabor if (elemtype(t).isPrimitive() || elemtype(s).isPrimitive()) { 1608219019Sgabor return elemtype(t).hasTag(elemtype(s).getTag()); 1609219019Sgabor } else { 1610219019Sgabor return visit(elemtype(t), elemtype(s)); 1611219019Sgabor } 1612219019Sgabor default: 1613219019Sgabor return false; 1614219019Sgabor } 1615219019Sgabor } 1616219019Sgabor 1617219019Sgabor @Override 1618219019Sgabor public Boolean visitTypeVar(TypeVar t, Type s) { 1619219019Sgabor switch (s.getTag()) { 1620219019Sgabor case ERROR: 1621219019Sgabor case BOT: 1622219019Sgabor return true; 1623219019Sgabor case TYPEVAR: 1624219019Sgabor if (isSubtype(t, s)) { 1625219019Sgabor return true; 1626219019Sgabor } else if (isCastable(t.bound, s, noWarnings)) { 1627219019Sgabor warnStack.head.warn(LintCategory.UNCHECKED); 1628219019Sgabor return true; 1629219019Sgabor } else { 1630219019Sgabor return false; 1631219019Sgabor } 1632219019Sgabor default: 1633219019Sgabor return isCastable(t.bound, s, warnStack.head); 1634219019Sgabor } 1635219019Sgabor } 1636219019Sgabor 1637219019Sgabor @Override 1638219019Sgabor public Boolean visitErrorType(ErrorType t, Type s) { 1639219019Sgabor return true; 1640219019Sgabor } 1641219019Sgabor }; 1642219019Sgabor // </editor-fold> 1643219019Sgabor 1644219019Sgabor // <editor-fold defaultstate="collapsed" desc="disjointTypes"> 1645219019Sgabor public boolean disjointTypes(List<Type> ts, List<Type> ss) { 1646219019Sgabor while (ts.tail != null && ss.tail != null) { 1647219019Sgabor if (disjointType(ts.head, ss.head)) return true; 1648219019Sgabor ts = ts.tail; 1649219019Sgabor ss = ss.tail; 1650219019Sgabor } 1651219019Sgabor return false; 1652219019Sgabor } 1653219019Sgabor 1654219019Sgabor /** 1655219019Sgabor * Two types or wildcards are considered disjoint if it can be 1656219019Sgabor * proven that no type can be contained in both. It is 1657219019Sgabor * conservative in that it is allowed to say that two types are 1658219019Sgabor * not disjoint, even though they actually are. 1659219019Sgabor * 1660219019Sgabor * The type {@code C<X>} is castable to {@code C<Y>} exactly if 1661219019Sgabor * {@code X} and {@code Y} are not disjoint. 1662219019Sgabor */ 1663219019Sgabor public boolean disjointType(Type t, Type s) { 1664219019Sgabor return disjointType.visit(t, s); 1665219019Sgabor } 1666219019Sgabor // where 1667219019Sgabor private TypeRelation disjointType = new TypeRelation() { 1668219019Sgabor 1669219019Sgabor private Set<TypePair> cache = new HashSet<>(); 1670219019Sgabor 1671219019Sgabor @Override 1672219019Sgabor public Boolean visitType(Type t, Type s) { 1673219019Sgabor if (s.hasTag(WILDCARD)) 1674219019Sgabor return visit(s, t); 1675219019Sgabor else 1676219019Sgabor return notSoftSubtypeRecursive(t, s) || notSoftSubtypeRecursive(s, t); 1677219019Sgabor } 1678219019Sgabor 1679219019Sgabor private boolean isCastableRecursive(Type t, Type s) { 1680219019Sgabor TypePair pair = new TypePair(t, s); 1681219019Sgabor if (cache.add(pair)) { 1682219019Sgabor try { 1683219019Sgabor return Types.this.isCastable(t, s); 1684219019Sgabor } finally { 1685219019Sgabor cache.remove(pair); 1686219019Sgabor } 1687219019Sgabor } else { 1688219019Sgabor return true; 1689219019Sgabor } 1690219019Sgabor } 1691219019Sgabor 1692219019Sgabor private boolean notSoftSubtypeRecursive(Type t, Type s) { 1693219019Sgabor TypePair pair = new TypePair(t, s); 1694219019Sgabor if (cache.add(pair)) { 1695219019Sgabor try { 1696219019Sgabor return Types.this.notSoftSubtype(t, s); 1697219019Sgabor } finally { 1698219019Sgabor cache.remove(pair); 1699219019Sgabor } 1700219019Sgabor } else { 1701219019Sgabor return false; 1702219019Sgabor } 1703219019Sgabor } 1704219019Sgabor 1705219019Sgabor @Override 1706219019Sgabor public Boolean visitWildcardType(WildcardType t, Type s) { 1707219019Sgabor if (t.isUnbound()) 1708219019Sgabor return false; 1709219019Sgabor 1710219019Sgabor if (!s.hasTag(WILDCARD)) { 1711219019Sgabor if (t.isExtendsBound()) 1712219019Sgabor return notSoftSubtypeRecursive(s, t.type); 1713219019Sgabor else 1714219019Sgabor return notSoftSubtypeRecursive(t.type, s); 1715219019Sgabor } 1716219019Sgabor 1717219019Sgabor if (s.isUnbound()) 1718219019Sgabor return false; 1719219019Sgabor 1720219019Sgabor if (t.isExtendsBound()) { 1721219019Sgabor if (s.isExtendsBound()) 1722219019Sgabor return !isCastableRecursive(t.type, wildUpperBound(s)); 1723219019Sgabor else if (s.isSuperBound()) 1724219019Sgabor return notSoftSubtypeRecursive(wildLowerBound(s), t.type); 1725219019Sgabor } else if (t.isSuperBound()) { 1726219019Sgabor if (s.isExtendsBound()) 1727219019Sgabor return notSoftSubtypeRecursive(t.type, wildUpperBound(s)); 1728219019Sgabor } 1729219019Sgabor return false; 1730219019Sgabor } 1731219019Sgabor }; 1732219019Sgabor // </editor-fold> 1733219019Sgabor 1734219019Sgabor // <editor-fold defaultstate="collapsed" desc="cvarLowerBounds"> 1735219019Sgabor public List<Type> cvarLowerBounds(List<Type> ts) { 1736219019Sgabor return ts.map(cvarLowerBoundMapping); 1737219019Sgabor } 1738219019Sgabor private final TypeMapping<Void> cvarLowerBoundMapping = new TypeMapping<Void>() { 1739219019Sgabor @Override 1740219019Sgabor public Type visitCapturedType(CapturedType t, Void _unused) { 1741219019Sgabor return cvarLowerBound(t); 1742219019Sgabor } 1743219019Sgabor }; 1744219019Sgabor // </editor-fold> 1745219019Sgabor 1746219019Sgabor // <editor-fold defaultstate="collapsed" desc="notSoftSubtype"> 1747219019Sgabor /** 1748219019Sgabor * This relation answers the question: is impossible that 1749219019Sgabor * something of type `t' can be a subtype of `s'? This is 1750219019Sgabor * different from the question "is `t' not a subtype of `s'?" 1751219019Sgabor * when type variables are involved: Integer is not a subtype of T 1752219019Sgabor * where {@code <T extends Number>} but it is not true that Integer cannot 1753219019Sgabor * possibly be a subtype of T. 1754219019Sgabor */ 1755219019Sgabor public boolean notSoftSubtype(Type t, Type s) { 1756219019Sgabor if (t == s) return false; 1757219019Sgabor if (t.hasTag(TYPEVAR)) { 1758219019Sgabor TypeVar tv = (TypeVar) t; 1759219019Sgabor return !isCastable(tv.bound, 1760219019Sgabor relaxBound(s), 1761219019Sgabor noWarnings); 1762219019Sgabor } 1763219019Sgabor if (!s.hasTag(WILDCARD)) 1764219019Sgabor s = cvarUpperBound(s); 1765219019Sgabor 1766219019Sgabor return !isSubtype(t, relaxBound(s)); 1767219019Sgabor } 1768219019Sgabor 1769219019Sgabor private Type relaxBound(Type t) { 1770219019Sgabor return (t.hasTag(TYPEVAR)) ? 1771219019Sgabor rewriteQuantifiers(skipTypeVars(t, false), true, true) : 1772219019Sgabor t; 1773219019Sgabor } 1774219019Sgabor // </editor-fold> 1775219019Sgabor 1776219019Sgabor // <editor-fold defaultstate="collapsed" desc="isReifiable"> 1777219019Sgabor public boolean isReifiable(Type t) { 1778219019Sgabor return isReifiable.visit(t); 1779219019Sgabor } 1780219019Sgabor // where 1781219019Sgabor private UnaryVisitor<Boolean> isReifiable = new UnaryVisitor<Boolean>() { 1782219019Sgabor 1783219019Sgabor public Boolean visitType(Type t, Void ignored) { 1784219019Sgabor return true; 1785219019Sgabor } 1786219019Sgabor 1787219019Sgabor @Override 1788219019Sgabor public Boolean visitClassType(ClassType t, Void ignored) { 1789219019Sgabor if (t.isCompound()) 1790219019Sgabor return false; 1791219019Sgabor else { 1792219019Sgabor if (!t.isParameterized()) 1793219019Sgabor return true; 1794219019Sgabor 1795219019Sgabor for (Type param : t.allparams()) { 1796219019Sgabor if (!param.isUnbound()) 1797219019Sgabor return false; 1798219019Sgabor } 1799219019Sgabor return true; 1800219019Sgabor } 1801219019Sgabor } 1802219019Sgabor 1803219019Sgabor @Override 1804219019Sgabor public Boolean visitArrayType(ArrayType t, Void ignored) { 1805219019Sgabor return visit(t.elemtype); 1806219019Sgabor } 1807219019Sgabor 1808219019Sgabor @Override 1809219019Sgabor public Boolean visitTypeVar(TypeVar t, Void ignored) { 1810219019Sgabor return false; 1811219019Sgabor } 1812219019Sgabor }; 1813219019Sgabor // </editor-fold> 1814219019Sgabor 1815219019Sgabor // <editor-fold defaultstate="collapsed" desc="Array Utils"> 1816219019Sgabor public boolean isArray(Type t) { 1817219019Sgabor while (t.hasTag(WILDCARD)) 1818219019Sgabor t = wildUpperBound(t); 1819219019Sgabor return t.hasTag(ARRAY); 1820219019Sgabor } 1821219019Sgabor 1822219019Sgabor /** 1823219019Sgabor * The element type of an array. 1824219019Sgabor */ 1825219019Sgabor public Type elemtype(Type t) { 1826219019Sgabor switch (t.getTag()) { 1827219019Sgabor case WILDCARD: 1828219019Sgabor return elemtype(wildUpperBound(t)); 1829219019Sgabor case ARRAY: 1830219019Sgabor return ((ArrayType)t).elemtype; 1831219019Sgabor case FORALL: 1832219019Sgabor return elemtype(((ForAll)t).qtype); 1833219019Sgabor case ERROR: 1834219019Sgabor return t; 1835219019Sgabor default: 1836219019Sgabor return null; 1837219019Sgabor } 1838219019Sgabor } 1839219019Sgabor 1840219019Sgabor public Type elemtypeOrType(Type t) { 1841219019Sgabor Type elemtype = elemtype(t); 1842219019Sgabor return elemtype != null ? 1843219019Sgabor elemtype : 1844219019Sgabor t; 1845219019Sgabor } 1846219019Sgabor 1847219019Sgabor /** 1848219019Sgabor * Mapping to take element type of an arraytype 1849219019Sgabor */ 1850219019Sgabor private TypeMapping<Void> elemTypeFun = new TypeMapping<Void>() { 1851219019Sgabor @Override 1852219019Sgabor public Type visitArrayType(ArrayType t, Void _unused) { 1853219019Sgabor return t.elemtype; 1854219019Sgabor } 1855219019Sgabor 1856219019Sgabor @Override 1857219019Sgabor public Type visitTypeVar(TypeVar t, Void _unused) { 1858219019Sgabor return visit(skipTypeVars(t, false)); 1859219019Sgabor } 1860219019Sgabor }; 1861219019Sgabor 1862219019Sgabor /** 1863219019Sgabor * The number of dimensions of an array type. 1864219019Sgabor */ 1865219019Sgabor public int dimensions(Type t) { 1866219019Sgabor int result = 0; 1867219019Sgabor while (t.hasTag(ARRAY)) { 1868219019Sgabor result++; 1869219019Sgabor t = elemtype(t); 1870219019Sgabor } 1871219019Sgabor return result; 1872219019Sgabor } 1873219019Sgabor 1874219019Sgabor /** 1875219019Sgabor * Returns an ArrayType with the component type t 1876219019Sgabor * 1877219019Sgabor * @param t The component type of the ArrayType 1878219019Sgabor * @return the ArrayType for the given component 1879219019Sgabor */ 1880219019Sgabor public ArrayType makeArrayType(Type t) { 1881219019Sgabor if (t.hasTag(VOID) || t.hasTag(PACKAGE)) { 1882219019Sgabor Assert.error("Type t must not be a VOID or PACKAGE type, " + t.toString()); 1883219019Sgabor } 1884219019Sgabor return new ArrayType(t, syms.arrayClass); 1885219019Sgabor } 1886219019Sgabor // </editor-fold> 1887219019Sgabor 1888219019Sgabor // <editor-fold defaultstate="collapsed" desc="asSuper"> 1889219019Sgabor /** 1890219019Sgabor * Return the (most specific) base type of t that starts with the 1891219019Sgabor * given symbol. If none exists, return null. 1892219019Sgabor * 1893219019Sgabor * Caveat Emptor: Since javac represents the class of all arrays with a singleton 1894219019Sgabor * symbol Symtab.arrayClass, which by being a singleton cannot hold any discriminant, 1895219019Sgabor * this method could yield surprising answers when invoked on arrays. For example when 1896219019Sgabor * invoked with t being byte [] and sym being t.sym itself, asSuper would answer null. 1897219019Sgabor * 1898219019Sgabor * @param t a type 1899219019Sgabor * @param sym a symbol 1900219019Sgabor */ 1901219019Sgabor public Type asSuper(Type t, Symbol sym) { 1902219019Sgabor /* Some examples: 1903219019Sgabor * 1904219019Sgabor * (Enum<E>, Comparable) => Comparable<E> 1905219019Sgabor * (c.s.s.d.AttributeTree.ValueKind, Enum) => Enum<c.s.s.d.AttributeTree.ValueKind> 1906219019Sgabor * (c.s.s.t.ExpressionTree, c.s.s.t.Tree) => c.s.s.t.Tree 1907219019Sgabor * (j.u.List<capture#160 of ? extends c.s.s.d.DocTree>, Iterable) => 1908219019Sgabor * Iterable<capture#160 of ? extends c.s.s.d.DocTree> 1909219019Sgabor */ 1910219019Sgabor if (sym.type == syms.objectType) { //optimization 1911219019Sgabor return syms.objectType; 1912219019Sgabor } 1913219019Sgabor return asSuper.visit(t, sym); 1914219019Sgabor } 1915219019Sgabor // where 1916219019Sgabor private SimpleVisitor<Type,Symbol> asSuper = new SimpleVisitor<Type,Symbol>() { 1917219019Sgabor 1918219019Sgabor public Type visitType(Type t, Symbol sym) { 1919219019Sgabor return null; 1920219019Sgabor } 1921219019Sgabor 1922219019Sgabor @Override 1923219019Sgabor public Type visitClassType(ClassType t, Symbol sym) { 1924219019Sgabor if (t.tsym == sym) 1925219019Sgabor return t; 1926219019Sgabor 1927219019Sgabor Type st = supertype(t); 1928219019Sgabor if (st.hasTag(CLASS) || st.hasTag(TYPEVAR)) { 1929219019Sgabor Type x = asSuper(st, sym); 1930219019Sgabor if (x != null) 1931219019Sgabor return x; 1932219019Sgabor } 1933219019Sgabor if ((sym.flags() & INTERFACE) != 0) { 1934219019Sgabor for (List<Type> l = interfaces(t); l.nonEmpty(); l = l.tail) { 1935219019Sgabor if (!l.head.hasTag(ERROR)) { 1936219019Sgabor Type x = asSuper(l.head, sym); 1937219019Sgabor if (x != null) 1938219019Sgabor return x; 1939219019Sgabor } 1940219019Sgabor } 1941219019Sgabor } 1942219019Sgabor return null; 1943219019Sgabor } 1944219019Sgabor 1945219019Sgabor @Override 1946219019Sgabor public Type visitArrayType(ArrayType t, Symbol sym) { 1947219019Sgabor return isSubtype(t, sym.type) ? sym.type : null; 1948219019Sgabor } 1949219019Sgabor 1950219019Sgabor @Override 1951219019Sgabor public Type visitTypeVar(TypeVar t, Symbol sym) { 1952219019Sgabor if (t.tsym == sym) 1953219019Sgabor return t; 1954219019Sgabor else 1955219019Sgabor return asSuper(t.bound, sym); 1956219019Sgabor } 1957219019Sgabor 1958219019Sgabor @Override 1959219019Sgabor public Type visitErrorType(ErrorType t, Symbol sym) { 1960219019Sgabor return t; 1961219019Sgabor } 1962219019Sgabor }; 1963219019Sgabor 1964219019Sgabor /** 1965219019Sgabor * Return the base type of t or any of its outer types that starts 1966219019Sgabor * with the given symbol. If none exists, return null. 1967219019Sgabor * 1968219019Sgabor * @param t a type 1969219019Sgabor * @param sym a symbol 1970219019Sgabor */ 1971219019Sgabor public Type asOuterSuper(Type t, Symbol sym) { 1972219019Sgabor switch (t.getTag()) { 1973219019Sgabor case CLASS: 1974219019Sgabor do { 1975219019Sgabor Type s = asSuper(t, sym); 1976219019Sgabor if (s != null) return s; 1977219019Sgabor t = t.getEnclosingType(); 1978219019Sgabor } while (t.hasTag(CLASS)); 1979219019Sgabor return null; 1980219019Sgabor case ARRAY: 1981219019Sgabor return isSubtype(t, sym.type) ? sym.type : null; 1982219019Sgabor case TYPEVAR: 1983219019Sgabor return asSuper(t, sym); 1984219019Sgabor case ERROR: 1985219019Sgabor return t; 1986219019Sgabor default: 1987219019Sgabor return null; 1988219019Sgabor } 1989219019Sgabor } 1990219019Sgabor 1991219019Sgabor /** 1992219019Sgabor * Return the base type of t or any of its enclosing types that 1993219019Sgabor * starts with the given symbol. If none exists, return null. 1994219019Sgabor * 1995219019Sgabor * @param t a type 1996219019Sgabor * @param sym a symbol 1997219019Sgabor */ 1998219019Sgabor public Type asEnclosingSuper(Type t, Symbol sym) { 1999219019Sgabor switch (t.getTag()) { 2000219019Sgabor case CLASS: 2001219019Sgabor do { 2002219019Sgabor Type s = asSuper(t, sym); 2003219019Sgabor if (s != null) return s; 2004219019Sgabor Type outer = t.getEnclosingType(); 2005219019Sgabor t = (outer.hasTag(CLASS)) ? outer : 2006219019Sgabor (t.tsym.owner.enclClass() != null) ? t.tsym.owner.enclClass().type : 2007219019Sgabor Type.noType; 2008219019Sgabor } while (t.hasTag(CLASS)); 2009219019Sgabor return null; 2010219019Sgabor case ARRAY: 2011219019Sgabor return isSubtype(t, sym.type) ? sym.type : null; 2012219019Sgabor case TYPEVAR: 2013219019Sgabor return asSuper(t, sym); 2014219019Sgabor case ERROR: 2015219019Sgabor return t; 2016219019Sgabor default: 2017219019Sgabor return null; 2018219019Sgabor } 2019219019Sgabor } 2020219019Sgabor // </editor-fold> 2021219019Sgabor 2022219019Sgabor // <editor-fold defaultstate="collapsed" desc="memberType"> 2023219019Sgabor /** 2024219019Sgabor * The type of given symbol, seen as a member of t. 2025219019Sgabor * 2026219019Sgabor * @param t a type 2027219019Sgabor * @param sym a symbol 2028219019Sgabor */ 2029219019Sgabor public Type memberType(Type t, Symbol sym) { 2030219019Sgabor return (sym.flags() & STATIC) != 0 2031219019Sgabor ? sym.type 2032219019Sgabor : memberType.visit(t, sym); 2033219019Sgabor } 2034219019Sgabor // where 2035219019Sgabor private SimpleVisitor<Type,Symbol> memberType = new SimpleVisitor<Type,Symbol>() { 2036219019Sgabor 2037219019Sgabor public Type visitType(Type t, Symbol sym) { 2038219019Sgabor return sym.type; 2039219019Sgabor } 2040219019Sgabor 2041219019Sgabor @Override 2042219019Sgabor public Type visitWildcardType(WildcardType t, Symbol sym) { 2043219019Sgabor return memberType(wildUpperBound(t), sym); 2044219019Sgabor } 2045219019Sgabor 2046219019Sgabor @Override 2047219019Sgabor public Type visitClassType(ClassType t, Symbol sym) { 2048219019Sgabor Symbol owner = sym.owner; 2049219019Sgabor long flags = sym.flags(); 2050219019Sgabor if (((flags & STATIC) == 0) && owner.type.isParameterized()) { 2051219019Sgabor Type base = asOuterSuper(t, owner); 2052219019Sgabor //if t is an intersection type T = CT & I1 & I2 ... & In 2053219019Sgabor //its supertypes CT, I1, ... In might contain wildcards 2054219019Sgabor //so we need to go through capture conversion 2055219019Sgabor base = t.isCompound() ? capture(base) : base; 2056219019Sgabor if (base != null) { 2057219019Sgabor List<Type> ownerParams = owner.type.allparams(); 2058219019Sgabor List<Type> baseParams = base.allparams(); 2059219019Sgabor if (ownerParams.nonEmpty()) { 2060219019Sgabor if (baseParams.isEmpty()) { 2061219019Sgabor // then base is a raw type 2062219019Sgabor return erasure(sym.type); 2063219019Sgabor } else { 2064219019Sgabor return subst(sym.type, ownerParams, baseParams); 2065219019Sgabor } 2066219019Sgabor } 2067219019Sgabor } 2068219019Sgabor } 2069219019Sgabor return sym.type; 2070219019Sgabor } 2071219019Sgabor 2072219019Sgabor @Override 2073219019Sgabor public Type visitTypeVar(TypeVar t, Symbol sym) { 2074219019Sgabor return memberType(t.bound, sym); 2075219019Sgabor } 2076219019Sgabor 2077219019Sgabor @Override 2078219019Sgabor public Type visitErrorType(ErrorType t, Symbol sym) { 2079219019Sgabor return t; 2080219019Sgabor } 2081219019Sgabor }; 2082219019Sgabor // </editor-fold> 2083219019Sgabor 2084219019Sgabor // <editor-fold defaultstate="collapsed" desc="isAssignable"> 2085219019Sgabor public boolean isAssignable(Type t, Type s) { 2086219019Sgabor return isAssignable(t, s, noWarnings); 2087219019Sgabor } 2088219019Sgabor 2089219019Sgabor /** 2090219019Sgabor * Is t assignable to s?<br> 2091219019Sgabor * Equivalent to subtype except for constant values and raw 2092219019Sgabor * types.<br> 2093219019Sgabor * (not defined for Method and ForAll types) 2094219019Sgabor */ 2095219019Sgabor public boolean isAssignable(Type t, Type s, Warner warn) { 2096219019Sgabor if (t.hasTag(ERROR)) 2097219019Sgabor return true; 2098219019Sgabor if (t.getTag().isSubRangeOf(INT) && t.constValue() != null) { 2099219019Sgabor int value = ((Number)t.constValue()).intValue(); 2100219019Sgabor switch (s.getTag()) { 2101219019Sgabor case BYTE: 2102219019Sgabor if (Byte.MIN_VALUE <= value && value <= Byte.MAX_VALUE) 2103219019Sgabor return true; 2104219019Sgabor break; 2105219019Sgabor case CHAR: 2106219019Sgabor if (Character.MIN_VALUE <= value && value <= Character.MAX_VALUE) 2107219019Sgabor return true; 2108219019Sgabor break; 2109219019Sgabor case SHORT: 2110219019Sgabor if (Short.MIN_VALUE <= value && value <= Short.MAX_VALUE) 2111219019Sgabor return true; 2112219019Sgabor break; 2113219019Sgabor case INT: 2114219019Sgabor return true; 2115219019Sgabor case CLASS: 2116219019Sgabor switch (unboxedType(s).getTag()) { 2117219019Sgabor case BYTE: 2118219019Sgabor case CHAR: 2119219019Sgabor case SHORT: 2120219019Sgabor return isAssignable(t, unboxedType(s), warn); 2121219019Sgabor } 2122219019Sgabor break; 2123219019Sgabor } 2124219019Sgabor } 2125219019Sgabor return isConvertible(t, s, warn); 2126219019Sgabor } 2127219019Sgabor // </editor-fold> 2128219019Sgabor 2129219019Sgabor // <editor-fold defaultstate="collapsed" desc="erasure"> 2130219019Sgabor /** 2131219019Sgabor * The erasure of t {@code |t|} -- the type that results when all 2132219019Sgabor * type parameters in t are deleted. 2133219019Sgabor */ 2134219019Sgabor public Type erasure(Type t) { 2135219019Sgabor return eraseNotNeeded(t) ? t : erasure(t, false); 2136219019Sgabor } 2137219019Sgabor //where 2138219019Sgabor private boolean eraseNotNeeded(Type t) { 2139219019Sgabor // We don't want to erase primitive types and String type as that 2140219019Sgabor // operation is idempotent. Also, erasing these could result in loss 2141219019Sgabor // of information such as constant values attached to such types. 2142219019Sgabor return (t.isPrimitive()) || (syms.stringType.tsym == t.tsym); 2143219019Sgabor } 2144219019Sgabor 2145219019Sgabor private Type erasure(Type t, boolean recurse) { 2146219019Sgabor if (t.isPrimitive()) { 2147219019Sgabor return t; /* fast special case */ 2148219019Sgabor } else { 2149219019Sgabor Type out = erasure.visit(t, recurse); 2150219019Sgabor return out; 2151219019Sgabor } 2152219019Sgabor } 2153219019Sgabor // where 2154219019Sgabor private TypeMapping<Boolean> erasure = new TypeMapping<Boolean>() { 2155219019Sgabor private Type combineMetadata(final Type s, 2156219019Sgabor final Type t) { 2157219019Sgabor if (t.getMetadata() != TypeMetadata.EMPTY) { 2158219019Sgabor switch (s.getKind()) { 2159219019Sgabor case OTHER: 2160219019Sgabor case UNION: 2161219019Sgabor case INTERSECTION: 2162219019Sgabor case PACKAGE: 2163219019Sgabor case EXECUTABLE: 2164219019Sgabor case NONE: 2165219019Sgabor case VOID: 2166219019Sgabor case ERROR: 2167219019Sgabor return s; 2168219019Sgabor default: return s.cloneWithMetadata(s.getMetadata().without(Kind.ANNOTATIONS)); 2169219019Sgabor } 2170219019Sgabor } else { 2171219019Sgabor return s; 2172219019Sgabor } 2173219019Sgabor } 2174219019Sgabor 2175219019Sgabor public Type visitType(Type t, Boolean recurse) { 2176219019Sgabor if (t.isPrimitive()) 2177219019Sgabor return t; /*fast special case*/ 2178219019Sgabor else { 2179219019Sgabor //other cases already handled 2180219019Sgabor return combineMetadata(t, t); 2181219019Sgabor } 2182219019Sgabor } 2183219019Sgabor 2184219019Sgabor @Override 2185219019Sgabor public Type visitClassType(ClassType t, Boolean recurse) { 2186219019Sgabor Type erased = t.tsym.erasure(Types.this); 2187219019Sgabor if (recurse) { 2188219019Sgabor erased = new ErasedClassType(erased.getEnclosingType(),erased.tsym, 2189219019Sgabor t.getMetadata().without(Kind.ANNOTATIONS)); 2190219019Sgabor return erased; 2191219019Sgabor } else { 2192219019Sgabor return combineMetadata(erased, t); 2193219019Sgabor } 2194219019Sgabor } 2195219019Sgabor 2196219019Sgabor @Override 2197219019Sgabor public Type visitTypeVar(TypeVar t, Boolean recurse) { 2198219019Sgabor Type erased = erasure(t.bound, recurse); 2199219019Sgabor return combineMetadata(erased, t); 2200219019Sgabor } 2201219019Sgabor }; 2202219019Sgabor 2203219019Sgabor public List<Type> erasure(List<Type> ts) { 2204219019Sgabor return erasure.visit(ts, false); 2205219019Sgabor } 2206219019Sgabor 2207219019Sgabor public Type erasureRecursive(Type t) { 2208219019Sgabor return erasure(t, true); 2209219019Sgabor } 2210219019Sgabor 2211219019Sgabor public List<Type> erasureRecursive(List<Type> ts) { 2212219019Sgabor return erasure.visit(ts, true); 2213219019Sgabor } 2214219019Sgabor // </editor-fold> 2215219019Sgabor 2216219019Sgabor // <editor-fold defaultstate="collapsed" desc="makeIntersectionType"> 2217219019Sgabor /** 2218219019Sgabor * Make an intersection type from non-empty list of types. The list should be ordered according to 2219219019Sgabor * {@link TypeSymbol#precedes(TypeSymbol, Types)}. Note that this might cause a symbol completion. 2220219019Sgabor * Hence, this version of makeIntersectionType may not be called during a classfile read. 2221219019Sgabor * 2222219019Sgabor * @param bounds the types from which the intersection type is formed 2223219019Sgabor */ 2224219019Sgabor public IntersectionClassType makeIntersectionType(List<Type> bounds) { 2225219019Sgabor return makeIntersectionType(bounds, bounds.head.tsym.isInterface()); 2226219019Sgabor } 2227219019Sgabor 2228219019Sgabor /** 2229219019Sgabor * Make an intersection type from non-empty list of types. The list should be ordered according to 2230219019Sgabor * {@link TypeSymbol#precedes(TypeSymbol, Types)}. This does not cause symbol completion as 2231219019Sgabor * an extra parameter indicates as to whether all bounds are interfaces - in which case the 2232219019Sgabor * supertype is implicitly assumed to be 'Object'. 2233219019Sgabor * 2234219019Sgabor * @param bounds the types from which the intersection type is formed 2235219019Sgabor * @param allInterfaces are all bounds interface types? 2236219019Sgabor */ 2237219019Sgabor public IntersectionClassType makeIntersectionType(List<Type> bounds, boolean allInterfaces) { 2238219019Sgabor Assert.check(bounds.nonEmpty()); 2239219019Sgabor Type firstExplicitBound = bounds.head; 2240219019Sgabor if (allInterfaces) { 2241219019Sgabor bounds = bounds.prepend(syms.objectType); 2242219019Sgabor } 2243219019Sgabor ClassSymbol bc = 2244219019Sgabor new ClassSymbol(ABSTRACT|PUBLIC|SYNTHETIC|COMPOUND|ACYCLIC, 2245219019Sgabor Type.moreInfo 2246219019Sgabor ? names.fromString(bounds.toString()) 2247219019Sgabor : names.empty, 2248219019Sgabor null, 2249219019Sgabor syms.noSymbol); 2250219019Sgabor IntersectionClassType intersectionType = new IntersectionClassType(bounds, bc, allInterfaces); 2251219019Sgabor bc.type = intersectionType; 2252219019Sgabor bc.erasure_field = (bounds.head.hasTag(TYPEVAR)) ? 2253219019Sgabor syms.objectType : // error condition, recover 2254219019Sgabor erasure(firstExplicitBound); 2255219019Sgabor bc.members_field = WriteableScope.create(bc); 2256219019Sgabor return intersectionType; 2257219019Sgabor } 2258219019Sgabor // </editor-fold> 2259219019Sgabor 2260219019Sgabor // <editor-fold defaultstate="collapsed" desc="supertype"> 2261219019Sgabor public Type supertype(Type t) { 2262219019Sgabor return supertype.visit(t); 2263219019Sgabor } 2264219019Sgabor // where 2265219019Sgabor private UnaryVisitor<Type> supertype = new UnaryVisitor<Type>() { 2266219019Sgabor 2267219019Sgabor public Type visitType(Type t, Void ignored) { 2268219019Sgabor // A note on wildcards: there is no good way to 2269219019Sgabor // determine a supertype for a super bounded wildcard. 2270219019Sgabor return Type.noType; 2271219019Sgabor } 2272219019Sgabor 2273219019Sgabor @Override 2274219019Sgabor public Type visitClassType(ClassType t, Void ignored) { 2275219019Sgabor if (t.supertype_field == null) { 2276219019Sgabor Type supertype = ((ClassSymbol)t.tsym).getSuperclass(); 2277219019Sgabor // An interface has no superclass; its supertype is Object. 2278219019Sgabor if (t.isInterface()) 2279219019Sgabor supertype = ((ClassType)t.tsym.type).supertype_field; 2280219019Sgabor if (t.supertype_field == null) { 2281219019Sgabor List<Type> actuals = classBound(t).allparams(); 2282219019Sgabor List<Type> formals = t.tsym.type.allparams(); 2283219019Sgabor if (t.hasErasedSupertypes()) { 2284219019Sgabor t.supertype_field = erasureRecursive(supertype); 2285219019Sgabor } else if (formals.nonEmpty()) { 2286219019Sgabor t.supertype_field = subst(supertype, formals, actuals); 2287219019Sgabor } 2288219019Sgabor else { 2289219019Sgabor t.supertype_field = supertype; 2290219019Sgabor } 2291219019Sgabor } 2292219019Sgabor } 2293219019Sgabor return t.supertype_field; 2294219019Sgabor } 2295219019Sgabor 2296219019Sgabor /** 2297219019Sgabor * The supertype is always a class type. If the type 2298219019Sgabor * variable's bounds start with a class type, this is also 2299219019Sgabor * the supertype. Otherwise, the supertype is 2300219019Sgabor * java.lang.Object. 2301219019Sgabor */ 2302219019Sgabor @Override 2303219019Sgabor public Type visitTypeVar(TypeVar t, Void ignored) { 2304219019Sgabor if (t.bound.hasTag(TYPEVAR) || 2305219019Sgabor (!t.bound.isCompound() && !t.bound.isInterface())) { 2306219019Sgabor return t.bound; 2307219019Sgabor } else { 2308219019Sgabor return supertype(t.bound); 2309219019Sgabor } 2310219019Sgabor } 2311219019Sgabor 2312219019Sgabor @Override 2313219019Sgabor public Type visitArrayType(ArrayType t, Void ignored) { 2314219019Sgabor if (t.elemtype.isPrimitive() || isSameType(t.elemtype, syms.objectType)) 2315219019Sgabor return arraySuperType(); 2316219019Sgabor else 2317219019Sgabor return new ArrayType(supertype(t.elemtype), t.tsym); 2318219019Sgabor } 2319219019Sgabor 2320219019Sgabor @Override 2321219019Sgabor public Type visitErrorType(ErrorType t, Void ignored) { 2322219019Sgabor return Type.noType; 2323219019Sgabor } 2324219019Sgabor }; 2325219019Sgabor // </editor-fold> 2326219019Sgabor 2327219019Sgabor // <editor-fold defaultstate="collapsed" desc="interfaces"> 2328219019Sgabor /** 2329219019Sgabor * Return the interfaces implemented by this class. 2330219019Sgabor */ 2331219019Sgabor public List<Type> interfaces(Type t) { 2332219019Sgabor return interfaces.visit(t); 2333219019Sgabor } 2334219019Sgabor // where 2335219019Sgabor private UnaryVisitor<List<Type>> interfaces = new UnaryVisitor<List<Type>>() { 2336219019Sgabor 2337219019Sgabor public List<Type> visitType(Type t, Void ignored) { 2338219019Sgabor return List.nil(); 2339219019Sgabor } 2340219019Sgabor 2341219019Sgabor @Override 2342219019Sgabor public List<Type> visitClassType(ClassType t, Void ignored) { 2343219019Sgabor if (t.interfaces_field == null) { 2344219019Sgabor List<Type> interfaces = ((ClassSymbol)t.tsym).getInterfaces(); 2345219019Sgabor if (t.interfaces_field == null) { 2346219019Sgabor // If t.interfaces_field is null, then t must 2347219019Sgabor // be a parameterized type (not to be confused 2348219019Sgabor // with a generic type declaration). 2349219019Sgabor // Terminology: 2350219019Sgabor // Parameterized type: List<String> 2351219019Sgabor // Generic type declaration: class List<E> { ... } 2352219019Sgabor // So t corresponds to List<String> and 2353219019Sgabor // t.tsym.type corresponds to List<E>. 2354219019Sgabor // The reason t must be parameterized type is 2355219019Sgabor // that completion will happen as a side 2356219019Sgabor // effect of calling 2357219019Sgabor // ClassSymbol.getInterfaces. Since 2358219019Sgabor // t.interfaces_field is null after 2359219019Sgabor // completion, we can assume that t is not the 2360219019Sgabor // type of a class/interface declaration. 2361219019Sgabor Assert.check(t != t.tsym.type, t); 2362219019Sgabor List<Type> actuals = t.allparams(); 2363219019Sgabor List<Type> formals = t.tsym.type.allparams(); 2364219019Sgabor if (t.hasErasedSupertypes()) { 2365219019Sgabor t.interfaces_field = erasureRecursive(interfaces); 2366219019Sgabor } else if (formals.nonEmpty()) { 2367219019Sgabor t.interfaces_field = subst(interfaces, formals, actuals); 2368219019Sgabor } 2369219019Sgabor else { 2370219019Sgabor t.interfaces_field = interfaces; 2371219019Sgabor } 2372219019Sgabor } 2373219019Sgabor } 2374219019Sgabor return t.interfaces_field; 2375219019Sgabor } 2376219019Sgabor 2377219019Sgabor @Override 2378219019Sgabor public List<Type> visitTypeVar(TypeVar t, Void ignored) { 2379219019Sgabor if (t.bound.isCompound()) 2380219019Sgabor return interfaces(t.bound); 2381219019Sgabor 2382219019Sgabor if (t.bound.isInterface()) 2383219019Sgabor return List.of(t.bound); 2384219019Sgabor 2385219019Sgabor return List.nil(); 2386219019Sgabor } 2387219019Sgabor }; 2388219019Sgabor 2389219019Sgabor public List<Type> directSupertypes(Type t) { 2390219019Sgabor return directSupertypes.visit(t); 2391219019Sgabor } 2392219019Sgabor // where 2393219019Sgabor private final UnaryVisitor<List<Type>> directSupertypes = new UnaryVisitor<List<Type>>() { 2394219019Sgabor 2395219019Sgabor public List<Type> visitType(final Type type, final Void ignored) { 2396219019Sgabor if (!type.isIntersection()) { 2397219019Sgabor final Type sup = supertype(type); 2398219019Sgabor return (sup == Type.noType || sup == type || sup == null) 2399219019Sgabor ? interfaces(type) 2400219019Sgabor : interfaces(type).prepend(sup); 2401219019Sgabor } else { 2402219019Sgabor return visitIntersectionType((IntersectionClassType) type); 2403219019Sgabor } 2404219019Sgabor } 2405219019Sgabor 2406219019Sgabor private List<Type> visitIntersectionType(final IntersectionClassType it) { 2407219019Sgabor return it.getExplicitComponents(); 2408219019Sgabor } 2409219019Sgabor 2410219019Sgabor }; 2411219019Sgabor 2412219019Sgabor public boolean isDirectSuperInterface(TypeSymbol isym, TypeSymbol origin) { 2413219019Sgabor for (Type i2 : interfaces(origin.type)) { 2414219019Sgabor if (isym == i2.tsym) return true; 2415219019Sgabor } 2416219019Sgabor return false; 2417219019Sgabor } 2418219019Sgabor // </editor-fold> 2419219019Sgabor 2420219019Sgabor // <editor-fold defaultstate="collapsed" desc="isDerivedRaw"> 2421219019Sgabor Map<Type,Boolean> isDerivedRawCache = new HashMap<>(); 2422219019Sgabor 2423219019Sgabor public boolean isDerivedRaw(Type t) { 2424219019Sgabor Boolean result = isDerivedRawCache.get(t); 2425219019Sgabor if (result == null) { 2426219019Sgabor result = isDerivedRawInternal(t); 2427219019Sgabor isDerivedRawCache.put(t, result); 2428219019Sgabor } 2429219019Sgabor return result; 2430219019Sgabor } 2431219019Sgabor 2432219019Sgabor public boolean isDerivedRawInternal(Type t) { 2433219019Sgabor if (t.isErroneous()) 2434219019Sgabor return false; 2435219019Sgabor return 2436219019Sgabor t.isRaw() || 2437219019Sgabor supertype(t) != Type.noType && isDerivedRaw(supertype(t)) || 2438219019Sgabor isDerivedRaw(interfaces(t)); 2439219019Sgabor } 2440219019Sgabor 2441219019Sgabor public boolean isDerivedRaw(List<Type> ts) { 2442219019Sgabor List<Type> l = ts; 2443219019Sgabor while (l.nonEmpty() && !isDerivedRaw(l.head)) l = l.tail; 2444219019Sgabor return l.nonEmpty(); 2445219019Sgabor } 2446219019Sgabor // </editor-fold> 2447219019Sgabor 2448219019Sgabor // <editor-fold defaultstate="collapsed" desc="setBounds"> 2449219019Sgabor /** 2450219019Sgabor * Same as {@link Types#setBounds(TypeVar, List, boolean)}, except that third parameter is computed directly, 2451219019Sgabor * as follows: if all all bounds are interface types, the computed supertype is Object,otherwise 2452219019Sgabor * the supertype is simply left null (in this case, the supertype is assumed to be the head of 2453219019Sgabor * the bound list passed as second argument). Note that this check might cause a symbol completion. 2454219019Sgabor * Hence, this version of setBounds may not be called during a classfile read. 2455219019Sgabor * 2456219019Sgabor * @param t a type variable 2457219019Sgabor * @param bounds the bounds, must be nonempty 2458219019Sgabor */ 2459219019Sgabor public void setBounds(TypeVar t, List<Type> bounds) { 2460219019Sgabor setBounds(t, bounds, bounds.head.tsym.isInterface()); 2461219019Sgabor } 2462219019Sgabor 2463219019Sgabor /** 2464219019Sgabor * Set the bounds field of the given type variable to reflect a (possibly multiple) list of bounds. 2465219019Sgabor * This does not cause symbol completion as an extra parameter indicates as to whether all bounds 2466219019Sgabor * are interfaces - in which case the supertype is implicitly assumed to be 'Object'. 2467219019Sgabor * 2468219019Sgabor * @param t a type variable 2469219019Sgabor * @param bounds the bounds, must be nonempty 2470219019Sgabor * @param allInterfaces are all bounds interface types? 2471219019Sgabor */ 2472219019Sgabor public void setBounds(TypeVar t, List<Type> bounds, boolean allInterfaces) { 2473219019Sgabor t.bound = bounds.tail.isEmpty() ? 2474219019Sgabor bounds.head : 2475219019Sgabor makeIntersectionType(bounds, allInterfaces); 2476219019Sgabor t.rank_field = -1; 2477219019Sgabor } 2478219019Sgabor // </editor-fold> 2479219019Sgabor 2480219019Sgabor // <editor-fold defaultstate="collapsed" desc="getBounds"> 2481219019Sgabor /** 2482219019Sgabor * Return list of bounds of the given type variable. 2483219019Sgabor */ 2484219019Sgabor public List<Type> getBounds(TypeVar t) { 2485219019Sgabor if (t.bound.hasTag(NONE)) 2486219019Sgabor return List.nil(); 2487219019Sgabor else if (t.bound.isErroneous() || !t.bound.isCompound()) 2488219019Sgabor return List.of(t.bound); 2489219019Sgabor else if ((erasure(t).tsym.flags() & INTERFACE) == 0) 2490219019Sgabor return interfaces(t).prepend(supertype(t)); 2491219019Sgabor else 2492219019Sgabor // No superclass was given in bounds. 2493219019Sgabor // In this case, supertype is Object, erasure is first interface. 2494219019Sgabor return interfaces(t); 2495219019Sgabor } 2496219019Sgabor // </editor-fold> 2497219019Sgabor 2498219019Sgabor // <editor-fold defaultstate="collapsed" desc="classBound"> 2499219019Sgabor /** 2500219019Sgabor * If the given type is a (possibly selected) type variable, 2501219019Sgabor * return the bounding class of this type, otherwise return the 2502219019Sgabor * type itself. 2503219019Sgabor */ 2504219019Sgabor public Type classBound(Type t) { 2505219019Sgabor return classBound.visit(t); 2506219019Sgabor } 2507219019Sgabor // where 2508219019Sgabor private UnaryVisitor<Type> classBound = new UnaryVisitor<Type>() { 2509219019Sgabor 2510219019Sgabor public Type visitType(Type t, Void ignored) { 2511219019Sgabor return t; 2512219019Sgabor } 2513219019Sgabor 2514219019Sgabor @Override 2515219019Sgabor public Type visitClassType(ClassType t, Void ignored) { 2516219019Sgabor Type outer1 = classBound(t.getEnclosingType()); 2517219019Sgabor if (outer1 != t.getEnclosingType()) 2518219019Sgabor return new ClassType(outer1, t.getTypeArguments(), t.tsym, 2519219019Sgabor t.getMetadata()); 2520219019Sgabor else 2521219019Sgabor return t; 2522219019Sgabor } 2523219019Sgabor 2524219019Sgabor @Override 2525219019Sgabor public Type visitTypeVar(TypeVar t, Void ignored) { 2526219019Sgabor return classBound(supertype(t)); 2527219019Sgabor } 2528219019Sgabor 2529219019Sgabor @Override 2530219019Sgabor public Type visitErrorType(ErrorType t, Void ignored) { 2531219019Sgabor return t; 2532219019Sgabor } 2533219019Sgabor }; 2534219019Sgabor // </editor-fold> 2535219019Sgabor 2536219019Sgabor // <editor-fold defaultstate="collapsed" desc="sub signature / override equivalence"> 2537219019Sgabor /** 2538219019Sgabor * Returns true iff the first signature is a <em>sub 2539219019Sgabor * signature</em> of the other. This is <b>not</b> an equivalence 2540219019Sgabor * relation. 2541219019Sgabor * 2542219019Sgabor * @jls section 8.4.2. 2543219019Sgabor * @see #overrideEquivalent(Type t, Type s) 2544219019Sgabor * @param t first signature (possibly raw). 2545219019Sgabor * @param s second signature (could be subjected to erasure). 2546219019Sgabor * @return true if t is a sub signature of s. 2547219019Sgabor */ 2548219019Sgabor public boolean isSubSignature(Type t, Type s) { 2549219019Sgabor return isSubSignature(t, s, true); 2550219019Sgabor } 2551219019Sgabor 2552219019Sgabor public boolean isSubSignature(Type t, Type s, boolean strict) { 2553219019Sgabor return hasSameArgs(t, s, strict) || hasSameArgs(t, erasure(s), strict); 2554219019Sgabor } 2555219019Sgabor 2556219019Sgabor /** 2557219019Sgabor * Returns true iff these signatures are related by <em>override 2558219019Sgabor * equivalence</em>. This is the natural extension of 2559219019Sgabor * isSubSignature to an equivalence relation. 2560219019Sgabor * 2561219019Sgabor * @jls section 8.4.2. 2562219019Sgabor * @see #isSubSignature(Type t, Type s) 2563219019Sgabor * @param t a signature (possible raw, could be subjected to 2564219019Sgabor * erasure). 2565219019Sgabor * @param s a signature (possible raw, could be subjected to 2566219019Sgabor * erasure). 2567219019Sgabor * @return true if either argument is a sub signature of the other. 2568219019Sgabor */ 2569219019Sgabor public boolean overrideEquivalent(Type t, Type s) { 2570219019Sgabor return hasSameArgs(t, s) || 2571219019Sgabor hasSameArgs(t, erasure(s)) || hasSameArgs(erasure(t), s); 2572219019Sgabor } 2573219019Sgabor 2574219019Sgabor public boolean overridesObjectMethod(TypeSymbol origin, Symbol msym) { 2575219019Sgabor for (Symbol sym : syms.objectType.tsym.members().getSymbolsByName(msym.name)) { 2576219019Sgabor if (msym.overrides(sym, origin, Types.this, true)) { 2577219019Sgabor return true; 2578219019Sgabor } 2579219019Sgabor } 2580219019Sgabor return false; 2581219019Sgabor } 2582219019Sgabor 2583219019Sgabor // <editor-fold defaultstate="collapsed" desc="Determining method implementation in given site"> 2584219019Sgabor class ImplementationCache { 2585219019Sgabor 2586219019Sgabor private WeakHashMap<MethodSymbol, SoftReference<Map<TypeSymbol, Entry>>> _map = new WeakHashMap<>(); 2587219019Sgabor 2588219019Sgabor class Entry { 2589219019Sgabor final MethodSymbol cachedImpl; 2590219019Sgabor final Filter<Symbol> implFilter; 2591219019Sgabor final boolean checkResult; 2592219019Sgabor final int prevMark; 2593219019Sgabor 2594219019Sgabor public Entry(MethodSymbol cachedImpl, 2595219019Sgabor Filter<Symbol> scopeFilter, 2596219019Sgabor boolean checkResult, 2597219019Sgabor int prevMark) { 2598219019Sgabor this.cachedImpl = cachedImpl; 2599219019Sgabor this.implFilter = scopeFilter; 2600219019Sgabor this.checkResult = checkResult; 2601219019Sgabor this.prevMark = prevMark; 2602219019Sgabor } 2603219019Sgabor 2604219019Sgabor boolean matches(Filter<Symbol> scopeFilter, boolean checkResult, int mark) { 2605219019Sgabor return this.implFilter == scopeFilter && 2606219019Sgabor this.checkResult == checkResult && 2607219019Sgabor this.prevMark == mark; 2608219019Sgabor } 2609219019Sgabor } 2610219019Sgabor 2611219019Sgabor MethodSymbol get(MethodSymbol ms, TypeSymbol origin, boolean checkResult, Filter<Symbol> implFilter) { 2612219019Sgabor SoftReference<Map<TypeSymbol, Entry>> ref_cache = _map.get(ms); 2613219019Sgabor Map<TypeSymbol, Entry> cache = ref_cache != null ? ref_cache.get() : null; 2614219019Sgabor if (cache == null) { 2615219019Sgabor cache = new HashMap<>(); 2616219019Sgabor _map.put(ms, new SoftReference<>(cache)); 2617219019Sgabor } 2618219019Sgabor Entry e = cache.get(origin); 2619219019Sgabor CompoundScope members = membersClosure(origin.type, true); 2620219019Sgabor if (e == null || 2621219019Sgabor !e.matches(implFilter, checkResult, members.getMark())) { 2622219019Sgabor MethodSymbol impl = implementationInternal(ms, origin, checkResult, implFilter); 2623219019Sgabor cache.put(origin, new Entry(impl, implFilter, checkResult, members.getMark())); 2624219019Sgabor return impl; 2625219019Sgabor } 2626219019Sgabor else { 2627219019Sgabor return e.cachedImpl; 2628219019Sgabor } 2629219019Sgabor } 2630219019Sgabor 2631219019Sgabor private MethodSymbol implementationInternal(MethodSymbol ms, TypeSymbol origin, boolean checkResult, Filter<Symbol> implFilter) { 2632219019Sgabor for (Type t = origin.type; t.hasTag(CLASS) || t.hasTag(TYPEVAR); t = supertype(t)) { 2633219019Sgabor t = skipTypeVars(t, false); 2634219019Sgabor TypeSymbol c = t.tsym; 2635219019Sgabor Symbol bestSoFar = null; 2636219019Sgabor for (Symbol sym : c.members().getSymbolsByName(ms.name, implFilter)) { 2637219019Sgabor if (sym != null && sym.overrides(ms, origin, Types.this, checkResult)) { 2638219019Sgabor bestSoFar = sym; 2639219019Sgabor if ((sym.flags() & ABSTRACT) == 0) { 2640219019Sgabor //if concrete impl is found, exit immediately 2641219019Sgabor break; 2642219019Sgabor } 2643219019Sgabor } 2644219019Sgabor } 2645219019Sgabor if (bestSoFar != null) { 2646219019Sgabor //return either the (only) concrete implementation or the first abstract one 2647219019Sgabor return (MethodSymbol)bestSoFar; 2648219019Sgabor } 2649219019Sgabor } 2650219019Sgabor return null; 2651219019Sgabor } 2652219019Sgabor } 2653219019Sgabor 2654219019Sgabor private ImplementationCache implCache = new ImplementationCache(); 2655219019Sgabor 2656219019Sgabor public MethodSymbol implementation(MethodSymbol ms, TypeSymbol origin, boolean checkResult, Filter<Symbol> implFilter) { 2657219019Sgabor return implCache.get(ms, origin, checkResult, implFilter); 2658219019Sgabor } 2659219019Sgabor // </editor-fold> 2660219019Sgabor 2661219019Sgabor // <editor-fold defaultstate="collapsed" desc="compute transitive closure of all members in given site"> 2662219019Sgabor class MembersClosureCache extends SimpleVisitor<CompoundScope, Boolean> { 2663219019Sgabor 2664219019Sgabor private WeakHashMap<TypeSymbol, Entry> _map = new WeakHashMap<>(); 2665219019Sgabor 2666219019Sgabor class Entry { 2667219019Sgabor final boolean skipInterfaces; 2668219019Sgabor final CompoundScope compoundScope; 2669219019Sgabor 2670219019Sgabor public Entry(boolean skipInterfaces, CompoundScope compoundScope) { 2671219019Sgabor this.skipInterfaces = skipInterfaces; 2672219019Sgabor this.compoundScope = compoundScope; 2673219019Sgabor } 2674219019Sgabor 2675219019Sgabor boolean matches(boolean skipInterfaces) { 2676219019Sgabor return this.skipInterfaces == skipInterfaces; 2677219019Sgabor } 2678219019Sgabor } 2679219019Sgabor 2680219019Sgabor List<TypeSymbol> seenTypes = List.nil(); 2681219019Sgabor 2682219019Sgabor /** members closure visitor methods **/ 2683219019Sgabor 2684219019Sgabor public CompoundScope visitType(Type t, Boolean skipInterface) { 2685219019Sgabor return null; 2686219019Sgabor } 2687219019Sgabor 2688219019Sgabor @Override 2689219019Sgabor public CompoundScope visitClassType(ClassType t, Boolean skipInterface) { 2690219019Sgabor if (seenTypes.contains(t.tsym)) { 2691219019Sgabor //this is possible when an interface is implemented in multiple 2692219019Sgabor //superclasses, or when a classs hierarchy is circular - in such 2693219019Sgabor //cases we don't need to recurse (empty scope is returned) 2694219019Sgabor return new CompoundScope(t.tsym); 2695219019Sgabor } 2696219019Sgabor try { 2697219019Sgabor seenTypes = seenTypes.prepend(t.tsym); 2698219019Sgabor ClassSymbol csym = (ClassSymbol)t.tsym; 2699219019Sgabor Entry e = _map.get(csym); 2700219019Sgabor if (e == null || !e.matches(skipInterface)) { 2701219019Sgabor CompoundScope membersClosure = new CompoundScope(csym); 2702219019Sgabor if (!skipInterface) { 2703219019Sgabor for (Type i : interfaces(t)) { 2704219019Sgabor membersClosure.prependSubScope(visit(i, skipInterface)); 2705219019Sgabor } 2706219019Sgabor } 2707219019Sgabor membersClosure.prependSubScope(visit(supertype(t), skipInterface)); 2708219019Sgabor membersClosure.prependSubScope(csym.members()); 2709219019Sgabor e = new Entry(skipInterface, membersClosure); 2710219019Sgabor _map.put(csym, e); 2711219019Sgabor } 2712219019Sgabor return e.compoundScope; 2713219019Sgabor } 2714219019Sgabor finally { 2715219019Sgabor seenTypes = seenTypes.tail; 2716219019Sgabor } 2717219019Sgabor } 2718219019Sgabor 2719219019Sgabor @Override 2720219019Sgabor public CompoundScope visitTypeVar(TypeVar t, Boolean skipInterface) { 2721219019Sgabor return visit(t.getUpperBound(), skipInterface); 2722219019Sgabor } 2723219019Sgabor } 2724219019Sgabor 2725219019Sgabor private MembersClosureCache membersCache = new MembersClosureCache(); 2726219019Sgabor 2727219019Sgabor public CompoundScope membersClosure(Type site, boolean skipInterface) { 2728219019Sgabor return membersCache.visit(site, skipInterface); 2729219019Sgabor } 2730219019Sgabor // </editor-fold> 2731219019Sgabor 2732219019Sgabor 2733219019Sgabor /** Return first abstract member of class `sym'. 2734219019Sgabor */ 2735219019Sgabor public MethodSymbol firstUnimplementedAbstract(ClassSymbol sym) { 2736219019Sgabor try { 2737219019Sgabor return firstUnimplementedAbstractImpl(sym, sym); 2738219019Sgabor } catch (CompletionFailure ex) { 2739219019Sgabor chk.completionError(enter.getEnv(sym).tree.pos(), ex); 2740219019Sgabor return null; 2741219019Sgabor } 2742219019Sgabor } 2743219019Sgabor //where: 2744219019Sgabor private MethodSymbol firstUnimplementedAbstractImpl(ClassSymbol impl, ClassSymbol c) { 2745219019Sgabor MethodSymbol undef = null; 2746219019Sgabor // Do not bother to search in classes that are not abstract, 2747219019Sgabor // since they cannot have abstract members. 2748219019Sgabor if (c == impl || (c.flags() & (ABSTRACT | INTERFACE)) != 0) { 2749219019Sgabor Scope s = c.members(); 2750219019Sgabor for (Symbol sym : s.getSymbols(NON_RECURSIVE)) { 2751219019Sgabor if (sym.kind == MTH && 2752219019Sgabor (sym.flags() & (ABSTRACT|IPROXY|DEFAULT)) == ABSTRACT) { 2753219019Sgabor MethodSymbol absmeth = (MethodSymbol)sym; 2754219019Sgabor MethodSymbol implmeth = absmeth.implementation(impl, this, true); 2755219019Sgabor if (implmeth == null || implmeth == absmeth) { 2756219019Sgabor //look for default implementations 2757219019Sgabor if (allowDefaultMethods) { 2758219019Sgabor MethodSymbol prov = interfaceCandidates(impl.type, absmeth).head; 2759219019Sgabor if (prov != null && prov.overrides(absmeth, impl, this, true)) { 2760219019Sgabor implmeth = prov; 2761219019Sgabor } 2762219019Sgabor } 2763219019Sgabor } 2764219019Sgabor if (implmeth == null || implmeth == absmeth) { 2765219019Sgabor undef = absmeth; 2766219019Sgabor break; 2767219019Sgabor } 2768219019Sgabor } 2769219019Sgabor } 2770219019Sgabor if (undef == null) { 2771219019Sgabor Type st = supertype(c.type); 2772219019Sgabor if (st.hasTag(CLASS)) 2773219019Sgabor undef = firstUnimplementedAbstractImpl(impl, (ClassSymbol)st.tsym); 2774219019Sgabor } 2775219019Sgabor for (List<Type> l = interfaces(c.type); 2776219019Sgabor undef == null && l.nonEmpty(); 2777219019Sgabor l = l.tail) { 2778219019Sgabor undef = firstUnimplementedAbstractImpl(impl, (ClassSymbol)l.head.tsym); 2779219019Sgabor } 2780219019Sgabor } 2781219019Sgabor return undef; 2782219019Sgabor } 2783219019Sgabor 2784219019Sgabor 2785219019Sgabor //where 2786219019Sgabor public List<MethodSymbol> interfaceCandidates(Type site, MethodSymbol ms) { 2787219019Sgabor Filter<Symbol> filter = new MethodFilter(ms, site); 2788219019Sgabor List<MethodSymbol> candidates = List.nil(); 2789219019Sgabor for (Symbol s : membersClosure(site, false).getSymbols(filter)) { 2790219019Sgabor if (!site.tsym.isInterface() && !s.owner.isInterface()) { 2791219019Sgabor return List.of((MethodSymbol)s); 2792219019Sgabor } else if (!candidates.contains(s)) { 2793219019Sgabor candidates = candidates.prepend((MethodSymbol)s); 2794219019Sgabor } 2795219019Sgabor } 2796219019Sgabor return prune(candidates); 2797219019Sgabor } 2798219019Sgabor 2799219019Sgabor public List<MethodSymbol> prune(List<MethodSymbol> methods) { 2800219019Sgabor ListBuffer<MethodSymbol> methodsMin = new ListBuffer<>(); 2801219019Sgabor for (MethodSymbol m1 : methods) { 2802219019Sgabor boolean isMin_m1 = true; 2803219019Sgabor for (MethodSymbol m2 : methods) { 2804219019Sgabor if (m1 == m2) continue; 2805219019Sgabor if (m2.owner != m1.owner && 2806219019Sgabor asSuper(m2.owner.type, m1.owner) != null) { 2807219019Sgabor isMin_m1 = false; 2808219019Sgabor break; 2809219019Sgabor } 2810219019Sgabor } 2811219019Sgabor if (isMin_m1) 2812219019Sgabor methodsMin.append(m1); 2813219019Sgabor } 2814219019Sgabor return methodsMin.toList(); 2815219019Sgabor } 2816219019Sgabor // where 2817219019Sgabor private class MethodFilter implements Filter<Symbol> { 2818219019Sgabor 2819219019Sgabor Symbol msym; 2820219019Sgabor Type site; 2821219019Sgabor 2822219019Sgabor MethodFilter(Symbol msym, Type site) { 2823219019Sgabor this.msym = msym; 2824219019Sgabor this.site = site; 2825219019Sgabor } 2826219019Sgabor 2827219019Sgabor public boolean accepts(Symbol s) { 2828219019Sgabor return s.kind == MTH && 2829219019Sgabor s.name == msym.name && 2830219019Sgabor (s.flags() & SYNTHETIC) == 0 && 2831219019Sgabor s.isInheritedIn(site.tsym, Types.this) && 2832219019Sgabor overrideEquivalent(memberType(site, s), memberType(site, msym)); 2833219019Sgabor } 2834219019Sgabor } 2835219019Sgabor // </editor-fold> 2836219019Sgabor 2837219019Sgabor /** 2838219019Sgabor * Does t have the same arguments as s? It is assumed that both 2839219019Sgabor * types are (possibly polymorphic) method types. Monomorphic 2840219019Sgabor * method types "have the same arguments", if their argument lists 2841219019Sgabor * are equal. Polymorphic method types "have the same arguments", 2842219019Sgabor * if they have the same arguments after renaming all type 2843219019Sgabor * variables of one to corresponding type variables in the other, 2844219019Sgabor * where correspondence is by position in the type parameter list. 2845219019Sgabor */ 2846219019Sgabor public boolean hasSameArgs(Type t, Type s) { 2847219019Sgabor return hasSameArgs(t, s, true); 2848219019Sgabor } 2849219019Sgabor 2850219019Sgabor public boolean hasSameArgs(Type t, Type s, boolean strict) { 2851219019Sgabor return hasSameArgs(t, s, strict ? hasSameArgs_strict : hasSameArgs_nonstrict); 2852219019Sgabor } 2853219019Sgabor 2854219019Sgabor private boolean hasSameArgs(Type t, Type s, TypeRelation hasSameArgs) { 2855219019Sgabor return hasSameArgs.visit(t, s); 2856219019Sgabor } 2857219019Sgabor // where 2858219019Sgabor private class HasSameArgs extends TypeRelation { 2859219019Sgabor 2860219019Sgabor boolean strict; 2861219019Sgabor 2862219019Sgabor public HasSameArgs(boolean strict) { 2863219019Sgabor this.strict = strict; 2864219019Sgabor } 2865219019Sgabor 2866219019Sgabor public Boolean visitType(Type t, Type s) { 2867219019Sgabor throw new AssertionError(); 2868219019Sgabor } 2869219019Sgabor 2870219019Sgabor @Override 2871219019Sgabor public Boolean visitMethodType(MethodType t, Type s) { 2872219019Sgabor return s.hasTag(METHOD) 2873219019Sgabor && containsTypeEquivalent(t.argtypes, s.getParameterTypes()); 2874219019Sgabor } 2875219019Sgabor 2876219019Sgabor @Override 2877219019Sgabor public Boolean visitForAll(ForAll t, Type s) { 2878219019Sgabor if (!s.hasTag(FORALL)) 2879219019Sgabor return strict ? false : visitMethodType(t.asMethodType(), s); 2880219019Sgabor 2881219019Sgabor ForAll forAll = (ForAll)s; 2882219019Sgabor return hasSameBounds(t, forAll) 2883219019Sgabor && visit(t.qtype, subst(forAll.qtype, forAll.tvars, t.tvars)); 2884219019Sgabor } 2885219019Sgabor 2886219019Sgabor @Override 2887219019Sgabor public Boolean visitErrorType(ErrorType t, Type s) { 2888219019Sgabor return false; 2889219019Sgabor } 2890219019Sgabor } 2891219019Sgabor 2892219019Sgabor TypeRelation hasSameArgs_strict = new HasSameArgs(true); 2893219019Sgabor TypeRelation hasSameArgs_nonstrict = new HasSameArgs(false); 2894219019Sgabor 2895219019Sgabor // </editor-fold> 2896219019Sgabor 2897219019Sgabor // <editor-fold defaultstate="collapsed" desc="subst"> 2898219019Sgabor public List<Type> subst(List<Type> ts, 2899219019Sgabor List<Type> from, 2900219019Sgabor List<Type> to) { 2901219019Sgabor return ts.map(new Subst(from, to)); 2902219019Sgabor } 2903219019Sgabor 2904219019Sgabor /** 2905219019Sgabor * Substitute all occurrences of a type in `from' with the 2906219019Sgabor * corresponding type in `to' in 't'. Match lists `from' and `to' 2907219019Sgabor * from the right: If lists have different length, discard leading 2908219019Sgabor * elements of the longer list. 2909219019Sgabor */ 2910219019Sgabor public Type subst(Type t, List<Type> from, List<Type> to) { 2911219019Sgabor return t.map(new Subst(from, to)); 2912219019Sgabor } 2913219019Sgabor 2914219019Sgabor private class Subst extends TypeMapping<Void> { 2915219019Sgabor List<Type> from; 2916219019Sgabor List<Type> to; 2917219019Sgabor 2918219019Sgabor public Subst(List<Type> from, List<Type> to) { 2919219019Sgabor int fromLength = from.length(); 2920219019Sgabor int toLength = to.length(); 2921219019Sgabor while (fromLength > toLength) { 2922219019Sgabor fromLength--; 2923219019Sgabor from = from.tail; 2924219019Sgabor } 2925219019Sgabor while (fromLength < toLength) { 2926219019Sgabor toLength--; 2927219019Sgabor to = to.tail; 2928219019Sgabor } 2929219019Sgabor this.from = from; 2930219019Sgabor this.to = to; 2931219019Sgabor } 2932219019Sgabor 2933219019Sgabor @Override 2934219019Sgabor public Type visitTypeVar(TypeVar t, Void ignored) { 2935219019Sgabor for (List<Type> from = this.from, to = this.to; 2936219019Sgabor from.nonEmpty(); 2937219019Sgabor from = from.tail, to = to.tail) { 2938219019Sgabor if (t.equalsIgnoreMetadata(from.head)) { 2939219019Sgabor return to.head.withTypeVar(t); 2940219019Sgabor } 2941219019Sgabor } 2942219019Sgabor return t; 2943219019Sgabor } 2944219019Sgabor 2945219019Sgabor @Override 2946219019Sgabor public Type visitClassType(ClassType t, Void ignored) { 2947219019Sgabor if (!t.isCompound()) { 2948219019Sgabor return super.visitClassType(t, ignored); 2949219019Sgabor } else { 2950219019Sgabor Type st = visit(supertype(t)); 2951219019Sgabor List<Type> is = visit(interfaces(t), ignored); 2952219019Sgabor if (st == supertype(t) && is == interfaces(t)) 2953219019Sgabor return t; 2954219019Sgabor else 2955219019Sgabor return makeIntersectionType(is.prepend(st)); 2956219019Sgabor } 2957219019Sgabor } 2958219019Sgabor 2959219019Sgabor @Override 2960219019Sgabor public Type visitWildcardType(WildcardType t, Void ignored) { 2961219019Sgabor WildcardType t2 = (WildcardType)super.visitWildcardType(t, ignored); 2962219019Sgabor if (t2 != t && t.isExtendsBound() && t2.type.isExtendsBound()) { 2963219019Sgabor t2.type = wildUpperBound(t2.type); 2964219019Sgabor } 2965219019Sgabor return t2; 2966219019Sgabor } 2967219019Sgabor 2968219019Sgabor @Override 2969219019Sgabor public Type visitForAll(ForAll t, Void ignored) { 2970219019Sgabor if (Type.containsAny(to, t.tvars)) { 2971219019Sgabor //perform alpha-renaming of free-variables in 't' 2972219019Sgabor //if 'to' types contain variables that are free in 't' 2973219019Sgabor List<Type> freevars = newInstances(t.tvars); 2974219019Sgabor t = new ForAll(freevars, 2975219019Sgabor Types.this.subst(t.qtype, t.tvars, freevars)); 2976219019Sgabor } 2977219019Sgabor List<Type> tvars1 = substBounds(t.tvars, from, to); 2978219019Sgabor Type qtype1 = visit(t.qtype); 2979219019Sgabor if (tvars1 == t.tvars && qtype1 == t.qtype) { 2980219019Sgabor return t; 2981219019Sgabor } else if (tvars1 == t.tvars) { 2982219019Sgabor return new ForAll(tvars1, qtype1) { 2983219019Sgabor @Override 2984219019Sgabor public boolean needsStripping() { 2985219019Sgabor return true; 2986219019Sgabor } 2987219019Sgabor }; 2988219019Sgabor } else { 2989219019Sgabor return new ForAll(tvars1, Types.this.subst(qtype1, t.tvars, tvars1)) { 2990219019Sgabor @Override 2991219019Sgabor public boolean needsStripping() { 2992219019Sgabor return true; 2993219019Sgabor } 2994219019Sgabor }; 2995219019Sgabor } 2996219019Sgabor } 2997219019Sgabor } 2998219019Sgabor 2999219019Sgabor public List<Type> substBounds(List<Type> tvars, 3000219019Sgabor List<Type> from, 3001219019Sgabor List<Type> to) { 3002219019Sgabor if (tvars.isEmpty()) 3003219019Sgabor return tvars; 3004219019Sgabor ListBuffer<Type> newBoundsBuf = new ListBuffer<>(); 3005219019Sgabor boolean changed = false; 3006219019Sgabor // calculate new bounds 3007219019Sgabor for (Type t : tvars) { 3008219019Sgabor TypeVar tv = (TypeVar) t; 3009219019Sgabor Type bound = subst(tv.bound, from, to); 3010219019Sgabor if (bound != tv.bound) 3011219019Sgabor changed = true; 3012219019Sgabor newBoundsBuf.append(bound); 3013219019Sgabor } 3014219019Sgabor if (!changed) 3015219019Sgabor return tvars; 3016219019Sgabor ListBuffer<Type> newTvars = new ListBuffer<>(); 3017219019Sgabor // create new type variables without bounds 3018219019Sgabor for (Type t : tvars) { 3019219019Sgabor newTvars.append(new TypeVar(t.tsym, null, syms.botType, 3020219019Sgabor t.getMetadata())); 3021219019Sgabor } 3022219019Sgabor // the new bounds should use the new type variables in place 3023219019Sgabor // of the old 3024219019Sgabor List<Type> newBounds = newBoundsBuf.toList(); 3025219019Sgabor from = tvars; 3026219019Sgabor to = newTvars.toList(); 3027219019Sgabor for (; !newBounds.isEmpty(); newBounds = newBounds.tail) { 3028219019Sgabor newBounds.head = subst(newBounds.head, from, to); 3029219019Sgabor } 3030219019Sgabor newBounds = newBoundsBuf.toList(); 3031219019Sgabor // set the bounds of new type variables to the new bounds 3032219019Sgabor for (Type t : newTvars.toList()) { 3033219019Sgabor TypeVar tv = (TypeVar) t; 3034219019Sgabor tv.bound = newBounds.head; 3035219019Sgabor newBounds = newBounds.tail; 3036219019Sgabor } 3037219019Sgabor return newTvars.toList(); 3038219019Sgabor } 3039219019Sgabor 3040219019Sgabor public TypeVar substBound(TypeVar t, List<Type> from, List<Type> to) { 3041219019Sgabor Type bound1 = subst(t.bound, from, to); 3042219019Sgabor if (bound1 == t.bound) 3043219019Sgabor return t; 3044219019Sgabor else { 3045219019Sgabor // create new type variable without bounds 3046219019Sgabor TypeVar tv = new TypeVar(t.tsym, null, syms.botType, 3047219019Sgabor t.getMetadata()); 3048219019Sgabor // the new bound should use the new type variable in place 3049219019Sgabor // of the old 3050219019Sgabor tv.bound = subst(bound1, List.<Type>of(t), List.<Type>of(tv)); 3051219019Sgabor return tv; 3052219019Sgabor } 3053219019Sgabor } 3054219019Sgabor // </editor-fold> 3055219019Sgabor 3056219019Sgabor // <editor-fold defaultstate="collapsed" desc="hasSameBounds"> 3057219019Sgabor /** 3058219019Sgabor * Does t have the same bounds for quantified variables as s? 3059219019Sgabor */ 3060219019Sgabor public boolean hasSameBounds(ForAll t, ForAll s) { 3061219019Sgabor List<Type> l1 = t.tvars; 3062219019Sgabor List<Type> l2 = s.tvars; 3063219019Sgabor while (l1.nonEmpty() && l2.nonEmpty() && 3064219019Sgabor isSameType(l1.head.getUpperBound(), 3065219019Sgabor subst(l2.head.getUpperBound(), 3066219019Sgabor s.tvars, 3067219019Sgabor t.tvars))) { 3068219019Sgabor l1 = l1.tail; 3069219019Sgabor l2 = l2.tail; 3070219019Sgabor } 3071219019Sgabor return l1.isEmpty() && l2.isEmpty(); 3072219019Sgabor } 3073219019Sgabor // </editor-fold> 3074219019Sgabor 3075219019Sgabor // <editor-fold defaultstate="collapsed" desc="newInstances"> 3076219019Sgabor /** Create new vector of type variables from list of variables 3077219019Sgabor * changing all recursive bounds from old to new list. 3078219019Sgabor */ 3079219019Sgabor public List<Type> newInstances(List<Type> tvars) { 3080219019Sgabor List<Type> tvars1 = tvars.map(newInstanceFun); 3081219019Sgabor for (List<Type> l = tvars1; l.nonEmpty(); l = l.tail) { 3082219019Sgabor TypeVar tv = (TypeVar) l.head; 3083219019Sgabor tv.bound = subst(tv.bound, tvars, tvars1); 3084219019Sgabor } 3085219019Sgabor return tvars1; 3086219019Sgabor } 3087219019Sgabor private static final TypeMapping<Void> newInstanceFun = new TypeMapping<Void>() { 3088219019Sgabor @Override 3089219019Sgabor public TypeVar visitTypeVar(TypeVar t, Void _unused) { 3090219019Sgabor return new TypeVar(t.tsym, t.getUpperBound(), t.getLowerBound(), t.getMetadata()); 3091219019Sgabor } 3092219019Sgabor }; 3093219019Sgabor // </editor-fold> 3094219019Sgabor 3095219019Sgabor public Type createMethodTypeWithParameters(Type original, List<Type> newParams) { 3096219019Sgabor return original.accept(methodWithParameters, newParams); 3097219019Sgabor } 3098219019Sgabor // where 3099219019Sgabor private final MapVisitor<List<Type>> methodWithParameters = new MapVisitor<List<Type>>() { 3100219019Sgabor public Type visitType(Type t, List<Type> newParams) { 3101219019Sgabor throw new IllegalArgumentException("Not a method type: " + t); 3102219019Sgabor } 3103219019Sgabor public Type visitMethodType(MethodType t, List<Type> newParams) { 3104219019Sgabor return new MethodType(newParams, t.restype, t.thrown, t.tsym); 3105219019Sgabor } 3106219019Sgabor public Type visitForAll(ForAll t, List<Type> newParams) { 3107219019Sgabor return new ForAll(t.tvars, t.qtype.accept(this, newParams)); 3108219019Sgabor } 3109219019Sgabor }; 3110219019Sgabor 3111219019Sgabor public Type createMethodTypeWithThrown(Type original, List<Type> newThrown) { 3112219019Sgabor return original.accept(methodWithThrown, newThrown); 3113219019Sgabor } 3114219019Sgabor // where 3115219019Sgabor private final MapVisitor<List<Type>> methodWithThrown = new MapVisitor<List<Type>>() { 3116219019Sgabor public Type visitType(Type t, List<Type> newThrown) { 3117219019Sgabor throw new IllegalArgumentException("Not a method type: " + t); 3118219019Sgabor } 3119219019Sgabor public Type visitMethodType(MethodType t, List<Type> newThrown) { 3120219019Sgabor return new MethodType(t.argtypes, t.restype, newThrown, t.tsym); 3121219019Sgabor } 3122219019Sgabor public Type visitForAll(ForAll t, List<Type> newThrown) { 3123219019Sgabor return new ForAll(t.tvars, t.qtype.accept(this, newThrown)); 3124219019Sgabor } 3125219019Sgabor }; 3126219019Sgabor 3127219019Sgabor public Type createMethodTypeWithReturn(Type original, Type newReturn) { 3128219019Sgabor return original.accept(methodWithReturn, newReturn); 3129219019Sgabor } 3130219019Sgabor // where 3131219019Sgabor private final MapVisitor<Type> methodWithReturn = new MapVisitor<Type>() { 3132219019Sgabor public Type visitType(Type t, Type newReturn) { 3133219019Sgabor throw new IllegalArgumentException("Not a method type: " + t); 3134219019Sgabor } 3135219019Sgabor public Type visitMethodType(MethodType t, Type newReturn) { 3136219019Sgabor return new MethodType(t.argtypes, newReturn, t.thrown, t.tsym); 3137219019Sgabor } 3138219019Sgabor public Type visitForAll(ForAll t, Type newReturn) { 3139219019Sgabor return new ForAll(t.tvars, t.qtype.accept(this, newReturn)); 3140219019Sgabor } 3141219019Sgabor }; 3142219019Sgabor 3143219019Sgabor // <editor-fold defaultstate="collapsed" desc="createErrorType"> 3144219019Sgabor public Type createErrorType(Type originalType) { 3145219019Sgabor return new ErrorType(originalType, syms.errSymbol); 3146219019Sgabor } 3147219019Sgabor 3148219019Sgabor public Type createErrorType(ClassSymbol c, Type originalType) { 3149219019Sgabor return new ErrorType(c, originalType); 3150219019Sgabor } 3151219019Sgabor 3152219019Sgabor public Type createErrorType(Name name, TypeSymbol container, Type originalType) { 3153219019Sgabor return new ErrorType(name, container, originalType); 3154219019Sgabor } 3155219019Sgabor // </editor-fold> 3156219019Sgabor 3157219019Sgabor // <editor-fold defaultstate="collapsed" desc="rank"> 3158219019Sgabor /** 3159219019Sgabor * The rank of a class is the length of the longest path between 3160219019Sgabor * the class and java.lang.Object in the class inheritance 3161219019Sgabor * graph. Undefined for all but reference types. 3162219019Sgabor */ 3163219019Sgabor public int rank(Type t) { 3164219019Sgabor switch(t.getTag()) { 3165219019Sgabor case CLASS: { 3166219019Sgabor ClassType cls = (ClassType)t; 3167219019Sgabor if (cls.rank_field < 0) { 3168219019Sgabor Name fullname = cls.tsym.getQualifiedName(); 3169219019Sgabor if (fullname == names.java_lang_Object) 3170219019Sgabor cls.rank_field = 0; 3171219019Sgabor else { 3172219019Sgabor int r = rank(supertype(cls)); 3173219019Sgabor for (List<Type> l = interfaces(cls); 3174219019Sgabor l.nonEmpty(); 3175219019Sgabor l = l.tail) { 3176219019Sgabor if (rank(l.head) > r) 3177219019Sgabor r = rank(l.head); 3178219019Sgabor } 3179219019Sgabor cls.rank_field = r + 1; 3180219019Sgabor } 3181219019Sgabor } 3182219019Sgabor return cls.rank_field; 3183219019Sgabor } 3184219019Sgabor case TYPEVAR: { 3185219019Sgabor TypeVar tvar = (TypeVar)t; 3186219019Sgabor if (tvar.rank_field < 0) { 3187219019Sgabor int r = rank(supertype(tvar)); 3188219019Sgabor for (List<Type> l = interfaces(tvar); 3189219019Sgabor l.nonEmpty(); 3190219019Sgabor l = l.tail) { 3191219019Sgabor if (rank(l.head) > r) r = rank(l.head); 3192219019Sgabor } 3193219019Sgabor tvar.rank_field = r + 1; 3194219019Sgabor } 3195219019Sgabor return tvar.rank_field; 3196219019Sgabor } 3197219019Sgabor case ERROR: 3198219019Sgabor case NONE: 3199219019Sgabor return 0; 3200219019Sgabor default: 3201219019Sgabor throw new AssertionError(); 3202219019Sgabor } 3203219019Sgabor } 3204219019Sgabor // </editor-fold> 3205219019Sgabor 3206219019Sgabor /** 3207219019Sgabor * Helper method for generating a string representation of a given type 3208219019Sgabor * accordingly to a given locale 3209219019Sgabor */ 3210219019Sgabor public String toString(Type t, Locale locale) { 3211219019Sgabor return Printer.createStandardPrinter(messages).visit(t, locale); 3212219019Sgabor } 3213219019Sgabor 3214219019Sgabor /** 3215219019Sgabor * Helper method for generating a string representation of a given type 3216219019Sgabor * accordingly to a given locale 3217219019Sgabor */ 3218219019Sgabor public String toString(Symbol t, Locale locale) { 3219219019Sgabor return Printer.createStandardPrinter(messages).visit(t, locale); 3220219019Sgabor } 3221219019Sgabor 3222219019Sgabor // <editor-fold defaultstate="collapsed" desc="toString"> 3223219019Sgabor /** 3224219019Sgabor * This toString is slightly more descriptive than the one on Type. 3225219019Sgabor * 3226219019Sgabor * @deprecated Types.toString(Type t, Locale l) provides better support 3227219019Sgabor * for localization 3228219019Sgabor */ 3229219019Sgabor @Deprecated 3230219019Sgabor public String toString(Type t) { 3231219019Sgabor if (t.hasTag(FORALL)) { 3232219019Sgabor ForAll forAll = (ForAll)t; 3233219019Sgabor return typaramsString(forAll.tvars) + forAll.qtype; 3234219019Sgabor } 3235219019Sgabor return "" + t; 3236219019Sgabor } 3237219019Sgabor // where 3238219019Sgabor private String typaramsString(List<Type> tvars) { 3239219019Sgabor StringBuilder s = new StringBuilder(); 3240219019Sgabor s.append('<'); 3241219019Sgabor boolean first = true; 3242219019Sgabor for (Type t : tvars) { 3243219019Sgabor if (!first) s.append(", "); 3244219019Sgabor first = false; 3245219019Sgabor appendTyparamString(((TypeVar)t), s); 3246219019Sgabor } 3247219019Sgabor s.append('>'); 3248219019Sgabor return s.toString(); 3249219019Sgabor } 3250219019Sgabor private void appendTyparamString(TypeVar t, StringBuilder buf) { 3251219019Sgabor buf.append(t); 3252219019Sgabor if (t.bound == null || 3253219019Sgabor t.bound.tsym.getQualifiedName() == names.java_lang_Object) 3254219019Sgabor return; 3255219019Sgabor buf.append(" extends "); // Java syntax; no need for i18n 3256219019Sgabor Type bound = t.bound; 3257219019Sgabor if (!bound.isCompound()) { 3258219019Sgabor buf.append(bound); 3259219019Sgabor } else if ((erasure(t).tsym.flags() & INTERFACE) == 0) { 3260219019Sgabor buf.append(supertype(t)); 3261219019Sgabor for (Type intf : interfaces(t)) { 3262219019Sgabor buf.append('&'); 3263219019Sgabor buf.append(intf); 3264219019Sgabor } 3265219019Sgabor } else { 3266219019Sgabor // No superclass was given in bounds. 3267219019Sgabor // In this case, supertype is Object, erasure is first interface. 3268219019Sgabor boolean first = true; 3269219019Sgabor for (Type intf : interfaces(t)) { 3270219019Sgabor if (!first) buf.append('&'); 3271219019Sgabor first = false; 3272219019Sgabor buf.append(intf); 3273219019Sgabor } 3274219019Sgabor } 3275219019Sgabor } 3276219019Sgabor // </editor-fold> 3277219019Sgabor 3278219019Sgabor // <editor-fold defaultstate="collapsed" desc="Determining least upper bounds of types"> 3279219019Sgabor /** 3280219019Sgabor * A cache for closures. 3281219019Sgabor * 3282219019Sgabor * <p>A closure is a list of all the supertypes and interfaces of 3283219019Sgabor * a class or interface type, ordered by ClassSymbol.precedes 3284219019Sgabor * (that is, subclasses come first, arbitrary but fixed 3285219019Sgabor * otherwise). 3286219019Sgabor */ 3287219019Sgabor private Map<Type,List<Type>> closureCache = new HashMap<>(); 3288219019Sgabor 3289219019Sgabor /** 3290219019Sgabor * Returns the closure of a class or interface type. 3291219019Sgabor */ 3292219019Sgabor public List<Type> closure(Type t) { 3293219019Sgabor List<Type> cl = closureCache.get(t); 3294219019Sgabor if (cl == null) { 3295219019Sgabor Type st = supertype(t); 3296219019Sgabor if (!t.isCompound()) { 3297219019Sgabor if (st.hasTag(CLASS)) { 3298219019Sgabor cl = insert(closure(st), t); 3299219019Sgabor } else if (st.hasTag(TYPEVAR)) { 3300219019Sgabor cl = closure(st).prepend(t); 3301219019Sgabor } else { 3302219019Sgabor cl = List.of(t); 3303219019Sgabor } 3304219019Sgabor } else { 3305219019Sgabor cl = closure(supertype(t)); 3306219019Sgabor } 3307219019Sgabor for (List<Type> l = interfaces(t); l.nonEmpty(); l = l.tail) 3308219019Sgabor cl = union(cl, closure(l.head)); 3309219019Sgabor closureCache.put(t, cl); 3310219019Sgabor } 3311219019Sgabor return cl; 3312219019Sgabor } 3313219019Sgabor 3314219019Sgabor /** 3315219019Sgabor * Collect types into a new closure (using a @code{ClosureHolder}) 3316219019Sgabor */ 3317219019Sgabor public Collector<Type, ClosureHolder, List<Type>> closureCollector(boolean minClosure, BiPredicate<Type, Type> shouldSkip) { 3318219019Sgabor return Collector.of(() -> new ClosureHolder(minClosure, shouldSkip), 3319219019Sgabor ClosureHolder::add, 3320219019Sgabor ClosureHolder::merge, 3321219019Sgabor ClosureHolder::closure); 3322219019Sgabor } 3323219019Sgabor //where 3324219019Sgabor class ClosureHolder { 3325219019Sgabor List<Type> closure; 3326219019Sgabor final boolean minClosure; 3327219019Sgabor final BiPredicate<Type, Type> shouldSkip; 3328219019Sgabor 3329219019Sgabor ClosureHolder(boolean minClosure, BiPredicate<Type, Type> shouldSkip) { 3330219019Sgabor this.closure = List.nil(); 3331219019Sgabor this.minClosure = minClosure; 3332219019Sgabor this.shouldSkip = shouldSkip; 3333219019Sgabor } 3334219019Sgabor 3335219019Sgabor void add(Type type) { 3336219019Sgabor closure = insert(closure, type, shouldSkip); 3337219019Sgabor } 3338219019Sgabor 3339219019Sgabor ClosureHolder merge(ClosureHolder other) { 3340219019Sgabor closure = union(closure, other.closure, shouldSkip); 3341219019Sgabor return this; 3342219019Sgabor } 3343219019Sgabor 3344219019Sgabor List<Type> closure() { 3345219019Sgabor return minClosure ? closureMin(closure) : closure; 3346219019Sgabor } 3347219019Sgabor } 3348219019Sgabor 3349219019Sgabor BiPredicate<Type, Type> basicClosureSkip = (t1, t2) -> t1.tsym == t2.tsym; 3350219019Sgabor 3351219019Sgabor /** 3352219019Sgabor * Insert a type in a closure 3353219019Sgabor */ 3354219019Sgabor public List<Type> insert(List<Type> cl, Type t, BiPredicate<Type, Type> shouldSkip) { 3355219019Sgabor if (cl.isEmpty()) { 3356219019Sgabor return cl.prepend(t); 3357219019Sgabor } else if (shouldSkip.test(t, cl.head)) { 3358219019Sgabor return cl; 3359219019Sgabor } else if (t.tsym.precedes(cl.head.tsym, this)) { 3360219019Sgabor return cl.prepend(t); 3361219019Sgabor } else { 3362219019Sgabor // t comes after head, or the two are unrelated 3363219019Sgabor return insert(cl.tail, t, shouldSkip).prepend(cl.head); 3364219019Sgabor } 3365219019Sgabor } 3366219019Sgabor 3367219019Sgabor public List<Type> insert(List<Type> cl, Type t) { 3368219019Sgabor return insert(cl, t, basicClosureSkip); 3369219019Sgabor } 3370219019Sgabor 3371219019Sgabor /** 3372219019Sgabor * Form the union of two closures 3373219019Sgabor */ 3374219019Sgabor public List<Type> union(List<Type> cl1, List<Type> cl2, BiPredicate<Type, Type> shouldSkip) { 3375219019Sgabor if (cl1.isEmpty()) { 3376219019Sgabor return cl2; 3377219019Sgabor } else if (cl2.isEmpty()) { 3378219019Sgabor return cl1; 3379219019Sgabor } else if (shouldSkip.test(cl1.head, cl2.head)) { 3380219019Sgabor return union(cl1.tail, cl2.tail, shouldSkip).prepend(cl1.head); 3381219019Sgabor } else if (cl1.head.tsym.precedes(cl2.head.tsym, this)) { 3382219019Sgabor return union(cl1.tail, cl2, shouldSkip).prepend(cl1.head); 3383219019Sgabor } else if (cl2.head.tsym.precedes(cl1.head.tsym, this)) { 3384219019Sgabor return union(cl1, cl2.tail, shouldSkip).prepend(cl2.head); 3385219019Sgabor } else { 3386219019Sgabor // unrelated types 3387219019Sgabor return union(cl1.tail, cl2, shouldSkip).prepend(cl1.head); 3388219019Sgabor } 3389219019Sgabor } 3390219019Sgabor 3391219019Sgabor public List<Type> union(List<Type> cl1, List<Type> cl2) { 3392219019Sgabor return union(cl1, cl2, basicClosureSkip); 3393219019Sgabor } 3394219019Sgabor 3395219019Sgabor /** 3396219019Sgabor * Intersect two closures 3397219019Sgabor */ 3398219019Sgabor public List<Type> intersect(List<Type> cl1, List<Type> cl2) { 3399219019Sgabor if (cl1 == cl2) 3400219019Sgabor return cl1; 3401219019Sgabor if (cl1.isEmpty() || cl2.isEmpty()) 3402219019Sgabor return List.nil(); 3403219019Sgabor if (cl1.head.tsym.precedes(cl2.head.tsym, this)) 3404219019Sgabor return intersect(cl1.tail, cl2); 3405219019Sgabor if (cl2.head.tsym.precedes(cl1.head.tsym, this)) 3406219019Sgabor return intersect(cl1, cl2.tail); 3407219019Sgabor if (isSameType(cl1.head, cl2.head)) 3408219019Sgabor return intersect(cl1.tail, cl2.tail).prepend(cl1.head); 3409219019Sgabor if (cl1.head.tsym == cl2.head.tsym && 3410219019Sgabor cl1.head.hasTag(CLASS) && cl2.head.hasTag(CLASS)) { 3411219019Sgabor if (cl1.head.isParameterized() && cl2.head.isParameterized()) { 3412219019Sgabor Type merge = merge(cl1.head,cl2.head); 3413219019Sgabor return intersect(cl1.tail, cl2.tail).prepend(merge); 3414219019Sgabor } 3415219019Sgabor if (cl1.head.isRaw() || cl2.head.isRaw()) 3416219019Sgabor return intersect(cl1.tail, cl2.tail).prepend(erasure(cl1.head)); 3417219019Sgabor } 3418219019Sgabor return intersect(cl1.tail, cl2.tail); 3419219019Sgabor } 3420219019Sgabor // where 3421219019Sgabor class TypePair { 3422219019Sgabor final Type t1; 3423219019Sgabor final Type t2; 3424219019Sgabor boolean strict; 3425219019Sgabor 3426219019Sgabor TypePair(Type t1, Type t2) { 3427219019Sgabor this(t1, t2, false); 3428219019Sgabor } 3429219019Sgabor 3430219019Sgabor TypePair(Type t1, Type t2, boolean strict) { 3431219019Sgabor this.t1 = t1; 3432219019Sgabor this.t2 = t2; 3433219019Sgabor this.strict = strict; 3434219019Sgabor } 3435219019Sgabor @Override 3436219019Sgabor public int hashCode() { 3437219019Sgabor return 127 * Types.this.hashCode(t1) + Types.this.hashCode(t2); 3438219019Sgabor } 3439219019Sgabor @Override 3440219019Sgabor public boolean equals(Object obj) { 3441219019Sgabor if (!(obj instanceof TypePair)) 3442219019Sgabor return false; 3443219019Sgabor TypePair typePair = (TypePair)obj; 3444219019Sgabor return isSameType(t1, typePair.t1, strict) 3445219019Sgabor && isSameType(t2, typePair.t2, strict); 3446219019Sgabor } 3447219019Sgabor } 3448219019Sgabor Set<TypePair> mergeCache = new HashSet<>(); 3449219019Sgabor private Type merge(Type c1, Type c2) { 3450219019Sgabor ClassType class1 = (ClassType) c1; 3451219019Sgabor List<Type> act1 = class1.getTypeArguments(); 3452219019Sgabor ClassType class2 = (ClassType) c2; 3453219019Sgabor List<Type> act2 = class2.getTypeArguments(); 3454219019Sgabor ListBuffer<Type> merged = new ListBuffer<>(); 3455219019Sgabor List<Type> typarams = class1.tsym.type.getTypeArguments(); 3456219019Sgabor 3457219019Sgabor while (act1.nonEmpty() && act2.nonEmpty() && typarams.nonEmpty()) { 3458219019Sgabor if (containsType(act1.head, act2.head)) { 3459219019Sgabor merged.append(act1.head); 3460219019Sgabor } else if (containsType(act2.head, act1.head)) { 3461219019Sgabor merged.append(act2.head); 3462219019Sgabor } else { 3463219019Sgabor TypePair pair = new TypePair(c1, c2); 3464219019Sgabor Type m; 3465219019Sgabor if (mergeCache.add(pair)) { 3466219019Sgabor m = new WildcardType(lub(wildUpperBound(act1.head), 3467219019Sgabor wildUpperBound(act2.head)), 3468219019Sgabor BoundKind.EXTENDS, 3469219019Sgabor syms.boundClass); 3470219019Sgabor mergeCache.remove(pair); 3471219019Sgabor } else { 3472219019Sgabor m = new WildcardType(syms.objectType, 3473219019Sgabor BoundKind.UNBOUND, 3474219019Sgabor syms.boundClass); 3475219019Sgabor } 3476219019Sgabor merged.append(m.withTypeVar(typarams.head)); 3477219019Sgabor } 3478219019Sgabor act1 = act1.tail; 3479219019Sgabor act2 = act2.tail; 3480219019Sgabor typarams = typarams.tail; 3481219019Sgabor } 3482219019Sgabor Assert.check(act1.isEmpty() && act2.isEmpty() && typarams.isEmpty()); 3483219019Sgabor // There is no spec detailing how type annotations are to 3484219019Sgabor // be inherited. So set it to noAnnotations for now 3485219019Sgabor return new ClassType(class1.getEnclosingType(), merged.toList(), 3486219019Sgabor class1.tsym); 3487219019Sgabor } 3488219019Sgabor 3489219019Sgabor /** 3490219019Sgabor * Return the minimum type of a closure, a compound type if no 3491219019Sgabor * unique minimum exists. 3492219019Sgabor */ 3493219019Sgabor private Type compoundMin(List<Type> cl) { 3494219019Sgabor if (cl.isEmpty()) return syms.objectType; 3495219019Sgabor List<Type> compound = closureMin(cl); 3496219019Sgabor if (compound.isEmpty()) 3497219019Sgabor return null; 3498219019Sgabor else if (compound.tail.isEmpty()) 3499219019Sgabor return compound.head; 3500219019Sgabor else 3501219019Sgabor return makeIntersectionType(compound); 3502219019Sgabor } 3503219019Sgabor 3504219019Sgabor /** 3505219019Sgabor * Return the minimum types of a closure, suitable for computing 3506219019Sgabor * compoundMin or glb. 3507219019Sgabor */ 3508219019Sgabor private List<Type> closureMin(List<Type> cl) { 3509219019Sgabor ListBuffer<Type> classes = new ListBuffer<>(); 3510219019Sgabor ListBuffer<Type> interfaces = new ListBuffer<>(); 3511219019Sgabor Set<Type> toSkip = new HashSet<>(); 3512219019Sgabor while (!cl.isEmpty()) { 3513219019Sgabor Type current = cl.head; 3514219019Sgabor boolean keep = !toSkip.contains(current); 3515219019Sgabor if (keep && current.hasTag(TYPEVAR)) { 3516219019Sgabor // skip lower-bounded variables with a subtype in cl.tail 3517219019Sgabor for (Type t : cl.tail) { 3518219019Sgabor if (isSubtypeNoCapture(t, current)) { 3519219019Sgabor keep = false; 3520219019Sgabor break; 3521219019Sgabor } 3522219019Sgabor } 3523219019Sgabor } 3524219019Sgabor if (keep) { 3525219019Sgabor if (current.isInterface()) 3526219019Sgabor interfaces.append(current); 3527219019Sgabor else 3528219019Sgabor classes.append(current); 3529219019Sgabor for (Type t : cl.tail) { 3530219019Sgabor // skip supertypes of 'current' in cl.tail 3531219019Sgabor if (isSubtypeNoCapture(current, t)) 3532219019Sgabor toSkip.add(t); 3533219019Sgabor } 3534219019Sgabor } 3535219019Sgabor cl = cl.tail; 3536219019Sgabor } 3537219019Sgabor return classes.appendList(interfaces).toList(); 3538219019Sgabor } 3539219019Sgabor 3540219019Sgabor /** 3541219019Sgabor * Return the least upper bound of list of types. if the lub does 3542219019Sgabor * not exist return null. 3543219019Sgabor */ 3544219019Sgabor public Type lub(List<Type> ts) { 3545219019Sgabor return lub(ts.toArray(new Type[ts.length()])); 3546219019Sgabor } 3547219019Sgabor 3548219019Sgabor /** 3549219019Sgabor * Return the least upper bound (lub) of set of types. If the lub 3550219019Sgabor * does not exist return the type of null (bottom). 3551219019Sgabor */ 3552219019Sgabor public Type lub(Type... ts) { 3553219019Sgabor final int UNKNOWN_BOUND = 0; 3554219019Sgabor final int ARRAY_BOUND = 1; 3555219019Sgabor final int CLASS_BOUND = 2; 3556219019Sgabor 3557219019Sgabor int[] kinds = new int[ts.length]; 3558219019Sgabor 3559219019Sgabor int boundkind = UNKNOWN_BOUND; 3560219019Sgabor for (int i = 0 ; i < ts.length ; i++) { 3561219019Sgabor Type t = ts[i]; 3562219019Sgabor switch (t.getTag()) { 3563219019Sgabor case CLASS: 3564219019Sgabor boundkind |= kinds[i] = CLASS_BOUND; 3565219019Sgabor break; 3566219019Sgabor case ARRAY: 3567219019Sgabor boundkind |= kinds[i] = ARRAY_BOUND; 3568219019Sgabor break; 3569219019Sgabor case TYPEVAR: 3570219019Sgabor do { 3571219019Sgabor t = t.getUpperBound(); 3572219019Sgabor } while (t.hasTag(TYPEVAR)); 3573219019Sgabor if (t.hasTag(ARRAY)) { 3574219019Sgabor boundkind |= kinds[i] = ARRAY_BOUND; 3575219019Sgabor } else { 3576219019Sgabor boundkind |= kinds[i] = CLASS_BOUND; 3577219019Sgabor } 3578219019Sgabor break; 3579219019Sgabor default: 3580219019Sgabor kinds[i] = UNKNOWN_BOUND; 3581219019Sgabor if (t.isPrimitive()) 3582219019Sgabor return syms.errType; 3583219019Sgabor } 3584219019Sgabor } 3585219019Sgabor switch (boundkind) { 3586219019Sgabor case 0: 3587219019Sgabor return syms.botType; 3588219019Sgabor 3589219019Sgabor case ARRAY_BOUND: 3590219019Sgabor // calculate lub(A[], B[]) 3591219019Sgabor Type[] elements = new Type[ts.length]; 3592219019Sgabor for (int i = 0 ; i < ts.length ; i++) { 3593219019Sgabor Type elem = elements[i] = elemTypeFun.apply(ts[i]); 3594219019Sgabor if (elem.isPrimitive()) { 3595219019Sgabor // if a primitive type is found, then return 3596219019Sgabor // arraySuperType unless all the types are the 3597219019Sgabor // same 3598219019Sgabor Type first = ts[0]; 3599219019Sgabor for (int j = 1 ; j < ts.length ; j++) { 3600219019Sgabor if (!isSameType(first, ts[j])) { 3601219019Sgabor // lub(int[], B[]) is Cloneable & Serializable 3602219019Sgabor return arraySuperType(); 3603219019Sgabor } 3604219019Sgabor } 3605219019Sgabor // all the array types are the same, return one 3606219019Sgabor // lub(int[], int[]) is int[] 3607219019Sgabor return first; 3608219019Sgabor } 3609219019Sgabor } 3610219019Sgabor // lub(A[], B[]) is lub(A, B)[] 3611219019Sgabor return new ArrayType(lub(elements), syms.arrayClass); 3612219019Sgabor 3613219019Sgabor case CLASS_BOUND: 3614219019Sgabor // calculate lub(A, B) 3615219019Sgabor int startIdx = 0; 3616219019Sgabor for (int i = 0; i < ts.length ; i++) { 3617219019Sgabor Type t = ts[i]; 3618219019Sgabor if (t.hasTag(CLASS) || t.hasTag(TYPEVAR)) { 3619219019Sgabor break; 3620219019Sgabor } else { 3621219019Sgabor startIdx++; 3622219019Sgabor } 3623219019Sgabor } 3624219019Sgabor Assert.check(startIdx < ts.length); 3625219019Sgabor //step 1 - compute erased candidate set (EC) 3626219019Sgabor List<Type> cl = erasedSupertypes(ts[startIdx]); 3627219019Sgabor for (int i = startIdx + 1 ; i < ts.length ; i++) { 3628219019Sgabor Type t = ts[i]; 3629219019Sgabor if (t.hasTag(CLASS) || t.hasTag(TYPEVAR)) 3630219019Sgabor cl = intersect(cl, erasedSupertypes(t)); 3631219019Sgabor } 3632219019Sgabor //step 2 - compute minimal erased candidate set (MEC) 3633219019Sgabor List<Type> mec = closureMin(cl); 3634219019Sgabor //step 3 - for each element G in MEC, compute lci(Inv(G)) 3635219019Sgabor List<Type> candidates = List.nil(); 3636219019Sgabor for (Type erasedSupertype : mec) { 3637219019Sgabor List<Type> lci = List.of(asSuper(ts[startIdx], erasedSupertype.tsym)); 3638219019Sgabor for (int i = startIdx + 1 ; i < ts.length ; i++) { 3639219019Sgabor Type superType = asSuper(ts[i], erasedSupertype.tsym); 3640219019Sgabor lci = intersect(lci, superType != null ? List.of(superType) : List.<Type>nil()); 3641219019Sgabor } 3642219019Sgabor candidates = candidates.appendList(lci); 3643219019Sgabor } 3644219019Sgabor //step 4 - let MEC be { G1, G2 ... Gn }, then we have that 3645219019Sgabor //lub = lci(Inv(G1)) & lci(Inv(G2)) & ... & lci(Inv(Gn)) 3646219019Sgabor return compoundMin(candidates); 3647219019Sgabor 3648219019Sgabor default: 3649219019Sgabor // calculate lub(A, B[]) 3650219019Sgabor List<Type> classes = List.of(arraySuperType()); 3651219019Sgabor for (int i = 0 ; i < ts.length ; i++) { 3652219019Sgabor if (kinds[i] != ARRAY_BOUND) // Filter out any arrays 3653219019Sgabor classes = classes.prepend(ts[i]); 3654219019Sgabor } 3655219019Sgabor // lub(A, B[]) is lub(A, arraySuperType) 3656219019Sgabor return lub(classes); 3657219019Sgabor } 3658219019Sgabor } 3659219019Sgabor // where 3660219019Sgabor List<Type> erasedSupertypes(Type t) { 3661219019Sgabor ListBuffer<Type> buf = new ListBuffer<>(); 3662219019Sgabor for (Type sup : closure(t)) { 3663219019Sgabor if (sup.hasTag(TYPEVAR)) { 3664219019Sgabor buf.append(sup); 3665219019Sgabor } else { 3666219019Sgabor buf.append(erasure(sup)); 3667219019Sgabor } 3668219019Sgabor } 3669219019Sgabor return buf.toList(); 3670219019Sgabor } 3671219019Sgabor 3672219019Sgabor private Type arraySuperType = null; 3673219019Sgabor private Type arraySuperType() { 3674219019Sgabor // initialized lazily to avoid problems during compiler startup 3675219019Sgabor if (arraySuperType == null) { 3676219019Sgabor synchronized (this) { 3677219019Sgabor if (arraySuperType == null) { 3678219019Sgabor // JLS 10.8: all arrays implement Cloneable and Serializable. 3679219019Sgabor arraySuperType = makeIntersectionType(List.of(syms.serializableType, 3680219019Sgabor syms.cloneableType), true); 3681219019Sgabor } 3682219019Sgabor } 3683219019Sgabor } 3684219019Sgabor return arraySuperType; 3685219019Sgabor } 3686219019Sgabor // </editor-fold> 3687219019Sgabor 3688219019Sgabor // <editor-fold defaultstate="collapsed" desc="Greatest lower bound"> 3689219019Sgabor public Type glb(List<Type> ts) { 3690219019Sgabor Type t1 = ts.head; 3691219019Sgabor for (Type t2 : ts.tail) { 3692219019Sgabor if (t1.isErroneous()) 3693219019Sgabor return t1; 3694219019Sgabor t1 = glb(t1, t2); 3695219019Sgabor } 3696219019Sgabor return t1; 3697219019Sgabor } 3698219019Sgabor //where 3699219019Sgabor public Type glb(Type t, Type s) { 3700219019Sgabor if (s == null) 3701219019Sgabor return t; 3702219019Sgabor else if (t.isPrimitive() || s.isPrimitive()) 3703219019Sgabor return syms.errType; 3704219019Sgabor else if (isSubtypeNoCapture(t, s)) 3705219019Sgabor return t; 3706219019Sgabor else if (isSubtypeNoCapture(s, t)) 3707219019Sgabor return s; 3708219019Sgabor 3709219019Sgabor List<Type> closure = union(closure(t), closure(s)); 3710219019Sgabor return glbFlattened(closure, t); 3711219019Sgabor } 3712219019Sgabor //where 3713219019Sgabor /** 3714219019Sgabor * Perform glb for a list of non-primitive, non-error, non-compound types; 3715219019Sgabor * redundant elements are removed. Bounds should be ordered according to 3716219019Sgabor * {@link Symbol#precedes(TypeSymbol,Types)}. 3717219019Sgabor * 3718219019Sgabor * @param flatBounds List of type to glb 3719219019Sgabor * @param errT Original type to use if the result is an error type 3720219019Sgabor */ 3721219019Sgabor private Type glbFlattened(List<Type> flatBounds, Type errT) { 3722219019Sgabor List<Type> bounds = closureMin(flatBounds); 3723219019Sgabor 3724219019Sgabor if (bounds.isEmpty()) { // length == 0 3725219019Sgabor return syms.objectType; 3726219019Sgabor } else if (bounds.tail.isEmpty()) { // length == 1 3727219019Sgabor return bounds.head; 3728219019Sgabor } else { // length > 1 3729219019Sgabor int classCount = 0; 3730219019Sgabor List<Type> lowers = List.nil(); 3731219019Sgabor for (Type bound : bounds) { 3732219019Sgabor if (!bound.isInterface()) { 3733219019Sgabor classCount++; 3734219019Sgabor Type lower = cvarLowerBound(bound); 3735219019Sgabor if (bound != lower && !lower.hasTag(BOT)) 3736219019Sgabor lowers = insert(lowers, lower); 3737219019Sgabor } 3738219019Sgabor } 3739219019Sgabor if (classCount > 1) { 3740219019Sgabor if (lowers.isEmpty()) 3741219019Sgabor return createErrorType(errT); 3742219019Sgabor else 3743219019Sgabor return glbFlattened(union(bounds, lowers), errT); 3744219019Sgabor } 3745219019Sgabor } 3746219019Sgabor return makeIntersectionType(bounds); 3747219019Sgabor } 3748219019Sgabor // </editor-fold> 3749219019Sgabor 3750219019Sgabor // <editor-fold defaultstate="collapsed" desc="hashCode"> 3751219019Sgabor /** 3752219019Sgabor * Compute a hash code on a type. 3753219019Sgabor */ 3754219019Sgabor public int hashCode(Type t) { 3755219019Sgabor return hashCode.visit(t); 3756219019Sgabor } 3757219019Sgabor // where 3758219019Sgabor private static final UnaryVisitor<Integer> hashCode = new UnaryVisitor<Integer>() { 3759219019Sgabor 3760219019Sgabor public Integer visitType(Type t, Void ignored) { 3761219019Sgabor return t.getTag().ordinal(); 3762219019Sgabor } 3763219019Sgabor 3764219019Sgabor @Override 3765219019Sgabor public Integer visitClassType(ClassType t, Void ignored) { 3766219019Sgabor int result = visit(t.getEnclosingType()); 3767219019Sgabor result *= 127; 3768219019Sgabor result += t.tsym.flatName().hashCode(); 3769219019Sgabor for (Type s : t.getTypeArguments()) { 3770219019Sgabor result *= 127; 3771219019Sgabor result += visit(s); 3772219019Sgabor } 3773219019Sgabor return result; 3774219019Sgabor } 3775219019Sgabor 3776219019Sgabor @Override 3777219019Sgabor public Integer visitMethodType(MethodType t, Void ignored) { 3778219019Sgabor int h = METHOD.ordinal(); 3779219019Sgabor for (List<Type> thisargs = t.argtypes; 3780219019Sgabor thisargs.tail != null; 3781219019Sgabor thisargs = thisargs.tail) 3782219019Sgabor h = (h << 5) + visit(thisargs.head); 3783219019Sgabor return (h << 5) + visit(t.restype); 3784219019Sgabor } 3785219019Sgabor 3786219019Sgabor @Override 3787219019Sgabor public Integer visitWildcardType(WildcardType t, Void ignored) { 3788219019Sgabor int result = t.kind.hashCode(); 3789219019Sgabor if (t.type != null) { 3790219019Sgabor result *= 127; 3791219019Sgabor result += visit(t.type); 3792219019Sgabor } 3793219019Sgabor return result; 3794219019Sgabor } 3795219019Sgabor 3796219019Sgabor @Override 3797219019Sgabor public Integer visitArrayType(ArrayType t, Void ignored) { 3798219019Sgabor return visit(t.elemtype) + 12; 3799219019Sgabor } 3800219019Sgabor 3801219019Sgabor @Override 3802219019Sgabor public Integer visitTypeVar(TypeVar t, Void ignored) { 3803219019Sgabor return System.identityHashCode(t.tsym); 3804219019Sgabor } 3805219019Sgabor 3806219019Sgabor @Override 3807219019Sgabor public Integer visitUndetVar(UndetVar t, Void ignored) { 3808219019Sgabor return System.identityHashCode(t); 3809219019Sgabor } 3810219019Sgabor 3811219019Sgabor @Override 3812219019Sgabor public Integer visitErrorType(ErrorType t, Void ignored) { 3813219019Sgabor return 0; 3814219019Sgabor } 3815219019Sgabor }; 3816219019Sgabor // </editor-fold> 3817219019Sgabor 3818219019Sgabor // <editor-fold defaultstate="collapsed" desc="Return-Type-Substitutable"> 3819219019Sgabor /** 3820219019Sgabor * Does t have a result that is a subtype of the result type of s, 3821219019Sgabor * suitable for covariant returns? It is assumed that both types 3822219019Sgabor * are (possibly polymorphic) method types. Monomorphic method 3823219019Sgabor * types are handled in the obvious way. Polymorphic method types 3824219019Sgabor * require renaming all type variables of one to corresponding 3825219019Sgabor * type variables in the other, where correspondence is by 3826219019Sgabor * position in the type parameter list. */ 3827219019Sgabor public boolean resultSubtype(Type t, Type s, Warner warner) { 3828219019Sgabor List<Type> tvars = t.getTypeArguments(); 3829219019Sgabor List<Type> svars = s.getTypeArguments(); 3830219019Sgabor Type tres = t.getReturnType(); 3831219019Sgabor Type sres = subst(s.getReturnType(), svars, tvars); 3832219019Sgabor return covariantReturnType(tres, sres, warner); 3833219019Sgabor } 3834219019Sgabor 3835219019Sgabor /** 3836219019Sgabor * Return-Type-Substitutable. 3837219019Sgabor * @jls section 8.4.5 3838219019Sgabor */ 3839219019Sgabor public boolean returnTypeSubstitutable(Type r1, Type r2) { 3840219019Sgabor if (hasSameArgs(r1, r2)) 3841219019Sgabor return resultSubtype(r1, r2, noWarnings); 3842219019Sgabor else 3843219019Sgabor return covariantReturnType(r1.getReturnType(), 3844219019Sgabor erasure(r2.getReturnType()), 3845219019Sgabor noWarnings); 3846219019Sgabor } 3847219019Sgabor 3848219019Sgabor public boolean returnTypeSubstitutable(Type r1, 3849219019Sgabor Type r2, Type r2res, 3850219019Sgabor Warner warner) { 3851219019Sgabor if (isSameType(r1.getReturnType(), r2res)) 3852219019Sgabor return true; 3853219019Sgabor if (r1.getReturnType().isPrimitive() || r2res.isPrimitive()) 3854219019Sgabor return false; 3855219019Sgabor 3856219019Sgabor if (hasSameArgs(r1, r2)) 3857219019Sgabor return covariantReturnType(r1.getReturnType(), r2res, warner); 3858219019Sgabor if (isSubtypeUnchecked(r1.getReturnType(), r2res, warner)) 3859219019Sgabor return true; 3860219019Sgabor if (!isSubtype(r1.getReturnType(), erasure(r2res))) 3861219019Sgabor return false; 3862219019Sgabor warner.warn(LintCategory.UNCHECKED); 3863219019Sgabor return true; 3864219019Sgabor } 3865219019Sgabor 3866219019Sgabor /** 3867219019Sgabor * Is t an appropriate return type in an overrider for a 3868219019Sgabor * method that returns s? 3869219019Sgabor */ 3870219019Sgabor public boolean covariantReturnType(Type t, Type s, Warner warner) { 3871219019Sgabor return 3872219019Sgabor isSameType(t, s) || 3873219019Sgabor !t.isPrimitive() && 3874219019Sgabor !s.isPrimitive() && 3875219019Sgabor isAssignable(t, s, warner); 3876219019Sgabor } 3877219019Sgabor // </editor-fold> 3878219019Sgabor 3879219019Sgabor // <editor-fold defaultstate="collapsed" desc="Box/unbox support"> 3880219019Sgabor /** 3881219019Sgabor * Return the class that boxes the given primitive. 3882219019Sgabor */ 3883219019Sgabor public ClassSymbol boxedClass(Type t) { 3884219019Sgabor return syms.enterClass(syms.boxedName[t.getTag().ordinal()]); 3885219019Sgabor } 3886219019Sgabor 3887219019Sgabor /** 3888219019Sgabor * Return the boxed type if 't' is primitive, otherwise return 't' itself. 3889219019Sgabor */ 3890219019Sgabor public Type boxedTypeOrType(Type t) { 3891219019Sgabor return t.isPrimitive() ? 3892219019Sgabor boxedClass(t).type : 3893219019Sgabor t; 3894219019Sgabor } 3895219019Sgabor 3896219019Sgabor /** 3897219019Sgabor * Return the primitive type corresponding to a boxed type. 3898219019Sgabor */ 3899219019Sgabor public Type unboxedType(Type t) { 3900219019Sgabor for (int i=0; i<syms.boxedName.length; i++) { 3901219019Sgabor Name box = syms.boxedName[i]; 3902219019Sgabor if (box != null && 3903219019Sgabor asSuper(t, syms.enterClass(box)) != null) 3904219019Sgabor return syms.typeOfTag[i]; 3905219019Sgabor } 3906219019Sgabor return Type.noType; 3907219019Sgabor } 3908219019Sgabor 3909219019Sgabor /** 3910219019Sgabor * Return the unboxed type if 't' is a boxed class, otherwise return 't' itself. 3911219019Sgabor */ 3912219019Sgabor public Type unboxedTypeOrType(Type t) { 3913219019Sgabor Type unboxedType = unboxedType(t); 3914219019Sgabor return unboxedType.hasTag(NONE) ? t : unboxedType; 3915219019Sgabor } 3916219019Sgabor // </editor-fold> 3917219019Sgabor 3918219019Sgabor // <editor-fold defaultstate="collapsed" desc="Capture conversion"> 3919219019Sgabor /* 3920219019Sgabor * JLS 5.1.10 Capture Conversion: 3921219019Sgabor * 3922219019Sgabor * Let G name a generic type declaration with n formal type 3923219019Sgabor * parameters A1 ... An with corresponding bounds U1 ... Un. There 3924219019Sgabor * exists a capture conversion from G<T1 ... Tn> to G<S1 ... Sn>, 3925219019Sgabor * where, for 1 <= i <= n: 3926219019Sgabor * 3927219019Sgabor * + If Ti is a wildcard type argument (4.5.1) of the form ? then 3928219019Sgabor * Si is a fresh type variable whose upper bound is 3929219019Sgabor * Ui[A1 := S1, ..., An := Sn] and whose lower bound is the null 3930219019Sgabor * type. 3931219019Sgabor * 3932219019Sgabor * + If Ti is a wildcard type argument of the form ? extends Bi, 3933219019Sgabor * then Si is a fresh type variable whose upper bound is 3934219019Sgabor * glb(Bi, Ui[A1 := S1, ..., An := Sn]) and whose lower bound is 3935219019Sgabor * the null type, where glb(V1,... ,Vm) is V1 & ... & Vm. It is 3936219019Sgabor * a compile-time error if for any two classes (not interfaces) 3937219019Sgabor * Vi and Vj,Vi is not a subclass of Vj or vice versa. 3938219019Sgabor * 3939219019Sgabor * + If Ti is a wildcard type argument of the form ? super Bi, 3940219019Sgabor * then Si is a fresh type variable whose upper bound is 3941219019Sgabor * Ui[A1 := S1, ..., An := Sn] and whose lower bound is Bi. 3942219019Sgabor * 3943219019Sgabor * + Otherwise, Si = Ti. 3944219019Sgabor * 3945219019Sgabor * Capture conversion on any type other than a parameterized type 3946219019Sgabor * (4.5) acts as an identity conversion (5.1.1). Capture 3947219019Sgabor * conversions never require a special action at run time and 3948219019Sgabor * therefore never throw an exception at run time. 3949219019Sgabor * 3950219019Sgabor * Capture conversion is not applied recursively. 3951219019Sgabor */ 3952219019Sgabor /** 3953219019Sgabor * Capture conversion as specified by the JLS. 3954219019Sgabor */ 3955219019Sgabor 3956219019Sgabor public List<Type> capture(List<Type> ts) { 3957219019Sgabor List<Type> buf = List.nil(); 3958219019Sgabor for (Type t : ts) { 3959219019Sgabor buf = buf.prepend(capture(t)); 3960219019Sgabor } 3961219019Sgabor return buf.reverse(); 3962219019Sgabor } 3963219019Sgabor 3964219019Sgabor public Type capture(Type t) { 3965219019Sgabor if (!t.hasTag(CLASS)) { 3966219019Sgabor return t; 3967219019Sgabor } 3968219019Sgabor if (t.getEnclosingType() != Type.noType) { 3969219019Sgabor Type capturedEncl = capture(t.getEnclosingType()); 3970219019Sgabor if (capturedEncl != t.getEnclosingType()) { 3971219019Sgabor Type type1 = memberType(capturedEncl, t.tsym); 3972219019Sgabor t = subst(type1, t.tsym.type.getTypeArguments(), t.getTypeArguments()); 3973219019Sgabor } 3974219019Sgabor } 3975219019Sgabor ClassType cls = (ClassType)t; 3976219019Sgabor if (cls.isRaw() || !cls.isParameterized()) 3977219019Sgabor return cls; 3978219019Sgabor 3979219019Sgabor ClassType G = (ClassType)cls.asElement().asType(); 3980219019Sgabor List<Type> A = G.getTypeArguments(); 3981219019Sgabor List<Type> T = cls.getTypeArguments(); 3982219019Sgabor List<Type> S = freshTypeVariables(T); 3983219019Sgabor 3984219019Sgabor List<Type> currentA = A; 3985219019Sgabor List<Type> currentT = T; 3986219019Sgabor List<Type> currentS = S; 3987219019Sgabor boolean captured = false; 3988219019Sgabor while (!currentA.isEmpty() && 3989219019Sgabor !currentT.isEmpty() && 3990219019Sgabor !currentS.isEmpty()) { 3991219019Sgabor if (currentS.head != currentT.head) { 3992219019Sgabor captured = true; 3993219019Sgabor WildcardType Ti = (WildcardType)currentT.head; 3994219019Sgabor Type Ui = currentA.head.getUpperBound(); 3995219019Sgabor CapturedType Si = (CapturedType)currentS.head; 3996219019Sgabor if (Ui == null) 3997219019Sgabor Ui = syms.objectType; 3998219019Sgabor switch (Ti.kind) { 3999219019Sgabor case UNBOUND: 4000219019Sgabor Si.bound = subst(Ui, A, S); 4001219019Sgabor Si.lower = syms.botType; 4002219019Sgabor break; 4003219019Sgabor case EXTENDS: 4004219019Sgabor Si.bound = glb(Ti.getExtendsBound(), subst(Ui, A, S)); 4005219019Sgabor Si.lower = syms.botType; 4006219019Sgabor break; 4007219019Sgabor case SUPER: 4008219019Sgabor Si.bound = subst(Ui, A, S); 4009219019Sgabor Si.lower = Ti.getSuperBound(); 4010219019Sgabor break; 4011219019Sgabor } 4012219019Sgabor Type tmpBound = Si.bound.hasTag(UNDETVAR) ? ((UndetVar)Si.bound).qtype : Si.bound; 4013219019Sgabor Type tmpLower = Si.lower.hasTag(UNDETVAR) ? ((UndetVar)Si.lower).qtype : Si.lower; 4014219019Sgabor if (!Si.bound.hasTag(ERROR) && 4015219019Sgabor !Si.lower.hasTag(ERROR) && 4016219019Sgabor isSameType(tmpBound, tmpLower, false)) { 4017219019Sgabor currentS.head = Si.bound; 4018219019Sgabor } 4019219019Sgabor } 4020219019Sgabor currentA = currentA.tail; 4021219019Sgabor currentT = currentT.tail; 4022219019Sgabor currentS = currentS.tail; 4023219019Sgabor } 4024219019Sgabor if (!currentA.isEmpty() || !currentT.isEmpty() || !currentS.isEmpty()) 4025219019Sgabor return erasure(t); // some "rare" type involved 4026219019Sgabor 4027219019Sgabor if (captured) 4028219019Sgabor return new ClassType(cls.getEnclosingType(), S, cls.tsym, 4029219019Sgabor cls.getMetadata()); 4030219019Sgabor else 4031219019Sgabor return t; 4032219019Sgabor } 4033219019Sgabor // where 4034219019Sgabor public List<Type> freshTypeVariables(List<Type> types) { 4035219019Sgabor ListBuffer<Type> result = new ListBuffer<>(); 4036219019Sgabor for (Type t : types) { 4037219019Sgabor if (t.hasTag(WILDCARD)) { 4038219019Sgabor Type bound = ((WildcardType)t).getExtendsBound(); 4039219019Sgabor if (bound == null) 4040219019Sgabor bound = syms.objectType; 4041219019Sgabor result.append(new CapturedType(capturedName, 4042219019Sgabor syms.noSymbol, 4043219019Sgabor bound, 4044219019Sgabor syms.botType, 4045219019Sgabor (WildcardType)t)); 4046219019Sgabor } else { 4047219019Sgabor result.append(t); 4048219019Sgabor } 4049219019Sgabor } 4050219019Sgabor return result.toList(); 4051219019Sgabor } 4052219019Sgabor // </editor-fold> 4053219019Sgabor 4054219019Sgabor // <editor-fold defaultstate="collapsed" desc="Internal utility methods"> 4055219019Sgabor private boolean sideCast(Type from, Type to, Warner warn) { 4056219019Sgabor // We are casting from type $from$ to type $to$, which are 4057219019Sgabor // non-final unrelated types. This method 4058219019Sgabor // tries to reject a cast by transferring type parameters 4059219019Sgabor // from $to$ to $from$ by common superinterfaces. 4060219019Sgabor boolean reverse = false; 4061219019Sgabor Type target = to; 4062219019Sgabor if ((to.tsym.flags() & INTERFACE) == 0) { 4063219019Sgabor Assert.check((from.tsym.flags() & INTERFACE) != 0); 4064219019Sgabor reverse = true; 4065219019Sgabor to = from; 4066219019Sgabor from = target; 4067219019Sgabor } 4068219019Sgabor List<Type> commonSupers = superClosure(to, erasure(from)); 4069219019Sgabor boolean giveWarning = commonSupers.isEmpty(); 4070219019Sgabor // The arguments to the supers could be unified here to 4071219019Sgabor // get a more accurate analysis 4072219019Sgabor while (commonSupers.nonEmpty()) { 4073219019Sgabor Type t1 = asSuper(from, commonSupers.head.tsym); 4074219019Sgabor Type t2 = commonSupers.head; // same as asSuper(to, commonSupers.head.tsym); 4075219019Sgabor if (disjointTypes(t1.getTypeArguments(), t2.getTypeArguments())) 4076219019Sgabor return false; 4077219019Sgabor giveWarning = giveWarning || (reverse ? giveWarning(t2, t1) : giveWarning(t1, t2)); 4078219019Sgabor commonSupers = commonSupers.tail; 4079219019Sgabor } 4080219019Sgabor if (giveWarning && !isReifiable(reverse ? from : to)) 4081219019Sgabor warn.warn(LintCategory.UNCHECKED); 4082219019Sgabor return true; 4083219019Sgabor } 4084219019Sgabor 4085219019Sgabor private boolean sideCastFinal(Type from, Type to, Warner warn) { 4086219019Sgabor // We are casting from type $from$ to type $to$, which are 4087219019Sgabor // unrelated types one of which is final and the other of 4088219019Sgabor // which is an interface. This method 4089219019Sgabor // tries to reject a cast by transferring type parameters 4090219019Sgabor // from the final class to the interface. 4091219019Sgabor boolean reverse = false; 4092219019Sgabor Type target = to; 4093219019Sgabor if ((to.tsym.flags() & INTERFACE) == 0) { 4094219019Sgabor Assert.check((from.tsym.flags() & INTERFACE) != 0); 4095219019Sgabor reverse = true; 4096219019Sgabor to = from; 4097219019Sgabor from = target; 4098219019Sgabor } 4099219019Sgabor Assert.check((from.tsym.flags() & FINAL) != 0); 4100219019Sgabor Type t1 = asSuper(from, to.tsym); 4101219019Sgabor if (t1 == null) return false; 4102219019Sgabor Type t2 = to; 4103219019Sgabor if (disjointTypes(t1.getTypeArguments(), t2.getTypeArguments())) 4104219019Sgabor return false; 4105219019Sgabor if (!isReifiable(target) && 4106219019Sgabor (reverse ? giveWarning(t2, t1) : giveWarning(t1, t2))) 4107219019Sgabor warn.warn(LintCategory.UNCHECKED); 4108219019Sgabor return true; 4109219019Sgabor } 4110219019Sgabor 4111219019Sgabor private boolean giveWarning(Type from, Type to) { 4112219019Sgabor List<Type> bounds = to.isCompound() ? 4113219019Sgabor ((IntersectionClassType)to).getComponents() : List.of(to); 4114219019Sgabor for (Type b : bounds) { 4115219019Sgabor Type subFrom = asSub(from, b.tsym); 4116219019Sgabor if (b.isParameterized() && 4117219019Sgabor (!(isUnbounded(b) || 4118219019Sgabor isSubtype(from, b) || 4119219019Sgabor ((subFrom != null) && containsType(b.allparams(), subFrom.allparams()))))) { 4120219019Sgabor return true; 4121219019Sgabor } 4122219019Sgabor } 4123219019Sgabor return false; 4124219019Sgabor } 4125219019Sgabor 4126219019Sgabor private List<Type> superClosure(Type t, Type s) { 4127219019Sgabor List<Type> cl = List.nil(); 4128219019Sgabor for (List<Type> l = interfaces(t); l.nonEmpty(); l = l.tail) { 4129219019Sgabor if (isSubtype(s, erasure(l.head))) { 4130219019Sgabor cl = insert(cl, l.head); 4131219019Sgabor } else { 4132219019Sgabor cl = union(cl, superClosure(l.head, s)); 4133219019Sgabor } 4134219019Sgabor } 4135219019Sgabor return cl; 4136219019Sgabor } 4137219019Sgabor 4138219019Sgabor private boolean containsTypeEquivalent(Type t, Type s) { 4139219019Sgabor return isSameType(t, s) || // shortcut 4140219019Sgabor containsType(t, s) && containsType(s, t); 4141219019Sgabor } 4142219019Sgabor 4143219019Sgabor // <editor-fold defaultstate="collapsed" desc="adapt"> 4144219019Sgabor /** 4145219019Sgabor * Adapt a type by computing a substitution which maps a source 4146219019Sgabor * type to a target type. 4147219019Sgabor * 4148219019Sgabor * @param source the source type 4149219019Sgabor * @param target the target type 4150219019Sgabor * @param from the type variables of the computed substitution 4151219019Sgabor * @param to the types of the computed substitution. 4152219019Sgabor */ 4153219019Sgabor public void adapt(Type source, 4154219019Sgabor Type target, 4155219019Sgabor ListBuffer<Type> from, 4156219019Sgabor ListBuffer<Type> to) throws AdaptFailure { 4157219019Sgabor new Adapter(from, to).adapt(source, target); 4158219019Sgabor } 4159219019Sgabor 4160219019Sgabor class Adapter extends SimpleVisitor<Void, Type> { 4161219019Sgabor 4162219019Sgabor ListBuffer<Type> from; 4163219019Sgabor ListBuffer<Type> to; 4164219019Sgabor Map<Symbol,Type> mapping; 4165219019Sgabor 4166219019Sgabor Adapter(ListBuffer<Type> from, ListBuffer<Type> to) { 4167219019Sgabor this.from = from; 4168219019Sgabor this.to = to; 4169219019Sgabor mapping = new HashMap<>(); 4170219019Sgabor } 4171219019Sgabor 4172219019Sgabor public void adapt(Type source, Type target) throws AdaptFailure { 4173219019Sgabor visit(source, target); 4174219019Sgabor List<Type> fromList = from.toList(); 4175219019Sgabor List<Type> toList = to.toList(); 4176219019Sgabor while (!fromList.isEmpty()) { 4177219019Sgabor Type val = mapping.get(fromList.head.tsym); 4178219019Sgabor if (toList.head != val) 4179219019Sgabor toList.head = val; 4180219019Sgabor fromList = fromList.tail; 4181219019Sgabor toList = toList.tail; 4182219019Sgabor } 4183219019Sgabor } 4184219019Sgabor 4185219019Sgabor @Override 4186219019Sgabor public Void visitClassType(ClassType source, Type target) throws AdaptFailure { 4187219019Sgabor if (target.hasTag(CLASS)) 4188219019Sgabor adaptRecursive(source.allparams(), target.allparams()); 4189219019Sgabor return null; 4190219019Sgabor } 4191219019Sgabor 4192219019Sgabor @Override 4193219019Sgabor public Void visitArrayType(ArrayType source, Type target) throws AdaptFailure { 4194219019Sgabor if (target.hasTag(ARRAY)) 4195219019Sgabor adaptRecursive(elemtype(source), elemtype(target)); 4196219019Sgabor return null; 4197219019Sgabor } 4198219019Sgabor 4199219019Sgabor @Override 4200219019Sgabor public Void visitWildcardType(WildcardType source, Type target) throws AdaptFailure { 4201219019Sgabor if (source.isExtendsBound()) 4202219019Sgabor adaptRecursive(wildUpperBound(source), wildUpperBound(target)); 4203219019Sgabor else if (source.isSuperBound()) 4204219019Sgabor adaptRecursive(wildLowerBound(source), wildLowerBound(target)); 4205219019Sgabor return null; 4206219019Sgabor } 4207219019Sgabor 4208219019Sgabor @Override 4209219019Sgabor public Void visitTypeVar(TypeVar source, Type target) throws AdaptFailure { 4210219019Sgabor // Check to see if there is 4211219019Sgabor // already a mapping for $source$, in which case 4212219019Sgabor // the old mapping will be merged with the new 4213219019Sgabor Type val = mapping.get(source.tsym); 4214219019Sgabor if (val != null) { 4215219019Sgabor if (val.isSuperBound() && target.isSuperBound()) { 4216219019Sgabor val = isSubtype(wildLowerBound(val), wildLowerBound(target)) 4217219019Sgabor ? target : val; 4218219019Sgabor } else if (val.isExtendsBound() && target.isExtendsBound()) { 4219219019Sgabor val = isSubtype(wildUpperBound(val), wildUpperBound(target)) 4220219019Sgabor ? val : target; 4221219019Sgabor } else if (!isSameType(val, target)) { 4222219019Sgabor throw new AdaptFailure(); 4223219019Sgabor } 4224219019Sgabor } else { 4225219019Sgabor val = target; 4226219019Sgabor from.append(source); 4227219019Sgabor to.append(target); 4228219019Sgabor } 4229219019Sgabor mapping.put(source.tsym, val); 4230219019Sgabor return null; 4231219019Sgabor } 4232219019Sgabor 4233219019Sgabor @Override 4234219019Sgabor public Void visitType(Type source, Type target) { 4235219019Sgabor return null; 4236219019Sgabor } 4237219019Sgabor 4238219019Sgabor private Set<TypePair> cache = new HashSet<>(); 4239219019Sgabor 4240219019Sgabor private void adaptRecursive(Type source, Type target) { 4241219019Sgabor TypePair pair = new TypePair(source, target); 4242219019Sgabor if (cache.add(pair)) { 4243219019Sgabor try { 4244219019Sgabor visit(source, target); 4245219019Sgabor } finally { 4246219019Sgabor cache.remove(pair); 4247219019Sgabor } 4248219019Sgabor } 4249219019Sgabor } 4250219019Sgabor 4251219019Sgabor private void adaptRecursive(List<Type> source, List<Type> target) { 4252219019Sgabor if (source.length() == target.length()) { 4253219019Sgabor while (source.nonEmpty()) { 4254219019Sgabor adaptRecursive(source.head, target.head); 4255219019Sgabor source = source.tail; 4256219019Sgabor target = target.tail; 4257219019Sgabor } 4258219019Sgabor } 4259219019Sgabor } 4260219019Sgabor } 4261219019Sgabor 4262219019Sgabor public static class AdaptFailure extends RuntimeException { 4263219019Sgabor static final long serialVersionUID = -7490231548272701566L; 4264219019Sgabor } 4265219019Sgabor 4266219019Sgabor private void adaptSelf(Type t, 4267219019Sgabor ListBuffer<Type> from, 4268219019Sgabor ListBuffer<Type> to) { 4269219019Sgabor try { 4270219019Sgabor //if (t.tsym.type != t) 4271219019Sgabor adapt(t.tsym.type, t, from, to); 4272219019Sgabor } catch (AdaptFailure ex) { 4273219019Sgabor // Adapt should never fail calculating a mapping from 4274219019Sgabor // t.tsym.type to t as there can be no merge problem. 4275219019Sgabor throw new AssertionError(ex); 4276219019Sgabor } 4277219019Sgabor } 4278219019Sgabor // </editor-fold> 4279219019Sgabor 4280219019Sgabor /** 4281219019Sgabor * Rewrite all type variables (universal quantifiers) in the given 4282219019Sgabor * type to wildcards (existential quantifiers). This is used to 4283219019Sgabor * determine if a cast is allowed. For example, if high is true 4284219019Sgabor * and {@code T <: Number}, then {@code List<T>} is rewritten to 4285219019Sgabor * {@code List<? extends Number>}. Since {@code List<Integer> <: 4286219019Sgabor * List<? extends Number>} a {@code List<T>} can be cast to {@code 4287219019Sgabor * List<Integer>} with a warning. 4288219019Sgabor * @param t a type 4289219019Sgabor * @param high if true return an upper bound; otherwise a lower 4290219019Sgabor * bound 4291219019Sgabor * @param rewriteTypeVars only rewrite captured wildcards if false; 4292219019Sgabor * otherwise rewrite all type variables 4293219019Sgabor * @return the type rewritten with wildcards (existential 4294219019Sgabor * quantifiers) only 4295219019Sgabor */ 4296219019Sgabor private Type rewriteQuantifiers(Type t, boolean high, boolean rewriteTypeVars) { 4297219019Sgabor return new Rewriter(high, rewriteTypeVars).visit(t); 4298219019Sgabor } 4299219019Sgabor 4300219019Sgabor class Rewriter extends UnaryVisitor<Type> { 4301219019Sgabor 4302219019Sgabor boolean high; 4303219019Sgabor boolean rewriteTypeVars; 4304219019Sgabor 4305219019Sgabor Rewriter(boolean high, boolean rewriteTypeVars) { 4306219019Sgabor this.high = high; 4307219019Sgabor this.rewriteTypeVars = rewriteTypeVars; 4308219019Sgabor } 4309219019Sgabor 4310219019Sgabor @Override 4311219019Sgabor public Type visitClassType(ClassType t, Void s) { 4312219019Sgabor ListBuffer<Type> rewritten = new ListBuffer<>(); 4313219019Sgabor boolean changed = false; 4314219019Sgabor for (Type arg : t.allparams()) { 4315219019Sgabor Type bound = visit(arg); 4316219019Sgabor if (arg != bound) { 4317219019Sgabor changed = true; 4318219019Sgabor } 4319219019Sgabor rewritten.append(bound); 4320219019Sgabor } 4321219019Sgabor if (changed) 4322219019Sgabor return subst(t.tsym.type, 4323219019Sgabor t.tsym.type.allparams(), 4324219019Sgabor rewritten.toList()); 4325219019Sgabor else 4326219019Sgabor return t; 4327219019Sgabor } 4328219019Sgabor 4329219019Sgabor public Type visitType(Type t, Void s) { 4330219019Sgabor return t; 4331219019Sgabor } 4332219019Sgabor 4333219019Sgabor @Override 4334219019Sgabor public Type visitCapturedType(CapturedType t, Void s) { 4335219019Sgabor Type w_bound = t.wildcard.type; 4336219019Sgabor Type bound = w_bound.contains(t) ? 4337219019Sgabor erasure(w_bound) : 4338219019Sgabor visit(w_bound); 4339219019Sgabor return rewriteAsWildcardType(visit(bound), t.wildcard.bound, t.wildcard.kind); 4340219019Sgabor } 4341219019Sgabor 4342219019Sgabor @Override 4343219019Sgabor public Type visitTypeVar(TypeVar t, Void s) { 4344219019Sgabor if (rewriteTypeVars) { 4345219019Sgabor Type bound = t.bound.contains(t) ? 4346219019Sgabor erasure(t.bound) : 4347219019Sgabor visit(t.bound); 4348219019Sgabor return rewriteAsWildcardType(bound, t, EXTENDS); 4349219019Sgabor } else { 4350219019Sgabor return t; 4351219019Sgabor } 4352219019Sgabor } 4353219019Sgabor 4354219019Sgabor @Override 4355219019Sgabor public Type visitWildcardType(WildcardType t, Void s) { 4356219019Sgabor Type bound2 = visit(t.type); 4357219019Sgabor return t.type == bound2 ? t : rewriteAsWildcardType(bound2, t.bound, t.kind); 4358219019Sgabor } 4359219019Sgabor 4360219019Sgabor private Type rewriteAsWildcardType(Type bound, TypeVar formal, BoundKind bk) { 4361219019Sgabor switch (bk) { 4362219019Sgabor case EXTENDS: return high ? 4363219019Sgabor makeExtendsWildcard(B(bound), formal) : 4364219019Sgabor makeExtendsWildcard(syms.objectType, formal); 4365219019Sgabor case SUPER: return high ? 4366219019Sgabor makeSuperWildcard(syms.botType, formal) : 4367219019Sgabor makeSuperWildcard(B(bound), formal); 4368219019Sgabor case UNBOUND: return makeExtendsWildcard(syms.objectType, formal); 4369219019Sgabor default: 4370219019Sgabor Assert.error("Invalid bound kind " + bk); 4371219019Sgabor return null; 4372219019Sgabor } 4373219019Sgabor } 4374219019Sgabor 4375219019Sgabor Type B(Type t) { 4376219019Sgabor while (t.hasTag(WILDCARD)) { 4377219019Sgabor WildcardType w = (WildcardType)t; 4378219019Sgabor t = high ? 4379219019Sgabor w.getExtendsBound() : 4380219019Sgabor w.getSuperBound(); 4381219019Sgabor if (t == null) { 4382219019Sgabor t = high ? syms.objectType : syms.botType; 4383219019Sgabor } 4384219019Sgabor } 4385219019Sgabor return t; 4386219019Sgabor } 4387219019Sgabor } 4388219019Sgabor 4389219019Sgabor 4390219019Sgabor /** 4391219019Sgabor * Create a wildcard with the given upper (extends) bound; create 4392219019Sgabor * an unbounded wildcard if bound is Object. 4393219019Sgabor * 4394219019Sgabor * @param bound the upper bound 4395219019Sgabor * @param formal the formal type parameter that will be 4396219019Sgabor * substituted by the wildcard 4397219019Sgabor */ 4398219019Sgabor private WildcardType makeExtendsWildcard(Type bound, TypeVar formal) { 4399219019Sgabor if (bound == syms.objectType) { 4400219019Sgabor return new WildcardType(syms.objectType, 4401219019Sgabor BoundKind.UNBOUND, 4402219019Sgabor syms.boundClass, 4403219019Sgabor formal); 4404219019Sgabor } else { 4405219019Sgabor return new WildcardType(bound, 4406219019Sgabor BoundKind.EXTENDS, 4407219019Sgabor syms.boundClass, 4408219019Sgabor formal); 4409219019Sgabor } 4410219019Sgabor } 4411219019Sgabor 4412219019Sgabor /** 4413219019Sgabor * Create a wildcard with the given lower (super) bound; create an 4414219019Sgabor * unbounded wildcard if bound is bottom (type of {@code null}). 4415219019Sgabor * 4416219019Sgabor * @param bound the lower bound 4417219019Sgabor * @param formal the formal type parameter that will be 4418219019Sgabor * substituted by the wildcard 4419219019Sgabor */ 4420219019Sgabor private WildcardType makeSuperWildcard(Type bound, TypeVar formal) { 4421219019Sgabor if (bound.hasTag(BOT)) { 4422219019Sgabor return new WildcardType(syms.objectType, 4423219019Sgabor BoundKind.UNBOUND, 4424219019Sgabor syms.boundClass, 4425219019Sgabor formal); 4426219019Sgabor } else { 4427219019Sgabor return new WildcardType(bound, 4428219019Sgabor BoundKind.SUPER, 4429219019Sgabor syms.boundClass, 4430219019Sgabor formal); 4431219019Sgabor } 4432219019Sgabor } 4433219019Sgabor 4434219019Sgabor /** 4435219019Sgabor * A wrapper for a type that allows use in sets. 4436219019Sgabor */ 4437219019Sgabor public static class UniqueType { 4438219019Sgabor public final Type type; 4439219019Sgabor final Types types; 4440219019Sgabor 4441219019Sgabor public UniqueType(Type type, Types types) { 4442219019Sgabor this.type = type; 4443219019Sgabor this.types = types; 4444219019Sgabor } 4445219019Sgabor 4446219019Sgabor public int hashCode() { 4447219019Sgabor return types.hashCode(type); 4448219019Sgabor } 4449219019Sgabor 4450219019Sgabor public boolean equals(Object obj) { 4451219019Sgabor return (obj instanceof UniqueType) && 4452219019Sgabor types.isSameType(type, ((UniqueType)obj).type); 4453219019Sgabor } 4454219019Sgabor 4455219019Sgabor public String toString() { 4456219019Sgabor return type.toString(); 4457219019Sgabor } 4458219019Sgabor 4459219019Sgabor } 4460219019Sgabor // </editor-fold> 4461219019Sgabor 4462219019Sgabor // <editor-fold defaultstate="collapsed" desc="Visitors"> 4463219019Sgabor /** 4464219019Sgabor * A default visitor for types. All visitor methods except 4465219019Sgabor * visitType are implemented by delegating to visitType. Concrete 4466219019Sgabor * subclasses must provide an implementation of visitType and can 4467219019Sgabor * override other methods as needed. 4468219019Sgabor * 4469219019Sgabor * @param <R> the return type of the operation implemented by this 4470219019Sgabor * visitor; use Void if no return type is needed. 4471219019Sgabor * @param <S> the type of the second argument (the first being the 4472219019Sgabor * type itself) of the operation implemented by this visitor; use 4473219019Sgabor * Void if a second argument is not needed. 4474219019Sgabor */ 4475219019Sgabor public static abstract class DefaultTypeVisitor<R,S> implements Type.Visitor<R,S> { 4476219019Sgabor final public R visit(Type t, S s) { return t.accept(this, s); } 4477219019Sgabor public R visitClassType(ClassType t, S s) { return visitType(t, s); } 4478219019Sgabor public R visitWildcardType(WildcardType t, S s) { return visitType(t, s); } 4479219019Sgabor public R visitArrayType(ArrayType t, S s) { return visitType(t, s); } 4480219019Sgabor public R visitMethodType(MethodType t, S s) { return visitType(t, s); } 4481219019Sgabor public R visitPackageType(PackageType t, S s) { return visitType(t, s); } 4482219019Sgabor public R visitTypeVar(TypeVar t, S s) { return visitType(t, s); } 4483219019Sgabor public R visitCapturedType(CapturedType t, S s) { return visitType(t, s); } 4484219019Sgabor public R visitForAll(ForAll t, S s) { return visitType(t, s); } 4485219019Sgabor public R visitUndetVar(UndetVar t, S s) { return visitType(t, s); } 4486219019Sgabor public R visitErrorType(ErrorType t, S s) { return visitType(t, s); } 4487219019Sgabor } 4488219019Sgabor 4489219019Sgabor /** 4490219019Sgabor * A default visitor for symbols. All visitor methods except 4491219019Sgabor * visitSymbol are implemented by delegating to visitSymbol. Concrete 4492219019Sgabor * subclasses must provide an implementation of visitSymbol and can 4493219019Sgabor * override other methods as needed. 4494219019Sgabor * 4495219019Sgabor * @param <R> the return type of the operation implemented by this 4496219019Sgabor * visitor; use Void if no return type is needed. 4497219019Sgabor * @param <S> the type of the second argument (the first being the 4498219019Sgabor * symbol itself) of the operation implemented by this visitor; use 4499219019Sgabor * Void if a second argument is not needed. 4500219019Sgabor */ 4501219019Sgabor public static abstract class DefaultSymbolVisitor<R,S> implements Symbol.Visitor<R,S> { 4502219019Sgabor final public R visit(Symbol s, S arg) { return s.accept(this, arg); } 4503219019Sgabor public R visitClassSymbol(ClassSymbol s, S arg) { return visitSymbol(s, arg); } 4504219019Sgabor public R visitMethodSymbol(MethodSymbol s, S arg) { return visitSymbol(s, arg); } 4505219019Sgabor public R visitOperatorSymbol(OperatorSymbol s, S arg) { return visitSymbol(s, arg); } 4506219019Sgabor public R visitPackageSymbol(PackageSymbol s, S arg) { return visitSymbol(s, arg); } 4507219019Sgabor public R visitTypeSymbol(TypeSymbol s, S arg) { return visitSymbol(s, arg); } 4508219019Sgabor public R visitVarSymbol(VarSymbol s, S arg) { return visitSymbol(s, arg); } 4509219019Sgabor } 4510219019Sgabor 4511219019Sgabor /** 4512219019Sgabor * A <em>simple</em> visitor for types. This visitor is simple as 4513219019Sgabor * captured wildcards, for-all types (generic methods), and 4514219019Sgabor * undetermined type variables (part of inference) are hidden. 4515219019Sgabor * Captured wildcards are hidden by treating them as type 4516219019Sgabor * variables and the rest are hidden by visiting their qtypes. 4517219019Sgabor * 4518219019Sgabor * @param <R> the return type of the operation implemented by this 4519219019Sgabor * visitor; use Void if no return type is needed. 4520219019Sgabor * @param <S> the type of the second argument (the first being the 4521219019Sgabor * type itself) of the operation implemented by this visitor; use 4522219019Sgabor * Void if a second argument is not needed. 4523219019Sgabor */ 4524219019Sgabor public static abstract class SimpleVisitor<R,S> extends DefaultTypeVisitor<R,S> { 4525219019Sgabor @Override 4526219019Sgabor public R visitCapturedType(CapturedType t, S s) { 4527219019Sgabor return visitTypeVar(t, s); 4528219019Sgabor } 4529219019Sgabor @Override 4530219019Sgabor public R visitForAll(ForAll t, S s) { 4531219019Sgabor return visit(t.qtype, s); 4532219019Sgabor } 4533219019Sgabor @Override 4534219019Sgabor public R visitUndetVar(UndetVar t, S s) { 4535219019Sgabor return visit(t.qtype, s); 4536219019Sgabor } 4537219019Sgabor } 4538219019Sgabor 4539219019Sgabor /** 4540219019Sgabor * A plain relation on types. That is a 2-ary function on the 4541219019Sgabor * form Type × Type → Boolean. 4542219019Sgabor * <!-- In plain text: Type x Type -> Boolean --> 4543219019Sgabor */ 4544219019Sgabor public static abstract class TypeRelation extends SimpleVisitor<Boolean,Type> {} 4545219019Sgabor 4546219019Sgabor /** 4547219019Sgabor * A convenience visitor for implementing operations that only 4548219019Sgabor * require one argument (the type itself), that is, unary 4549219019Sgabor * operations. 4550219019Sgabor * 4551219019Sgabor * @param <R> the return type of the operation implemented by this 4552219019Sgabor * visitor; use Void if no return type is needed. 4553219019Sgabor */ 4554219019Sgabor public static abstract class UnaryVisitor<R> extends SimpleVisitor<R,Void> { 4555219019Sgabor final public R visit(Type t) { return t.accept(this, null); } 4556219019Sgabor } 4557219019Sgabor 4558219019Sgabor /** 4559219019Sgabor * A visitor for implementing a mapping from types to types. The 4560219019Sgabor * default behavior of this class is to implement the identity 4561219019Sgabor * mapping (mapping a type to itself). This can be overridden in 4562219019Sgabor * subclasses. 4563219019Sgabor * 4564219019Sgabor * @param <S> the type of the second argument (the first being the 4565219019Sgabor * type itself) of this mapping; use Void if a second argument is 4566219019Sgabor * not needed. 4567219019Sgabor */ 4568219019Sgabor public static class MapVisitor<S> extends DefaultTypeVisitor<Type,S> { 4569219019Sgabor final public Type visit(Type t) { return t.accept(this, null); } 4570219019Sgabor public Type visitType(Type t, S s) { return t; } 4571219019Sgabor } 4572219019Sgabor // </editor-fold> 4573219019Sgabor 4574219019Sgabor 4575219019Sgabor // <editor-fold defaultstate="collapsed" desc="Annotation support"> 4576219019Sgabor 4577219019Sgabor public RetentionPolicy getRetention(Attribute.Compound a) { 4578219019Sgabor return getRetention(a.type.tsym); 4579219019Sgabor } 4580219019Sgabor 4581219019Sgabor public RetentionPolicy getRetention(TypeSymbol sym) { 4582219019Sgabor RetentionPolicy vis = RetentionPolicy.CLASS; // the default 4583219019Sgabor Attribute.Compound c = sym.attribute(syms.retentionType.tsym); 4584219019Sgabor if (c != null) { 4585219019Sgabor Attribute value = c.member(names.value); 4586219019Sgabor if (value != null && value instanceof Attribute.Enum) { 4587219019Sgabor Name levelName = ((Attribute.Enum)value).value.name; 4588219019Sgabor if (levelName == names.SOURCE) vis = RetentionPolicy.SOURCE; 4589219019Sgabor else if (levelName == names.CLASS) vis = RetentionPolicy.CLASS; 4590219019Sgabor else if (levelName == names.RUNTIME) vis = RetentionPolicy.RUNTIME; 4591219019Sgabor else ;// /* fail soft */ throw new AssertionError(levelName); 4592219019Sgabor } 4593219019Sgabor } 4594219019Sgabor return vis; 4595219019Sgabor } 4596219019Sgabor // </editor-fold> 4597219019Sgabor 4598219019Sgabor // <editor-fold defaultstate="collapsed" desc="Signature Generation"> 4599219019Sgabor 4600219019Sgabor public static abstract class SignatureGenerator { 4601219019Sgabor 4602219019Sgabor private final Types types; 4603219019Sgabor 4604219019Sgabor protected abstract void append(char ch); 4605219019Sgabor protected abstract void append(byte[] ba); 4606219019Sgabor protected abstract void append(Name name); 4607219019Sgabor protected void classReference(ClassSymbol c) { /* by default: no-op */ } 4608219019Sgabor 4609219019Sgabor protected SignatureGenerator(Types types) { 4610219019Sgabor this.types = types; 4611219019Sgabor } 4612219019Sgabor 4613219019Sgabor /** 4614219019Sgabor * Assemble signature of given type in string buffer. 4615219019Sgabor */ 4616219019Sgabor public void assembleSig(Type type) { 4617219019Sgabor switch (type.getTag()) { 4618219019Sgabor case BYTE: 4619219019Sgabor append('B'); 4620219019Sgabor break; 4621219019Sgabor case SHORT: 4622219019Sgabor append('S'); 4623219019Sgabor break; 4624219019Sgabor case CHAR: 4625219019Sgabor append('C'); 4626219019Sgabor break; 4627219019Sgabor case INT: 4628219019Sgabor append('I'); 4629219019Sgabor break; 4630219019Sgabor case LONG: 4631219019Sgabor append('J'); 4632219019Sgabor break; 4633219019Sgabor case FLOAT: 4634219019Sgabor append('F'); 4635219019Sgabor break; 4636219019Sgabor case DOUBLE: 4637219019Sgabor append('D'); 4638219019Sgabor break; 4639219019Sgabor case BOOLEAN: 4640219019Sgabor append('Z'); 4641219019Sgabor break; 4642219019Sgabor case VOID: 4643219019Sgabor append('V'); 4644219019Sgabor break; 4645219019Sgabor case CLASS: 4646219019Sgabor append('L'); 4647219019Sgabor assembleClassSig(type); 4648219019Sgabor append(';'); 4649219019Sgabor break; 4650219019Sgabor case ARRAY: 4651219019Sgabor ArrayType at = (ArrayType) type; 4652219019Sgabor append('['); 4653219019Sgabor assembleSig(at.elemtype); 4654219019Sgabor break; 4655219019Sgabor case METHOD: 4656219019Sgabor MethodType mt = (MethodType) type; 4657219019Sgabor append('('); 4658219019Sgabor assembleSig(mt.argtypes); 4659219019Sgabor append(')'); 4660219019Sgabor assembleSig(mt.restype); 4661219019Sgabor if (hasTypeVar(mt.thrown)) { 4662219019Sgabor for (List<Type> l = mt.thrown; l.nonEmpty(); l = l.tail) { 4663219019Sgabor append('^'); 4664219019Sgabor assembleSig(l.head); 4665219019Sgabor } 4666219019Sgabor } 4667219019Sgabor break; 4668219019Sgabor case WILDCARD: { 4669219019Sgabor Type.WildcardType ta = (Type.WildcardType) type; 4670219019Sgabor switch (ta.kind) { 4671219019Sgabor case SUPER: 4672219019Sgabor append('-'); 4673219019Sgabor assembleSig(ta.type); 4674219019Sgabor break; 4675219019Sgabor case EXTENDS: 4676219019Sgabor append('+'); 4677219019Sgabor assembleSig(ta.type); 4678219019Sgabor break; 4679219019Sgabor case UNBOUND: 4680219019Sgabor append('*'); 4681219019Sgabor break; 4682219019Sgabor default: 4683219019Sgabor throw new AssertionError(ta.kind); 4684219019Sgabor } 4685219019Sgabor break; 4686219019Sgabor } 4687219019Sgabor case TYPEVAR: 4688219019Sgabor append('T'); 4689219019Sgabor append(type.tsym.name); 4690219019Sgabor append(';'); 4691219019Sgabor break; 4692219019Sgabor case FORALL: 4693219019Sgabor Type.ForAll ft = (Type.ForAll) type; 4694219019Sgabor assembleParamsSig(ft.tvars); 4695219019Sgabor assembleSig(ft.qtype); 4696219019Sgabor break; 4697219019Sgabor default: 4698219019Sgabor throw new AssertionError("typeSig " + type.getTag()); 4699219019Sgabor } 4700219019Sgabor } 4701219019Sgabor 4702219019Sgabor public boolean hasTypeVar(List<Type> l) { 4703219019Sgabor while (l.nonEmpty()) { 4704219019Sgabor if (l.head.hasTag(TypeTag.TYPEVAR)) { 4705219019Sgabor return true; 4706219019Sgabor } 4707219019Sgabor l = l.tail; 4708219019Sgabor } 4709219019Sgabor return false; 4710219019Sgabor } 4711219019Sgabor 4712219019Sgabor public void assembleClassSig(Type type) { 4713219019Sgabor ClassType ct = (ClassType) type; 4714219019Sgabor ClassSymbol c = (ClassSymbol) ct.tsym; 4715219019Sgabor classReference(c); 4716219019Sgabor Type outer = ct.getEnclosingType(); 4717219019Sgabor if (outer.allparams().nonEmpty()) { 4718219019Sgabor boolean rawOuter = 4719219019Sgabor c.owner.kind == MTH || // either a local class 4720219019Sgabor c.name == types.names.empty; // or anonymous 4721219019Sgabor assembleClassSig(rawOuter 4722219019Sgabor ? types.erasure(outer) 4723219019Sgabor : outer); 4724219019Sgabor append(rawOuter ? '$' : '.'); 4725219019Sgabor Assert.check(c.flatname.startsWith(c.owner.enclClass().flatname)); 4726219019Sgabor append(rawOuter 4727219019Sgabor ? c.flatname.subName(c.owner.enclClass().flatname.getByteLength() + 1, c.flatname.getByteLength()) 4728219019Sgabor : c.name); 4729219019Sgabor } else { 4730219019Sgabor append(externalize(c.flatname)); 4731219019Sgabor } 4732219019Sgabor if (ct.getTypeArguments().nonEmpty()) { 4733219019Sgabor append('<'); 4734219019Sgabor assembleSig(ct.getTypeArguments()); 4735219019Sgabor append('>'); 4736219019Sgabor } 4737219019Sgabor } 4738219019Sgabor 4739219019Sgabor public void assembleParamsSig(List<Type> typarams) { 4740219019Sgabor append('<'); 4741219019Sgabor for (List<Type> ts = typarams; ts.nonEmpty(); ts = ts.tail) { 4742219019Sgabor Type.TypeVar tvar = (Type.TypeVar) ts.head; 4743219019Sgabor append(tvar.tsym.name); 4744219019Sgabor List<Type> bounds = types.getBounds(tvar); 4745219019Sgabor if ((bounds.head.tsym.flags() & INTERFACE) != 0) { 4746219019Sgabor append(':'); 4747219019Sgabor } 4748219019Sgabor for (List<Type> l = bounds; l.nonEmpty(); l = l.tail) { 4749219019Sgabor append(':'); 4750219019Sgabor assembleSig(l.head); 4751219019Sgabor } 4752219019Sgabor } 4753219019Sgabor append('>'); 4754219019Sgabor } 4755219019Sgabor 4756219019Sgabor private void assembleSig(List<Type> types) { 4757219019Sgabor for (List<Type> ts = types; ts.nonEmpty(); ts = ts.tail) { 4758219019Sgabor assembleSig(ts.head); 4759219019Sgabor } 4760219019Sgabor } 4761219019Sgabor } 4762219019Sgabor // </editor-fold> 4763219019Sgabor 4764219019Sgabor public void newRound() { 4765219019Sgabor descCache._map.clear(); 4766219019Sgabor isDerivedRawCache.clear(); 4767219019Sgabor implCache._map.clear(); 4768219019Sgabor membersCache._map.clear(); 4769219019Sgabor closureCache.clear(); 4770219019Sgabor } 4771219019Sgabor} 4772219019Sgabor