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