Types.java revision 2856:eb7b825ad678
1/* 2 * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26package com.sun.tools.javac.code; 27 28import java.lang.ref.SoftReference; 29import java.util.HashSet; 30import java.util.HashMap; 31import java.util.Locale; 32import java.util.Map; 33import java.util.Set; 34import java.util.WeakHashMap; 35import java.util.function.BiPredicate; 36import java.util.stream.Collector; 37 38import javax.tools.JavaFileObject; 39 40import com.sun.tools.javac.code.Attribute.RetentionPolicy; 41import com.sun.tools.javac.code.Lint.LintCategory; 42import com.sun.tools.javac.code.Type.UndetVar.InferenceBound; 43import com.sun.tools.javac.comp.AttrContext; 44import com.sun.tools.javac.comp.Check; 45import com.sun.tools.javac.comp.Enter; 46import com.sun.tools.javac.comp.Env; 47import com.sun.tools.javac.util.*; 48 49import static com.sun.tools.javac.code.BoundKind.*; 50import static com.sun.tools.javac.code.Flags.*; 51import static com.sun.tools.javac.code.Kinds.Kind.*; 52import static com.sun.tools.javac.code.Scope.*; 53import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE; 54import static com.sun.tools.javac.code.Symbol.*; 55import static com.sun.tools.javac.code.Type.*; 56import static com.sun.tools.javac.code.TypeTag.*; 57import static com.sun.tools.javac.jvm.ClassFile.externalize; 58 59/** 60 * Utility class containing various operations on types. 61 * 62 * <p>Unless other names are more illustrative, the following naming 63 * conventions should be observed in this file: 64 * 65 * <dl> 66 * <dt>t</dt> 67 * <dd>If the first argument to an operation is a type, it should be named t.</dd> 68 * <dt>s</dt> 69 * <dd>Similarly, if the second argument to an operation is a type, it should be named s.</dd> 70 * <dt>ts</dt> 71 * <dd>If an operations takes a list of types, the first should be named ts.</dd> 72 * <dt>ss</dt> 73 * <dd>A second list of types should be named ss.</dd> 74 * </dl> 75 * 76 * <p><b>This is NOT part of any supported API. 77 * If you write code that depends on this, you do so at your own risk. 78 * This code and its internal interfaces are subject to change or 79 * deletion without notice.</b> 80 */ 81public class Types { 82 protected static final Context.Key<Types> typesKey = new Context.Key<>(); 83 84 final Symtab syms; 85 final JavacMessages messages; 86 final Names names; 87 final boolean allowObjectToPrimitiveCast; 88 final boolean allowDefaultMethods; 89 final Check chk; 90 final Enter enter; 91 JCDiagnostic.Factory diags; 92 List<Warner> warnStack = List.nil(); 93 final Name capturedName; 94 private final FunctionDescriptorLookupError functionDescriptorLookupError; 95 96 public final Warner noWarnings; 97 98 // <editor-fold defaultstate="collapsed" desc="Instantiating"> 99 public static Types instance(Context context) { 100 Types instance = context.get(typesKey); 101 if (instance == null) 102 instance = new Types(context); 103 return instance; 104 } 105 106 protected Types(Context context) { 107 context.put(typesKey, this); 108 syms = Symtab.instance(context); 109 names = Names.instance(context); 110 Source source = Source.instance(context); 111 allowObjectToPrimitiveCast = source.allowObjectToPrimitiveCast(); 112 allowDefaultMethods = source.allowDefaultMethods(); 113 chk = Check.instance(context); 114 enter = Enter.instance(context); 115 capturedName = names.fromString("<captured wildcard>"); 116 messages = JavacMessages.instance(context); 117 diags = JCDiagnostic.Factory.instance(context); 118 functionDescriptorLookupError = new FunctionDescriptorLookupError(); 119 noWarnings = new Warner(null); 120 } 121 // </editor-fold> 122 123 // <editor-fold defaultstate="collapsed" desc="bounds"> 124 /** 125 * Get a wildcard's upper bound, returning non-wildcards unchanged. 126 * @param t a type argument, either a wildcard or a type 127 */ 128 public Type wildUpperBound(Type t) { 129 if (t.hasTag(WILDCARD)) { 130 WildcardType w = (WildcardType) t; 131 if (w.isSuperBound()) 132 return w.bound == null ? syms.objectType : w.bound.bound; 133 else 134 return wildUpperBound(w.type); 135 } 136 else return t; 137 } 138 139 /** 140 * Get a capture variable's upper bound, returning other types unchanged. 141 * @param t a type 142 */ 143 public Type cvarUpperBound(Type t) { 144 if (t.hasTag(TYPEVAR)) { 145 TypeVar v = (TypeVar) t; 146 return v.isCaptured() ? cvarUpperBound(v.bound) : v; 147 } 148 else return t; 149 } 150 151 /** 152 * Get a wildcard's lower bound, returning non-wildcards unchanged. 153 * @param t a type argument, either a wildcard or a type 154 */ 155 public Type wildLowerBound(Type t) { 156 if (t.hasTag(WILDCARD)) { 157 WildcardType w = (WildcardType) t; 158 return w.isExtendsBound() ? syms.botType : wildLowerBound(w.type); 159 } 160 else return t; 161 } 162 163 /** 164 * Get a capture variable's lower bound, returning other types unchanged. 165 * @param t a type 166 */ 167 public Type cvarLowerBound(Type t) { 168 if (t.hasTag(TYPEVAR) && ((TypeVar) t).isCaptured()) { 169 return cvarLowerBound(t.getLowerBound()); 170 } 171 else return t; 172 } 173 174 /** 175 * Recursively skip type-variables until a class/array type is found; capture conversion is then 176 * (optionally) applied to the resulting type. This is useful for i.e. computing a site that is 177 * suitable for a method lookup. 178 */ 179 public Type skipTypeVars(Type site, boolean capture) { 180 while (site.hasTag(TYPEVAR)) { 181 site = site.getUpperBound(); 182 } 183 return capture ? capture(site) : site; 184 } 185 // </editor-fold> 186 187 // <editor-fold defaultstate="collapsed" desc="isUnbounded"> 188 /** 189 * Checks that all the arguments to a class are unbounded 190 * wildcards or something else that doesn't make any restrictions 191 * on the arguments. If a class isUnbounded, a raw super- or 192 * subclass can be cast to it without a warning. 193 * @param t a type 194 * @return true iff the given type is unbounded or raw 195 */ 196 public boolean isUnbounded(Type t) { 197 return isUnbounded.visit(t); 198 } 199 // where 200 private final UnaryVisitor<Boolean> isUnbounded = new UnaryVisitor<Boolean>() { 201 202 public Boolean visitType(Type t, Void ignored) { 203 return true; 204 } 205 206 @Override 207 public Boolean visitClassType(ClassType t, Void ignored) { 208 List<Type> parms = t.tsym.type.allparams(); 209 List<Type> args = t.allparams(); 210 while (parms.nonEmpty()) { 211 WildcardType unb = new WildcardType(syms.objectType, 212 BoundKind.UNBOUND, 213 syms.boundClass, 214 (TypeVar)parms.head); 215 if (!containsType(args.head, unb)) 216 return false; 217 parms = parms.tail; 218 args = args.tail; 219 } 220 return true; 221 } 222 }; 223 // </editor-fold> 224 225 // <editor-fold defaultstate="collapsed" desc="asSub"> 226 /** 227 * Return the least specific subtype of t that starts with symbol 228 * sym. If none exists, return null. The least specific subtype 229 * is determined as follows: 230 * 231 * <p>If there is exactly one parameterized instance of sym that is a 232 * subtype of t, that parameterized instance is returned.<br> 233 * Otherwise, if the plain type or raw type `sym' is a subtype of 234 * type t, the type `sym' itself is returned. Otherwise, null is 235 * returned. 236 */ 237 public Type asSub(Type t, Symbol sym) { 238 return asSub.visit(t, sym); 239 } 240 // where 241 private final SimpleVisitor<Type,Symbol> asSub = new SimpleVisitor<Type,Symbol>() { 242 243 public Type visitType(Type t, Symbol sym) { 244 return null; 245 } 246 247 @Override 248 public Type visitClassType(ClassType t, Symbol sym) { 249 if (t.tsym == sym) 250 return t; 251 Type base = asSuper(sym.type, t.tsym); 252 if (base == null) 253 return null; 254 ListBuffer<Type> from = new ListBuffer<>(); 255 ListBuffer<Type> to = new ListBuffer<>(); 256 try { 257 adapt(base, t, from, to); 258 } catch (AdaptFailure ex) { 259 return null; 260 } 261 Type res = subst(sym.type, from.toList(), to.toList()); 262 if (!isSubtype(res, t)) 263 return null; 264 ListBuffer<Type> openVars = new ListBuffer<>(); 265 for (List<Type> l = sym.type.allparams(); 266 l.nonEmpty(); l = l.tail) 267 if (res.contains(l.head) && !t.contains(l.head)) 268 openVars.append(l.head); 269 if (openVars.nonEmpty()) { 270 if (t.isRaw()) { 271 // The subtype of a raw type is raw 272 res = erasure(res); 273 } else { 274 // Unbound type arguments default to ? 275 List<Type> opens = openVars.toList(); 276 ListBuffer<Type> qs = new ListBuffer<>(); 277 for (List<Type> iter = opens; iter.nonEmpty(); iter = iter.tail) { 278 qs.append(new WildcardType(syms.objectType, BoundKind.UNBOUND, 279 syms.boundClass, (TypeVar) iter.head)); 280 } 281 res = subst(res, opens, qs.toList()); 282 } 283 } 284 return res; 285 } 286 287 @Override 288 public Type visitErrorType(ErrorType t, Symbol sym) { 289 return t; 290 } 291 }; 292 // </editor-fold> 293 294 // <editor-fold defaultstate="collapsed" desc="isConvertible"> 295 /** 296 * Is t a subtype of or convertible via boxing/unboxing 297 * conversion to s? 298 */ 299 public boolean isConvertible(Type t, Type s, Warner warn) { 300 if (t.hasTag(ERROR)) { 301 return true; 302 } 303 boolean tPrimitive = t.isPrimitive(); 304 boolean sPrimitive = s.isPrimitive(); 305 if (tPrimitive == sPrimitive) { 306 return isSubtypeUnchecked(t, s, warn); 307 } 308 return tPrimitive 309 ? isSubtype(boxedClass(t).type, s) 310 : isSubtype(unboxedType(t), s); 311 } 312 313 /** 314 * Is t a subtype of or convertible via boxing/unboxing 315 * conversions to s? 316 */ 317 public boolean isConvertible(Type t, Type s) { 318 return isConvertible(t, s, noWarnings); 319 } 320 // </editor-fold> 321 322 // <editor-fold defaultstate="collapsed" desc="findSam"> 323 324 /** 325 * Exception used to report a function descriptor lookup failure. The exception 326 * wraps a diagnostic that can be used to generate more details error 327 * messages. 328 */ 329 public static class FunctionDescriptorLookupError extends RuntimeException { 330 private static final long serialVersionUID = 0; 331 332 JCDiagnostic diagnostic; 333 334 FunctionDescriptorLookupError() { 335 this.diagnostic = null; 336 } 337 338 FunctionDescriptorLookupError setMessage(JCDiagnostic diag) { 339 this.diagnostic = diag; 340 return this; 341 } 342 343 public JCDiagnostic getDiagnostic() { 344 return diagnostic; 345 } 346 } 347 348 /** 349 * A cache that keeps track of function descriptors associated with given 350 * functional interfaces. 351 */ 352 class DescriptorCache { 353 354 private WeakHashMap<TypeSymbol, Entry> _map = new WeakHashMap<>(); 355 356 class FunctionDescriptor { 357 Symbol descSym; 358 359 FunctionDescriptor(Symbol descSym) { 360 this.descSym = descSym; 361 } 362 363 public Symbol getSymbol() { 364 return descSym; 365 } 366 367 public Type getType(Type site) { 368 site = removeWildcards(site); 369 if (!chk.checkValidGenericType(site)) { 370 //if the inferred functional interface type is not well-formed, 371 //or if it's not a subtype of the original target, issue an error 372 throw failure(diags.fragment("no.suitable.functional.intf.inst", site)); 373 } 374 return memberType(site, descSym); 375 } 376 } 377 378 class Entry { 379 final FunctionDescriptor cachedDescRes; 380 final int prevMark; 381 382 public Entry(FunctionDescriptor cachedDescRes, 383 int prevMark) { 384 this.cachedDescRes = cachedDescRes; 385 this.prevMark = prevMark; 386 } 387 388 boolean matches(int mark) { 389 return this.prevMark == mark; 390 } 391 } 392 393 FunctionDescriptor get(TypeSymbol origin) throws FunctionDescriptorLookupError { 394 Entry e = _map.get(origin); 395 CompoundScope members = membersClosure(origin.type, false); 396 if (e == null || 397 !e.matches(members.getMark())) { 398 FunctionDescriptor descRes = findDescriptorInternal(origin, members); 399 _map.put(origin, new Entry(descRes, members.getMark())); 400 return descRes; 401 } 402 else { 403 return e.cachedDescRes; 404 } 405 } 406 407 /** 408 * Compute the function descriptor associated with a given functional interface 409 */ 410 public FunctionDescriptor findDescriptorInternal(TypeSymbol origin, 411 CompoundScope membersCache) throws FunctionDescriptorLookupError { 412 if (!origin.isInterface() || (origin.flags() & ANNOTATION) != 0) { 413 //t must be an interface 414 throw failure("not.a.functional.intf", origin); 415 } 416 417 final ListBuffer<Symbol> abstracts = new ListBuffer<>(); 418 for (Symbol sym : membersCache.getSymbols(new DescriptorFilter(origin))) { 419 Type mtype = memberType(origin.type, sym); 420 if (abstracts.isEmpty() || 421 (sym.name == abstracts.first().name && 422 overrideEquivalent(mtype, memberType(origin.type, abstracts.first())))) { 423 abstracts.append(sym); 424 } else { 425 //the target method(s) should be the only abstract members of t 426 throw failure("not.a.functional.intf.1", origin, 427 diags.fragment("incompatible.abstracts", Kinds.kindName(origin), origin)); 428 } 429 } 430 if (abstracts.isEmpty()) { 431 //t must define a suitable non-generic method 432 throw failure("not.a.functional.intf.1", origin, 433 diags.fragment("no.abstracts", Kinds.kindName(origin), origin)); 434 } else if (abstracts.size() == 1) { 435 return new FunctionDescriptor(abstracts.first()); 436 } else { // size > 1 437 FunctionDescriptor descRes = mergeDescriptors(origin, abstracts.toList()); 438 if (descRes == null) { 439 //we can get here if the functional interface is ill-formed 440 ListBuffer<JCDiagnostic> descriptors = new ListBuffer<>(); 441 for (Symbol desc : abstracts) { 442 String key = desc.type.getThrownTypes().nonEmpty() ? 443 "descriptor.throws" : "descriptor"; 444 descriptors.append(diags.fragment(key, desc.name, 445 desc.type.getParameterTypes(), 446 desc.type.getReturnType(), 447 desc.type.getThrownTypes())); 448 } 449 JCDiagnostic.MultilineDiagnostic incompatibleDescriptors = 450 new JCDiagnostic.MultilineDiagnostic(diags.fragment("incompatible.descs.in.functional.intf", 451 Kinds.kindName(origin), origin), descriptors.toList()); 452 throw failure(incompatibleDescriptors); 453 } 454 return descRes; 455 } 456 } 457 458 /** 459 * Compute a synthetic type for the target descriptor given a list 460 * of override-equivalent methods in the functional interface type. 461 * The resulting method type is a method type that is override-equivalent 462 * and return-type substitutable with each method in the original list. 463 */ 464 private FunctionDescriptor mergeDescriptors(TypeSymbol origin, List<Symbol> methodSyms) { 465 //pick argument types - simply take the signature that is a 466 //subsignature of all other signatures in the list (as per JLS 8.4.2) 467 List<Symbol> mostSpecific = List.nil(); 468 outer: for (Symbol msym1 : methodSyms) { 469 Type mt1 = memberType(origin.type, msym1); 470 for (Symbol msym2 : methodSyms) { 471 Type mt2 = memberType(origin.type, msym2); 472 if (!isSubSignature(mt1, mt2)) { 473 continue outer; 474 } 475 } 476 mostSpecific = mostSpecific.prepend(msym1); 477 } 478 if (mostSpecific.isEmpty()) { 479 return null; 480 } 481 482 483 //pick return types - this is done in two phases: (i) first, the most 484 //specific return type is chosen using strict subtyping; if this fails, 485 //a second attempt is made using return type substitutability (see JLS 8.4.5) 486 boolean phase2 = false; 487 Symbol bestSoFar = null; 488 while (bestSoFar == null) { 489 outer: for (Symbol msym1 : mostSpecific) { 490 Type mt1 = memberType(origin.type, msym1); 491 for (Symbol msym2 : methodSyms) { 492 Type mt2 = memberType(origin.type, msym2); 493 if (phase2 ? 494 !returnTypeSubstitutable(mt1, mt2) : 495 !isSubtypeInternal(mt1.getReturnType(), mt2.getReturnType())) { 496 continue outer; 497 } 498 } 499 bestSoFar = msym1; 500 } 501 if (phase2) { 502 break; 503 } else { 504 phase2 = true; 505 } 506 } 507 if (bestSoFar == null) return null; 508 509 //merge thrown types - form the intersection of all the thrown types in 510 //all the signatures in the list 511 boolean toErase = !bestSoFar.type.hasTag(FORALL); 512 List<Type> thrown = null; 513 Type mt1 = memberType(origin.type, bestSoFar); 514 for (Symbol msym2 : methodSyms) { 515 Type mt2 = memberType(origin.type, msym2); 516 List<Type> thrown_mt2 = mt2.getThrownTypes(); 517 if (toErase) { 518 thrown_mt2 = erasure(thrown_mt2); 519 } else { 520 /* If bestSoFar is generic then all the methods are generic. 521 * The opposite is not true: a non generic method can override 522 * a generic method (raw override) so it's safe to cast mt1 and 523 * mt2 to ForAll. 524 */ 525 ForAll fa1 = (ForAll)mt1; 526 ForAll fa2 = (ForAll)mt2; 527 thrown_mt2 = subst(thrown_mt2, fa2.tvars, fa1.tvars); 528 } 529 thrown = (thrown == null) ? 530 thrown_mt2 : 531 chk.intersect(thrown_mt2, thrown); 532 } 533 534 final List<Type> thrown1 = thrown; 535 return new FunctionDescriptor(bestSoFar) { 536 @Override 537 public Type getType(Type origin) { 538 Type mt = memberType(origin, getSymbol()); 539 return createMethodTypeWithThrown(mt, thrown1); 540 } 541 }; 542 } 543 544 boolean isSubtypeInternal(Type s, Type t) { 545 return (s.isPrimitive() && t.isPrimitive()) ? 546 isSameType(t, s) : 547 isSubtype(s, t); 548 } 549 550 FunctionDescriptorLookupError failure(String msg, Object... args) { 551 return failure(diags.fragment(msg, args)); 552 } 553 554 FunctionDescriptorLookupError failure(JCDiagnostic diag) { 555 return functionDescriptorLookupError.setMessage(diag); 556 } 557 } 558 559 private DescriptorCache descCache = new DescriptorCache(); 560 561 /** 562 * Find the method descriptor associated to this class symbol - if the 563 * symbol 'origin' is not a functional interface, an exception is thrown. 564 */ 565 public Symbol findDescriptorSymbol(TypeSymbol origin) throws FunctionDescriptorLookupError { 566 return descCache.get(origin).getSymbol(); 567 } 568 569 /** 570 * Find the type of the method descriptor associated to this class symbol - 571 * if the symbol 'origin' is not a functional interface, an exception is thrown. 572 */ 573 public Type findDescriptorType(Type origin) throws FunctionDescriptorLookupError { 574 return descCache.get(origin.tsym).getType(origin); 575 } 576 577 /** 578 * Is given type a functional interface? 579 */ 580 public boolean isFunctionalInterface(TypeSymbol tsym) { 581 try { 582 findDescriptorSymbol(tsym); 583 return true; 584 } catch (FunctionDescriptorLookupError ex) { 585 return false; 586 } 587 } 588 589 public boolean isFunctionalInterface(Type site) { 590 try { 591 findDescriptorType(site); 592 return true; 593 } catch (FunctionDescriptorLookupError ex) { 594 return false; 595 } 596 } 597 598 public Type removeWildcards(Type site) { 599 Type capturedSite = capture(site); 600 if (capturedSite != site) { 601 Type formalInterface = site.tsym.type; 602 ListBuffer<Type> typeargs = new ListBuffer<>(); 603 List<Type> actualTypeargs = site.getTypeArguments(); 604 List<Type> capturedTypeargs = capturedSite.getTypeArguments(); 605 //simply replace the wildcards with its bound 606 for (Type t : formalInterface.getTypeArguments()) { 607 if (actualTypeargs.head.hasTag(WILDCARD)) { 608 WildcardType wt = (WildcardType)actualTypeargs.head; 609 Type bound; 610 switch (wt.kind) { 611 case EXTENDS: 612 case UNBOUND: 613 CapturedType capVar = (CapturedType)capturedTypeargs.head; 614 //use declared bound if it doesn't depend on formal type-args 615 bound = capVar.bound.containsAny(capturedSite.getTypeArguments()) ? 616 wt.type : capVar.bound; 617 break; 618 default: 619 bound = wt.type; 620 } 621 typeargs.append(bound); 622 } else { 623 typeargs.append(actualTypeargs.head); 624 } 625 actualTypeargs = actualTypeargs.tail; 626 capturedTypeargs = capturedTypeargs.tail; 627 } 628 return subst(formalInterface, formalInterface.getTypeArguments(), typeargs.toList()); 629 } else { 630 return site; 631 } 632 } 633 634 /** 635 * Create a symbol for a class that implements a given functional interface 636 * and overrides its functional descriptor. This routine is used for two 637 * main purposes: (i) checking well-formedness of a functional interface; 638 * (ii) perform functional interface bridge calculation. 639 */ 640 public ClassSymbol makeFunctionalInterfaceClass(Env<AttrContext> env, Name name, List<Type> targets, long cflags) { 641 if (targets.isEmpty()) { 642 return null; 643 } 644 Symbol descSym = findDescriptorSymbol(targets.head.tsym); 645 Type descType = findDescriptorType(targets.head); 646 ClassSymbol csym = new ClassSymbol(cflags, name, env.enclClass.sym.outermostClass()); 647 csym.completer = null; 648 csym.members_field = WriteableScope.create(csym); 649 MethodSymbol instDescSym = new MethodSymbol(descSym.flags(), descSym.name, descType, csym); 650 csym.members_field.enter(instDescSym); 651 Type.ClassType ctype = new Type.ClassType(Type.noType, List.<Type>nil(), csym); 652 ctype.supertype_field = syms.objectType; 653 ctype.interfaces_field = targets; 654 csym.type = ctype; 655 csym.sourcefile = ((ClassSymbol)csym.owner).sourcefile; 656 return csym; 657 } 658 659 /** 660 * Find the minimal set of methods that are overridden by the functional 661 * descriptor in 'origin'. All returned methods are assumed to have different 662 * erased signatures. 663 */ 664 public List<Symbol> functionalInterfaceBridges(TypeSymbol origin) { 665 Assert.check(isFunctionalInterface(origin)); 666 Symbol descSym = findDescriptorSymbol(origin); 667 CompoundScope members = membersClosure(origin.type, false); 668 ListBuffer<Symbol> overridden = new ListBuffer<>(); 669 outer: for (Symbol m2 : members.getSymbolsByName(descSym.name, bridgeFilter)) { 670 if (m2 == descSym) continue; 671 else if (descSym.overrides(m2, origin, Types.this, false)) { 672 for (Symbol m3 : overridden) { 673 if (isSameType(m3.erasure(Types.this), m2.erasure(Types.this)) || 674 (m3.overrides(m2, origin, Types.this, false) && 675 (pendingBridges((ClassSymbol)origin, m3.enclClass()) || 676 (((MethodSymbol)m2).binaryImplementation((ClassSymbol)m3.owner, Types.this) != null)))) { 677 continue outer; 678 } 679 } 680 overridden.add(m2); 681 } 682 } 683 return overridden.toList(); 684 } 685 //where 686 private Filter<Symbol> bridgeFilter = new Filter<Symbol>() { 687 public boolean accepts(Symbol t) { 688 return t.kind == MTH && 689 t.name != names.init && 690 t.name != names.clinit && 691 (t.flags() & SYNTHETIC) == 0; 692 } 693 }; 694 private boolean pendingBridges(ClassSymbol origin, TypeSymbol s) { 695 //a symbol will be completed from a classfile if (a) symbol has 696 //an associated file object with CLASS kind and (b) the symbol has 697 //not been entered 698 if (origin.classfile != null && 699 origin.classfile.getKind() == JavaFileObject.Kind.CLASS && 700 enter.getEnv(origin) == null) { 701 return false; 702 } 703 if (origin == s) { 704 return true; 705 } 706 for (Type t : interfaces(origin.type)) { 707 if (pendingBridges((ClassSymbol)t.tsym, s)) { 708 return true; 709 } 710 } 711 return false; 712 } 713 // </editor-fold> 714 715 /** 716 * Scope filter used to skip methods that should be ignored (such as methods 717 * overridden by j.l.Object) during function interface conversion interface check 718 */ 719 class DescriptorFilter implements Filter<Symbol> { 720 721 TypeSymbol origin; 722 723 DescriptorFilter(TypeSymbol origin) { 724 this.origin = origin; 725 } 726 727 @Override 728 public boolean accepts(Symbol sym) { 729 return sym.kind == MTH && 730 (sym.flags() & (ABSTRACT | DEFAULT)) == ABSTRACT && 731 !overridesObjectMethod(origin, sym) && 732 (interfaceCandidates(origin.type, (MethodSymbol)sym).head.flags() & DEFAULT) == 0; 733 } 734 } 735 736 // <editor-fold defaultstate="collapsed" desc="isSubtype"> 737 /** 738 * Is t an unchecked subtype of s? 739 */ 740 public boolean isSubtypeUnchecked(Type t, Type s) { 741 return isSubtypeUnchecked(t, s, noWarnings); 742 } 743 /** 744 * Is t an unchecked subtype of s? 745 */ 746 public boolean isSubtypeUnchecked(Type t, Type s, Warner warn) { 747 boolean result = isSubtypeUncheckedInternal(t, s, warn); 748 if (result) { 749 checkUnsafeVarargsConversion(t, s, warn); 750 } 751 return result; 752 } 753 //where 754 private boolean isSubtypeUncheckedInternal(Type t, Type s, Warner warn) { 755 if (t.hasTag(ARRAY) && s.hasTag(ARRAY)) { 756 if (((ArrayType)t).elemtype.isPrimitive()) { 757 return isSameType(elemtype(t), elemtype(s)); 758 } else { 759 return isSubtypeUnchecked(elemtype(t), elemtype(s), warn); 760 } 761 } else if (isSubtype(t, s)) { 762 return true; 763 } else if (t.hasTag(TYPEVAR)) { 764 return isSubtypeUnchecked(t.getUpperBound(), s, warn); 765 } else if (!s.isRaw()) { 766 Type t2 = asSuper(t, s.tsym); 767 if (t2 != null && t2.isRaw()) { 768 if (isReifiable(s)) { 769 warn.silentWarn(LintCategory.UNCHECKED); 770 } else { 771 warn.warn(LintCategory.UNCHECKED); 772 } 773 return true; 774 } 775 } 776 return false; 777 } 778 779 private void checkUnsafeVarargsConversion(Type t, Type s, Warner warn) { 780 if (!t.hasTag(ARRAY) || isReifiable(t)) { 781 return; 782 } 783 ArrayType from = (ArrayType)t; 784 boolean shouldWarn = false; 785 switch (s.getTag()) { 786 case ARRAY: 787 ArrayType to = (ArrayType)s; 788 shouldWarn = from.isVarargs() && 789 !to.isVarargs() && 790 !isReifiable(from); 791 break; 792 case CLASS: 793 shouldWarn = from.isVarargs(); 794 break; 795 } 796 if (shouldWarn) { 797 warn.warn(LintCategory.VARARGS); 798 } 799 } 800 801 /** 802 * Is t a subtype of s?<br> 803 * (not defined for Method and ForAll types) 804 */ 805 final public boolean isSubtype(Type t, Type s) { 806 return isSubtype(t, s, true); 807 } 808 final public boolean isSubtypeNoCapture(Type t, Type s) { 809 return isSubtype(t, s, false); 810 } 811 public boolean isSubtype(Type t, Type s, boolean capture) { 812 if (t == s) 813 return true; 814 if (s.isPartial()) 815 return isSuperType(s, t); 816 817 if (s.isCompound()) { 818 for (Type s2 : interfaces(s).prepend(supertype(s))) { 819 if (!isSubtype(t, s2, capture)) 820 return false; 821 } 822 return true; 823 } 824 825 // Generally, if 's' is a lower-bounded type variable, recur on lower bound; but 826 // for inference variables and intersections, we need to keep 's' 827 // (see JLS 4.10.2 for intersections and 18.2.3 for inference vars) 828 if (!t.hasTag(UNDETVAR) && !t.isCompound()) { 829 // TODO: JDK-8039198, bounds checking sometimes passes in a wildcard as s 830 Type lower = cvarLowerBound(wildLowerBound(s)); 831 if (s != lower && !lower.hasTag(BOT)) 832 return isSubtype(capture ? capture(t) : t, lower, false); 833 } 834 835 return isSubtype.visit(capture ? capture(t) : t, s); 836 } 837 // where 838 private TypeRelation isSubtype = new TypeRelation() 839 { 840 @Override 841 public Boolean visitType(Type t, Type s) { 842 switch (t.getTag()) { 843 case BYTE: 844 return (!s.hasTag(CHAR) && t.getTag().isSubRangeOf(s.getTag())); 845 case CHAR: 846 return (!s.hasTag(SHORT) && t.getTag().isSubRangeOf(s.getTag())); 847 case SHORT: case INT: case LONG: 848 case FLOAT: case DOUBLE: 849 return t.getTag().isSubRangeOf(s.getTag()); 850 case BOOLEAN: case VOID: 851 return t.hasTag(s.getTag()); 852 case TYPEVAR: 853 return isSubtypeNoCapture(t.getUpperBound(), s); 854 case BOT: 855 return 856 s.hasTag(BOT) || s.hasTag(CLASS) || 857 s.hasTag(ARRAY) || s.hasTag(TYPEVAR); 858 case WILDCARD: //we shouldn't be here - avoids crash (see 7034495) 859 case NONE: 860 return false; 861 default: 862 throw new AssertionError("isSubtype " + t.getTag()); 863 } 864 } 865 866 private Set<TypePair> cache = new HashSet<>(); 867 868 private boolean containsTypeRecursive(Type t, Type s) { 869 TypePair pair = new TypePair(t, s); 870 if (cache.add(pair)) { 871 try { 872 return containsType(t.getTypeArguments(), 873 s.getTypeArguments()); 874 } finally { 875 cache.remove(pair); 876 } 877 } else { 878 return containsType(t.getTypeArguments(), 879 rewriteSupers(s).getTypeArguments()); 880 } 881 } 882 883 private Type rewriteSupers(Type t) { 884 if (!t.isParameterized()) 885 return t; 886 ListBuffer<Type> from = new ListBuffer<>(); 887 ListBuffer<Type> to = new ListBuffer<>(); 888 adaptSelf(t, from, to); 889 if (from.isEmpty()) 890 return t; 891 ListBuffer<Type> rewrite = new ListBuffer<>(); 892 boolean changed = false; 893 for (Type orig : to.toList()) { 894 Type s = rewriteSupers(orig); 895 if (s.isSuperBound() && !s.isExtendsBound()) { 896 s = new WildcardType(syms.objectType, 897 BoundKind.UNBOUND, 898 syms.boundClass, 899 s.getMetadata()); 900 changed = true; 901 } else if (s != orig) { 902 s = new WildcardType(wildUpperBound(s), 903 BoundKind.EXTENDS, 904 syms.boundClass, 905 s.getMetadata()); 906 changed = true; 907 } 908 rewrite.append(s); 909 } 910 if (changed) 911 return subst(t.tsym.type, from.toList(), rewrite.toList()); 912 else 913 return t; 914 } 915 916 @Override 917 public Boolean visitClassType(ClassType t, Type s) { 918 Type sup = asSuper(t, s.tsym); 919 if (sup == null) return false; 920 // If t is an intersection, sup might not be a class type 921 if (!sup.hasTag(CLASS)) return isSubtypeNoCapture(sup, s); 922 return sup.tsym == s.tsym 923 // Check type variable containment 924 && (!s.isParameterized() || containsTypeRecursive(s, sup)) 925 && isSubtypeNoCapture(sup.getEnclosingType(), 926 s.getEnclosingType()); 927 } 928 929 @Override 930 public Boolean visitArrayType(ArrayType t, Type s) { 931 if (s.hasTag(ARRAY)) { 932 if (t.elemtype.isPrimitive()) 933 return isSameType(t.elemtype, elemtype(s)); 934 else 935 return isSubtypeNoCapture(t.elemtype, elemtype(s)); 936 } 937 938 if (s.hasTag(CLASS)) { 939 Name sname = s.tsym.getQualifiedName(); 940 return sname == names.java_lang_Object 941 || sname == names.java_lang_Cloneable 942 || sname == names.java_io_Serializable; 943 } 944 945 return false; 946 } 947 948 @Override 949 public Boolean visitUndetVar(UndetVar t, Type s) { 950 //todo: test against origin needed? or replace with substitution? 951 if (t == s || t.qtype == s || s.hasTag(ERROR) || s.hasTag(UNKNOWN)) { 952 return true; 953 } else if (s.hasTag(BOT)) { 954 //if 's' is 'null' there's no instantiated type U for which 955 //U <: s (but 'null' itself, which is not a valid type) 956 return false; 957 } 958 959 t.addBound(InferenceBound.UPPER, s, Types.this); 960 return true; 961 } 962 963 @Override 964 public Boolean visitErrorType(ErrorType t, Type s) { 965 return true; 966 } 967 }; 968 969 /** 970 * Is t a subtype of every type in given list `ts'?<br> 971 * (not defined for Method and ForAll types)<br> 972 * Allows unchecked conversions. 973 */ 974 public boolean isSubtypeUnchecked(Type t, List<Type> ts, Warner warn) { 975 for (List<Type> l = ts; l.nonEmpty(); l = l.tail) 976 if (!isSubtypeUnchecked(t, l.head, warn)) 977 return false; 978 return true; 979 } 980 981 /** 982 * Are corresponding elements of ts subtypes of ss? If lists are 983 * of different length, return false. 984 */ 985 public boolean isSubtypes(List<Type> ts, List<Type> ss) { 986 while (ts.tail != null && ss.tail != null 987 /*inlined: ts.nonEmpty() && ss.nonEmpty()*/ && 988 isSubtype(ts.head, ss.head)) { 989 ts = ts.tail; 990 ss = ss.tail; 991 } 992 return ts.tail == null && ss.tail == null; 993 /*inlined: ts.isEmpty() && ss.isEmpty();*/ 994 } 995 996 /** 997 * Are corresponding elements of ts subtypes of ss, allowing 998 * unchecked conversions? If lists are of different length, 999 * return false. 1000 **/ 1001 public boolean isSubtypesUnchecked(List<Type> ts, List<Type> ss, Warner warn) { 1002 while (ts.tail != null && ss.tail != null 1003 /*inlined: ts.nonEmpty() && ss.nonEmpty()*/ && 1004 isSubtypeUnchecked(ts.head, ss.head, warn)) { 1005 ts = ts.tail; 1006 ss = ss.tail; 1007 } 1008 return ts.tail == null && ss.tail == null; 1009 /*inlined: ts.isEmpty() && ss.isEmpty();*/ 1010 } 1011 // </editor-fold> 1012 1013 // <editor-fold defaultstate="collapsed" desc="isSuperType"> 1014 /** 1015 * Is t a supertype of s? 1016 */ 1017 public boolean isSuperType(Type t, Type s) { 1018 switch (t.getTag()) { 1019 case ERROR: 1020 return true; 1021 case UNDETVAR: { 1022 UndetVar undet = (UndetVar)t; 1023 if (t == s || 1024 undet.qtype == s || 1025 s.hasTag(ERROR) || 1026 s.hasTag(BOT)) { 1027 return true; 1028 } 1029 undet.addBound(InferenceBound.LOWER, s, this); 1030 return true; 1031 } 1032 default: 1033 return isSubtype(s, t); 1034 } 1035 } 1036 // </editor-fold> 1037 1038 // <editor-fold defaultstate="collapsed" desc="isSameType"> 1039 /** 1040 * Are corresponding elements of the lists the same type? If 1041 * lists are of different length, return false. 1042 */ 1043 public boolean isSameTypes(List<Type> ts, List<Type> ss) { 1044 return isSameTypes(ts, ss, false); 1045 } 1046 public boolean isSameTypes(List<Type> ts, List<Type> ss, boolean strict) { 1047 while (ts.tail != null && ss.tail != null 1048 /*inlined: ts.nonEmpty() && ss.nonEmpty()*/ && 1049 isSameType(ts.head, ss.head, strict)) { 1050 ts = ts.tail; 1051 ss = ss.tail; 1052 } 1053 return ts.tail == null && ss.tail == null; 1054 /*inlined: ts.isEmpty() && ss.isEmpty();*/ 1055 } 1056 1057 /** 1058 * A polymorphic signature method (JLS SE 7, 8.4.1) is a method that 1059 * (i) is declared in the java.lang.invoke.MethodHandle class, (ii) takes 1060 * a single variable arity parameter (iii) whose declared type is Object[], 1061 * (iv) has a return type of Object and (v) is native. 1062 */ 1063 public boolean isSignaturePolymorphic(MethodSymbol msym) { 1064 List<Type> argtypes = msym.type.getParameterTypes(); 1065 return (msym.flags_field & NATIVE) != 0 && 1066 msym.owner == syms.methodHandleType.tsym && 1067 argtypes.tail.tail == null && 1068 argtypes.head.hasTag(TypeTag.ARRAY) && 1069 msym.type.getReturnType().tsym == syms.objectType.tsym && 1070 ((ArrayType)argtypes.head).elemtype.tsym == syms.objectType.tsym; 1071 } 1072 1073 /** 1074 * Is t the same type as s? 1075 */ 1076 public boolean isSameType(Type t, Type s) { 1077 return isSameType(t, s, false); 1078 } 1079 public boolean isSameType(Type t, Type s, boolean strict) { 1080 return strict ? 1081 isSameTypeStrict.visit(t, s) : 1082 isSameTypeLoose.visit(t, s); 1083 } 1084 public boolean isSameAnnotatedType(Type t, Type s) { 1085 return isSameAnnotatedType.visit(t, s); 1086 } 1087 // where 1088 abstract class SameTypeVisitor extends TypeRelation { 1089 1090 public Boolean visitType(Type t, Type s) { 1091 if (t == s) 1092 return true; 1093 1094 if (s.isPartial()) 1095 return visit(s, t); 1096 1097 switch (t.getTag()) { 1098 case BYTE: case CHAR: case SHORT: case INT: case LONG: case FLOAT: 1099 case DOUBLE: case BOOLEAN: case VOID: case BOT: case NONE: 1100 return t.hasTag(s.getTag()); 1101 case TYPEVAR: { 1102 if (s.hasTag(TYPEVAR)) { 1103 //type-substitution does not preserve type-var types 1104 //check that type var symbols and bounds are indeed the same 1105 return sameTypeVars((TypeVar)t, (TypeVar)s); 1106 } 1107 else { 1108 //special case for s == ? super X, where upper(s) = u 1109 //check that u == t, where u has been set by Type.withTypeVar 1110 return s.isSuperBound() && 1111 !s.isExtendsBound() && 1112 visit(t, wildUpperBound(s)); 1113 } 1114 } 1115 default: 1116 throw new AssertionError("isSameType " + t.getTag()); 1117 } 1118 } 1119 1120 abstract boolean sameTypeVars(TypeVar tv1, TypeVar tv2); 1121 1122 @Override 1123 public Boolean visitWildcardType(WildcardType t, Type s) { 1124 if (s.isPartial()) 1125 return visit(s, t); 1126 else 1127 return false; 1128 } 1129 1130 @Override 1131 public Boolean visitClassType(ClassType t, Type s) { 1132 if (t == s) 1133 return true; 1134 1135 if (s.isPartial()) 1136 return visit(s, t); 1137 1138 if (s.isSuperBound() && !s.isExtendsBound()) 1139 return visit(t, wildUpperBound(s)) && visit(t, wildLowerBound(s)); 1140 1141 if (t.isCompound() && s.isCompound()) { 1142 if (!visit(supertype(t), supertype(s))) 1143 return false; 1144 1145 HashSet<UniqueType> set = new HashSet<>(); 1146 for (Type x : interfaces(t)) 1147 set.add(new UniqueType(x, Types.this)); 1148 for (Type x : interfaces(s)) { 1149 if (!set.remove(new UniqueType(x, Types.this))) 1150 return false; 1151 } 1152 return (set.isEmpty()); 1153 } 1154 return t.tsym == s.tsym 1155 && visit(t.getEnclosingType(), s.getEnclosingType()) 1156 && containsTypes(t.getTypeArguments(), s.getTypeArguments()); 1157 } 1158 1159 abstract protected boolean containsTypes(List<Type> ts1, List<Type> ts2); 1160 1161 @Override 1162 public Boolean visitArrayType(ArrayType t, Type s) { 1163 if (t == s) 1164 return true; 1165 1166 if (s.isPartial()) 1167 return visit(s, t); 1168 1169 return s.hasTag(ARRAY) 1170 && containsTypeEquivalent(t.elemtype, elemtype(s)); 1171 } 1172 1173 @Override 1174 public Boolean visitMethodType(MethodType t, Type s) { 1175 // isSameType for methods does not take thrown 1176 // exceptions into account! 1177 return hasSameArgs(t, s) && visit(t.getReturnType(), s.getReturnType()); 1178 } 1179 1180 @Override 1181 public Boolean visitPackageType(PackageType t, Type s) { 1182 return t == s; 1183 } 1184 1185 @Override 1186 public Boolean visitForAll(ForAll t, Type s) { 1187 if (!s.hasTag(FORALL)) { 1188 return false; 1189 } 1190 1191 ForAll forAll = (ForAll)s; 1192 return hasSameBounds(t, forAll) 1193 && visit(t.qtype, subst(forAll.qtype, forAll.tvars, t.tvars)); 1194 } 1195 1196 @Override 1197 public Boolean visitUndetVar(UndetVar t, Type s) { 1198 if (s.hasTag(WILDCARD)) { 1199 // FIXME, this might be leftovers from before capture conversion 1200 return false; 1201 } 1202 1203 if (t == s || t.qtype == s || s.hasTag(ERROR) || s.hasTag(UNKNOWN)) { 1204 return true; 1205 } 1206 1207 t.addBound(InferenceBound.EQ, s, Types.this); 1208 1209 return true; 1210 } 1211 1212 @Override 1213 public Boolean visitErrorType(ErrorType t, Type s) { 1214 return true; 1215 } 1216 } 1217 1218 /** 1219 * Standard type-equality relation - type variables are considered 1220 * equals if they share the same type symbol. 1221 */ 1222 TypeRelation isSameTypeLoose = new LooseSameTypeVisitor(); 1223 1224 private class LooseSameTypeVisitor extends SameTypeVisitor { 1225 1226 /** cache of the type-variable pairs being (recursively) tested. */ 1227 private Set<TypePair> cache = new HashSet<>(); 1228 1229 @Override 1230 boolean sameTypeVars(TypeVar tv1, TypeVar tv2) { 1231 return tv1.tsym == tv2.tsym && checkSameBounds(tv1, tv2); 1232 } 1233 @Override 1234 protected boolean containsTypes(List<Type> ts1, List<Type> ts2) { 1235 return containsTypeEquivalent(ts1, ts2); 1236 } 1237 1238 /** 1239 * Since type-variable bounds can be recursive, we need to protect against 1240 * infinite loops - where the same bounds are checked over and over recursively. 1241 */ 1242 private boolean checkSameBounds(TypeVar tv1, TypeVar tv2) { 1243 TypePair p = new TypePair(tv1, tv2, true); 1244 if (cache.add(p)) { 1245 try { 1246 return visit(tv1.getUpperBound(), tv2.getUpperBound()); 1247 } finally { 1248 cache.remove(p); 1249 } 1250 } else { 1251 return false; 1252 } 1253 } 1254 }; 1255 1256 /** 1257 * Strict type-equality relation - type variables are considered 1258 * equals if they share the same object identity. 1259 */ 1260 TypeRelation isSameTypeStrict = new SameTypeVisitor() { 1261 @Override 1262 boolean sameTypeVars(TypeVar tv1, TypeVar tv2) { 1263 return tv1 == tv2; 1264 } 1265 @Override 1266 protected boolean containsTypes(List<Type> ts1, List<Type> ts2) { 1267 return isSameTypes(ts1, ts2, true); 1268 } 1269 1270 @Override 1271 public Boolean visitWildcardType(WildcardType t, Type s) { 1272 if (!s.hasTag(WILDCARD)) { 1273 return false; 1274 } else { 1275 WildcardType t2 = (WildcardType)s; 1276 return t.kind == t2.kind && 1277 isSameType(t.type, t2.type, true); 1278 } 1279 } 1280 }; 1281 1282 // </editor-fold> 1283 1284 TypeRelation isSameAnnotatedType = new LooseSameTypeVisitor() { 1285 private Boolean compareAnnotations(Type t1, Type t2) { 1286 List<Attribute.TypeCompound> annos1 = t1.getAnnotationMirrors(); 1287 List<Attribute.TypeCompound> annos2 = t2.getAnnotationMirrors(); 1288 return annos1.containsAll(annos2) && annos2.containsAll(annos1); 1289 } 1290 1291 @Override 1292 public Boolean visitType(Type t, Type s) { 1293 return compareAnnotations(t, s) && super.visitType(t, s); 1294 } 1295 1296 @Override 1297 public Boolean visitWildcardType(WildcardType t, Type s) { 1298 return compareAnnotations(t, s) && super.visitWildcardType(t, s); 1299 } 1300 1301 @Override 1302 public Boolean visitClassType(ClassType t, Type s) { 1303 return compareAnnotations(t, s) && super.visitClassType(t, s); 1304 } 1305 1306 @Override 1307 public Boolean visitArrayType(ArrayType t, Type s) { 1308 return compareAnnotations(t, s) && super.visitArrayType(t, s); 1309 } 1310 1311 @Override 1312 public Boolean visitForAll(ForAll t, Type s) { 1313 return compareAnnotations(t, s) && super.visitForAll(t, s); 1314 } 1315 }; 1316 1317 // <editor-fold defaultstate="collapsed" desc="Contains Type"> 1318 public boolean containedBy(Type t, Type s) { 1319 switch (t.getTag()) { 1320 case UNDETVAR: 1321 if (s.hasTag(WILDCARD)) { 1322 UndetVar undetvar = (UndetVar)t; 1323 WildcardType wt = (WildcardType)s; 1324 switch(wt.kind) { 1325 case UNBOUND: 1326 break; 1327 case EXTENDS: { 1328 Type bound = wildUpperBound(s); 1329 undetvar.addBound(InferenceBound.UPPER, bound, this); 1330 break; 1331 } 1332 case SUPER: { 1333 Type bound = wildLowerBound(s); 1334 undetvar.addBound(InferenceBound.LOWER, bound, this); 1335 break; 1336 } 1337 } 1338 return true; 1339 } else { 1340 return isSameType(t, s); 1341 } 1342 case ERROR: 1343 return true; 1344 default: 1345 return containsType(s, t); 1346 } 1347 } 1348 1349 boolean containsType(List<Type> ts, List<Type> ss) { 1350 while (ts.nonEmpty() && ss.nonEmpty() 1351 && containsType(ts.head, ss.head)) { 1352 ts = ts.tail; 1353 ss = ss.tail; 1354 } 1355 return ts.isEmpty() && ss.isEmpty(); 1356 } 1357 1358 /** 1359 * Check if t contains s. 1360 * 1361 * <p>T contains S if: 1362 * 1363 * <p>{@code L(T) <: L(S) && U(S) <: U(T)} 1364 * 1365 * <p>This relation is only used by ClassType.isSubtype(), that 1366 * is, 1367 * 1368 * <p>{@code C<S> <: C<T> if T contains S.} 1369 * 1370 * <p>Because of F-bounds, this relation can lead to infinite 1371 * recursion. Thus we must somehow break that recursion. Notice 1372 * that containsType() is only called from ClassType.isSubtype(). 1373 * Since the arguments have already been checked against their 1374 * bounds, we know: 1375 * 1376 * <p>{@code U(S) <: U(T) if T is "super" bound (U(T) *is* the bound)} 1377 * 1378 * <p>{@code L(T) <: L(S) if T is "extends" bound (L(T) is bottom)} 1379 * 1380 * @param t a type 1381 * @param s a type 1382 */ 1383 public boolean containsType(Type t, Type s) { 1384 return containsType.visit(t, s); 1385 } 1386 // where 1387 private TypeRelation containsType = new TypeRelation() { 1388 1389 public Boolean visitType(Type t, Type s) { 1390 if (s.isPartial()) 1391 return containedBy(s, t); 1392 else 1393 return isSameType(t, s); 1394 } 1395 1396// void debugContainsType(WildcardType t, Type s) { 1397// System.err.println(); 1398// System.err.format(" does %s contain %s?%n", t, s); 1399// System.err.format(" %s U(%s) <: U(%s) %s = %s%n", 1400// wildUpperBound(s), s, t, wildUpperBound(t), 1401// t.isSuperBound() 1402// || isSubtypeNoCapture(wildUpperBound(s), wildUpperBound(t))); 1403// System.err.format(" %s L(%s) <: L(%s) %s = %s%n", 1404// wildLowerBound(t), t, s, wildLowerBound(s), 1405// t.isExtendsBound() 1406// || isSubtypeNoCapture(wildLowerBound(t), wildLowerBound(s))); 1407// System.err.println(); 1408// } 1409 1410 @Override 1411 public Boolean visitWildcardType(WildcardType t, Type s) { 1412 if (s.isPartial()) 1413 return containedBy(s, t); 1414 else { 1415// debugContainsType(t, s); 1416 return isSameWildcard(t, s) 1417 || isCaptureOf(s, t) 1418 || ((t.isExtendsBound() || isSubtypeNoCapture(wildLowerBound(t), wildLowerBound(s))) && 1419 (t.isSuperBound() || isSubtypeNoCapture(wildUpperBound(s), wildUpperBound(t)))); 1420 } 1421 } 1422 1423 @Override 1424 public Boolean visitUndetVar(UndetVar t, Type s) { 1425 if (!s.hasTag(WILDCARD)) { 1426 return isSameType(t, s); 1427 } else { 1428 return false; 1429 } 1430 } 1431 1432 @Override 1433 public Boolean visitErrorType(ErrorType t, Type s) { 1434 return true; 1435 } 1436 }; 1437 1438 public boolean isCaptureOf(Type s, WildcardType t) { 1439 if (!s.hasTag(TYPEVAR) || !((TypeVar)s).isCaptured()) 1440 return false; 1441 return isSameWildcard(t, ((CapturedType)s).wildcard); 1442 } 1443 1444 public boolean isSameWildcard(WildcardType t, Type s) { 1445 if (!s.hasTag(WILDCARD)) 1446 return false; 1447 WildcardType w = (WildcardType)s; 1448 return w.kind == t.kind && w.type == t.type; 1449 } 1450 1451 public boolean containsTypeEquivalent(List<Type> ts, List<Type> ss) { 1452 while (ts.nonEmpty() && ss.nonEmpty() 1453 && containsTypeEquivalent(ts.head, ss.head)) { 1454 ts = ts.tail; 1455 ss = ss.tail; 1456 } 1457 return ts.isEmpty() && ss.isEmpty(); 1458 } 1459 // </editor-fold> 1460 1461 // <editor-fold defaultstate="collapsed" desc="isCastable"> 1462 public boolean isCastable(Type t, Type s) { 1463 return isCastable(t, s, noWarnings); 1464 } 1465 1466 /** 1467 * Is t is castable to s?<br> 1468 * s is assumed to be an erased type.<br> 1469 * (not defined for Method and ForAll types). 1470 */ 1471 public boolean isCastable(Type t, Type s, Warner warn) { 1472 if (t == s) 1473 return true; 1474 1475 if (t.isPrimitive() != s.isPrimitive()) 1476 return (isConvertible(t, s, warn) 1477 || (allowObjectToPrimitiveCast && 1478 s.isPrimitive() && 1479 isSubtype(boxedClass(s).type, t))); 1480 if (warn != warnStack.head) { 1481 try { 1482 warnStack = warnStack.prepend(warn); 1483 checkUnsafeVarargsConversion(t, s, warn); 1484 return isCastable.visit(t,s); 1485 } finally { 1486 warnStack = warnStack.tail; 1487 } 1488 } else { 1489 return isCastable.visit(t,s); 1490 } 1491 } 1492 // where 1493 private TypeRelation isCastable = new TypeRelation() { 1494 1495 public Boolean visitType(Type t, Type s) { 1496 if (s.hasTag(ERROR)) 1497 return true; 1498 1499 switch (t.getTag()) { 1500 case BYTE: case CHAR: case SHORT: case INT: case LONG: case FLOAT: 1501 case DOUBLE: 1502 return s.isNumeric(); 1503 case BOOLEAN: 1504 return s.hasTag(BOOLEAN); 1505 case VOID: 1506 return false; 1507 case BOT: 1508 return isSubtype(t, s); 1509 default: 1510 throw new AssertionError(); 1511 } 1512 } 1513 1514 @Override 1515 public Boolean visitWildcardType(WildcardType t, Type s) { 1516 return isCastable(wildUpperBound(t), s, warnStack.head); 1517 } 1518 1519 @Override 1520 public Boolean visitClassType(ClassType t, Type s) { 1521 if (s.hasTag(ERROR) || s.hasTag(BOT)) 1522 return true; 1523 1524 if (s.hasTag(TYPEVAR)) { 1525 if (isCastable(t, s.getUpperBound(), noWarnings)) { 1526 warnStack.head.warn(LintCategory.UNCHECKED); 1527 return true; 1528 } else { 1529 return false; 1530 } 1531 } 1532 1533 if (t.isIntersection() || s.isIntersection()) { 1534 return !t.isIntersection() ? 1535 visitIntersectionType((IntersectionClassType)s, t, true) : 1536 visitIntersectionType((IntersectionClassType)t, s, false); 1537 } 1538 1539 if (s.hasTag(CLASS) || s.hasTag(ARRAY)) { 1540 boolean upcast; 1541 if ((upcast = isSubtype(erasure(t), erasure(s))) 1542 || isSubtype(erasure(s), erasure(t))) { 1543 if (!upcast && s.hasTag(ARRAY)) { 1544 if (!isReifiable(s)) 1545 warnStack.head.warn(LintCategory.UNCHECKED); 1546 return true; 1547 } else if (s.isRaw()) { 1548 return true; 1549 } else if (t.isRaw()) { 1550 if (!isUnbounded(s)) 1551 warnStack.head.warn(LintCategory.UNCHECKED); 1552 return true; 1553 } 1554 // Assume |a| <: |b| 1555 final Type a = upcast ? t : s; 1556 final Type b = upcast ? s : t; 1557 final boolean HIGH = true; 1558 final boolean LOW = false; 1559 final boolean DONT_REWRITE_TYPEVARS = false; 1560 Type aHigh = rewriteQuantifiers(a, HIGH, DONT_REWRITE_TYPEVARS); 1561 Type aLow = rewriteQuantifiers(a, LOW, DONT_REWRITE_TYPEVARS); 1562 Type bHigh = rewriteQuantifiers(b, HIGH, DONT_REWRITE_TYPEVARS); 1563 Type bLow = rewriteQuantifiers(b, LOW, DONT_REWRITE_TYPEVARS); 1564 Type lowSub = asSub(bLow, aLow.tsym); 1565 Type highSub = (lowSub == null) ? null : asSub(bHigh, aHigh.tsym); 1566 if (highSub == null) { 1567 final boolean REWRITE_TYPEVARS = true; 1568 aHigh = rewriteQuantifiers(a, HIGH, REWRITE_TYPEVARS); 1569 aLow = rewriteQuantifiers(a, LOW, REWRITE_TYPEVARS); 1570 bHigh = rewriteQuantifiers(b, HIGH, REWRITE_TYPEVARS); 1571 bLow = rewriteQuantifiers(b, LOW, REWRITE_TYPEVARS); 1572 lowSub = asSub(bLow, aLow.tsym); 1573 highSub = (lowSub == null) ? null : asSub(bHigh, aHigh.tsym); 1574 } 1575 if (highSub != null) { 1576 if (!(a.tsym == highSub.tsym && a.tsym == lowSub.tsym)) { 1577 Assert.error(a.tsym + " != " + highSub.tsym + " != " + lowSub.tsym); 1578 } 1579 if (!disjointTypes(aHigh.allparams(), highSub.allparams()) 1580 && !disjointTypes(aHigh.allparams(), lowSub.allparams()) 1581 && !disjointTypes(aLow.allparams(), highSub.allparams()) 1582 && !disjointTypes(aLow.allparams(), lowSub.allparams())) { 1583 if (upcast ? giveWarning(a, b) : 1584 giveWarning(b, a)) 1585 warnStack.head.warn(LintCategory.UNCHECKED); 1586 return true; 1587 } 1588 } 1589 if (isReifiable(s)) 1590 return isSubtypeUnchecked(a, b); 1591 else 1592 return isSubtypeUnchecked(a, b, warnStack.head); 1593 } 1594 1595 // Sidecast 1596 if (s.hasTag(CLASS)) { 1597 if ((s.tsym.flags() & INTERFACE) != 0) { 1598 return ((t.tsym.flags() & FINAL) == 0) 1599 ? sideCast(t, s, warnStack.head) 1600 : sideCastFinal(t, s, warnStack.head); 1601 } else if ((t.tsym.flags() & INTERFACE) != 0) { 1602 return ((s.tsym.flags() & FINAL) == 0) 1603 ? sideCast(t, s, warnStack.head) 1604 : sideCastFinal(t, s, warnStack.head); 1605 } else { 1606 // unrelated class types 1607 return false; 1608 } 1609 } 1610 } 1611 return false; 1612 } 1613 1614 boolean visitIntersectionType(IntersectionClassType ict, Type s, boolean reverse) { 1615 Warner warn = noWarnings; 1616 for (Type c : ict.getComponents()) { 1617 warn.clear(); 1618 if (reverse ? !isCastable(s, c, warn) : !isCastable(c, s, warn)) 1619 return false; 1620 } 1621 if (warn.hasLint(LintCategory.UNCHECKED)) 1622 warnStack.head.warn(LintCategory.UNCHECKED); 1623 return true; 1624 } 1625 1626 @Override 1627 public Boolean visitArrayType(ArrayType t, Type s) { 1628 switch (s.getTag()) { 1629 case ERROR: 1630 case BOT: 1631 return true; 1632 case TYPEVAR: 1633 if (isCastable(s, t, noWarnings)) { 1634 warnStack.head.warn(LintCategory.UNCHECKED); 1635 return true; 1636 } else { 1637 return false; 1638 } 1639 case CLASS: 1640 return isSubtype(t, s); 1641 case ARRAY: 1642 if (elemtype(t).isPrimitive() || elemtype(s).isPrimitive()) { 1643 return elemtype(t).hasTag(elemtype(s).getTag()); 1644 } else { 1645 return visit(elemtype(t), elemtype(s)); 1646 } 1647 default: 1648 return false; 1649 } 1650 } 1651 1652 @Override 1653 public Boolean visitTypeVar(TypeVar t, Type s) { 1654 switch (s.getTag()) { 1655 case ERROR: 1656 case BOT: 1657 return true; 1658 case TYPEVAR: 1659 if (isSubtype(t, s)) { 1660 return true; 1661 } else if (isCastable(t.bound, s, noWarnings)) { 1662 warnStack.head.warn(LintCategory.UNCHECKED); 1663 return true; 1664 } else { 1665 return false; 1666 } 1667 default: 1668 return isCastable(t.bound, s, warnStack.head); 1669 } 1670 } 1671 1672 @Override 1673 public Boolean visitErrorType(ErrorType t, Type s) { 1674 return true; 1675 } 1676 }; 1677 // </editor-fold> 1678 1679 // <editor-fold defaultstate="collapsed" desc="disjointTypes"> 1680 public boolean disjointTypes(List<Type> ts, List<Type> ss) { 1681 while (ts.tail != null && ss.tail != null) { 1682 if (disjointType(ts.head, ss.head)) return true; 1683 ts = ts.tail; 1684 ss = ss.tail; 1685 } 1686 return false; 1687 } 1688 1689 /** 1690 * Two types or wildcards are considered disjoint if it can be 1691 * proven that no type can be contained in both. It is 1692 * conservative in that it is allowed to say that two types are 1693 * not disjoint, even though they actually are. 1694 * 1695 * The type {@code C<X>} is castable to {@code C<Y>} exactly if 1696 * {@code X} and {@code Y} are not disjoint. 1697 */ 1698 public boolean disjointType(Type t, Type s) { 1699 return disjointType.visit(t, s); 1700 } 1701 // where 1702 private TypeRelation disjointType = new TypeRelation() { 1703 1704 private Set<TypePair> cache = new HashSet<>(); 1705 1706 @Override 1707 public Boolean visitType(Type t, Type s) { 1708 if (s.hasTag(WILDCARD)) 1709 return visit(s, t); 1710 else 1711 return notSoftSubtypeRecursive(t, s) || notSoftSubtypeRecursive(s, t); 1712 } 1713 1714 private boolean isCastableRecursive(Type t, Type s) { 1715 TypePair pair = new TypePair(t, s); 1716 if (cache.add(pair)) { 1717 try { 1718 return Types.this.isCastable(t, s); 1719 } finally { 1720 cache.remove(pair); 1721 } 1722 } else { 1723 return true; 1724 } 1725 } 1726 1727 private boolean notSoftSubtypeRecursive(Type t, Type s) { 1728 TypePair pair = new TypePair(t, s); 1729 if (cache.add(pair)) { 1730 try { 1731 return Types.this.notSoftSubtype(t, s); 1732 } finally { 1733 cache.remove(pair); 1734 } 1735 } else { 1736 return false; 1737 } 1738 } 1739 1740 @Override 1741 public Boolean visitWildcardType(WildcardType t, Type s) { 1742 if (t.isUnbound()) 1743 return false; 1744 1745 if (!s.hasTag(WILDCARD)) { 1746 if (t.isExtendsBound()) 1747 return notSoftSubtypeRecursive(s, t.type); 1748 else 1749 return notSoftSubtypeRecursive(t.type, s); 1750 } 1751 1752 if (s.isUnbound()) 1753 return false; 1754 1755 if (t.isExtendsBound()) { 1756 if (s.isExtendsBound()) 1757 return !isCastableRecursive(t.type, wildUpperBound(s)); 1758 else if (s.isSuperBound()) 1759 return notSoftSubtypeRecursive(wildLowerBound(s), t.type); 1760 } else if (t.isSuperBound()) { 1761 if (s.isExtendsBound()) 1762 return notSoftSubtypeRecursive(t.type, wildUpperBound(s)); 1763 } 1764 return false; 1765 } 1766 }; 1767 // </editor-fold> 1768 1769 // <editor-fold defaultstate="collapsed" desc="cvarLowerBounds"> 1770 public List<Type> cvarLowerBounds(List<Type> ts) { 1771 return ts.map(cvarLowerBoundMapping); 1772 } 1773 private final TypeMapping<Void> cvarLowerBoundMapping = new TypeMapping<Void>() { 1774 @Override 1775 public Type visitCapturedType(CapturedType t, Void _unused) { 1776 return cvarLowerBound(t); 1777 } 1778 }; 1779 // </editor-fold> 1780 1781 // <editor-fold defaultstate="collapsed" desc="notSoftSubtype"> 1782 /** 1783 * This relation answers the question: is impossible that 1784 * something of type `t' can be a subtype of `s'? This is 1785 * different from the question "is `t' not a subtype of `s'?" 1786 * when type variables are involved: Integer is not a subtype of T 1787 * where {@code <T extends Number>} but it is not true that Integer cannot 1788 * possibly be a subtype of T. 1789 */ 1790 public boolean notSoftSubtype(Type t, Type s) { 1791 if (t == s) return false; 1792 if (t.hasTag(TYPEVAR)) { 1793 TypeVar tv = (TypeVar) t; 1794 return !isCastable(tv.bound, 1795 relaxBound(s), 1796 noWarnings); 1797 } 1798 if (!s.hasTag(WILDCARD)) 1799 s = cvarUpperBound(s); 1800 1801 return !isSubtype(t, relaxBound(s)); 1802 } 1803 1804 private Type relaxBound(Type t) { 1805 return (t.hasTag(TYPEVAR)) ? 1806 rewriteQuantifiers(skipTypeVars(t, false), true, true) : 1807 t; 1808 } 1809 // </editor-fold> 1810 1811 // <editor-fold defaultstate="collapsed" desc="isReifiable"> 1812 public boolean isReifiable(Type t) { 1813 return isReifiable.visit(t); 1814 } 1815 // where 1816 private UnaryVisitor<Boolean> isReifiable = new UnaryVisitor<Boolean>() { 1817 1818 public Boolean visitType(Type t, Void ignored) { 1819 return true; 1820 } 1821 1822 @Override 1823 public Boolean visitClassType(ClassType t, Void ignored) { 1824 if (t.isCompound()) 1825 return false; 1826 else { 1827 if (!t.isParameterized()) 1828 return true; 1829 1830 for (Type param : t.allparams()) { 1831 if (!param.isUnbound()) 1832 return false; 1833 } 1834 return true; 1835 } 1836 } 1837 1838 @Override 1839 public Boolean visitArrayType(ArrayType t, Void ignored) { 1840 return visit(t.elemtype); 1841 } 1842 1843 @Override 1844 public Boolean visitTypeVar(TypeVar t, Void ignored) { 1845 return false; 1846 } 1847 }; 1848 // </editor-fold> 1849 1850 // <editor-fold defaultstate="collapsed" desc="Array Utils"> 1851 public boolean isArray(Type t) { 1852 while (t.hasTag(WILDCARD)) 1853 t = wildUpperBound(t); 1854 return t.hasTag(ARRAY); 1855 } 1856 1857 /** 1858 * The element type of an array. 1859 */ 1860 public Type elemtype(Type t) { 1861 switch (t.getTag()) { 1862 case WILDCARD: 1863 return elemtype(wildUpperBound(t)); 1864 case ARRAY: 1865 return ((ArrayType)t).elemtype; 1866 case FORALL: 1867 return elemtype(((ForAll)t).qtype); 1868 case ERROR: 1869 return t; 1870 default: 1871 return null; 1872 } 1873 } 1874 1875 public Type elemtypeOrType(Type t) { 1876 Type elemtype = elemtype(t); 1877 return elemtype != null ? 1878 elemtype : 1879 t; 1880 } 1881 1882 /** 1883 * Mapping to take element type of an arraytype 1884 */ 1885 private TypeMapping<Void> elemTypeFun = new TypeMapping<Void>() { 1886 @Override 1887 public Type visitArrayType(ArrayType t, Void _unused) { 1888 return t.elemtype; 1889 } 1890 1891 @Override 1892 public Type visitTypeVar(TypeVar t, Void _unused) { 1893 return visit(skipTypeVars(t, false)); 1894 } 1895 }; 1896 1897 /** 1898 * The number of dimensions of an array type. 1899 */ 1900 public int dimensions(Type t) { 1901 int result = 0; 1902 while (t.hasTag(ARRAY)) { 1903 result++; 1904 t = elemtype(t); 1905 } 1906 return result; 1907 } 1908 1909 /** 1910 * Returns an ArrayType with the component type t 1911 * 1912 * @param t The component type of the ArrayType 1913 * @return the ArrayType for the given component 1914 */ 1915 public ArrayType makeArrayType(Type t) { 1916 if (t.hasTag(VOID) || t.hasTag(PACKAGE)) { 1917 Assert.error("Type t must not be a VOID or PACKAGE type, " + t.toString()); 1918 } 1919 return new ArrayType(t, syms.arrayClass); 1920 } 1921 // </editor-fold> 1922 1923 // <editor-fold defaultstate="collapsed" desc="asSuper"> 1924 /** 1925 * Return the (most specific) base type of t that starts with the 1926 * given symbol. If none exists, return null. 1927 * 1928 * Caveat Emptor: Since javac represents the class of all arrays with a singleton 1929 * symbol Symtab.arrayClass, which by being a singleton cannot hold any discriminant, 1930 * this method could yield surprising answers when invoked on arrays. For example when 1931 * invoked with t being byte [] and sym being t.sym itself, asSuper would answer null. 1932 * 1933 * @param t a type 1934 * @param sym a symbol 1935 */ 1936 public Type asSuper(Type t, Symbol sym) { 1937 /* Some examples: 1938 * 1939 * (Enum<E>, Comparable) => Comparable<E> 1940 * (c.s.s.d.AttributeTree.ValueKind, Enum) => Enum<c.s.s.d.AttributeTree.ValueKind> 1941 * (c.s.s.t.ExpressionTree, c.s.s.t.Tree) => c.s.s.t.Tree 1942 * (j.u.List<capture#160 of ? extends c.s.s.d.DocTree>, Iterable) => 1943 * Iterable<capture#160 of ? extends c.s.s.d.DocTree> 1944 */ 1945 if (sym.type == syms.objectType) { //optimization 1946 return syms.objectType; 1947 } 1948 return asSuper.visit(t, sym); 1949 } 1950 // where 1951 private SimpleVisitor<Type,Symbol> asSuper = new SimpleVisitor<Type,Symbol>() { 1952 1953 public Type visitType(Type t, Symbol sym) { 1954 return null; 1955 } 1956 1957 @Override 1958 public Type visitClassType(ClassType t, Symbol sym) { 1959 if (t.tsym == sym) 1960 return t; 1961 1962 Type st = supertype(t); 1963 if (st.hasTag(CLASS) || st.hasTag(TYPEVAR)) { 1964 Type x = asSuper(st, sym); 1965 if (x != null) 1966 return x; 1967 } 1968 if ((sym.flags() & INTERFACE) != 0) { 1969 for (List<Type> l = interfaces(t); l.nonEmpty(); l = l.tail) { 1970 if (!l.head.hasTag(ERROR)) { 1971 Type x = asSuper(l.head, sym); 1972 if (x != null) 1973 return x; 1974 } 1975 } 1976 } 1977 return null; 1978 } 1979 1980 @Override 1981 public Type visitArrayType(ArrayType t, Symbol sym) { 1982 return isSubtype(t, sym.type) ? sym.type : null; 1983 } 1984 1985 @Override 1986 public Type visitTypeVar(TypeVar t, Symbol sym) { 1987 if (t.tsym == sym) 1988 return t; 1989 else 1990 return asSuper(t.bound, sym); 1991 } 1992 1993 @Override 1994 public Type visitErrorType(ErrorType t, Symbol sym) { 1995 return t; 1996 } 1997 }; 1998 1999 /** 2000 * Return the base type of t or any of its outer types that starts 2001 * with the given symbol. If none exists, return null. 2002 * 2003 * @param t a type 2004 * @param sym a symbol 2005 */ 2006 public Type asOuterSuper(Type t, Symbol sym) { 2007 switch (t.getTag()) { 2008 case CLASS: 2009 do { 2010 Type s = asSuper(t, sym); 2011 if (s != null) return s; 2012 t = t.getEnclosingType(); 2013 } while (t.hasTag(CLASS)); 2014 return null; 2015 case ARRAY: 2016 return isSubtype(t, sym.type) ? sym.type : null; 2017 case TYPEVAR: 2018 return asSuper(t, sym); 2019 case ERROR: 2020 return t; 2021 default: 2022 return null; 2023 } 2024 } 2025 2026 /** 2027 * Return the base type of t or any of its enclosing types that 2028 * starts with the given symbol. If none exists, return null. 2029 * 2030 * @param t a type 2031 * @param sym a symbol 2032 */ 2033 public Type asEnclosingSuper(Type t, Symbol sym) { 2034 switch (t.getTag()) { 2035 case CLASS: 2036 do { 2037 Type s = asSuper(t, sym); 2038 if (s != null) return s; 2039 Type outer = t.getEnclosingType(); 2040 t = (outer.hasTag(CLASS)) ? outer : 2041 (t.tsym.owner.enclClass() != null) ? t.tsym.owner.enclClass().type : 2042 Type.noType; 2043 } while (t.hasTag(CLASS)); 2044 return null; 2045 case ARRAY: 2046 return isSubtype(t, sym.type) ? sym.type : null; 2047 case TYPEVAR: 2048 return asSuper(t, sym); 2049 case ERROR: 2050 return t; 2051 default: 2052 return null; 2053 } 2054 } 2055 // </editor-fold> 2056 2057 // <editor-fold defaultstate="collapsed" desc="memberType"> 2058 /** 2059 * The type of given symbol, seen as a member of t. 2060 * 2061 * @param t a type 2062 * @param sym a symbol 2063 */ 2064 public Type memberType(Type t, Symbol sym) { 2065 return (sym.flags() & STATIC) != 0 2066 ? sym.type 2067 : memberType.visit(t, sym); 2068 } 2069 // where 2070 private SimpleVisitor<Type,Symbol> memberType = new SimpleVisitor<Type,Symbol>() { 2071 2072 public Type visitType(Type t, Symbol sym) { 2073 return sym.type; 2074 } 2075 2076 @Override 2077 public Type visitWildcardType(WildcardType t, Symbol sym) { 2078 return memberType(wildUpperBound(t), sym); 2079 } 2080 2081 @Override 2082 public Type visitClassType(ClassType t, Symbol sym) { 2083 Symbol owner = sym.owner; 2084 long flags = sym.flags(); 2085 if (((flags & STATIC) == 0) && owner.type.isParameterized()) { 2086 Type base = asOuterSuper(t, owner); 2087 //if t is an intersection type T = CT & I1 & I2 ... & In 2088 //its supertypes CT, I1, ... In might contain wildcards 2089 //so we need to go through capture conversion 2090 base = t.isCompound() ? capture(base) : base; 2091 if (base != null) { 2092 List<Type> ownerParams = owner.type.allparams(); 2093 List<Type> baseParams = base.allparams(); 2094 if (ownerParams.nonEmpty()) { 2095 if (baseParams.isEmpty()) { 2096 // then base is a raw type 2097 return erasure(sym.type); 2098 } else { 2099 return subst(sym.type, ownerParams, baseParams); 2100 } 2101 } 2102 } 2103 } 2104 return sym.type; 2105 } 2106 2107 @Override 2108 public Type visitTypeVar(TypeVar t, Symbol sym) { 2109 return memberType(t.bound, sym); 2110 } 2111 2112 @Override 2113 public Type visitErrorType(ErrorType t, Symbol sym) { 2114 return t; 2115 } 2116 }; 2117 // </editor-fold> 2118 2119 // <editor-fold defaultstate="collapsed" desc="isAssignable"> 2120 public boolean isAssignable(Type t, Type s) { 2121 return isAssignable(t, s, noWarnings); 2122 } 2123 2124 /** 2125 * Is t assignable to s?<br> 2126 * Equivalent to subtype except for constant values and raw 2127 * types.<br> 2128 * (not defined for Method and ForAll types) 2129 */ 2130 public boolean isAssignable(Type t, Type s, Warner warn) { 2131 if (t.hasTag(ERROR)) 2132 return true; 2133 if (t.getTag().isSubRangeOf(INT) && t.constValue() != null) { 2134 int value = ((Number)t.constValue()).intValue(); 2135 switch (s.getTag()) { 2136 case BYTE: 2137 if (Byte.MIN_VALUE <= value && value <= Byte.MAX_VALUE) 2138 return true; 2139 break; 2140 case CHAR: 2141 if (Character.MIN_VALUE <= value && value <= Character.MAX_VALUE) 2142 return true; 2143 break; 2144 case SHORT: 2145 if (Short.MIN_VALUE <= value && value <= Short.MAX_VALUE) 2146 return true; 2147 break; 2148 case INT: 2149 return true; 2150 case CLASS: 2151 switch (unboxedType(s).getTag()) { 2152 case BYTE: 2153 case CHAR: 2154 case SHORT: 2155 return isAssignable(t, unboxedType(s), warn); 2156 } 2157 break; 2158 } 2159 } 2160 return isConvertible(t, s, warn); 2161 } 2162 // </editor-fold> 2163 2164 // <editor-fold defaultstate="collapsed" desc="erasure"> 2165 /** 2166 * The erasure of t {@code |t|} -- the type that results when all 2167 * type parameters in t are deleted. 2168 */ 2169 public Type erasure(Type t) { 2170 return eraseNotNeeded(t)? t : erasure(t, false); 2171 } 2172 //where 2173 private boolean eraseNotNeeded(Type t) { 2174 // We don't want to erase primitive types and String type as that 2175 // operation is idempotent. Also, erasing these could result in loss 2176 // of information such as constant values attached to such types. 2177 return (t.isPrimitive()) || (syms.stringType.tsym == t.tsym); 2178 } 2179 2180 private Type erasure(Type t, boolean recurse) { 2181 if (t.isPrimitive()) { 2182 return t; /* fast special case */ 2183 } else { 2184 Type out = erasure.visit(t, recurse); 2185 return out; 2186 } 2187 } 2188 // where 2189 private TypeMapping<Boolean> erasure = new TypeMapping<Boolean>() { 2190 private Type combineMetadata(final Type ty, 2191 final TypeMetadata md) { 2192 if (!md.isEmpty()) { 2193 switch (ty.getKind()) { 2194 default: return ty.clone(ty.metadata.combine(md)); 2195 case OTHER: 2196 case UNION: 2197 case INTERSECTION: 2198 case PACKAGE: 2199 case EXECUTABLE: 2200 case NONE: 2201 case VOID: 2202 case ERROR: 2203 return ty; 2204 } 2205 } else { 2206 return ty; 2207 } 2208 } 2209 2210 public Type visitType(Type t, Boolean recurse) { 2211 if (t.isPrimitive()) 2212 return t; /*fast special case*/ 2213 else { 2214 //other cases already handled 2215 return combineMetadata(t, t.getMetadata()); 2216 } 2217 } 2218 2219 @Override 2220 public Type visitClassType(ClassType t, Boolean recurse) { 2221 Type erased = t.tsym.erasure(Types.this); 2222 if (recurse) { 2223 erased = new ErasedClassType(erased.getEnclosingType(),erased.tsym, t.getMetadata()); 2224 return erased; 2225 } else { 2226 return combineMetadata(erased, t.getMetadata()); 2227 } 2228 } 2229 2230 @Override 2231 public Type visitTypeVar(TypeVar t, Boolean recurse) { 2232 Type erased = erasure(t.bound, recurse); 2233 return combineMetadata(erased, t.getMetadata()); 2234 } 2235 }; 2236 2237 public List<Type> erasure(List<Type> ts) { 2238 return erasure.visit(ts, false); 2239 } 2240 2241 public Type erasureRecursive(Type t) { 2242 return erasure(t, true); 2243 } 2244 2245 public List<Type> erasureRecursive(List<Type> ts) { 2246 return erasure.visit(ts, true); 2247 } 2248 // </editor-fold> 2249 2250 // <editor-fold defaultstate="collapsed" desc="makeIntersectionType"> 2251 /** 2252 * Make an intersection type from non-empty list of types. The list should be ordered according to 2253 * {@link TypeSymbol#precedes(TypeSymbol, Types)}. Note that this might cause a symbol completion. 2254 * Hence, this version of makeIntersectionType may not be called during a classfile read. 2255 * 2256 * @param bounds the types from which the intersection type is formed 2257 */ 2258 public IntersectionClassType makeIntersectionType(List<Type> bounds) { 2259 return makeIntersectionType(bounds, bounds.head.tsym.isInterface()); 2260 } 2261 2262 /** 2263 * Make an intersection type from non-empty list of types. The list should be ordered according to 2264 * {@link TypeSymbol#precedes(TypeSymbol, Types)}. This does not cause symbol completion as 2265 * an extra parameter indicates as to whether all bounds are interfaces - in which case the 2266 * supertype is implicitly assumed to be 'Object'. 2267 * 2268 * @param bounds the types from which the intersection type is formed 2269 * @param allInterfaces are all bounds interface types? 2270 */ 2271 public IntersectionClassType makeIntersectionType(List<Type> bounds, boolean allInterfaces) { 2272 Assert.check(bounds.nonEmpty()); 2273 Type firstExplicitBound = bounds.head; 2274 if (allInterfaces) { 2275 bounds = bounds.prepend(syms.objectType); 2276 } 2277 ClassSymbol bc = 2278 new ClassSymbol(ABSTRACT|PUBLIC|SYNTHETIC|COMPOUND|ACYCLIC, 2279 Type.moreInfo 2280 ? names.fromString(bounds.toString()) 2281 : names.empty, 2282 null, 2283 syms.noSymbol); 2284 IntersectionClassType intersectionType = new IntersectionClassType(bounds, bc, allInterfaces); 2285 bc.type = intersectionType; 2286 bc.erasure_field = (bounds.head.hasTag(TYPEVAR)) ? 2287 syms.objectType : // error condition, recover 2288 erasure(firstExplicitBound); 2289 bc.members_field = WriteableScope.create(bc); 2290 return intersectionType; 2291 } 2292 // </editor-fold> 2293 2294 // <editor-fold defaultstate="collapsed" desc="supertype"> 2295 public Type supertype(Type t) { 2296 return supertype.visit(t); 2297 } 2298 // where 2299 private UnaryVisitor<Type> supertype = new UnaryVisitor<Type>() { 2300 2301 public Type visitType(Type t, Void ignored) { 2302 // A note on wildcards: there is no good way to 2303 // determine a supertype for a super bounded wildcard. 2304 return Type.noType; 2305 } 2306 2307 @Override 2308 public Type visitClassType(ClassType t, Void ignored) { 2309 if (t.supertype_field == null) { 2310 Type supertype = ((ClassSymbol)t.tsym).getSuperclass(); 2311 // An interface has no superclass; its supertype is Object. 2312 if (t.isInterface()) 2313 supertype = ((ClassType)t.tsym.type).supertype_field; 2314 if (t.supertype_field == null) { 2315 List<Type> actuals = classBound(t).allparams(); 2316 List<Type> formals = t.tsym.type.allparams(); 2317 if (t.hasErasedSupertypes()) { 2318 t.supertype_field = erasureRecursive(supertype); 2319 } else if (formals.nonEmpty()) { 2320 t.supertype_field = subst(supertype, formals, actuals); 2321 } 2322 else { 2323 t.supertype_field = supertype; 2324 } 2325 } 2326 } 2327 return t.supertype_field; 2328 } 2329 2330 /** 2331 * The supertype is always a class type. If the type 2332 * variable's bounds start with a class type, this is also 2333 * the supertype. Otherwise, the supertype is 2334 * java.lang.Object. 2335 */ 2336 @Override 2337 public Type visitTypeVar(TypeVar t, Void ignored) { 2338 if (t.bound.hasTag(TYPEVAR) || 2339 (!t.bound.isCompound() && !t.bound.isInterface())) { 2340 return t.bound; 2341 } else { 2342 return supertype(t.bound); 2343 } 2344 } 2345 2346 @Override 2347 public Type visitArrayType(ArrayType t, Void ignored) { 2348 if (t.elemtype.isPrimitive() || isSameType(t.elemtype, syms.objectType)) 2349 return arraySuperType(); 2350 else 2351 return new ArrayType(supertype(t.elemtype), t.tsym); 2352 } 2353 2354 @Override 2355 public Type visitErrorType(ErrorType t, Void ignored) { 2356 return Type.noType; 2357 } 2358 }; 2359 // </editor-fold> 2360 2361 // <editor-fold defaultstate="collapsed" desc="interfaces"> 2362 /** 2363 * Return the interfaces implemented by this class. 2364 */ 2365 public List<Type> interfaces(Type t) { 2366 return interfaces.visit(t); 2367 } 2368 // where 2369 private UnaryVisitor<List<Type>> interfaces = new UnaryVisitor<List<Type>>() { 2370 2371 public List<Type> visitType(Type t, Void ignored) { 2372 return List.nil(); 2373 } 2374 2375 @Override 2376 public List<Type> visitClassType(ClassType t, Void ignored) { 2377 if (t.interfaces_field == null) { 2378 List<Type> interfaces = ((ClassSymbol)t.tsym).getInterfaces(); 2379 if (t.interfaces_field == null) { 2380 // If t.interfaces_field is null, then t must 2381 // be a parameterized type (not to be confused 2382 // with a generic type declaration). 2383 // Terminology: 2384 // Parameterized type: List<String> 2385 // Generic type declaration: class List<E> { ... } 2386 // So t corresponds to List<String> and 2387 // t.tsym.type corresponds to List<E>. 2388 // The reason t must be parameterized type is 2389 // that completion will happen as a side 2390 // effect of calling 2391 // ClassSymbol.getInterfaces. Since 2392 // t.interfaces_field is null after 2393 // completion, we can assume that t is not the 2394 // type of a class/interface declaration. 2395 Assert.check(t != t.tsym.type, t); 2396 List<Type> actuals = t.allparams(); 2397 List<Type> formals = t.tsym.type.allparams(); 2398 if (t.hasErasedSupertypes()) { 2399 t.interfaces_field = erasureRecursive(interfaces); 2400 } else if (formals.nonEmpty()) { 2401 t.interfaces_field = subst(interfaces, formals, actuals); 2402 } 2403 else { 2404 t.interfaces_field = interfaces; 2405 } 2406 } 2407 } 2408 return t.interfaces_field; 2409 } 2410 2411 @Override 2412 public List<Type> visitTypeVar(TypeVar t, Void ignored) { 2413 if (t.bound.isCompound()) 2414 return interfaces(t.bound); 2415 2416 if (t.bound.isInterface()) 2417 return List.of(t.bound); 2418 2419 return List.nil(); 2420 } 2421 }; 2422 2423 public List<Type> directSupertypes(Type t) { 2424 return directSupertypes.visit(t); 2425 } 2426 // where 2427 private final UnaryVisitor<List<Type>> directSupertypes = new UnaryVisitor<List<Type>>() { 2428 2429 public List<Type> visitType(final Type type, final Void ignored) { 2430 if (!type.isIntersection()) { 2431 final Type sup = supertype(type); 2432 return (sup == Type.noType || sup == type || sup == null) 2433 ? interfaces(type) 2434 : interfaces(type).prepend(sup); 2435 } else { 2436 return visitIntersectionType((IntersectionClassType) type); 2437 } 2438 } 2439 2440 private List<Type> visitIntersectionType(final IntersectionClassType it) { 2441 return it.getExplicitComponents(); 2442 } 2443 2444 }; 2445 2446 public boolean isDirectSuperInterface(TypeSymbol isym, TypeSymbol origin) { 2447 for (Type i2 : interfaces(origin.type)) { 2448 if (isym == i2.tsym) return true; 2449 } 2450 return false; 2451 } 2452 // </editor-fold> 2453 2454 // <editor-fold defaultstate="collapsed" desc="isDerivedRaw"> 2455 Map<Type,Boolean> isDerivedRawCache = new HashMap<>(); 2456 2457 public boolean isDerivedRaw(Type t) { 2458 Boolean result = isDerivedRawCache.get(t); 2459 if (result == null) { 2460 result = isDerivedRawInternal(t); 2461 isDerivedRawCache.put(t, result); 2462 } 2463 return result; 2464 } 2465 2466 public boolean isDerivedRawInternal(Type t) { 2467 if (t.isErroneous()) 2468 return false; 2469 return 2470 t.isRaw() || 2471 supertype(t) != Type.noType && isDerivedRaw(supertype(t)) || 2472 isDerivedRaw(interfaces(t)); 2473 } 2474 2475 public boolean isDerivedRaw(List<Type> ts) { 2476 List<Type> l = ts; 2477 while (l.nonEmpty() && !isDerivedRaw(l.head)) l = l.tail; 2478 return l.nonEmpty(); 2479 } 2480 // </editor-fold> 2481 2482 // <editor-fold defaultstate="collapsed" desc="setBounds"> 2483 /** 2484 * Same as {@link Types#setBounds(TypeVar, List, boolean)}, except that third parameter is computed directly, 2485 * as follows: if all all bounds are interface types, the computed supertype is Object,otherwise 2486 * the supertype is simply left null (in this case, the supertype is assumed to be the head of 2487 * the bound list passed as second argument). Note that this check might cause a symbol completion. 2488 * Hence, this version of setBounds may not be called during a classfile read. 2489 * 2490 * @param t a type variable 2491 * @param bounds the bounds, must be nonempty 2492 */ 2493 public void setBounds(TypeVar t, List<Type> bounds) { 2494 setBounds(t, bounds, bounds.head.tsym.isInterface()); 2495 } 2496 2497 /** 2498 * Set the bounds field of the given type variable to reflect a (possibly multiple) list of bounds. 2499 * This does not cause symbol completion as an extra parameter indicates as to whether all bounds 2500 * are interfaces - in which case the supertype is implicitly assumed to be 'Object'. 2501 * 2502 * @param t a type variable 2503 * @param bounds the bounds, must be nonempty 2504 * @param allInterfaces are all bounds interface types? 2505 */ 2506 public void setBounds(TypeVar t, List<Type> bounds, boolean allInterfaces) { 2507 t.bound = bounds.tail.isEmpty() ? 2508 bounds.head : 2509 makeIntersectionType(bounds, allInterfaces); 2510 t.rank_field = -1; 2511 } 2512 // </editor-fold> 2513 2514 // <editor-fold defaultstate="collapsed" desc="getBounds"> 2515 /** 2516 * Return list of bounds of the given type variable. 2517 */ 2518 public List<Type> getBounds(TypeVar t) { 2519 if (t.bound.hasTag(NONE)) 2520 return List.nil(); 2521 else if (t.bound.isErroneous() || !t.bound.isCompound()) 2522 return List.of(t.bound); 2523 else if ((erasure(t).tsym.flags() & INTERFACE) == 0) 2524 return interfaces(t).prepend(supertype(t)); 2525 else 2526 // No superclass was given in bounds. 2527 // In this case, supertype is Object, erasure is first interface. 2528 return interfaces(t); 2529 } 2530 // </editor-fold> 2531 2532 // <editor-fold defaultstate="collapsed" desc="classBound"> 2533 /** 2534 * If the given type is a (possibly selected) type variable, 2535 * return the bounding class of this type, otherwise return the 2536 * type itself. 2537 */ 2538 public Type classBound(Type t) { 2539 return classBound.visit(t); 2540 } 2541 // where 2542 private UnaryVisitor<Type> classBound = new UnaryVisitor<Type>() { 2543 2544 public Type visitType(Type t, Void ignored) { 2545 return t; 2546 } 2547 2548 @Override 2549 public Type visitClassType(ClassType t, Void ignored) { 2550 Type outer1 = classBound(t.getEnclosingType()); 2551 if (outer1 != t.getEnclosingType()) 2552 return new ClassType(outer1, t.getTypeArguments(), t.tsym, 2553 t.getMetadata()); 2554 else 2555 return t; 2556 } 2557 2558 @Override 2559 public Type visitTypeVar(TypeVar t, Void ignored) { 2560 return classBound(supertype(t)); 2561 } 2562 2563 @Override 2564 public Type visitErrorType(ErrorType t, Void ignored) { 2565 return t; 2566 } 2567 }; 2568 // </editor-fold> 2569 2570 // <editor-fold defaultstate="collapsed" desc="sub signature / override equivalence"> 2571 /** 2572 * Returns true iff the first signature is a <em>sub 2573 * signature</em> of the other. This is <b>not</b> an equivalence 2574 * relation. 2575 * 2576 * @jls section 8.4.2. 2577 * @see #overrideEquivalent(Type t, Type s) 2578 * @param t first signature (possibly raw). 2579 * @param s second signature (could be subjected to erasure). 2580 * @return true if t is a sub signature of s. 2581 */ 2582 public boolean isSubSignature(Type t, Type s) { 2583 return isSubSignature(t, s, true); 2584 } 2585 2586 public boolean isSubSignature(Type t, Type s, boolean strict) { 2587 return hasSameArgs(t, s, strict) || hasSameArgs(t, erasure(s), strict); 2588 } 2589 2590 /** 2591 * Returns true iff these signatures are related by <em>override 2592 * equivalence</em>. This is the natural extension of 2593 * isSubSignature to an equivalence relation. 2594 * 2595 * @jls section 8.4.2. 2596 * @see #isSubSignature(Type t, Type s) 2597 * @param t a signature (possible raw, could be subjected to 2598 * erasure). 2599 * @param s a signature (possible raw, could be subjected to 2600 * erasure). 2601 * @return true if either argument is a sub signature of the other. 2602 */ 2603 public boolean overrideEquivalent(Type t, Type s) { 2604 return hasSameArgs(t, s) || 2605 hasSameArgs(t, erasure(s)) || hasSameArgs(erasure(t), s); 2606 } 2607 2608 public boolean overridesObjectMethod(TypeSymbol origin, Symbol msym) { 2609 for (Symbol sym : syms.objectType.tsym.members().getSymbolsByName(msym.name)) { 2610 if (msym.overrides(sym, origin, Types.this, true)) { 2611 return true; 2612 } 2613 } 2614 return false; 2615 } 2616 2617 // <editor-fold defaultstate="collapsed" desc="Determining method implementation in given site"> 2618 class ImplementationCache { 2619 2620 private WeakHashMap<MethodSymbol, SoftReference<Map<TypeSymbol, Entry>>> _map = new WeakHashMap<>(); 2621 2622 class Entry { 2623 final MethodSymbol cachedImpl; 2624 final Filter<Symbol> implFilter; 2625 final boolean checkResult; 2626 final int prevMark; 2627 2628 public Entry(MethodSymbol cachedImpl, 2629 Filter<Symbol> scopeFilter, 2630 boolean checkResult, 2631 int prevMark) { 2632 this.cachedImpl = cachedImpl; 2633 this.implFilter = scopeFilter; 2634 this.checkResult = checkResult; 2635 this.prevMark = prevMark; 2636 } 2637 2638 boolean matches(Filter<Symbol> scopeFilter, boolean checkResult, int mark) { 2639 return this.implFilter == scopeFilter && 2640 this.checkResult == checkResult && 2641 this.prevMark == mark; 2642 } 2643 } 2644 2645 MethodSymbol get(MethodSymbol ms, TypeSymbol origin, boolean checkResult, Filter<Symbol> implFilter) { 2646 SoftReference<Map<TypeSymbol, Entry>> ref_cache = _map.get(ms); 2647 Map<TypeSymbol, Entry> cache = ref_cache != null ? ref_cache.get() : null; 2648 if (cache == null) { 2649 cache = new HashMap<>(); 2650 _map.put(ms, new SoftReference<>(cache)); 2651 } 2652 Entry e = cache.get(origin); 2653 CompoundScope members = membersClosure(origin.type, true); 2654 if (e == null || 2655 !e.matches(implFilter, checkResult, members.getMark())) { 2656 MethodSymbol impl = implementationInternal(ms, origin, checkResult, implFilter); 2657 cache.put(origin, new Entry(impl, implFilter, checkResult, members.getMark())); 2658 return impl; 2659 } 2660 else { 2661 return e.cachedImpl; 2662 } 2663 } 2664 2665 private MethodSymbol implementationInternal(MethodSymbol ms, TypeSymbol origin, boolean checkResult, Filter<Symbol> implFilter) { 2666 for (Type t = origin.type; t.hasTag(CLASS) || t.hasTag(TYPEVAR); t = supertype(t)) { 2667 t = skipTypeVars(t, false); 2668 TypeSymbol c = t.tsym; 2669 Symbol bestSoFar = null; 2670 for (Symbol sym : c.members().getSymbolsByName(ms.name, implFilter)) { 2671 if (sym != null && sym.overrides(ms, origin, Types.this, checkResult)) { 2672 bestSoFar = sym; 2673 if ((sym.flags() & ABSTRACT) == 0) { 2674 //if concrete impl is found, exit immediately 2675 break; 2676 } 2677 } 2678 } 2679 if (bestSoFar != null) { 2680 //return either the (only) concrete implementation or the first abstract one 2681 return (MethodSymbol)bestSoFar; 2682 } 2683 } 2684 return null; 2685 } 2686 } 2687 2688 private ImplementationCache implCache = new ImplementationCache(); 2689 2690 public MethodSymbol implementation(MethodSymbol ms, TypeSymbol origin, boolean checkResult, Filter<Symbol> implFilter) { 2691 return implCache.get(ms, origin, checkResult, implFilter); 2692 } 2693 // </editor-fold> 2694 2695 // <editor-fold defaultstate="collapsed" desc="compute transitive closure of all members in given site"> 2696 class MembersClosureCache extends SimpleVisitor<CompoundScope, Boolean> { 2697 2698 private WeakHashMap<TypeSymbol, Entry> _map = new WeakHashMap<>(); 2699 2700 class Entry { 2701 final boolean skipInterfaces; 2702 final CompoundScope compoundScope; 2703 2704 public Entry(boolean skipInterfaces, CompoundScope compoundScope) { 2705 this.skipInterfaces = skipInterfaces; 2706 this.compoundScope = compoundScope; 2707 } 2708 2709 boolean matches(boolean skipInterfaces) { 2710 return this.skipInterfaces == skipInterfaces; 2711 } 2712 } 2713 2714 List<TypeSymbol> seenTypes = List.nil(); 2715 2716 /** members closure visitor methods **/ 2717 2718 public CompoundScope visitType(Type t, Boolean skipInterface) { 2719 return null; 2720 } 2721 2722 @Override 2723 public CompoundScope visitClassType(ClassType t, Boolean skipInterface) { 2724 if (seenTypes.contains(t.tsym)) { 2725 //this is possible when an interface is implemented in multiple 2726 //superclasses, or when a classs hierarchy is circular - in such 2727 //cases we don't need to recurse (empty scope is returned) 2728 return new CompoundScope(t.tsym); 2729 } 2730 try { 2731 seenTypes = seenTypes.prepend(t.tsym); 2732 ClassSymbol csym = (ClassSymbol)t.tsym; 2733 Entry e = _map.get(csym); 2734 if (e == null || !e.matches(skipInterface)) { 2735 CompoundScope membersClosure = new CompoundScope(csym); 2736 if (!skipInterface) { 2737 for (Type i : interfaces(t)) { 2738 membersClosure.prependSubScope(visit(i, skipInterface)); 2739 } 2740 } 2741 membersClosure.prependSubScope(visit(supertype(t), skipInterface)); 2742 membersClosure.prependSubScope(csym.members()); 2743 e = new Entry(skipInterface, membersClosure); 2744 _map.put(csym, e); 2745 } 2746 return e.compoundScope; 2747 } 2748 finally { 2749 seenTypes = seenTypes.tail; 2750 } 2751 } 2752 2753 @Override 2754 public CompoundScope visitTypeVar(TypeVar t, Boolean skipInterface) { 2755 return visit(t.getUpperBound(), skipInterface); 2756 } 2757 } 2758 2759 private MembersClosureCache membersCache = new MembersClosureCache(); 2760 2761 public CompoundScope membersClosure(Type site, boolean skipInterface) { 2762 return membersCache.visit(site, skipInterface); 2763 } 2764 // </editor-fold> 2765 2766 2767 /** Return first abstract member of class `sym'. 2768 */ 2769 public MethodSymbol firstUnimplementedAbstract(ClassSymbol sym) { 2770 try { 2771 return firstUnimplementedAbstractImpl(sym, sym); 2772 } catch (CompletionFailure ex) { 2773 chk.completionError(enter.getEnv(sym).tree.pos(), ex); 2774 return null; 2775 } 2776 } 2777 //where: 2778 private MethodSymbol firstUnimplementedAbstractImpl(ClassSymbol impl, ClassSymbol c) { 2779 MethodSymbol undef = null; 2780 // Do not bother to search in classes that are not abstract, 2781 // since they cannot have abstract members. 2782 if (c == impl || (c.flags() & (ABSTRACT | INTERFACE)) != 0) { 2783 Scope s = c.members(); 2784 for (Symbol sym : s.getSymbols(NON_RECURSIVE)) { 2785 if (sym.kind == MTH && 2786 (sym.flags() & (ABSTRACT|IPROXY|DEFAULT)) == ABSTRACT) { 2787 MethodSymbol absmeth = (MethodSymbol)sym; 2788 MethodSymbol implmeth = absmeth.implementation(impl, this, true); 2789 if (implmeth == null || implmeth == absmeth) { 2790 //look for default implementations 2791 if (allowDefaultMethods) { 2792 MethodSymbol prov = interfaceCandidates(impl.type, absmeth).head; 2793 if (prov != null && prov.overrides(absmeth, impl, this, true)) { 2794 implmeth = prov; 2795 } 2796 } 2797 } 2798 if (implmeth == null || implmeth == absmeth) { 2799 undef = absmeth; 2800 break; 2801 } 2802 } 2803 } 2804 if (undef == null) { 2805 Type st = supertype(c.type); 2806 if (st.hasTag(CLASS)) 2807 undef = firstUnimplementedAbstractImpl(impl, (ClassSymbol)st.tsym); 2808 } 2809 for (List<Type> l = interfaces(c.type); 2810 undef == null && l.nonEmpty(); 2811 l = l.tail) { 2812 undef = firstUnimplementedAbstractImpl(impl, (ClassSymbol)l.head.tsym); 2813 } 2814 } 2815 return undef; 2816 } 2817 2818 2819 //where 2820 public List<MethodSymbol> interfaceCandidates(Type site, MethodSymbol ms) { 2821 Filter<Symbol> filter = new MethodFilter(ms, site); 2822 List<MethodSymbol> candidates = List.nil(); 2823 for (Symbol s : membersClosure(site, false).getSymbols(filter)) { 2824 if (!site.tsym.isInterface() && !s.owner.isInterface()) { 2825 return List.of((MethodSymbol)s); 2826 } else if (!candidates.contains(s)) { 2827 candidates = candidates.prepend((MethodSymbol)s); 2828 } 2829 } 2830 return prune(candidates); 2831 } 2832 2833 public List<MethodSymbol> prune(List<MethodSymbol> methods) { 2834 ListBuffer<MethodSymbol> methodsMin = new ListBuffer<>(); 2835 for (MethodSymbol m1 : methods) { 2836 boolean isMin_m1 = true; 2837 for (MethodSymbol m2 : methods) { 2838 if (m1 == m2) continue; 2839 if (m2.owner != m1.owner && 2840 asSuper(m2.owner.type, m1.owner) != null) { 2841 isMin_m1 = false; 2842 break; 2843 } 2844 } 2845 if (isMin_m1) 2846 methodsMin.append(m1); 2847 } 2848 return methodsMin.toList(); 2849 } 2850 // where 2851 private class MethodFilter implements Filter<Symbol> { 2852 2853 Symbol msym; 2854 Type site; 2855 2856 MethodFilter(Symbol msym, Type site) { 2857 this.msym = msym; 2858 this.site = site; 2859 } 2860 2861 public boolean accepts(Symbol s) { 2862 return s.kind == MTH && 2863 s.name == msym.name && 2864 (s.flags() & SYNTHETIC) == 0 && 2865 s.isInheritedIn(site.tsym, Types.this) && 2866 overrideEquivalent(memberType(site, s), memberType(site, msym)); 2867 } 2868 } 2869 // </editor-fold> 2870 2871 /** 2872 * Does t have the same arguments as s? It is assumed that both 2873 * types are (possibly polymorphic) method types. Monomorphic 2874 * method types "have the same arguments", if their argument lists 2875 * are equal. Polymorphic method types "have the same arguments", 2876 * if they have the same arguments after renaming all type 2877 * variables of one to corresponding type variables in the other, 2878 * where correspondence is by position in the type parameter list. 2879 */ 2880 public boolean hasSameArgs(Type t, Type s) { 2881 return hasSameArgs(t, s, true); 2882 } 2883 2884 public boolean hasSameArgs(Type t, Type s, boolean strict) { 2885 return hasSameArgs(t, s, strict ? hasSameArgs_strict : hasSameArgs_nonstrict); 2886 } 2887 2888 private boolean hasSameArgs(Type t, Type s, TypeRelation hasSameArgs) { 2889 return hasSameArgs.visit(t, s); 2890 } 2891 // where 2892 private class HasSameArgs extends TypeRelation { 2893 2894 boolean strict; 2895 2896 public HasSameArgs(boolean strict) { 2897 this.strict = strict; 2898 } 2899 2900 public Boolean visitType(Type t, Type s) { 2901 throw new AssertionError(); 2902 } 2903 2904 @Override 2905 public Boolean visitMethodType(MethodType t, Type s) { 2906 return s.hasTag(METHOD) 2907 && containsTypeEquivalent(t.argtypes, s.getParameterTypes()); 2908 } 2909 2910 @Override 2911 public Boolean visitForAll(ForAll t, Type s) { 2912 if (!s.hasTag(FORALL)) 2913 return strict ? false : visitMethodType(t.asMethodType(), s); 2914 2915 ForAll forAll = (ForAll)s; 2916 return hasSameBounds(t, forAll) 2917 && visit(t.qtype, subst(forAll.qtype, forAll.tvars, t.tvars)); 2918 } 2919 2920 @Override 2921 public Boolean visitErrorType(ErrorType t, Type s) { 2922 return false; 2923 } 2924 } 2925 2926 TypeRelation hasSameArgs_strict = new HasSameArgs(true); 2927 TypeRelation hasSameArgs_nonstrict = new HasSameArgs(false); 2928 2929 // </editor-fold> 2930 2931 // <editor-fold defaultstate="collapsed" desc="subst"> 2932 public List<Type> subst(List<Type> ts, 2933 List<Type> from, 2934 List<Type> to) { 2935 return new Subst(from, to).subst(ts); 2936 } 2937 2938 /** 2939 * Substitute all occurrences of a type in `from' with the 2940 * corresponding type in `to' in 't'. Match lists `from' and `to' 2941 * from the right: If lists have different length, discard leading 2942 * elements of the longer list. 2943 */ 2944 public Type subst(Type t, List<Type> from, List<Type> to) { 2945 return new Subst(from, to).subst(t); 2946 } 2947 2948 private class Subst extends UnaryVisitor<Type> { 2949 List<Type> from; 2950 List<Type> to; 2951 2952 public Subst(List<Type> from, List<Type> to) { 2953 int fromLength = from.length(); 2954 int toLength = to.length(); 2955 while (fromLength > toLength) { 2956 fromLength--; 2957 from = from.tail; 2958 } 2959 while (fromLength < toLength) { 2960 toLength--; 2961 to = to.tail; 2962 } 2963 this.from = from; 2964 this.to = to; 2965 } 2966 2967 Type subst(Type t) { 2968 if (from.tail == null) 2969 return t; 2970 else 2971 return visit(t); 2972 } 2973 2974 List<Type> subst(List<Type> ts) { 2975 if (from.tail == null) 2976 return ts; 2977 boolean wild = false; 2978 if (ts.nonEmpty() && from.nonEmpty()) { 2979 Type head1 = subst(ts.head); 2980 List<Type> tail1 = subst(ts.tail); 2981 if (head1 != ts.head || tail1 != ts.tail) 2982 return tail1.prepend(head1); 2983 } 2984 return ts; 2985 } 2986 2987 public Type visitType(Type t, Void ignored) { 2988 return t; 2989 } 2990 2991 @Override 2992 public Type visitMethodType(MethodType t, Void ignored) { 2993 List<Type> argtypes = subst(t.argtypes); 2994 Type restype = subst(t.restype); 2995 List<Type> thrown = subst(t.thrown); 2996 if (argtypes == t.argtypes && 2997 restype == t.restype && 2998 thrown == t.thrown) 2999 return t; 3000 else 3001 return new MethodType(argtypes, restype, thrown, t.tsym); 3002 } 3003 3004 @Override 3005 public Type visitTypeVar(TypeVar t, Void ignored) { 3006 for (List<Type> from = this.from, to = this.to; 3007 from.nonEmpty(); 3008 from = from.tail, to = to.tail) { 3009 if (t == from.head) { 3010 return to.head.withTypeVar(t); 3011 } 3012 } 3013 return t; 3014 } 3015 3016 @Override 3017 public Type visitUndetVar(UndetVar t, Void ignored) { 3018 //do nothing - we should not replace inside undet variables 3019 return t; 3020 } 3021 3022 @Override 3023 public Type visitClassType(ClassType t, Void ignored) { 3024 if (!t.isCompound()) { 3025 List<Type> typarams = t.getTypeArguments(); 3026 List<Type> typarams1 = subst(typarams); 3027 Type outer = t.getEnclosingType(); 3028 Type outer1 = subst(outer); 3029 if (typarams1 == typarams && outer1 == outer) 3030 return t; 3031 else 3032 return new ClassType(outer1, typarams1, t.tsym, 3033 t.getMetadata()); 3034 } else { 3035 Type st = subst(supertype(t)); 3036 List<Type> is = subst(interfaces(t)); 3037 if (st == supertype(t) && is == interfaces(t)) 3038 return t; 3039 else 3040 return makeIntersectionType(is.prepend(st)); 3041 } 3042 } 3043 3044 @Override 3045 public Type visitWildcardType(WildcardType t, Void ignored) { 3046 Type bound = t.type; 3047 if (t.kind != BoundKind.UNBOUND) 3048 bound = subst(bound); 3049 if (bound == t.type) { 3050 return t; 3051 } else { 3052 if (t.isExtendsBound() && bound.isExtendsBound()) 3053 bound = wildUpperBound(bound); 3054 return new WildcardType(bound, t.kind, syms.boundClass, 3055 t.bound, t.getMetadata()); 3056 } 3057 } 3058 3059 @Override 3060 public Type visitArrayType(ArrayType t, Void ignored) { 3061 Type elemtype = subst(t.elemtype); 3062 if (elemtype == t.elemtype) 3063 return t; 3064 else 3065 return new ArrayType(elemtype, t.tsym, t.getMetadata()); 3066 } 3067 3068 @Override 3069 public Type visitForAll(ForAll t, Void ignored) { 3070 if (Type.containsAny(to, t.tvars)) { 3071 //perform alpha-renaming of free-variables in 't' 3072 //if 'to' types contain variables that are free in 't' 3073 List<Type> freevars = newInstances(t.tvars); 3074 t = new ForAll(freevars, 3075 Types.this.subst(t.qtype, t.tvars, freevars)); 3076 } 3077 List<Type> tvars1 = substBounds(t.tvars, from, to); 3078 Type qtype1 = subst(t.qtype); 3079 if (tvars1 == t.tvars && qtype1 == t.qtype) { 3080 return t; 3081 } else if (tvars1 == t.tvars) { 3082 return new ForAll(tvars1, qtype1); 3083 } else { 3084 return new ForAll(tvars1, 3085 Types.this.subst(qtype1, t.tvars, tvars1)); 3086 } 3087 } 3088 3089 @Override 3090 public Type visitErrorType(ErrorType t, Void ignored) { 3091 return t; 3092 } 3093 } 3094 3095 public List<Type> substBounds(List<Type> tvars, 3096 List<Type> from, 3097 List<Type> to) { 3098 if (tvars.isEmpty()) 3099 return tvars; 3100 ListBuffer<Type> newBoundsBuf = new ListBuffer<>(); 3101 boolean changed = false; 3102 // calculate new bounds 3103 for (Type t : tvars) { 3104 TypeVar tv = (TypeVar) t; 3105 Type bound = subst(tv.bound, from, to); 3106 if (bound != tv.bound) 3107 changed = true; 3108 newBoundsBuf.append(bound); 3109 } 3110 if (!changed) 3111 return tvars; 3112 ListBuffer<Type> newTvars = new ListBuffer<>(); 3113 // create new type variables without bounds 3114 for (Type t : tvars) { 3115 newTvars.append(new TypeVar(t.tsym, null, syms.botType, 3116 t.getMetadata())); 3117 } 3118 // the new bounds should use the new type variables in place 3119 // of the old 3120 List<Type> newBounds = newBoundsBuf.toList(); 3121 from = tvars; 3122 to = newTvars.toList(); 3123 for (; !newBounds.isEmpty(); newBounds = newBounds.tail) { 3124 newBounds.head = subst(newBounds.head, from, to); 3125 } 3126 newBounds = newBoundsBuf.toList(); 3127 // set the bounds of new type variables to the new bounds 3128 for (Type t : newTvars.toList()) { 3129 TypeVar tv = (TypeVar) t; 3130 tv.bound = newBounds.head; 3131 newBounds = newBounds.tail; 3132 } 3133 return newTvars.toList(); 3134 } 3135 3136 public TypeVar substBound(TypeVar t, List<Type> from, List<Type> to) { 3137 Type bound1 = subst(t.bound, from, to); 3138 if (bound1 == t.bound) 3139 return t; 3140 else { 3141 // create new type variable without bounds 3142 TypeVar tv = new TypeVar(t.tsym, null, syms.botType, 3143 t.getMetadata()); 3144 // the new bound should use the new type variable in place 3145 // of the old 3146 tv.bound = subst(bound1, List.<Type>of(t), List.<Type>of(tv)); 3147 return tv; 3148 } 3149 } 3150 // </editor-fold> 3151 3152 // <editor-fold defaultstate="collapsed" desc="hasSameBounds"> 3153 /** 3154 * Does t have the same bounds for quantified variables as s? 3155 */ 3156 public boolean hasSameBounds(ForAll t, ForAll s) { 3157 List<Type> l1 = t.tvars; 3158 List<Type> l2 = s.tvars; 3159 while (l1.nonEmpty() && l2.nonEmpty() && 3160 isSameType(l1.head.getUpperBound(), 3161 subst(l2.head.getUpperBound(), 3162 s.tvars, 3163 t.tvars))) { 3164 l1 = l1.tail; 3165 l2 = l2.tail; 3166 } 3167 return l1.isEmpty() && l2.isEmpty(); 3168 } 3169 // </editor-fold> 3170 3171 // <editor-fold defaultstate="collapsed" desc="newInstances"> 3172 /** Create new vector of type variables from list of variables 3173 * changing all recursive bounds from old to new list. 3174 */ 3175 public List<Type> newInstances(List<Type> tvars) { 3176 List<Type> tvars1 = tvars.map(newInstanceFun); 3177 for (List<Type> l = tvars1; l.nonEmpty(); l = l.tail) { 3178 TypeVar tv = (TypeVar) l.head; 3179 tv.bound = subst(tv.bound, tvars, tvars1); 3180 } 3181 return tvars1; 3182 } 3183 private static final TypeMapping<Void> newInstanceFun = new TypeMapping<Void>() { 3184 @Override 3185 public TypeVar visitTypeVar(TypeVar t, Void _unused) { 3186 return new TypeVar(t.tsym, t.getUpperBound(), t.getLowerBound(), t.getMetadata()); 3187 } 3188 }; 3189 // </editor-fold> 3190 3191 public Type createMethodTypeWithParameters(Type original, List<Type> newParams) { 3192 return original.accept(methodWithParameters, newParams); 3193 } 3194 // where 3195 private final MapVisitor<List<Type>> methodWithParameters = new MapVisitor<List<Type>>() { 3196 public Type visitType(Type t, List<Type> newParams) { 3197 throw new IllegalArgumentException("Not a method type: " + t); 3198 } 3199 public Type visitMethodType(MethodType t, List<Type> newParams) { 3200 return new MethodType(newParams, t.restype, t.thrown, t.tsym); 3201 } 3202 public Type visitForAll(ForAll t, List<Type> newParams) { 3203 return new ForAll(t.tvars, t.qtype.accept(this, newParams)); 3204 } 3205 }; 3206 3207 public Type createMethodTypeWithThrown(Type original, List<Type> newThrown) { 3208 return original.accept(methodWithThrown, newThrown); 3209 } 3210 // where 3211 private final MapVisitor<List<Type>> methodWithThrown = new MapVisitor<List<Type>>() { 3212 public Type visitType(Type t, List<Type> newThrown) { 3213 throw new IllegalArgumentException("Not a method type: " + t); 3214 } 3215 public Type visitMethodType(MethodType t, List<Type> newThrown) { 3216 return new MethodType(t.argtypes, t.restype, newThrown, t.tsym); 3217 } 3218 public Type visitForAll(ForAll t, List<Type> newThrown) { 3219 return new ForAll(t.tvars, t.qtype.accept(this, newThrown)); 3220 } 3221 }; 3222 3223 public Type createMethodTypeWithReturn(Type original, Type newReturn) { 3224 return original.accept(methodWithReturn, newReturn); 3225 } 3226 // where 3227 private final MapVisitor<Type> methodWithReturn = new MapVisitor<Type>() { 3228 public Type visitType(Type t, Type newReturn) { 3229 throw new IllegalArgumentException("Not a method type: " + t); 3230 } 3231 public Type visitMethodType(MethodType t, Type newReturn) { 3232 return new MethodType(t.argtypes, newReturn, t.thrown, t.tsym); 3233 } 3234 public Type visitForAll(ForAll t, Type newReturn) { 3235 return new ForAll(t.tvars, t.qtype.accept(this, newReturn)); 3236 } 3237 }; 3238 3239 // <editor-fold defaultstate="collapsed" desc="createErrorType"> 3240 public Type createErrorType(Type originalType) { 3241 return new ErrorType(originalType, syms.errSymbol); 3242 } 3243 3244 public Type createErrorType(ClassSymbol c, Type originalType) { 3245 return new ErrorType(c, originalType); 3246 } 3247 3248 public Type createErrorType(Name name, TypeSymbol container, Type originalType) { 3249 return new ErrorType(name, container, originalType); 3250 } 3251 // </editor-fold> 3252 3253 // <editor-fold defaultstate="collapsed" desc="rank"> 3254 /** 3255 * The rank of a class is the length of the longest path between 3256 * the class and java.lang.Object in the class inheritance 3257 * graph. Undefined for all but reference types. 3258 */ 3259 public int rank(Type t) { 3260 switch(t.getTag()) { 3261 case CLASS: { 3262 ClassType cls = (ClassType)t; 3263 if (cls.rank_field < 0) { 3264 Name fullname = cls.tsym.getQualifiedName(); 3265 if (fullname == names.java_lang_Object) 3266 cls.rank_field = 0; 3267 else { 3268 int r = rank(supertype(cls)); 3269 for (List<Type> l = interfaces(cls); 3270 l.nonEmpty(); 3271 l = l.tail) { 3272 if (rank(l.head) > r) 3273 r = rank(l.head); 3274 } 3275 cls.rank_field = r + 1; 3276 } 3277 } 3278 return cls.rank_field; 3279 } 3280 case TYPEVAR: { 3281 TypeVar tvar = (TypeVar)t; 3282 if (tvar.rank_field < 0) { 3283 int r = rank(supertype(tvar)); 3284 for (List<Type> l = interfaces(tvar); 3285 l.nonEmpty(); 3286 l = l.tail) { 3287 if (rank(l.head) > r) r = rank(l.head); 3288 } 3289 tvar.rank_field = r + 1; 3290 } 3291 return tvar.rank_field; 3292 } 3293 case ERROR: 3294 case NONE: 3295 return 0; 3296 default: 3297 throw new AssertionError(); 3298 } 3299 } 3300 // </editor-fold> 3301 3302 /** 3303 * Helper method for generating a string representation of a given type 3304 * accordingly to a given locale 3305 */ 3306 public String toString(Type t, Locale locale) { 3307 return Printer.createStandardPrinter(messages).visit(t, locale); 3308 } 3309 3310 /** 3311 * Helper method for generating a string representation of a given type 3312 * accordingly to a given locale 3313 */ 3314 public String toString(Symbol t, Locale locale) { 3315 return Printer.createStandardPrinter(messages).visit(t, locale); 3316 } 3317 3318 // <editor-fold defaultstate="collapsed" desc="toString"> 3319 /** 3320 * This toString is slightly more descriptive than the one on Type. 3321 * 3322 * @deprecated Types.toString(Type t, Locale l) provides better support 3323 * for localization 3324 */ 3325 @Deprecated 3326 public String toString(Type t) { 3327 if (t.hasTag(FORALL)) { 3328 ForAll forAll = (ForAll)t; 3329 return typaramsString(forAll.tvars) + forAll.qtype; 3330 } 3331 return "" + t; 3332 } 3333 // where 3334 private String typaramsString(List<Type> tvars) { 3335 StringBuilder s = new StringBuilder(); 3336 s.append('<'); 3337 boolean first = true; 3338 for (Type t : tvars) { 3339 if (!first) s.append(", "); 3340 first = false; 3341 appendTyparamString(((TypeVar)t), s); 3342 } 3343 s.append('>'); 3344 return s.toString(); 3345 } 3346 private void appendTyparamString(TypeVar t, StringBuilder buf) { 3347 buf.append(t); 3348 if (t.bound == null || 3349 t.bound.tsym.getQualifiedName() == names.java_lang_Object) 3350 return; 3351 buf.append(" extends "); // Java syntax; no need for i18n 3352 Type bound = t.bound; 3353 if (!bound.isCompound()) { 3354 buf.append(bound); 3355 } else if ((erasure(t).tsym.flags() & INTERFACE) == 0) { 3356 buf.append(supertype(t)); 3357 for (Type intf : interfaces(t)) { 3358 buf.append('&'); 3359 buf.append(intf); 3360 } 3361 } else { 3362 // No superclass was given in bounds. 3363 // In this case, supertype is Object, erasure is first interface. 3364 boolean first = true; 3365 for (Type intf : interfaces(t)) { 3366 if (!first) buf.append('&'); 3367 first = false; 3368 buf.append(intf); 3369 } 3370 } 3371 } 3372 // </editor-fold> 3373 3374 // <editor-fold defaultstate="collapsed" desc="Determining least upper bounds of types"> 3375 /** 3376 * A cache for closures. 3377 * 3378 * <p>A closure is a list of all the supertypes and interfaces of 3379 * a class or interface type, ordered by ClassSymbol.precedes 3380 * (that is, subclasses come first, arbitrary but fixed 3381 * otherwise). 3382 */ 3383 private Map<Type,List<Type>> closureCache = new HashMap<>(); 3384 3385 /** 3386 * Returns the closure of a class or interface type. 3387 */ 3388 public List<Type> closure(Type t) { 3389 List<Type> cl = closureCache.get(t); 3390 if (cl == null) { 3391 Type st = supertype(t); 3392 if (!t.isCompound()) { 3393 if (st.hasTag(CLASS)) { 3394 cl = insert(closure(st), t); 3395 } else if (st.hasTag(TYPEVAR)) { 3396 cl = closure(st).prepend(t); 3397 } else { 3398 cl = List.of(t); 3399 } 3400 } else { 3401 cl = closure(supertype(t)); 3402 } 3403 for (List<Type> l = interfaces(t); l.nonEmpty(); l = l.tail) 3404 cl = union(cl, closure(l.head)); 3405 closureCache.put(t, cl); 3406 } 3407 return cl; 3408 } 3409 3410 /** 3411 * Collect types into a new closure (using a @code{ClosureHolder}) 3412 */ 3413 public Collector<Type, ClosureHolder, List<Type>> closureCollector(boolean minClosure, BiPredicate<Type, Type> shouldSkip) { 3414 return Collector.of(() -> new ClosureHolder(minClosure, shouldSkip), 3415 ClosureHolder::add, 3416 ClosureHolder::merge, 3417 ClosureHolder::closure); 3418 } 3419 //where 3420 class ClosureHolder { 3421 List<Type> closure; 3422 final boolean minClosure; 3423 final BiPredicate<Type, Type> shouldSkip; 3424 3425 ClosureHolder(boolean minClosure, BiPredicate<Type, Type> shouldSkip) { 3426 this.closure = List.nil(); 3427 this.minClosure = minClosure; 3428 this.shouldSkip = shouldSkip; 3429 } 3430 3431 void add(Type type) { 3432 closure = insert(closure, type, shouldSkip); 3433 } 3434 3435 ClosureHolder merge(ClosureHolder other) { 3436 closure = union(closure, other.closure, shouldSkip); 3437 return this; 3438 } 3439 3440 List<Type> closure() { 3441 return minClosure ? closureMin(closure) : closure; 3442 } 3443 } 3444 3445 BiPredicate<Type, Type> basicClosureSkip = (t1, t2) -> t1.tsym == t2.tsym; 3446 3447 /** 3448 * Insert a type in a closure 3449 */ 3450 public List<Type> insert(List<Type> cl, Type t, BiPredicate<Type, Type> shouldSkip) { 3451 if (cl.isEmpty()) { 3452 return cl.prepend(t); 3453 } else if (shouldSkip.test(t, cl.head)) { 3454 return cl; 3455 } else if (t.tsym.precedes(cl.head.tsym, this)) { 3456 return cl.prepend(t); 3457 } else { 3458 // t comes after head, or the two are unrelated 3459 return insert(cl.tail, t, shouldSkip).prepend(cl.head); 3460 } 3461 } 3462 3463 public List<Type> insert(List<Type> cl, Type t) { 3464 return insert(cl, t, basicClosureSkip); 3465 } 3466 3467 /** 3468 * Form the union of two closures 3469 */ 3470 public List<Type> union(List<Type> cl1, List<Type> cl2, BiPredicate<Type, Type> shouldSkip) { 3471 if (cl1.isEmpty()) { 3472 return cl2; 3473 } else if (cl2.isEmpty()) { 3474 return cl1; 3475 } else if (shouldSkip.test(cl1.head, cl2.head)) { 3476 return union(cl1.tail, cl2.tail, shouldSkip).prepend(cl1.head); 3477 } else if (cl1.head.tsym.precedes(cl2.head.tsym, this)) { 3478 return union(cl1.tail, cl2, shouldSkip).prepend(cl1.head); 3479 } else if (cl2.head.tsym.precedes(cl1.head.tsym, this)) { 3480 return union(cl1, cl2.tail, shouldSkip).prepend(cl2.head); 3481 } else { 3482 // unrelated types 3483 return union(cl1.tail, cl2, shouldSkip).prepend(cl1.head); 3484 } 3485 } 3486 3487 public List<Type> union(List<Type> cl1, List<Type> cl2) { 3488 return union(cl1, cl2, basicClosureSkip); 3489 } 3490 3491 /** 3492 * Intersect two closures 3493 */ 3494 public List<Type> intersect(List<Type> cl1, List<Type> cl2) { 3495 if (cl1 == cl2) 3496 return cl1; 3497 if (cl1.isEmpty() || cl2.isEmpty()) 3498 return List.nil(); 3499 if (cl1.head.tsym.precedes(cl2.head.tsym, this)) 3500 return intersect(cl1.tail, cl2); 3501 if (cl2.head.tsym.precedes(cl1.head.tsym, this)) 3502 return intersect(cl1, cl2.tail); 3503 if (isSameType(cl1.head, cl2.head)) 3504 return intersect(cl1.tail, cl2.tail).prepend(cl1.head); 3505 if (cl1.head.tsym == cl2.head.tsym && 3506 cl1.head.hasTag(CLASS) && cl2.head.hasTag(CLASS)) { 3507 if (cl1.head.isParameterized() && cl2.head.isParameterized()) { 3508 Type merge = merge(cl1.head,cl2.head); 3509 return intersect(cl1.tail, cl2.tail).prepend(merge); 3510 } 3511 if (cl1.head.isRaw() || cl2.head.isRaw()) 3512 return intersect(cl1.tail, cl2.tail).prepend(erasure(cl1.head)); 3513 } 3514 return intersect(cl1.tail, cl2.tail); 3515 } 3516 // where 3517 class TypePair { 3518 final Type t1; 3519 final Type t2; 3520 boolean strict; 3521 3522 TypePair(Type t1, Type t2) { 3523 this(t1, t2, false); 3524 } 3525 3526 TypePair(Type t1, Type t2, boolean strict) { 3527 this.t1 = t1; 3528 this.t2 = t2; 3529 this.strict = strict; 3530 } 3531 @Override 3532 public int hashCode() { 3533 return 127 * Types.this.hashCode(t1) + Types.this.hashCode(t2); 3534 } 3535 @Override 3536 public boolean equals(Object obj) { 3537 if (!(obj instanceof TypePair)) 3538 return false; 3539 TypePair typePair = (TypePair)obj; 3540 return isSameType(t1, typePair.t1, strict) 3541 && isSameType(t2, typePair.t2, strict); 3542 } 3543 } 3544 Set<TypePair> mergeCache = new HashSet<>(); 3545 private Type merge(Type c1, Type c2) { 3546 ClassType class1 = (ClassType) c1; 3547 List<Type> act1 = class1.getTypeArguments(); 3548 ClassType class2 = (ClassType) c2; 3549 List<Type> act2 = class2.getTypeArguments(); 3550 ListBuffer<Type> merged = new ListBuffer<>(); 3551 List<Type> typarams = class1.tsym.type.getTypeArguments(); 3552 3553 while (act1.nonEmpty() && act2.nonEmpty() && typarams.nonEmpty()) { 3554 if (containsType(act1.head, act2.head)) { 3555 merged.append(act1.head); 3556 } else if (containsType(act2.head, act1.head)) { 3557 merged.append(act2.head); 3558 } else { 3559 TypePair pair = new TypePair(c1, c2); 3560 Type m; 3561 if (mergeCache.add(pair)) { 3562 m = new WildcardType(lub(wildUpperBound(act1.head), 3563 wildUpperBound(act2.head)), 3564 BoundKind.EXTENDS, 3565 syms.boundClass); 3566 mergeCache.remove(pair); 3567 } else { 3568 m = new WildcardType(syms.objectType, 3569 BoundKind.UNBOUND, 3570 syms.boundClass); 3571 } 3572 merged.append(m.withTypeVar(typarams.head)); 3573 } 3574 act1 = act1.tail; 3575 act2 = act2.tail; 3576 typarams = typarams.tail; 3577 } 3578 Assert.check(act1.isEmpty() && act2.isEmpty() && typarams.isEmpty()); 3579 // There is no spec detailing how type annotations are to 3580 // be inherited. So set it to noAnnotations for now 3581 return new ClassType(class1.getEnclosingType(), merged.toList(), 3582 class1.tsym); 3583 } 3584 3585 /** 3586 * Return the minimum type of a closure, a compound type if no 3587 * unique minimum exists. 3588 */ 3589 private Type compoundMin(List<Type> cl) { 3590 if (cl.isEmpty()) return syms.objectType; 3591 List<Type> compound = closureMin(cl); 3592 if (compound.isEmpty()) 3593 return null; 3594 else if (compound.tail.isEmpty()) 3595 return compound.head; 3596 else 3597 return makeIntersectionType(compound); 3598 } 3599 3600 /** 3601 * Return the minimum types of a closure, suitable for computing 3602 * compoundMin or glb. 3603 */ 3604 private List<Type> closureMin(List<Type> cl) { 3605 ListBuffer<Type> classes = new ListBuffer<>(); 3606 ListBuffer<Type> interfaces = new ListBuffer<>(); 3607 Set<Type> toSkip = new HashSet<>(); 3608 while (!cl.isEmpty()) { 3609 Type current = cl.head; 3610 boolean keep = !toSkip.contains(current); 3611 if (keep && current.hasTag(TYPEVAR)) { 3612 // skip lower-bounded variables with a subtype in cl.tail 3613 for (Type t : cl.tail) { 3614 if (isSubtypeNoCapture(t, current)) { 3615 keep = false; 3616 break; 3617 } 3618 } 3619 } 3620 if (keep) { 3621 if (current.isInterface()) 3622 interfaces.append(current); 3623 else 3624 classes.append(current); 3625 for (Type t : cl.tail) { 3626 // skip supertypes of 'current' in cl.tail 3627 if (isSubtypeNoCapture(current, t)) 3628 toSkip.add(t); 3629 } 3630 } 3631 cl = cl.tail; 3632 } 3633 return classes.appendList(interfaces).toList(); 3634 } 3635 3636 /** 3637 * Return the least upper bound of list of types. if the lub does 3638 * not exist return null. 3639 */ 3640 public Type lub(List<Type> ts) { 3641 return lub(ts.toArray(new Type[ts.length()])); 3642 } 3643 3644 /** 3645 * Return the least upper bound (lub) of set of types. If the lub 3646 * does not exist return the type of null (bottom). 3647 */ 3648 public Type lub(Type... ts) { 3649 final int UNKNOWN_BOUND = 0; 3650 final int ARRAY_BOUND = 1; 3651 final int CLASS_BOUND = 2; 3652 3653 int[] kinds = new int[ts.length]; 3654 3655 int boundkind = UNKNOWN_BOUND; 3656 for (int i = 0 ; i < ts.length ; i++) { 3657 Type t = ts[i]; 3658 switch (t.getTag()) { 3659 case CLASS: 3660 boundkind |= kinds[i] = CLASS_BOUND; 3661 break; 3662 case ARRAY: 3663 boundkind |= kinds[i] = ARRAY_BOUND; 3664 break; 3665 case TYPEVAR: 3666 do { 3667 t = t.getUpperBound(); 3668 } while (t.hasTag(TYPEVAR)); 3669 if (t.hasTag(ARRAY)) { 3670 boundkind |= kinds[i] = ARRAY_BOUND; 3671 } else { 3672 boundkind |= kinds[i] = CLASS_BOUND; 3673 } 3674 break; 3675 default: 3676 kinds[i] = UNKNOWN_BOUND; 3677 if (t.isPrimitive()) 3678 return syms.errType; 3679 } 3680 } 3681 switch (boundkind) { 3682 case 0: 3683 return syms.botType; 3684 3685 case ARRAY_BOUND: 3686 // calculate lub(A[], B[]) 3687 Type[] elements = new Type[ts.length]; 3688 for (int i = 0 ; i < ts.length ; i++) { 3689 Type elem = elements[i] = elemTypeFun.apply(ts[i]); 3690 if (elem.isPrimitive()) { 3691 // if a primitive type is found, then return 3692 // arraySuperType unless all the types are the 3693 // same 3694 Type first = ts[0]; 3695 for (int j = 1 ; j < ts.length ; j++) { 3696 if (!isSameType(first, ts[j])) { 3697 // lub(int[], B[]) is Cloneable & Serializable 3698 return arraySuperType(); 3699 } 3700 } 3701 // all the array types are the same, return one 3702 // lub(int[], int[]) is int[] 3703 return first; 3704 } 3705 } 3706 // lub(A[], B[]) is lub(A, B)[] 3707 return new ArrayType(lub(elements), syms.arrayClass); 3708 3709 case CLASS_BOUND: 3710 // calculate lub(A, B) 3711 int startIdx = 0; 3712 for (int i = 0; i < ts.length ; i++) { 3713 Type t = ts[i]; 3714 if (t.hasTag(CLASS) || t.hasTag(TYPEVAR)) { 3715 break; 3716 } else { 3717 startIdx++; 3718 } 3719 } 3720 Assert.check(startIdx < ts.length); 3721 //step 1 - compute erased candidate set (EC) 3722 List<Type> cl = erasedSupertypes(ts[startIdx]); 3723 for (int i = startIdx + 1 ; i < ts.length ; i++) { 3724 Type t = ts[i]; 3725 if (t.hasTag(CLASS) || t.hasTag(TYPEVAR)) 3726 cl = intersect(cl, erasedSupertypes(t)); 3727 } 3728 //step 2 - compute minimal erased candidate set (MEC) 3729 List<Type> mec = closureMin(cl); 3730 //step 3 - for each element G in MEC, compute lci(Inv(G)) 3731 List<Type> candidates = List.nil(); 3732 for (Type erasedSupertype : mec) { 3733 List<Type> lci = List.of(asSuper(ts[startIdx], erasedSupertype.tsym)); 3734 for (int i = startIdx + 1 ; i < ts.length ; i++) { 3735 Type superType = asSuper(ts[i], erasedSupertype.tsym); 3736 lci = intersect(lci, superType != null ? List.of(superType) : List.<Type>nil()); 3737 } 3738 candidates = candidates.appendList(lci); 3739 } 3740 //step 4 - let MEC be { G1, G2 ... Gn }, then we have that 3741 //lub = lci(Inv(G1)) & lci(Inv(G2)) & ... & lci(Inv(Gn)) 3742 return compoundMin(candidates); 3743 3744 default: 3745 // calculate lub(A, B[]) 3746 List<Type> classes = List.of(arraySuperType()); 3747 for (int i = 0 ; i < ts.length ; i++) { 3748 if (kinds[i] != ARRAY_BOUND) // Filter out any arrays 3749 classes = classes.prepend(ts[i]); 3750 } 3751 // lub(A, B[]) is lub(A, arraySuperType) 3752 return lub(classes); 3753 } 3754 } 3755 // where 3756 List<Type> erasedSupertypes(Type t) { 3757 ListBuffer<Type> buf = new ListBuffer<>(); 3758 for (Type sup : closure(t)) { 3759 if (sup.hasTag(TYPEVAR)) { 3760 buf.append(sup); 3761 } else { 3762 buf.append(erasure(sup)); 3763 } 3764 } 3765 return buf.toList(); 3766 } 3767 3768 private Type arraySuperType = null; 3769 private Type arraySuperType() { 3770 // initialized lazily to avoid problems during compiler startup 3771 if (arraySuperType == null) { 3772 synchronized (this) { 3773 if (arraySuperType == null) { 3774 // JLS 10.8: all arrays implement Cloneable and Serializable. 3775 arraySuperType = makeIntersectionType(List.of(syms.serializableType, 3776 syms.cloneableType), true); 3777 } 3778 } 3779 } 3780 return arraySuperType; 3781 } 3782 // </editor-fold> 3783 3784 // <editor-fold defaultstate="collapsed" desc="Greatest lower bound"> 3785 public Type glb(List<Type> ts) { 3786 Type t1 = ts.head; 3787 for (Type t2 : ts.tail) { 3788 if (t1.isErroneous()) 3789 return t1; 3790 t1 = glb(t1, t2); 3791 } 3792 return t1; 3793 } 3794 //where 3795 public Type glb(Type t, Type s) { 3796 if (s == null) 3797 return t; 3798 else if (t.isPrimitive() || s.isPrimitive()) 3799 return syms.errType; 3800 else if (isSubtypeNoCapture(t, s)) 3801 return t; 3802 else if (isSubtypeNoCapture(s, t)) 3803 return s; 3804 3805 List<Type> closure = union(closure(t), closure(s)); 3806 return glbFlattened(closure, t); 3807 } 3808 //where 3809 /** 3810 * Perform glb for a list of non-primitive, non-error, non-compound types; 3811 * redundant elements are removed. Bounds should be ordered according to 3812 * {@link Symbol#precedes(TypeSymbol,Types)}. 3813 * 3814 * @param flatBounds List of type to glb 3815 * @param errT Original type to use if the result is an error type 3816 */ 3817 private Type glbFlattened(List<Type> flatBounds, Type errT) { 3818 List<Type> bounds = closureMin(flatBounds); 3819 3820 if (bounds.isEmpty()) { // length == 0 3821 return syms.objectType; 3822 } else if (bounds.tail.isEmpty()) { // length == 1 3823 return bounds.head; 3824 } else { // length > 1 3825 int classCount = 0; 3826 List<Type> lowers = List.nil(); 3827 for (Type bound : bounds) { 3828 if (!bound.isInterface()) { 3829 classCount++; 3830 Type lower = cvarLowerBound(bound); 3831 if (bound != lower && !lower.hasTag(BOT)) 3832 lowers = insert(lowers, lower); 3833 } 3834 } 3835 if (classCount > 1) { 3836 if (lowers.isEmpty()) 3837 return createErrorType(errT); 3838 else 3839 return glbFlattened(union(bounds, lowers), errT); 3840 } 3841 } 3842 return makeIntersectionType(bounds); 3843 } 3844 // </editor-fold> 3845 3846 // <editor-fold defaultstate="collapsed" desc="hashCode"> 3847 /** 3848 * Compute a hash code on a type. 3849 */ 3850 public int hashCode(Type t) { 3851 return hashCode.visit(t); 3852 } 3853 // where 3854 private static final UnaryVisitor<Integer> hashCode = new UnaryVisitor<Integer>() { 3855 3856 public Integer visitType(Type t, Void ignored) { 3857 return t.getTag().ordinal(); 3858 } 3859 3860 @Override 3861 public Integer visitClassType(ClassType t, Void ignored) { 3862 int result = visit(t.getEnclosingType()); 3863 result *= 127; 3864 result += t.tsym.flatName().hashCode(); 3865 for (Type s : t.getTypeArguments()) { 3866 result *= 127; 3867 result += visit(s); 3868 } 3869 return result; 3870 } 3871 3872 @Override 3873 public Integer visitMethodType(MethodType t, Void ignored) { 3874 int h = METHOD.ordinal(); 3875 for (List<Type> thisargs = t.argtypes; 3876 thisargs.tail != null; 3877 thisargs = thisargs.tail) 3878 h = (h << 5) + visit(thisargs.head); 3879 return (h << 5) + visit(t.restype); 3880 } 3881 3882 @Override 3883 public Integer visitWildcardType(WildcardType t, Void ignored) { 3884 int result = t.kind.hashCode(); 3885 if (t.type != null) { 3886 result *= 127; 3887 result += visit(t.type); 3888 } 3889 return result; 3890 } 3891 3892 @Override 3893 public Integer visitArrayType(ArrayType t, Void ignored) { 3894 return visit(t.elemtype) + 12; 3895 } 3896 3897 @Override 3898 public Integer visitTypeVar(TypeVar t, Void ignored) { 3899 return System.identityHashCode(t.tsym); 3900 } 3901 3902 @Override 3903 public Integer visitUndetVar(UndetVar t, Void ignored) { 3904 return System.identityHashCode(t); 3905 } 3906 3907 @Override 3908 public Integer visitErrorType(ErrorType t, Void ignored) { 3909 return 0; 3910 } 3911 }; 3912 // </editor-fold> 3913 3914 // <editor-fold defaultstate="collapsed" desc="Return-Type-Substitutable"> 3915 /** 3916 * Does t have a result that is a subtype of the result type of s, 3917 * suitable for covariant returns? It is assumed that both types 3918 * are (possibly polymorphic) method types. Monomorphic method 3919 * types are handled in the obvious way. Polymorphic method types 3920 * require renaming all type variables of one to corresponding 3921 * type variables in the other, where correspondence is by 3922 * position in the type parameter list. */ 3923 public boolean resultSubtype(Type t, Type s, Warner warner) { 3924 List<Type> tvars = t.getTypeArguments(); 3925 List<Type> svars = s.getTypeArguments(); 3926 Type tres = t.getReturnType(); 3927 Type sres = subst(s.getReturnType(), svars, tvars); 3928 return covariantReturnType(tres, sres, warner); 3929 } 3930 3931 /** 3932 * Return-Type-Substitutable. 3933 * @jls section 8.4.5 3934 */ 3935 public boolean returnTypeSubstitutable(Type r1, Type r2) { 3936 if (hasSameArgs(r1, r2)) 3937 return resultSubtype(r1, r2, noWarnings); 3938 else 3939 return covariantReturnType(r1.getReturnType(), 3940 erasure(r2.getReturnType()), 3941 noWarnings); 3942 } 3943 3944 public boolean returnTypeSubstitutable(Type r1, 3945 Type r2, Type r2res, 3946 Warner warner) { 3947 if (isSameType(r1.getReturnType(), r2res)) 3948 return true; 3949 if (r1.getReturnType().isPrimitive() || r2res.isPrimitive()) 3950 return false; 3951 3952 if (hasSameArgs(r1, r2)) 3953 return covariantReturnType(r1.getReturnType(), r2res, warner); 3954 if (isSubtypeUnchecked(r1.getReturnType(), r2res, warner)) 3955 return true; 3956 if (!isSubtype(r1.getReturnType(), erasure(r2res))) 3957 return false; 3958 warner.warn(LintCategory.UNCHECKED); 3959 return true; 3960 } 3961 3962 /** 3963 * Is t an appropriate return type in an overrider for a 3964 * method that returns s? 3965 */ 3966 public boolean covariantReturnType(Type t, Type s, Warner warner) { 3967 return 3968 isSameType(t, s) || 3969 !t.isPrimitive() && 3970 !s.isPrimitive() && 3971 isAssignable(t, s, warner); 3972 } 3973 // </editor-fold> 3974 3975 // <editor-fold defaultstate="collapsed" desc="Box/unbox support"> 3976 /** 3977 * Return the class that boxes the given primitive. 3978 */ 3979 public ClassSymbol boxedClass(Type t) { 3980 return syms.enterClass(syms.boxedName[t.getTag().ordinal()]); 3981 } 3982 3983 /** 3984 * Return the boxed type if 't' is primitive, otherwise return 't' itself. 3985 */ 3986 public Type boxedTypeOrType(Type t) { 3987 return t.isPrimitive() ? 3988 boxedClass(t).type : 3989 t; 3990 } 3991 3992 /** 3993 * Return the primitive type corresponding to a boxed type. 3994 */ 3995 public Type unboxedType(Type t) { 3996 for (int i=0; i<syms.boxedName.length; i++) { 3997 Name box = syms.boxedName[i]; 3998 if (box != null && 3999 asSuper(t, syms.enterClass(box)) != null) 4000 return syms.typeOfTag[i]; 4001 } 4002 return Type.noType; 4003 } 4004 4005 /** 4006 * Return the unboxed type if 't' is a boxed class, otherwise return 't' itself. 4007 */ 4008 public Type unboxedTypeOrType(Type t) { 4009 Type unboxedType = unboxedType(t); 4010 return unboxedType.hasTag(NONE) ? t : unboxedType; 4011 } 4012 // </editor-fold> 4013 4014 // <editor-fold defaultstate="collapsed" desc="Capture conversion"> 4015 /* 4016 * JLS 5.1.10 Capture Conversion: 4017 * 4018 * Let G name a generic type declaration with n formal type 4019 * parameters A1 ... An with corresponding bounds U1 ... Un. There 4020 * exists a capture conversion from G<T1 ... Tn> to G<S1 ... Sn>, 4021 * where, for 1 <= i <= n: 4022 * 4023 * + If Ti is a wildcard type argument (4.5.1) of the form ? then 4024 * Si is a fresh type variable whose upper bound is 4025 * Ui[A1 := S1, ..., An := Sn] and whose lower bound is the null 4026 * type. 4027 * 4028 * + If Ti is a wildcard type argument of the form ? extends Bi, 4029 * then Si is a fresh type variable whose upper bound is 4030 * glb(Bi, Ui[A1 := S1, ..., An := Sn]) and whose lower bound is 4031 * the null type, where glb(V1,... ,Vm) is V1 & ... & Vm. It is 4032 * a compile-time error if for any two classes (not interfaces) 4033 * Vi and Vj,Vi is not a subclass of Vj or vice versa. 4034 * 4035 * + If Ti is a wildcard type argument of the form ? super Bi, 4036 * then Si is a fresh type variable whose upper bound is 4037 * Ui[A1 := S1, ..., An := Sn] and whose lower bound is Bi. 4038 * 4039 * + Otherwise, Si = Ti. 4040 * 4041 * Capture conversion on any type other than a parameterized type 4042 * (4.5) acts as an identity conversion (5.1.1). Capture 4043 * conversions never require a special action at run time and 4044 * therefore never throw an exception at run time. 4045 * 4046 * Capture conversion is not applied recursively. 4047 */ 4048 /** 4049 * Capture conversion as specified by the JLS. 4050 */ 4051 4052 public List<Type> capture(List<Type> ts) { 4053 List<Type> buf = List.nil(); 4054 for (Type t : ts) { 4055 buf = buf.prepend(capture(t)); 4056 } 4057 return buf.reverse(); 4058 } 4059 4060 public Type capture(Type t) { 4061 if (!t.hasTag(CLASS)) { 4062 return t; 4063 } 4064 if (t.getEnclosingType() != Type.noType) { 4065 Type capturedEncl = capture(t.getEnclosingType()); 4066 if (capturedEncl != t.getEnclosingType()) { 4067 Type type1 = memberType(capturedEncl, t.tsym); 4068 t = subst(type1, t.tsym.type.getTypeArguments(), t.getTypeArguments()); 4069 } 4070 } 4071 ClassType cls = (ClassType)t; 4072 if (cls.isRaw() || !cls.isParameterized()) 4073 return cls; 4074 4075 ClassType G = (ClassType)cls.asElement().asType(); 4076 List<Type> A = G.getTypeArguments(); 4077 List<Type> T = cls.getTypeArguments(); 4078 List<Type> S = freshTypeVariables(T); 4079 4080 List<Type> currentA = A; 4081 List<Type> currentT = T; 4082 List<Type> currentS = S; 4083 boolean captured = false; 4084 while (!currentA.isEmpty() && 4085 !currentT.isEmpty() && 4086 !currentS.isEmpty()) { 4087 if (currentS.head != currentT.head) { 4088 captured = true; 4089 WildcardType Ti = (WildcardType)currentT.head; 4090 Type Ui = currentA.head.getUpperBound(); 4091 CapturedType Si = (CapturedType)currentS.head; 4092 if (Ui == null) 4093 Ui = syms.objectType; 4094 switch (Ti.kind) { 4095 case UNBOUND: 4096 Si.bound = subst(Ui, A, S); 4097 Si.lower = syms.botType; 4098 break; 4099 case EXTENDS: 4100 Si.bound = glb(Ti.getExtendsBound(), subst(Ui, A, S)); 4101 Si.lower = syms.botType; 4102 break; 4103 case SUPER: 4104 Si.bound = subst(Ui, A, S); 4105 Si.lower = Ti.getSuperBound(); 4106 break; 4107 } 4108 Type tmpBound = Si.bound.hasTag(UNDETVAR) ? ((UndetVar)Si.bound).qtype : Si.bound; 4109 Type tmpLower = Si.lower.hasTag(UNDETVAR) ? ((UndetVar)Si.lower).qtype : Si.lower; 4110 if (!Si.bound.hasTag(ERROR) && 4111 !Si.lower.hasTag(ERROR) && 4112 isSameType(tmpBound, tmpLower, false)) { 4113 currentS.head = Si.bound; 4114 } 4115 } 4116 currentA = currentA.tail; 4117 currentT = currentT.tail; 4118 currentS = currentS.tail; 4119 } 4120 if (!currentA.isEmpty() || !currentT.isEmpty() || !currentS.isEmpty()) 4121 return erasure(t); // some "rare" type involved 4122 4123 if (captured) 4124 return new ClassType(cls.getEnclosingType(), S, cls.tsym, 4125 cls.getMetadata()); 4126 else 4127 return t; 4128 } 4129 // where 4130 public List<Type> freshTypeVariables(List<Type> types) { 4131 ListBuffer<Type> result = new ListBuffer<>(); 4132 for (Type t : types) { 4133 if (t.hasTag(WILDCARD)) { 4134 Type bound = ((WildcardType)t).getExtendsBound(); 4135 if (bound == null) 4136 bound = syms.objectType; 4137 result.append(new CapturedType(capturedName, 4138 syms.noSymbol, 4139 bound, 4140 syms.botType, 4141 (WildcardType)t)); 4142 } else { 4143 result.append(t); 4144 } 4145 } 4146 return result.toList(); 4147 } 4148 // </editor-fold> 4149 4150 // <editor-fold defaultstate="collapsed" desc="Internal utility methods"> 4151 private boolean sideCast(Type from, Type to, Warner warn) { 4152 // We are casting from type $from$ to type $to$, which are 4153 // non-final unrelated types. This method 4154 // tries to reject a cast by transferring type parameters 4155 // from $to$ to $from$ by common superinterfaces. 4156 boolean reverse = false; 4157 Type target = to; 4158 if ((to.tsym.flags() & INTERFACE) == 0) { 4159 Assert.check((from.tsym.flags() & INTERFACE) != 0); 4160 reverse = true; 4161 to = from; 4162 from = target; 4163 } 4164 List<Type> commonSupers = superClosure(to, erasure(from)); 4165 boolean giveWarning = commonSupers.isEmpty(); 4166 // The arguments to the supers could be unified here to 4167 // get a more accurate analysis 4168 while (commonSupers.nonEmpty()) { 4169 Type t1 = asSuper(from, commonSupers.head.tsym); 4170 Type t2 = commonSupers.head; // same as asSuper(to, commonSupers.head.tsym); 4171 if (disjointTypes(t1.getTypeArguments(), t2.getTypeArguments())) 4172 return false; 4173 giveWarning = giveWarning || (reverse ? giveWarning(t2, t1) : giveWarning(t1, t2)); 4174 commonSupers = commonSupers.tail; 4175 } 4176 if (giveWarning && !isReifiable(reverse ? from : to)) 4177 warn.warn(LintCategory.UNCHECKED); 4178 return true; 4179 } 4180 4181 private boolean sideCastFinal(Type from, Type to, Warner warn) { 4182 // We are casting from type $from$ to type $to$, which are 4183 // unrelated types one of which is final and the other of 4184 // which is an interface. This method 4185 // tries to reject a cast by transferring type parameters 4186 // from the final class to the interface. 4187 boolean reverse = false; 4188 Type target = to; 4189 if ((to.tsym.flags() & INTERFACE) == 0) { 4190 Assert.check((from.tsym.flags() & INTERFACE) != 0); 4191 reverse = true; 4192 to = from; 4193 from = target; 4194 } 4195 Assert.check((from.tsym.flags() & FINAL) != 0); 4196 Type t1 = asSuper(from, to.tsym); 4197 if (t1 == null) return false; 4198 Type t2 = to; 4199 if (disjointTypes(t1.getTypeArguments(), t2.getTypeArguments())) 4200 return false; 4201 if (!isReifiable(target) && 4202 (reverse ? giveWarning(t2, t1) : giveWarning(t1, t2))) 4203 warn.warn(LintCategory.UNCHECKED); 4204 return true; 4205 } 4206 4207 private boolean giveWarning(Type from, Type to) { 4208 List<Type> bounds = to.isCompound() ? 4209 ((IntersectionClassType)to).getComponents() : List.of(to); 4210 for (Type b : bounds) { 4211 Type subFrom = asSub(from, b.tsym); 4212 if (b.isParameterized() && 4213 (!(isUnbounded(b) || 4214 isSubtype(from, b) || 4215 ((subFrom != null) && containsType(b.allparams(), subFrom.allparams()))))) { 4216 return true; 4217 } 4218 } 4219 return false; 4220 } 4221 4222 private List<Type> superClosure(Type t, Type s) { 4223 List<Type> cl = List.nil(); 4224 for (List<Type> l = interfaces(t); l.nonEmpty(); l = l.tail) { 4225 if (isSubtype(s, erasure(l.head))) { 4226 cl = insert(cl, l.head); 4227 } else { 4228 cl = union(cl, superClosure(l.head, s)); 4229 } 4230 } 4231 return cl; 4232 } 4233 4234 private boolean containsTypeEquivalent(Type t, Type s) { 4235 return 4236 isSameType(t, s) || // shortcut 4237 containsType(t, s) && containsType(s, t); 4238 } 4239 4240 // <editor-fold defaultstate="collapsed" desc="adapt"> 4241 /** 4242 * Adapt a type by computing a substitution which maps a source 4243 * type to a target type. 4244 * 4245 * @param source the source type 4246 * @param target the target type 4247 * @param from the type variables of the computed substitution 4248 * @param to the types of the computed substitution. 4249 */ 4250 public void adapt(Type source, 4251 Type target, 4252 ListBuffer<Type> from, 4253 ListBuffer<Type> to) throws AdaptFailure { 4254 new Adapter(from, to).adapt(source, target); 4255 } 4256 4257 class Adapter extends SimpleVisitor<Void, Type> { 4258 4259 ListBuffer<Type> from; 4260 ListBuffer<Type> to; 4261 Map<Symbol,Type> mapping; 4262 4263 Adapter(ListBuffer<Type> from, ListBuffer<Type> to) { 4264 this.from = from; 4265 this.to = to; 4266 mapping = new HashMap<>(); 4267 } 4268 4269 public void adapt(Type source, Type target) throws AdaptFailure { 4270 visit(source, target); 4271 List<Type> fromList = from.toList(); 4272 List<Type> toList = to.toList(); 4273 while (!fromList.isEmpty()) { 4274 Type val = mapping.get(fromList.head.tsym); 4275 if (toList.head != val) 4276 toList.head = val; 4277 fromList = fromList.tail; 4278 toList = toList.tail; 4279 } 4280 } 4281 4282 @Override 4283 public Void visitClassType(ClassType source, Type target) throws AdaptFailure { 4284 if (target.hasTag(CLASS)) 4285 adaptRecursive(source.allparams(), target.allparams()); 4286 return null; 4287 } 4288 4289 @Override 4290 public Void visitArrayType(ArrayType source, Type target) throws AdaptFailure { 4291 if (target.hasTag(ARRAY)) 4292 adaptRecursive(elemtype(source), elemtype(target)); 4293 return null; 4294 } 4295 4296 @Override 4297 public Void visitWildcardType(WildcardType source, Type target) throws AdaptFailure { 4298 if (source.isExtendsBound()) 4299 adaptRecursive(wildUpperBound(source), wildUpperBound(target)); 4300 else if (source.isSuperBound()) 4301 adaptRecursive(wildLowerBound(source), wildLowerBound(target)); 4302 return null; 4303 } 4304 4305 @Override 4306 public Void visitTypeVar(TypeVar source, Type target) throws AdaptFailure { 4307 // Check to see if there is 4308 // already a mapping for $source$, in which case 4309 // the old mapping will be merged with the new 4310 Type val = mapping.get(source.tsym); 4311 if (val != null) { 4312 if (val.isSuperBound() && target.isSuperBound()) { 4313 val = isSubtype(wildLowerBound(val), wildLowerBound(target)) 4314 ? target : val; 4315 } else if (val.isExtendsBound() && target.isExtendsBound()) { 4316 val = isSubtype(wildUpperBound(val), wildUpperBound(target)) 4317 ? val : target; 4318 } else if (!isSameType(val, target)) { 4319 throw new AdaptFailure(); 4320 } 4321 } else { 4322 val = target; 4323 from.append(source); 4324 to.append(target); 4325 } 4326 mapping.put(source.tsym, val); 4327 return null; 4328 } 4329 4330 @Override 4331 public Void visitType(Type source, Type target) { 4332 return null; 4333 } 4334 4335 private Set<TypePair> cache = new HashSet<>(); 4336 4337 private void adaptRecursive(Type source, Type target) { 4338 TypePair pair = new TypePair(source, target); 4339 if (cache.add(pair)) { 4340 try { 4341 visit(source, target); 4342 } finally { 4343 cache.remove(pair); 4344 } 4345 } 4346 } 4347 4348 private void adaptRecursive(List<Type> source, List<Type> target) { 4349 if (source.length() == target.length()) { 4350 while (source.nonEmpty()) { 4351 adaptRecursive(source.head, target.head); 4352 source = source.tail; 4353 target = target.tail; 4354 } 4355 } 4356 } 4357 } 4358 4359 public static class AdaptFailure extends RuntimeException { 4360 static final long serialVersionUID = -7490231548272701566L; 4361 } 4362 4363 private void adaptSelf(Type t, 4364 ListBuffer<Type> from, 4365 ListBuffer<Type> to) { 4366 try { 4367 //if (t.tsym.type != t) 4368 adapt(t.tsym.type, t, from, to); 4369 } catch (AdaptFailure ex) { 4370 // Adapt should never fail calculating a mapping from 4371 // t.tsym.type to t as there can be no merge problem. 4372 throw new AssertionError(ex); 4373 } 4374 } 4375 // </editor-fold> 4376 4377 /** 4378 * Rewrite all type variables (universal quantifiers) in the given 4379 * type to wildcards (existential quantifiers). This is used to 4380 * determine if a cast is allowed. For example, if high is true 4381 * and {@code T <: Number}, then {@code List<T>} is rewritten to 4382 * {@code List<? extends Number>}. Since {@code List<Integer> <: 4383 * List<? extends Number>} a {@code List<T>} can be cast to {@code 4384 * List<Integer>} with a warning. 4385 * @param t a type 4386 * @param high if true return an upper bound; otherwise a lower 4387 * bound 4388 * @param rewriteTypeVars only rewrite captured wildcards if false; 4389 * otherwise rewrite all type variables 4390 * @return the type rewritten with wildcards (existential 4391 * quantifiers) only 4392 */ 4393 private Type rewriteQuantifiers(Type t, boolean high, boolean rewriteTypeVars) { 4394 return new Rewriter(high, rewriteTypeVars).visit(t); 4395 } 4396 4397 class Rewriter extends UnaryVisitor<Type> { 4398 4399 boolean high; 4400 boolean rewriteTypeVars; 4401 4402 Rewriter(boolean high, boolean rewriteTypeVars) { 4403 this.high = high; 4404 this.rewriteTypeVars = rewriteTypeVars; 4405 } 4406 4407 @Override 4408 public Type visitClassType(ClassType t, Void s) { 4409 ListBuffer<Type> rewritten = new ListBuffer<>(); 4410 boolean changed = false; 4411 for (Type arg : t.allparams()) { 4412 Type bound = visit(arg); 4413 if (arg != bound) { 4414 changed = true; 4415 } 4416 rewritten.append(bound); 4417 } 4418 if (changed) 4419 return subst(t.tsym.type, 4420 t.tsym.type.allparams(), 4421 rewritten.toList()); 4422 else 4423 return t; 4424 } 4425 4426 public Type visitType(Type t, Void s) { 4427 return t; 4428 } 4429 4430 @Override 4431 public Type visitCapturedType(CapturedType t, Void s) { 4432 Type w_bound = t.wildcard.type; 4433 Type bound = w_bound.contains(t) ? 4434 erasure(w_bound) : 4435 visit(w_bound); 4436 return rewriteAsWildcardType(visit(bound), t.wildcard.bound, t.wildcard.kind); 4437 } 4438 4439 @Override 4440 public Type visitTypeVar(TypeVar t, Void s) { 4441 if (rewriteTypeVars) { 4442 Type bound = t.bound.contains(t) ? 4443 erasure(t.bound) : 4444 visit(t.bound); 4445 return rewriteAsWildcardType(bound, t, EXTENDS); 4446 } else { 4447 return t; 4448 } 4449 } 4450 4451 @Override 4452 public Type visitWildcardType(WildcardType t, Void s) { 4453 Type bound2 = visit(t.type); 4454 return t.type == bound2 ? t : rewriteAsWildcardType(bound2, t.bound, t.kind); 4455 } 4456 4457 private Type rewriteAsWildcardType(Type bound, TypeVar formal, BoundKind bk) { 4458 switch (bk) { 4459 case EXTENDS: return high ? 4460 makeExtendsWildcard(B(bound), formal) : 4461 makeExtendsWildcard(syms.objectType, formal); 4462 case SUPER: return high ? 4463 makeSuperWildcard(syms.botType, formal) : 4464 makeSuperWildcard(B(bound), formal); 4465 case UNBOUND: return makeExtendsWildcard(syms.objectType, formal); 4466 default: 4467 Assert.error("Invalid bound kind " + bk); 4468 return null; 4469 } 4470 } 4471 4472 Type B(Type t) { 4473 while (t.hasTag(WILDCARD)) { 4474 WildcardType w = (WildcardType)t; 4475 t = high ? 4476 w.getExtendsBound() : 4477 w.getSuperBound(); 4478 if (t == null) { 4479 t = high ? syms.objectType : syms.botType; 4480 } 4481 } 4482 return t; 4483 } 4484 } 4485 4486 4487 /** 4488 * Create a wildcard with the given upper (extends) bound; create 4489 * an unbounded wildcard if bound is Object. 4490 * 4491 * @param bound the upper bound 4492 * @param formal the formal type parameter that will be 4493 * substituted by the wildcard 4494 */ 4495 private WildcardType makeExtendsWildcard(Type bound, TypeVar formal) { 4496 if (bound == syms.objectType) { 4497 return new WildcardType(syms.objectType, 4498 BoundKind.UNBOUND, 4499 syms.boundClass, 4500 formal); 4501 } else { 4502 return new WildcardType(bound, 4503 BoundKind.EXTENDS, 4504 syms.boundClass, 4505 formal); 4506 } 4507 } 4508 4509 /** 4510 * Create a wildcard with the given lower (super) bound; create an 4511 * unbounded wildcard if bound is bottom (type of {@code null}). 4512 * 4513 * @param bound the lower bound 4514 * @param formal the formal type parameter that will be 4515 * substituted by the wildcard 4516 */ 4517 private WildcardType makeSuperWildcard(Type bound, TypeVar formal) { 4518 if (bound.hasTag(BOT)) { 4519 return new WildcardType(syms.objectType, 4520 BoundKind.UNBOUND, 4521 syms.boundClass, 4522 formal); 4523 } else { 4524 return new WildcardType(bound, 4525 BoundKind.SUPER, 4526 syms.boundClass, 4527 formal); 4528 } 4529 } 4530 4531 /** 4532 * A wrapper for a type that allows use in sets. 4533 */ 4534 public static class UniqueType { 4535 public final Type type; 4536 final Types types; 4537 4538 public UniqueType(Type type, Types types) { 4539 this.type = type; 4540 this.types = types; 4541 } 4542 4543 public int hashCode() { 4544 return types.hashCode(type); 4545 } 4546 4547 public boolean equals(Object obj) { 4548 return (obj instanceof UniqueType) && 4549 types.isSameType(type, ((UniqueType)obj).type); 4550 } 4551 4552 public String toString() { 4553 return type.toString(); 4554 } 4555 4556 } 4557 // </editor-fold> 4558 4559 // <editor-fold defaultstate="collapsed" desc="Visitors"> 4560 /** 4561 * A default visitor for types. All visitor methods except 4562 * visitType are implemented by delegating to visitType. Concrete 4563 * subclasses must provide an implementation of visitType and can 4564 * override other methods as needed. 4565 * 4566 * @param <R> the return type of the operation implemented by this 4567 * visitor; use Void if no return type is needed. 4568 * @param <S> the type of the second argument (the first being the 4569 * type itself) of the operation implemented by this visitor; use 4570 * Void if a second argument is not needed. 4571 */ 4572 public static abstract class DefaultTypeVisitor<R,S> implements Type.Visitor<R,S> { 4573 final public R visit(Type t, S s) { return t.accept(this, s); } 4574 public R visitClassType(ClassType t, S s) { return visitType(t, s); } 4575 public R visitWildcardType(WildcardType t, S s) { return visitType(t, s); } 4576 public R visitArrayType(ArrayType t, S s) { return visitType(t, s); } 4577 public R visitMethodType(MethodType t, S s) { return visitType(t, s); } 4578 public R visitPackageType(PackageType t, S s) { return visitType(t, s); } 4579 public R visitTypeVar(TypeVar t, S s) { return visitType(t, s); } 4580 public R visitCapturedType(CapturedType t, S s) { return visitType(t, s); } 4581 public R visitForAll(ForAll t, S s) { return visitType(t, s); } 4582 public R visitUndetVar(UndetVar t, S s) { return visitType(t, s); } 4583 public R visitErrorType(ErrorType t, S s) { return visitType(t, s); } 4584 } 4585 4586 /** 4587 * A default visitor for symbols. All visitor methods except 4588 * visitSymbol are implemented by delegating to visitSymbol. Concrete 4589 * subclasses must provide an implementation of visitSymbol and can 4590 * override other methods as needed. 4591 * 4592 * @param <R> the return type of the operation implemented by this 4593 * visitor; use Void if no return type is needed. 4594 * @param <S> the type of the second argument (the first being the 4595 * symbol itself) of the operation implemented by this visitor; use 4596 * Void if a second argument is not needed. 4597 */ 4598 public static abstract class DefaultSymbolVisitor<R,S> implements Symbol.Visitor<R,S> { 4599 final public R visit(Symbol s, S arg) { return s.accept(this, arg); } 4600 public R visitClassSymbol(ClassSymbol s, S arg) { return visitSymbol(s, arg); } 4601 public R visitMethodSymbol(MethodSymbol s, S arg) { return visitSymbol(s, arg); } 4602 public R visitOperatorSymbol(OperatorSymbol s, S arg) { return visitSymbol(s, arg); } 4603 public R visitPackageSymbol(PackageSymbol s, S arg) { return visitSymbol(s, arg); } 4604 public R visitTypeSymbol(TypeSymbol s, S arg) { return visitSymbol(s, arg); } 4605 public R visitVarSymbol(VarSymbol s, S arg) { return visitSymbol(s, arg); } 4606 } 4607 4608 /** 4609 * A <em>simple</em> visitor for types. This visitor is simple as 4610 * captured wildcards, for-all types (generic methods), and 4611 * undetermined type variables (part of inference) are hidden. 4612 * Captured wildcards are hidden by treating them as type 4613 * variables and the rest are hidden by visiting their qtypes. 4614 * 4615 * @param <R> the return type of the operation implemented by this 4616 * visitor; use Void if no return type is needed. 4617 * @param <S> the type of the second argument (the first being the 4618 * type itself) of the operation implemented by this visitor; use 4619 * Void if a second argument is not needed. 4620 */ 4621 public static abstract class SimpleVisitor<R,S> extends DefaultTypeVisitor<R,S> { 4622 @Override 4623 public R visitCapturedType(CapturedType t, S s) { 4624 return visitTypeVar(t, s); 4625 } 4626 @Override 4627 public R visitForAll(ForAll t, S s) { 4628 return visit(t.qtype, s); 4629 } 4630 @Override 4631 public R visitUndetVar(UndetVar t, S s) { 4632 return visit(t.qtype, s); 4633 } 4634 } 4635 4636 /** 4637 * A plain relation on types. That is a 2-ary function on the 4638 * form Type × Type → Boolean. 4639 * <!-- In plain text: Type x Type -> Boolean --> 4640 */ 4641 public static abstract class TypeRelation extends SimpleVisitor<Boolean,Type> {} 4642 4643 /** 4644 * A convenience visitor for implementing operations that only 4645 * require one argument (the type itself), that is, unary 4646 * operations. 4647 * 4648 * @param <R> the return type of the operation implemented by this 4649 * visitor; use Void if no return type is needed. 4650 */ 4651 public static abstract class UnaryVisitor<R> extends SimpleVisitor<R,Void> { 4652 final public R visit(Type t) { return t.accept(this, null); } 4653 } 4654 4655 /** 4656 * A visitor for implementing a mapping from types to types. The 4657 * default behavior of this class is to implement the identity 4658 * mapping (mapping a type to itself). This can be overridden in 4659 * subclasses. 4660 * 4661 * @param <S> the type of the second argument (the first being the 4662 * type itself) of this mapping; use Void if a second argument is 4663 * not needed. 4664 */ 4665 public static class MapVisitor<S> extends DefaultTypeVisitor<Type,S> { 4666 final public Type visit(Type t) { return t.accept(this, null); } 4667 public Type visitType(Type t, S s) { return t; } 4668 } 4669 // </editor-fold> 4670 4671 4672 // <editor-fold defaultstate="collapsed" desc="Annotation support"> 4673 4674 public RetentionPolicy getRetention(Attribute.Compound a) { 4675 return getRetention(a.type.tsym); 4676 } 4677 4678 public RetentionPolicy getRetention(Symbol sym) { 4679 RetentionPolicy vis = RetentionPolicy.CLASS; // the default 4680 Attribute.Compound c = sym.attribute(syms.retentionType.tsym); 4681 if (c != null) { 4682 Attribute value = c.member(names.value); 4683 if (value != null && value instanceof Attribute.Enum) { 4684 Name levelName = ((Attribute.Enum)value).value.name; 4685 if (levelName == names.SOURCE) vis = RetentionPolicy.SOURCE; 4686 else if (levelName == names.CLASS) vis = RetentionPolicy.CLASS; 4687 else if (levelName == names.RUNTIME) vis = RetentionPolicy.RUNTIME; 4688 else ;// /* fail soft */ throw new AssertionError(levelName); 4689 } 4690 } 4691 return vis; 4692 } 4693 // </editor-fold> 4694 4695 // <editor-fold defaultstate="collapsed" desc="Signature Generation"> 4696 4697 public static abstract class SignatureGenerator { 4698 4699 private final Types types; 4700 4701 protected abstract void append(char ch); 4702 protected abstract void append(byte[] ba); 4703 protected abstract void append(Name name); 4704 protected void classReference(ClassSymbol c) { /* by default: no-op */ } 4705 4706 protected SignatureGenerator(Types types) { 4707 this.types = types; 4708 } 4709 4710 /** 4711 * Assemble signature of given type in string buffer. 4712 */ 4713 public void assembleSig(Type type) { 4714 switch (type.getTag()) { 4715 case BYTE: 4716 append('B'); 4717 break; 4718 case SHORT: 4719 append('S'); 4720 break; 4721 case CHAR: 4722 append('C'); 4723 break; 4724 case INT: 4725 append('I'); 4726 break; 4727 case LONG: 4728 append('J'); 4729 break; 4730 case FLOAT: 4731 append('F'); 4732 break; 4733 case DOUBLE: 4734 append('D'); 4735 break; 4736 case BOOLEAN: 4737 append('Z'); 4738 break; 4739 case VOID: 4740 append('V'); 4741 break; 4742 case CLASS: 4743 append('L'); 4744 assembleClassSig(type); 4745 append(';'); 4746 break; 4747 case ARRAY: 4748 ArrayType at = (ArrayType) type; 4749 append('['); 4750 assembleSig(at.elemtype); 4751 break; 4752 case METHOD: 4753 MethodType mt = (MethodType) type; 4754 append('('); 4755 assembleSig(mt.argtypes); 4756 append(')'); 4757 assembleSig(mt.restype); 4758 if (hasTypeVar(mt.thrown)) { 4759 for (List<Type> l = mt.thrown; l.nonEmpty(); l = l.tail) { 4760 append('^'); 4761 assembleSig(l.head); 4762 } 4763 } 4764 break; 4765 case WILDCARD: { 4766 Type.WildcardType ta = (Type.WildcardType) type; 4767 switch (ta.kind) { 4768 case SUPER: 4769 append('-'); 4770 assembleSig(ta.type); 4771 break; 4772 case EXTENDS: 4773 append('+'); 4774 assembleSig(ta.type); 4775 break; 4776 case UNBOUND: 4777 append('*'); 4778 break; 4779 default: 4780 throw new AssertionError(ta.kind); 4781 } 4782 break; 4783 } 4784 case TYPEVAR: 4785 append('T'); 4786 append(type.tsym.name); 4787 append(';'); 4788 break; 4789 case FORALL: 4790 Type.ForAll ft = (Type.ForAll) type; 4791 assembleParamsSig(ft.tvars); 4792 assembleSig(ft.qtype); 4793 break; 4794 default: 4795 throw new AssertionError("typeSig " + type.getTag()); 4796 } 4797 } 4798 4799 public boolean hasTypeVar(List<Type> l) { 4800 while (l.nonEmpty()) { 4801 if (l.head.hasTag(TypeTag.TYPEVAR)) { 4802 return true; 4803 } 4804 l = l.tail; 4805 } 4806 return false; 4807 } 4808 4809 public void assembleClassSig(Type type) { 4810 ClassType ct = (ClassType) type; 4811 ClassSymbol c = (ClassSymbol) ct.tsym; 4812 classReference(c); 4813 Type outer = ct.getEnclosingType(); 4814 if (outer.allparams().nonEmpty()) { 4815 boolean rawOuter = 4816 c.owner.kind == MTH || // either a local class 4817 c.name == types.names.empty; // or anonymous 4818 assembleClassSig(rawOuter 4819 ? types.erasure(outer) 4820 : outer); 4821 append(rawOuter ? '$' : '.'); 4822 Assert.check(c.flatname.startsWith(c.owner.enclClass().flatname)); 4823 append(rawOuter 4824 ? c.flatname.subName(c.owner.enclClass().flatname.getByteLength() + 1, c.flatname.getByteLength()) 4825 : c.name); 4826 } else { 4827 append(externalize(c.flatname)); 4828 } 4829 if (ct.getTypeArguments().nonEmpty()) { 4830 append('<'); 4831 assembleSig(ct.getTypeArguments()); 4832 append('>'); 4833 } 4834 } 4835 4836 public void assembleParamsSig(List<Type> typarams) { 4837 append('<'); 4838 for (List<Type> ts = typarams; ts.nonEmpty(); ts = ts.tail) { 4839 Type.TypeVar tvar = (Type.TypeVar) ts.head; 4840 append(tvar.tsym.name); 4841 List<Type> bounds = types.getBounds(tvar); 4842 if ((bounds.head.tsym.flags() & INTERFACE) != 0) { 4843 append(':'); 4844 } 4845 for (List<Type> l = bounds; l.nonEmpty(); l = l.tail) { 4846 append(':'); 4847 assembleSig(l.head); 4848 } 4849 } 4850 append('>'); 4851 } 4852 4853 private void assembleSig(List<Type> types) { 4854 for (List<Type> ts = types; ts.nonEmpty(); ts = ts.tail) { 4855 assembleSig(ts.head); 4856 } 4857 } 4858 } 4859 // </editor-fold> 4860 4861 public void newRound() { 4862 descCache._map.clear(); 4863 isDerivedRawCache.clear(); 4864 implCache._map.clear(); 4865 membersCache._map.clear(); 4866 closureCache.clear(); 4867 } 4868} 4869