diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java index 6b14e35d93a..d3c1ebc41ef 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java @@ -1225,7 +1225,7 @@ public TypeMirror getOriginalType(javax.lang.model.type.ErrorType errorType) { ClassType ct = (ClassType) errorType; return extraType2OriginalMap.computeIfAbsent(ct, tt -> new ClassType(ct.getEnclosingType(), ct.typarams_field, - ct.tsym, ct.getMetadata()) { + ct.tsym, ct.getMetadata(), ct.isReferenceProjection()) { @Override public Type baseType() { return ct; } @Override diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Printer.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Printer.java index a9f9e4a498a..de7f6add141 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Printer.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Printer.java @@ -234,6 +234,10 @@ public String visitClassType(ClassType t, Locale locale) { buf.append(printAnnotations(t)); buf.append(className(t, true, locale)); } + if (t.isReferenceProjection()) { + buf.append('.'); + buf.append(t.tsym.name.table.names.ref); + } if (t.getTypeArguments().nonEmpty()) { buf.append('<'); buf.append(visitTypes(t.getTypeArguments(), locale)); diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java index 6f1c9611355..ad60c8ef2c8 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java @@ -426,18 +426,10 @@ public boolean isReferenceProjection() { } /** - * Return the value projection IFF 'this' happens to be derived reference projection, null - * otherwise. + * If this is the symbol for a reference projection class, what is the class for which + * this is a projection ?? */ - public Symbol valueProjection() { - return null; - } - - /** - * Return the reference projection IFF 'this' happens to be inline class, null - * otherwise. - */ - public Symbol referenceProjection() { + public ClassSymbol valueProjection() { return null; } @@ -1328,12 +1320,6 @@ public static class ClassSymbol extends TypeSymbol implements TypeElement { */ private List recordComponents = List.nil(); - /* the 'other' projection: If 'this' is an inline class then 'projection' is its reference projection - and vice versa. - */ - public ClassSymbol projection; - - // sealed classes related fields /** The classes, or interfaces, permitted to extend this class, or interface */ @@ -1393,7 +1379,8 @@ public Type erasure(Types types) { if (erasure_field == null) erasure_field = new ClassType(types.erasure(type.getEnclosingType()), List.nil(), this, - type.getMetadata()); + type.getMetadata(), + type.isReferenceProjection()); return erasure_field; } @@ -1663,65 +1650,6 @@ public boolean isRecord() { return (flags_field & RECORD) != 0; } - @Override - public boolean isReferenceProjection() { - return projection != null && projection.isPrimitiveClass(); - } - - @Override - public ClassSymbol valueProjection() { - return isReferenceProjection() ? projection : null; - } - - @Override - public ClassSymbol referenceProjection() { - if (!isPrimitiveClass()) - return null; - - if (projection != null) - return projection; - - ClassType ct = (ClassType) this.type; - ClassType projectedType = new ClassType(ct.getEnclosingType(), ct.typarams_field, null); - projectedType.allparams_field = ct.allparams_field; - projectedType.supertype_field = ct.supertype_field; - - projectedType.interfaces_field = ct.interfaces_field; - projectedType.all_interfaces_field = ct.all_interfaces_field; - projectedType.projection = ct; - ct.projection = projectedType; - - Name projectionName = this.name.append('$', this.name.table.names.ref); - long projectionFlags = (this.flags() & ~(PRIMITIVE_CLASS | UNATTRIBUTED | FINAL)) | SEALED; - - projection = new ClassSymbol(projectionFlags, projectionName, projectedType, this.owner); - projection.members_field = WriteableScope.create(projection); - for (Symbol s : this.members().getSymbols(s->(s.kind == MTH || s.kind == VAR), NON_RECURSIVE)) { - Symbol clone = null; - if (s.kind == MTH) { - MethodSymbol valMethod = (MethodSymbol)s; - MethodSymbol refMethod = valMethod.clone(projection); - valMethod.projection = refMethod; - refMethod.projection = valMethod; - clone = refMethod; - } else if (s.kind == VAR) { - VarSymbol valVar = (VarSymbol)s; - VarSymbol refVar = valVar.clone(projection); - valVar.projection = refVar; - refVar.projection = valVar; - clone = refVar; - } - projection.members_field.enter(clone); - } - projection.completer = Completer.NULL_COMPLETER; - projection.sourcefile = this.sourcefile; - projection.flatname = this.flatname.append('$', this.name.table.names.ref); - projection.permitted = List.of(this); - projection.projection = this; - projectedType.tsym = projection; - return projection; - } - @DefinedBy(Api.LANGUAGE_MODEL) public List getPermittedSubclasses() { return permitted.map(s -> s.type); @@ -1748,11 +1676,6 @@ public static class VarSymbol extends Symbol implements VariableElement { */ public int adr = -1; - /* The 'other' projection: If 'this' is a field of an inline class, then 'projection' is the - its doppleganger in its referene projection class and vice versa. - */ - public VarSymbol projection; - /** Construct a variable symbol, given its flags, name, type and owner. */ public VarSymbol(long flags, Name name, Type type, Symbol owner) { @@ -1785,7 +1708,6 @@ public Object poolKey(Types types) { v.pos = pos; v.adr = adr; v.data = data; - v.projection = projection; // System.out.println("clone " + v + " in " + newOwner);//DEBUG return v; } @@ -1838,18 +1760,6 @@ public void setLazyConstValue(final Env env, setData((Callable)() -> attr.attribLazyConstantValue(env, variable, type)); } - @Override - public VarSymbol referenceProjection() { - return this.owner.isPrimitiveClass() ? - this.owner.referenceProjection() != null ? projection : null - : null; - } - - @Override - public VarSymbol valueProjection() { - return projection != null ? projection.owner.isPrimitiveClass() ? projection : null: null; - } - /** * The variable's constant value, if this is a constant. * Before the constant value is evaluated, it points to an @@ -2026,11 +1936,6 @@ public static class MethodSymbol extends Symbol implements ExecutableElement { */ public Attribute defaultValue = null; - /* The 'other' projection: If 'this' is a method of an inline class, then 'projection' is the - its doppleganger in its referene projection class and vice versa. - */ - public MethodSymbol projection; - /** Construct a method symbol, given its flags, name, type and owner. */ public MethodSymbol(long flags, Name name, Type type, Symbol owner) { @@ -2053,7 +1958,6 @@ public Object poolKey(Types types) { } }; m.code = code; - m.projection = projection; return m; } @@ -2138,7 +2042,7 @@ public boolean binaryOverrides(Symbol _other, TypeSymbol origin, Types types) { // check for a direct implementation if (other.isOverridableIn((TypeSymbol)owner) && - types.asSuper(owner.type, other.owner) != null && + types.asSuper(owner.type.referenceProjectionOrSelf(), other.owner) != null && types.isSameType(erasure(types), other.erasure(types))) return true; @@ -2202,24 +2106,12 @@ public boolean overrides(Symbol _other, TypeSymbol origin, Types types, boolean boolean requireConcreteIfInherited) { if (isConstructor() || _other.kind != MTH) return false; - - /* If any inline types are involved, ask the same question in the reference universe, - where the hierarchy is navigable - */ - if (origin.isPrimitiveClass()) - origin = (TypeSymbol) origin.referenceProjection(); - - if (this.owner.isPrimitiveClass()) { - return this.projection != null && - this.projection.overrides(_other, origin, types, checkResult, requireConcreteIfInherited); - } - if (this == _other) return true; MethodSymbol other = (MethodSymbol)_other; // check for a direct implementation if (other.isOverridableIn((TypeSymbol)owner) && - types.asSuper(owner.type, other.owner) != null) { + types.asSuper(owner.type.referenceProjectionOrSelf(), other.owner) != null) { Type mt = types.memberType(owner.type, this); Type ot = types.memberType(owner.type, other); if (types.isSubSignature(mt, ot)) { @@ -2269,14 +2161,6 @@ private boolean isOverridableIn(TypeSymbol origin) { @Override public boolean isInheritedIn(Symbol clazz, Types types) { - /* If any inline types are involved, ask the same question in the reference universe, - where the hierarchy is navigable - */ - if (clazz.isPrimitiveClass()) - clazz = clazz.referenceProjection(); - if (this.owner.isPrimitiveClass()) - return this.projection.isInheritedIn(clazz, types); - switch ((int)(flags_field & Flags.AccessFlags)) { case PUBLIC: return !this.owner.isInterface() || @@ -2291,18 +2175,6 @@ public boolean isLambdaMethod() { return (flags() & LAMBDA_METHOD) == LAMBDA_METHOD; } - @Override - public MethodSymbol referenceProjection() { - return this.owner.isPrimitiveClass() ? - this.owner.referenceProjection() != null ? projection : null - : null; - } - - @Override - public MethodSymbol valueProjection() { - return projection != null ? projection.owner.isPrimitiveClass() ? projection : null : null; - } - /** override this method to point to the original enclosing method if this method symbol represents a synthetic * lambda method */ diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java index 829a95a5776..9ae5a803b0a 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java @@ -256,13 +256,21 @@ public Type valueProjection() { } /** - * @return the reference projection type IFF the receiver is an inline type + * @return the reference projection type IFF the receiver is a primitive class type * and null otherwise */ public Type referenceProjection() { return null; } + /** + * @return the reference projection type IFF the receiver is a primitive class type or self otherwise. + */ + public Type referenceProjectionOrSelf() { + Type projection = referenceProjection(); + return projection != null ? projection : this; + } + /** * A subclass of {@link Types.TypeMapping} which applies a mapping recursively to the subterms * of a given type expression. This mapping returns the original type is no changes occurred @@ -277,7 +285,7 @@ public Type visitClassType(ClassType t, S s) { List typarams = t.getTypeArguments(); List typarams1 = visit(typarams, s); if (outer1 == outer && typarams1 == typarams) return t; - else return new ClassType(outer1, typarams1, t.tsym, t.metadata) { + else return new ClassType(outer1, typarams1, t.tsym, t.metadata, t.isReferenceProjection()) { @Override protected boolean needsStripping() { return true; @@ -1036,23 +1044,33 @@ public static class ClassType extends Type implements DeclaredType, LoadableCons */ public List all_interfaces_field; - /* The 'other' projection: If 'this' is type of an inline class, then 'projection' is the - its doppleganger in its referene projection world and vice versa. + /** The 'other' projection: If 'this' is type of a primitive class, then 'projection' is the + * reference projection type and vice versa. Lazily initialized, not to be accessed directly. */ public ClassType projection; + /** Is this class type a reference projection of a primitive class type ? + */ + private boolean isReferenceProjection; + public ClassType(Type outer, List typarams, TypeSymbol tsym) { - this(outer, typarams, tsym, TypeMetadata.EMPTY); + this(outer, typarams, tsym, TypeMetadata.EMPTY, false); } public ClassType(Type outer, List typarams, TypeSymbol tsym, TypeMetadata metadata) { + this(outer, typarams, tsym, metadata, false); + } + + public ClassType(Type outer, List typarams, TypeSymbol tsym, + TypeMetadata metadata, boolean isReferenceProjection) { super(tsym, metadata); - this.outer_field = outer; + this.outer_field = outer != null && outer.isReferenceProjection() ? outer.valueProjection() : outer; this.typarams_field = typarams; this.allparams_field = null; this.supertype_field = null; this.interfaces_field = null; + this.isReferenceProjection = isReferenceProjection; } public int poolTag() { @@ -1061,7 +1079,7 @@ public int poolTag() { @Override public ClassType cloneWithMetadata(TypeMetadata md) { - return new ClassType(outer_field, typarams_field, tsym, md) { + return new ClassType(outer_field, typarams_field, tsym, md, isReferenceProjection) { @Override public Type baseType() { return ClassType.this.baseType(); } }; @@ -1079,7 +1097,7 @@ public R accept(Type.Visitor v, S s) { public Type constType(Object constValue) { final Object value = constValue; - return new ClassType(getEnclosingType(), typarams_field, tsym, metadata) { + return new ClassType(getEnclosingType(), typarams_field, tsym, metadata, isReferenceProjection) { @Override public Object constValue() { return value; @@ -1106,6 +1124,11 @@ public String toString() { buf.append(className(tsym, true)); } + if (isReferenceProjection) { + buf.append('.'); + buf.append(tsym.name.table.names.ref); + } + if (getTypeArguments().nonEmpty()) { buf.append('<'); buf.append(getTypeArguments().toString()); @@ -1167,7 +1190,7 @@ public Type getEnclosingType() { } public void setEnclosingType(Type outer) { - outer_field = outer; + outer_field = outer != null && outer.isReferenceProjection() ? outer.valueProjection() : outer; } public List allparams() { @@ -1196,12 +1219,12 @@ public boolean isReference() { @Override public boolean isPrimitiveClass() { - return tsym != null && tsym.isPrimitiveClass(); + return !isReferenceProjection && tsym != null && tsym.isPrimitiveClass(); } @Override public boolean isReferenceProjection() { - return tsym != null && tsym.isReferenceProjection(); + return isReferenceProjection; } @Override @@ -1212,10 +1235,7 @@ public Type valueProjection() { if (projection != null) return projection; - // Make a best case effort to cache the other projection. - ClassSymbol valueClass = (ClassSymbol) tsym.valueProjection(); - - projection = new ClassType(outer_field, typarams_field, valueClass); + projection = new ClassType(outer_field, typarams_field, tsym, getMetadata(), false); projection.allparams_field = allparams_field; projection.supertype_field = supertype_field; @@ -1229,13 +1249,13 @@ public Type valueProjection() { @Override public ClassType referenceProjection() { - if (!isPrimitiveClass() || projection != null) - return projection; + if (!isPrimitiveClass()) + return null; - // make a best case effort to cache the other projection. - ClassSymbol refClass = (ClassSymbol) tsym.referenceProjection(); + if (projection != null) + return projection; - projection = new ClassType(outer_field, typarams_field, refClass); + projection = new ClassType(outer_field, typarams_field, tsym, getMetadata(), true); projection.allparams_field = allparams_field; projection.supertype_field = supertype_field; @@ -1293,7 +1313,7 @@ public R accept(TypeVisitor v, P p) { public static class ErasedClassType extends ClassType { public ErasedClassType(Type outer, TypeSymbol tsym, TypeMetadata metadata) { - super(outer, List.nil(), tsym, metadata); + super(outer, List.nil(), tsym, metadata, false); } @Override diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotations.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotations.java index f88fbace541..bb144226d9d 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotations.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotations.java @@ -627,7 +627,7 @@ public Type visitClassType(ClassType t, List s) { } else { ClassType ret = new ClassType(t.getEnclosingType().accept(this, s), t.typarams_field, t.tsym, - t.getMetadata()); + t.getMetadata(), t.isReferenceProjection()); ret.all_interfaces_field = t.all_interfaces_field; ret.allparams_field = t.allparams_field; ret.interfaces_field = t.interfaces_field; diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java index 237b1440ef4..df9d2f82a09 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java @@ -274,7 +274,7 @@ public Type visitClassType(ClassType t, ProjectionKind pkind) { formals = formals.tail; } if (outer1 == outer && !changed) return t; - else return new ClassType(outer1, typarams1.toList(), t.tsym, t.getMetadata()) { + else return new ClassType(outer1, typarams1.toList(), t.tsym, t.getMetadata(), t.isReferenceProjection()) { @Override protected boolean needsStripping() { return true; @@ -1008,7 +1008,7 @@ public boolean accepts(Symbol sym) { } public boolean isPrimitiveClass(Type t) { - return t != null && t.tsym != null && (t.tsym.flags_field & Flags.PRIMITIVE_CLASS) != 0; + return t != null && !t.isReferenceProjection() && t.tsym != null && (t.tsym.flags_field & Flags.PRIMITIVE_CLASS) != 0; } // @@ -1208,6 +1208,7 @@ public Boolean visitClassType(ClassType t, Type s) { // If t is an intersection, sup might not be a class type if (!sup.hasTag(CLASS)) return isSubtypeNoCapture(sup, s); return sup.tsym == s.tsym + && (t.tsym != s.tsym || t.isReferenceProjection() == s.isReferenceProjection()) // Check type variable containment && (!s.isParameterized() || containsTypeRecursive(s, sup)) && isSubtypeNoCapture(sup.getEnclosingType(), @@ -1453,9 +1454,18 @@ public Boolean visitClassType(ClassType t, Type s) { return tMap.isEmpty(); } return t.tsym == s.tsym - && visit(t.getEnclosingType(), s.getEnclosingType()) + && t.isReferenceProjection() == s.isReferenceProjection() + && visit(getEnclosingType(t), getEnclosingType(s)) && containsTypeEquivalent(t.getTypeArguments(), s.getTypeArguments()); } + // where + private Type getEnclosingType(Type t) { + Type et = t.getEnclosingType(); + if (et.isReferenceProjection()) { + et = et.valueProjection(); + } + return et; + } @Override public Boolean visitArrayType(ArrayType t, Type s) { @@ -1713,14 +1723,6 @@ public boolean isCastable(Type t, Type s, Warner warn) { } // where private boolean areDisjoint(ClassSymbol ts, ClassSymbol ss) { - /* The disjointsness checks below are driven by subtyping. At the language level - a reference projection type and its value projection type are not related by - subtyping, thereby necessitating special handling. - */ - if ((ss.isReferenceProjection() && ss.valueProjection() == ts) || - (ss.isPrimitiveClass() && ss.referenceProjection() == ts)) { - return false; - } if (isSubtype(erasure(ts.type), erasure(ss.type))) { return false; } @@ -2200,27 +2202,39 @@ public ArrayType makeArrayType(Type t) { * this method could yield surprising answers when invoked on arrays. For example when * invoked with t being byte [] and sym being t.sym itself, asSuper would answer null. * - * @param t a type - * @param sym a symbol - */ - public Type asSuper(Type t, Symbol sym) { - return asSuper(t, sym, false); - } - - /** - * Return the (most specific) base type of t that starts with the - * given symbol. If none exists, return null. + * Further caveats in Valhalla: There are two "hazards" we need to watch out for when using + * this method. * - * Caveat Emptor: Since javac represents the class of all arrays with a singleton - * symbol Symtab.arrayClass, which by being a singleton cannot hold any discriminant, - * this method could yield surprising answers when invoked on arrays. For example when - * invoked with t being byte [] and sym being t.sym itself, asSuper would answer null. + * 1. Since Foo.ref and Foo.val share the same symbol, that of Foo.class, a call to + * asSuper(Foo.ref.type, Foo.val.type.tsym) would return non-null. This MAY NOT BE correct + * depending on the call site. Foo.val is NOT a super type of Foo.ref either in the language + * model or in the VM's world view. An example of such an hazardous call used to exist in + * Gen.visitTypeCast. When we emit code for (Foo) Foo.ref.instance a check for whether we + * really need the cast cannot/shouldn't be gated on + * + * asSuper(tree.expr.type, tree.clazz.type.tsym) == null) + * + * but use !types.isSubtype(tree.expr.type, tree.clazz.type) which operates in terms of + * types. When we operate in terms of symbols, there is a loss of type information leading + * to a hazard. Whether a call to asSuper should be transformed into a isSubtype call is + * tricky. isSubtype returns just a boolean while asSuper returns richer information which + * may be required at the call site. Also where the concerned symbol corresponds to a + * generic class, an asSuper call cannot be conveniently rewritten as an isSubtype call + * (see that asSuper(ArrayList.type, List.tsym) != null while + * isSubType(ArrayList.type, List.type) is false;) So care needs to be exercised. + * + * 2. Given a primitive class Foo, a call to asSuper(Foo.type, SuperclassOfFoo.tsym) and/or + * a call to asSuper(Foo.type, SuperinterfaceOfFoo.tsym) would answer null. In many places + * that is NOT what we want. An example of such a hazardous call used to occur in + * Attr.visitForeachLoop when checking to make sure the for loop's control variable of a type + * that implements Iterable: viz: types.asSuper(exprType, syms.iterableType.tsym); + * These hazardous calls should be rewritten as + * types.asSuper(exprType.referenceProjectionOrSelf(), syms.iterableType.tsym); instead. * * @param t a type * @param sym a symbol - * @param checkReferenceProjection if true, first compute reference projection of t */ - public Type asSuper(Type t, Symbol sym, boolean checkReferenceProjection) { + public Type asSuper(Type t, Symbol sym) { /* Some examples: * * (Enum, Comparable) => Comparable @@ -2230,13 +2244,6 @@ public Type asSuper(Type t, Symbol sym, boolean checkReferenceProjection) { * Iterable */ - /* For a (value or identity) class V, whether it implements an interface I, boils down to whether - V.ref is a subtype of I. OIOW, whether asSuper(V.ref, sym) != null. (Likewise for an abstract - superclass) - */ - if (checkReferenceProjection) - t = t.isPrimitiveClass() ? t.referenceProjection() : t; - if (sym.type == syms.objectType) { //optimization if (!isPrimitiveClass(t)) return syms.objectType; @@ -2399,9 +2406,6 @@ public Type memberType(Type t, Symbol sym) { if (t.isPrimitiveClass()) t = t.referenceProjection(); - if (sym.owner.isPrimitiveClass()) - sym = sym.referenceProjection(); - return memberType.visit(t, sym); } // where @@ -2555,15 +2559,26 @@ public Type visitWildcardType(WildcardType t, Boolean recurse) { @Override public Type visitClassType(ClassType t, Boolean recurse) { - Type erased = t.tsym.erasure(Types.this); - if (recurse) { - erased = new ErasedClassType(erased.getEnclosingType(),erased.tsym, - t.getMetadata().without(Kind.ANNOTATIONS)); - return erased; - } else { - return combineMetadata(erased, t); + // erasure(projection(primitive)) = projection(erasure(primitive)) + Type erased = eraseClassType(t, recurse); + if (t.isReferenceProjection()) { + erased = new ClassType(erased.getEnclosingType(), + List.nil(), erased.tsym, + erased.getMetadata(), true); + } + return erased; + } + // where + private Type eraseClassType(ClassType t, Boolean recurse) { + Type erased = t.tsym.erasure(Types.this); + if (recurse) { + erased = new ErasedClassType(erased.getEnclosingType(), erased.tsym, + t.getMetadata().without(Kind.ANNOTATIONS)); + return erased; + } else { + return combineMetadata(erased, t); + } } - } @Override public Type visitTypeVar(TypeVar t, Boolean recurse) { @@ -2886,7 +2901,7 @@ public Type visitClassType(ClassType t, Void ignored) { Type outer1 = classBound(t.getEnclosingType()); if (outer1 != t.getEnclosingType()) return new ClassType(outer1, t.getTypeArguments(), t.tsym, - t.getMetadata()); + t.getMetadata(), t.isReferenceProjection()); else return t; } @@ -4579,7 +4594,7 @@ public Type capture(Type t) { if (captured) return new ClassType(cls.getEnclosingType(), S, cls.tsym, - cls.getMetadata()); + cls.getMetadata(), cls.isReferenceProjection()); else return t; } @@ -5343,6 +5358,10 @@ public void assembleClassSig(Type type) { } else { append(externalize(c.flatname)); } + if (ct.isReferenceProjection()) { + append('$'); + append(types.names.ref); + } if (ct.getTypeArguments().nonEmpty()) { append('<'); assembleSig(ct.getTypeArguments()); diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java index d086972632c..900c93ec8f1 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java @@ -1594,7 +1594,7 @@ public void visitForeachLoop(JCEnhancedForLoop tree) { Type elemtype = types.elemtype(exprType); // perhaps expr is an array? if (elemtype == null) { // or perhaps expr implements Iterable? - Type base = types.asSuper(exprType, syms.iterableType.tsym, true); + Type base = types.asSuper(exprType.referenceProjectionOrSelf(), syms.iterableType.tsym); if (base == null) { log.error(tree.expr.pos(), Errors.ForeachNotApplicableToType(exprType, @@ -1916,7 +1916,7 @@ public void report(DiagnosticPosition pos, JCDiagnostic details) { void checkAutoCloseable(DiagnosticPosition pos, Env env, Type resource) { if (!resource.isErroneous() && - types.asSuper(resource, syms.autoCloseableType.tsym, true) != null && + types.asSuper(resource.referenceProjectionOrSelf(), syms.autoCloseableType.tsym) != null && !types.isSameType(resource, syms.autoCloseableType)) { // Don't emit warning for AutoCloseable itself Symbol close = syms.noSymbol; Log.DiagnosticHandler discardHandler = new Log.DiscardDiagnosticHandler(log); @@ -2609,7 +2609,8 @@ Type adjustMethodReturnType(Symbol msym, Type qualifierType, Name methodName, Li BoundKind.EXTENDS, syms.boundClass)), restype.tsym, - restype.getMetadata()); + restype.getMetadata(), + restype.isReferenceProjection()); } else if (msym != null && msym.owner == syms.arrayClass && methodName == names.clone && @@ -2810,7 +2811,8 @@ public void visitNewClass(final JCNewClass tree) { ClassType site = new ClassType(clazztype.getEnclosingType(), clazztype.tsym.type.getTypeArguments(), clazztype.tsym, - clazztype.getMetadata()); + clazztype.getMetadata(), + clazztype.isReferenceProjection()); Env diamondEnv = localEnv.dup(tree); diamondEnv.info.selectSuper = cdef != null || tree.classDeclRemoved(); @@ -4381,7 +4383,7 @@ public void visitSelect(JCFieldAccess tree) { if (site.isRaw()) { // Determine argument types for site. - Type site1 = types.asSuper(env.enclClass.sym.type, site.tsym); + Type site1 = types.asSuper(env.enclClass.sym.type.referenceProjectionOrSelf(), site.tsym); if (site1 != null) site = site1; } } @@ -4424,9 +4426,7 @@ private Symbol selectSym(JCFieldAccess tree, // In this case, we have already made sure in // visitSelect that qualifier expression is a type. return syms.getClassField(site, types); - } else if (name == names.ref && site.isPrimitiveClass() && resultInfo.pkind.contains(KindSelector.TYP)) { - return site.tsym.referenceProjection(); - } else if (name == names.val && site.isPrimitiveClass() && resultInfo.pkind.contains(KindSelector.TYP)) { + } else if (site.isPrimitiveClass() && resultInfo.pkind.contains(KindSelector.TYP) && (name == names.ref || name == names.val)) { return site.tsym; } else { // We are seeing a plain identifier as selector. @@ -4531,20 +4531,27 @@ Type checkIdInternal(JCTree tree, switch (sym.kind) { case TYP: // For types, the computed type equals the symbol's type, - // except for two situations: + // except for three situations: owntype = sym.type; if (owntype.hasTag(CLASS)) { chk.checkForBadAuxiliaryClassAccess(tree.pos(), env, (ClassSymbol)sym); Type ownOuter = owntype.getEnclosingType(); - // (a) If the symbol's type is parameterized, erase it + // (a) If symbol is a primitive class and its reference projection + // is requested via the .ref notation, then adjust the computed type to + // reflect this. + if (owntype.isPrimitiveClass() && tree.hasTag(SELECT) && ((JCFieldAccess) tree).name == names.ref) { + owntype = new ClassType(owntype.getEnclosingType(), owntype.getTypeArguments(), (TypeSymbol)sym, owntype.getMetadata(), true); + } + + // (b) If the symbol's type is parameterized, erase it // because no type parameters were given. // We recover generic outer type later in visitTypeApply. if (owntype.tsym.type.getTypeArguments().nonEmpty()) { owntype = types.erasure(owntype); } - // (b) If the symbol's type is an inner class, then + // (c) If the symbol's type is an inner class, then // we have to interpret its outer type as a superclass // of the site type. Example: // @@ -4564,7 +4571,7 @@ else if (ownOuter.hasTag(CLASS) && site != ownOuter) { if (normOuter != ownOuter) owntype = new ClassType( normOuter, List.nil(), owntype.tsym, - owntype.getMetadata()); + owntype.getMetadata(), owntype.isReferenceProjection()); } } break; @@ -4975,7 +4982,7 @@ public void visitTypeApply(JCTypeApply tree) { } } owntype = new ClassType(clazzOuter, actuals, clazztype.tsym, - clazztype.getMetadata()); + clazztype.getMetadata(), clazztype.isReferenceProjection()); } else { if (formals.length() != 0) { log.error(tree.pos(), diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java index 3d365f726e8..7d2380e3086 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java @@ -2695,8 +2695,8 @@ void checkCompatibleSupertypes(DiagnosticPosition pos, Type c) { } checkCompatibleConcretes(pos, c); - boolean implementsIdentityObject = types.asSuper(c, syms.identityObjectType.tsym, true) != null; - boolean implementsPrimitiveObject = types.asSuper(c, syms.primitiveObjectType.tsym, true) != null; + boolean implementsIdentityObject = types.asSuper(c.referenceProjectionOrSelf(), syms.identityObjectType.tsym) != null; + boolean implementsPrimitiveObject = types.asSuper(c.referenceProjectionOrSelf(), syms.primitiveObjectType.tsym) != null; if (c.isPrimitiveClass() && implementsIdentityObject) { log.error(pos, Errors.PrimitiveClassMustNotImplementIdentityObject(c)); } else if (implementsPrimitiveObject && !c.isPrimitiveClass() && !c.isReferenceProjection() && !c.tsym.isInterface() && !c.tsym.isAbstract()) { diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Enter.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Enter.java index 772b2169f5d..ea1993b0ae2 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Enter.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Enter.java @@ -471,10 +471,6 @@ public void visitClassDef(JCClassDecl tree) { c.flags_field = chk.checkFlags(tree.pos(), tree.mods.flags, c, tree); c.sourcefile = env.toplevel.sourcefile; c.members_field = WriteableScope.create(c); - if (c.projection != null) { - // Do not carry around symbols from prior round. - c.projection.members_field = WriteableScope.create(c.projection); - } c.clearAnnotationMetadata(); ClassType ct = (ClassType)c.type; diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java index b2fd74e333c..579b5116f21 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java @@ -1237,7 +1237,7 @@ public void visitTry(JCTry tree) { types.interfaces(resource.type).prepend(types.supertype(resource.type)) : List.of(resource.type); for (Type sup : closeableSupertypes) { - if (types.asSuper(sup, syms.autoCloseableType.tsym, true) != null) { + if (types.asSuper(sup.referenceProjectionOrSelf(), syms.autoCloseableType.tsym) != null) { Symbol closeMethod = rs.resolveQualifiedMethod(tree, attrEnv, types.skipTypeVars(sup, false), diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java index 53147c59fc5..0b4315d71f6 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java @@ -370,7 +370,7 @@ public void visitLambda(JCLambda tree) { //create the method declaration hoisting the lambda body JCMethodDecl lambdaDecl = make.MethodDef(make.Modifiers(sym.flags_field), sym.name, - make.QualIdent(lambdaType.getReturnType().tsym), + make.QualIdent(lambdaType.getReturnType().tsym).setType(lambdaType.getReturnType()), List.nil(), localContext.syntheticParams, lambdaType.getThrownTypes() == null ? @@ -1859,7 +1859,7 @@ boolean isSerializable() { if (forceSerializable) { return true; } - return types.asSuper(tree.target, syms.serializableType.tsym) != null; + return types.asSuper(tree.target.referenceProjectionOrSelf(), syms.serializableType.tsym) != null; } /** @@ -2288,7 +2288,7 @@ boolean receiverAccessible() { C$ref.class and fail with a NoSuchMethodError. we need to workaround it ourselves. */ boolean receiverIsReferenceProjection() { - return tree.sym.kind == MTH && tree.sym.owner.isReferenceProjection(); + return tree.getQualifierExpression().type.isReferenceProjection(); } /** diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java index 6653962f60d..9045d20eaca 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java @@ -1134,9 +1134,15 @@ JCExpression access(Symbol sym, JCExpression tree, JCExpression enclOp, boolean switch (sym.kind) { case TYP: if (sym.owner.kind != PCK) { + // Make sure not to lose type fidelity due to symbol sharing between projections + boolean requireReferenceProjection = + tree.hasTag(SELECT) && ((JCFieldAccess) tree).name == names.ref && tree.type.isReferenceProjection(); // Convert type idents to // or . Name flatname = Convert.shortName(sym.flatName()); + if (requireReferenceProjection) { + flatname = flatname.append('$', names.ref); + } while (base != null && TreeInfo.symbol(base) != null && TreeInfo.symbol(base).kind != PCK) { @@ -1149,9 +1155,15 @@ JCExpression access(Symbol sym, JCExpression tree, JCExpression enclOp, boolean } else if (base == null) { tree = make.at(tree.pos).Ident(sym); ((JCIdent) tree).name = flatname; + if (requireReferenceProjection) { + tree.setType(tree.type.referenceProjection()); + } } else { ((JCFieldAccess) tree).selected = base; ((JCFieldAccess) tree).name = flatname; + if (requireReferenceProjection) { + tree.setType(tree.type.referenceProjection()); + } } } break; @@ -1710,7 +1722,7 @@ private JCBlock makeTwrBlock(List resources, JCBlock block, int depth) { private JCStatement makeResourceCloseInvocation(JCExpression resource) { // convert to AutoCloseable if needed - if (types.asSuper(resource.type, syms.autoCloseableType.tsym, true) == null) { + if (types.asSuper(resource.type.referenceProjectionOrSelf(), syms.autoCloseableType.tsym) == null) { resource = convert(resource, syms.autoCloseableType); } @@ -3504,8 +3516,8 @@ public void visitClassDef(JCClassDecl tree) {} private void visitIterableForeachLoop(JCEnhancedForLoop tree) { make_at(tree.expr.pos()); Type iteratorTarget = syms.objectType; - Type iterableType = types.asSuper(types.cvarUpperBound(tree.expr.type), - syms.iterableType.tsym, true); + Type iterableType = types.asSuper(types.cvarUpperBound(tree.expr.type.referenceProjectionOrSelf()), + syms.iterableType.tsym); if (iterableType.getTypeArguments().nonEmpty()) iteratorTarget = types.erasure(iterableType.getTypeArguments().head); Type eType = types.skipTypeVars(tree.expr.type, false); @@ -3517,7 +3529,7 @@ private void visitIterableForeachLoop(JCEnhancedForLoop tree) { eType, List.nil()); VarSymbol itvar = new VarSymbol(SYNTHETIC, names.fromString("i" + target.syntheticNameChar()), - types.erasure(types.asSuper(iterator.type.getReturnType(), syms.iteratorType.tsym)), + types.erasure(types.asSuper(iterator.type.getReturnType().referenceProjectionOrSelf(), syms.iteratorType.tsym)), currentMethodSym); JCStatement init = make. @@ -3979,7 +3991,7 @@ else if (tree.name == names._super && types.isDirectSuperInterface(tree.selected.type.tsym, currentClass)) { //default super call!! Not a classic qualified super call TypeSymbol supSym = tree.selected.type.tsym; - Assert.checkNonNull(types.asSuper(currentClass.type, supSym)); + Assert.checkNonNull(types.asSuper(currentClass.type.referenceProjectionOrSelf(), supSym)); result = tree; } else if (tree.name == names._this || tree.name == names._super) { diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/MemberEnter.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/MemberEnter.java index 0dfb2e401ce..5fd6f5af55e 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/MemberEnter.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/MemberEnter.java @@ -218,14 +218,7 @@ public void visitMethodDef(JCMethodDecl tree) { localEnv.info.scope.leave(); if (chk.checkUnique(tree.pos(), m, enclScope)) { - ClassSymbol refProjection = m.owner.isPrimitiveClass() ? (ClassSymbol) m.owner.referenceProjection() : null; enclScope.enter(m); - if (refProjection != null) { - MethodSymbol clone = m.clone(refProjection); - clone.projection = m; - m.projection = clone; - refProjection.members_field.enter(clone); - } } annotate.annotateLater(tree.mods.annotations, localEnv, m, tree.pos()); @@ -309,14 +302,7 @@ public void visitVarDef(JCVariableDecl tree) { } if (chk.checkUnique(tree.pos(), v, enclScope)) { chk.checkTransparentVar(tree.pos(), v, enclScope); - ClassSymbol refProjection = v.owner.isPrimitiveClass() ? (ClassSymbol) v.owner.referenceProjection() : null; enclScope.enter(v); - if (refProjection != null) { - VarSymbol clone = v.clone(refProjection); - clone.projection = v; - v.projection = clone; - refProjection.members_field.enter(clone); - } } else if (v.owner.kind == MTH || (v.flags_field & (Flags.PRIVATE | Flags.FINAL | Flags.GENERATED_MEMBER | Flags.RECORD)) != 0) { // if this is a parameter or a field obtained from a record component, enter it enclScope.enter(v); diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java index dbedbe8c05b..af0326d01f5 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java @@ -420,10 +420,6 @@ public boolean isAccessible(Env env, Type site, Symbol sym, boolean */ if (site.isPrimitiveClass()) site = site.referenceProjection(); - if (sym.owner.isPrimitiveClass()) - sym = sym.referenceProjection(); - if (env.enclClass.sym.isPrimitiveClass()) - env.enclClass.sym = env.enclClass.sym.referenceProjection(); } else if (sym.kind == TYP) { // A type is accessible in a reference projection if it was // accessible in the value projection. @@ -489,8 +485,6 @@ private boolean notOverriddenIn(Type site, Symbol sym) { */ if (site.isPrimitiveClass()) site = site.referenceProjection(); - if (sym.owner.isPrimitiveClass()) - sym = sym.referenceProjection(); Symbol s2 = ((MethodSymbol)sym).implementation(site.tsym, types, true); return (s2 == null || s2 == sym || sym.owner == s2.owner || @@ -1715,12 +1709,12 @@ Symbol mostSpecific(List argtypes, Symbol m1, // but we need to protect against cases where the methods are defined in some classfile // and make sure we issue an ambiguity error accordingly (by skipping the logic below). if (m1Owner != m2Owner) { - if (types.asSuper(m1Owner.type, m2Owner) != null && + if (types.asSuper(m1Owner.type.referenceProjectionOrSelf(), m2Owner) != null && ((m1.owner.flags_field & INTERFACE) == 0 || (m2.owner.flags_field & INTERFACE) != 0) && m1.overrides(m2, m1Owner, types, false)) return m1; - if (types.asSuper(m2Owner.type, m1Owner) != null && + if (types.asSuper(m2Owner.type.referenceProjectionOrSelf(), m1Owner) != null && ((m2.owner.flags_field & INTERFACE) == 0 || (m1.owner.flags_field & INTERFACE) != 0) && m2.overrides(m1, m2Owner, types, false)) @@ -2250,10 +2244,6 @@ Symbol findImmediateMemberType(Env env, Type site, Name name, TypeSymbol c) { - // ATM, inner/nested types are members of only the declaring inline class, - // although accessible via the reference projection. - if (c.isReferenceProjection()) - c = (TypeSymbol) c.valueProjection(); for (Symbol sym : c.members().getSymbolsByName(name)) { if (sym.kind == TYP) { return isAccessible(env, site, sym) @@ -3063,13 +3053,6 @@ public Symbol baseSymbol() { return sym; } }; - ClassSymbol refProjection = newConstr.owner.isPrimitiveClass() ? - (ClassSymbol) newConstr.owner.referenceProjection() : null; - if (refProjection != null) { - MethodSymbol clone = newConstr.clone(refProjection); - clone.projection = newConstr; - newConstr.projection = clone; - } bestSoFar = selectBest(env, site, argtypes, typeargtypes, newConstr, bestSoFar, @@ -3620,7 +3603,7 @@ ReferenceLookupHelper unboundLookup(InferenceContext inferenceContext) { if (TreeInfo.isStaticSelector(referenceTree.expr, names)) { if (argtypes.nonEmpty() && (argtypes.head.hasTag(NONE) || - types.isSubtypeUnchecked(inferenceContext.asUndetVar(argtypes.head), originalSite))) { + types.isSubtypeUnchecked(inferenceContext.asUndetVar(argtypes.head.referenceProjectionOrSelf()), originalSite))) { return new UnboundMethodReferenceLookupHelper(referenceTree, name, originalSite, argtypes, typeargtypes, maxPhase); } else { @@ -3673,7 +3656,7 @@ class UnboundMethodReferenceLookupHelper extends MethodReferenceLookupHelper { List argtypes, List typeargtypes, MethodResolutionPhase maxPhase) { super(referenceTree, name, site, argtypes.tail, typeargtypes, maxPhase); if (site.isRaw() && !argtypes.head.hasTag(NONE)) { - Type asSuperSite = types.asSuper(argtypes.head, site.tsym); + Type asSuperSite = types.asSuper(argtypes.head.referenceProjectionOrSelf(), site.tsym); this.site = types.skipTypeVars(asSuperSite, true); } } @@ -3732,7 +3715,7 @@ class ConstructorReferenceLookupHelper extends ReferenceLookupHelper { List typeargtypes, MethodResolutionPhase maxPhase) { super(referenceTree, names.init, site, argtypes, typeargtypes, maxPhase); if (site.isRaw()) { - this.site = new ClassType(site.getEnclosingType(), site.tsym.type.getTypeArguments(), site.tsym, site.getMetadata()); + this.site = new ClassType(site.getEnclosingType(), site.tsym.type.getTypeArguments(), site.tsym, site.getMetadata(), site.isReferenceProjection()); needsInference = true; } } @@ -3822,7 +3805,7 @@ Symbol resolveSelf(DiagnosticPosition pos, if (t.tsym == c) { env.info.defaultSuperCallSite = t; return new VarSymbol(0, names._super, - types.asSuper(env.enclClass.type, c), env.enclClass.sym); + types.asSuper(env.enclClass.type.referenceProjectionOrSelf(), c), env.enclClass.sym); } } //find a direct super type that is a subtype of 'c' diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java index 69053f2691c..b7655496abe 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java @@ -288,14 +288,7 @@ void addBridge(DiagnosticPosition pos, bridges.append(md); // Add bridge to scope of enclosing class and keep track of the bridge span. - ClassSymbol refProjection = origin.isPrimitiveClass() ? origin.referenceProjection() : null; origin.members().enter(bridge); - if (refProjection != null) { - MethodSymbol clone = bridge.clone(refProjection); - clone.projection = bridge; - bridge.projection = clone; - refProjection.members().enter(clone); - } } private List createBridgeParams(MethodSymbol impl, MethodSymbol bridge, diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java index 7ce91f949cf..1a2abb2ffd8 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java @@ -733,16 +733,6 @@ protected void attribSuperTypes(Env env, Env baseEnv) ct.all_interfaces_field = (all_interfaces == null) ? ct.interfaces_field : all_interfaces.toList(); } - if (ct.isPrimitiveClass()) { - ClassSymbol cSym = (ClassSymbol) ct.tsym; - if (cSym.projection != null) { - ClassType projectedType = (ClassType) cSym.projection.type; - projectedType.supertype_field = ct.supertype_field; - projectedType.interfaces_field = ct.interfaces_field; - projectedType.all_interfaces_field = ct.all_interfaces_field; - } - } - /* it could be that there are already some symbols in the permitted list, for the case * where there are subtypes in the same compilation unit but the permits list is empty * so don't overwrite the permitted list if it is not empty diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java index f849569cdc7..9825e919998 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java @@ -297,29 +297,8 @@ protected ClassReader(Context context) { private void enterMember(ClassSymbol c, Symbol sym) { // Synthetic members are not entered -- reason lost to history (optimization?). // Lambda methods must be entered because they may have inner classes (which reference them) - ClassSymbol refProjection = c.isPrimitiveClass() ? c.referenceProjection() : null; - if ((sym.flags_field & (SYNTHETIC|BRIDGE)) != SYNTHETIC || sym.name.startsWith(names.lambda)) { + if ((sym.flags_field & (SYNTHETIC|BRIDGE)) != SYNTHETIC || sym.name.startsWith(names.lambda)) c.members_field.enter(sym); - if (refProjection != null) { - Symbol clone = null; - if (sym.kind == MTH) { - MethodSymbol valMethod = (MethodSymbol)sym; - MethodSymbol refMethod = valMethod.clone(refProjection); - valMethod.projection = refMethod; - refMethod.projection = valMethod; - clone = refMethod; - } else if (sym.kind == VAR) { - VarSymbol valVar = (VarSymbol)sym; - VarSymbol refVar = valVar.clone(refProjection); - valVar.projection = refVar; - refVar.projection = valVar; - clone = refVar; - } - if (clone != null) { - refProjection.members_field.enter(clone); - } - } - } } /************************************************************************ @@ -561,6 +540,8 @@ Type classSigToType() { Convert.utf2string(signature, sigp, 10)); sigp++; Type outer = Type.noType; + Name name; + boolean requireProjection; int startSbp = sbp; while (true) { @@ -568,24 +549,37 @@ Type classSigToType() { switch (c) { case ';': { // end - ClassSymbol t = enterClass(names.fromUtf(signatureBuffer, - startSbp, - sbp - startSbp)); - + name = names.fromUtf(signatureBuffer, + startSbp, + sbp - startSbp); + if (allowPrimitiveClasses && name.toString().endsWith("$ref")) { + name = name.subName(0, name.length() - 4); + requireProjection = true; + } else { + requireProjection = false; + } + ClassSymbol t = enterClass(name); try { return (outer == Type.noType) ? - t.erasure(types) : - new ClassType(outer, List.nil(), t); + requireProjection ? t.erasure(types).referenceProjection() : t.erasure(types) : + new ClassType(outer, List.nil(), t, TypeMetadata.EMPTY, requireProjection); } finally { sbp = startSbp; } } case '<': // generic arguments - ClassSymbol t = enterClass(names.fromUtf(signatureBuffer, - startSbp, - sbp - startSbp)); - outer = new ClassType(outer, sigToTypes('>'), t) { + name = names.fromUtf(signatureBuffer, + startSbp, + sbp - startSbp); + if (allowPrimitiveClasses && name.toString().endsWith("$ref")) { + name = name.subName(0, name.length() - 4); + requireProjection = true; + } else { + requireProjection = false; + } + ClassSymbol t = enterClass(name); + outer = new ClassType(outer, sigToTypes('>'), t, TypeMetadata.EMPTY, requireProjection) { boolean completed = false; @Override @DefinedBy(Api.LANGUAGE_MODEL) public Type getEnclosingType() { @@ -645,10 +639,17 @@ public void setEnclosingType(Type outer) { case '.': //we have seen an enclosing non-generic class if (outer != Type.noType) { - t = enterClass(names.fromUtf(signatureBuffer, - startSbp, - sbp - startSbp)); - outer = new ClassType(outer, List.nil(), t); + name = names.fromUtf(signatureBuffer, + startSbp, + sbp - startSbp); + if (allowPrimitiveClasses && name.toString().endsWith("$ref")) { + name = name.subName(0, name.length() - 4); + requireProjection = true; + } else { + requireProjection = false; + } + t = enterClass(name); + outer = new ClassType(outer, List.nil(), t, TypeMetadata.EMPTY, requireProjection); } signatureBuffer[sbp++] = (byte)'$'; continue; @@ -2506,10 +2507,6 @@ protected void enterTypevars(Symbol sym, Type t) { } protected ClassSymbol enterClass(Name name) { - if (allowPrimitiveClasses && name.toString().endsWith("$ref")) { - ClassSymbol v = syms.enterClass(currentModule, name.subName(0, name.length() - 4)); - return v.referenceProjection(); - } return syms.enterClass(currentModule, name); } diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java index 2787f5fb6a8..828f291fd8b 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java @@ -40,6 +40,7 @@ import com.sun.tools.javac.code.*; import com.sun.tools.javac.code.Attribute.RetentionPolicy; import com.sun.tools.javac.code.Directive.*; +import com.sun.tools.javac.code.Scope.WriteableScope; import com.sun.tools.javac.code.Symbol.*; import com.sun.tools.javac.code.Type.*; import com.sun.tools.javac.code.Types.SignatureGenerator.InvalidSignatureException; @@ -820,11 +821,13 @@ int writeModuleAttribute(ClassSymbol c) { * Writing Objects **********************************************************************/ - /** Write "inner classes" attribute. + /** Write "inner classes" attribute. If a primitive class happens to be an inner class, + * the reference projection class will also be an inner class. */ void writeInnerClasses() { int alenIdx = writeAttr(names.InnerClasses); - databuf.appendChar(poolWriter.innerClasses.size()); + int icCountIdx = beginAttrs(); + int icCount = 0; for (ClassSymbol inner : poolWriter.innerClasses) { inner.markAbstractIfNeeded(types); char flags = (char) adjustFlags(inner.flags_field); @@ -841,7 +844,19 @@ void writeInnerClasses() { databuf.appendChar( !inner.name.isEmpty() ? poolWriter.putName(inner.name) : 0); databuf.appendChar(flags); + icCount++; + if (inner.isPrimitiveClass()) { + databuf.appendChar(poolWriter.putClass(inner.type.referenceProjection())); + databuf.appendChar( + inner.owner.kind == TYP && !inner.name.isEmpty() ? poolWriter.putClass((ClassSymbol)inner.owner) : 0); + databuf.appendChar( + !inner.name.isEmpty() ? poolWriter.putName(inner.name.append('$', names.ref)) : 0); + flags = (char) ((flags & ~(ACC_PRIMITIVE | FINAL)) | ABSTRACT); + databuf.appendChar(flags); + icCount++; + } } + endAttrs(icCountIdx, icCount); endAttr(alenIdx); } @@ -879,10 +894,17 @@ int writeNestMembersIfNeeded(ClassSymbol csym) { } if (!nestedUnique.isEmpty()) { int alenIdx = writeAttr(names.NestMembers); - databuf.appendChar(nestedUnique.size()); + int nmcIdx = beginAttrs(); + int nmc = 0; for (ClassSymbol s : nestedUnique) { databuf.appendChar(poolWriter.putClass(s)); + nmc++; + if (s.isPrimitiveClass() && s.owner.kind != PCK) { + databuf.appendChar(poolWriter.putClass(s.type.referenceProjection())); + nmc++; + } } + endAttrs(nmcIdx, nmc); endAttr(alenIdx); return 1; } @@ -898,9 +920,10 @@ int writeNestHostIfNeeded(ClassSymbol csym) { int alenIdx = writeAttr(names.NestHost); ClassSymbol outerMost = csym.outermostClass(); if (outerMost.isPrimitiveClass()) { - outerMost = outerMost.referenceProjection(); + databuf.appendChar(poolWriter.putClass(outerMost.type.referenceProjection())); + } else { + databuf.appendChar(poolWriter.putClass(outerMost)); } - databuf.appendChar(poolWriter.putClass(outerMost)); endAttr(alenIdx); return 1; } @@ -912,9 +935,6 @@ private void listNested(Symbol sym, Set seen) { ClassSymbol csym = (ClassSymbol)sym; if (csym.owner.kind != PCK) { seen.add(csym); - if (csym.isPrimitiveClass()) { - seen.add(csym.referenceProjection()); - } } if (csym.members() != null) { for (Symbol s : sym.members().getSymbols()) { @@ -1511,13 +1531,62 @@ public JavaFileObject writeClass(ClassSymbol c) { JavaFileObject javaFileObject = writeClassInternal(c); if (c.isPrimitiveClass()) { - ClassSymbol refProjection = c.referenceProjection(); - refProjection.flags_field = (refProjection.flags_field & ~FINAL) | ABSTRACT; - writeClassInternal(refProjection); + writeClassInternal(getReferenceProjection(c)); } return javaFileObject; } + // where + private static ClassSymbol getReferenceProjection(ClassSymbol c) { + + ClassSymbol projection; + ClassType projectedType; + + ClassType ct = (ClassType) c.type; + projectedType = new ClassType(ct.getEnclosingType(), ct.typarams_field, null, ct.getMetadata(), false); + projectedType.allparams_field = ct.allparams_field; + projectedType.supertype_field = ct.supertype_field; + + projectedType.interfaces_field = ct.interfaces_field; + projectedType.all_interfaces_field = ct.all_interfaces_field; + projectedType.projection = null; + + Name projectionName = c.name.append('$', c.name.table.names.ref); + long projectionFlags = (c.flags() & ~(PRIMITIVE_CLASS | UNATTRIBUTED | FINAL)) | (ABSTRACT | SEALED); + + projection = new ClassSymbol(projectionFlags, projectionName, projectedType, c.owner) { + @Override + public boolean isReferenceProjection() { + return true; + } + + @Override + public ClassSymbol valueProjection() { + return c; + } + }; + projection.members_field = WriteableScope.create(projection); + for (Symbol s : c.members().getSymbols(s->(s.kind == MTH || s.kind == VAR), NON_RECURSIVE)) { + Symbol clone = null; + if (s.kind == MTH) { + MethodSymbol valMethod = (MethodSymbol)s; + MethodSymbol refMethod = valMethod.clone(projection); + clone = refMethod; + } else if (s.kind == VAR) { + VarSymbol valVar = (VarSymbol)s; + VarSymbol refVar = valVar.clone(projection); + clone = refVar; + } + projection.members_field.enter(clone); + } + projection.completer = Completer.NULL_COMPLETER; + projection.sourcefile = c.sourcefile; + projection.flatname = c.flatname.append('$', c.name.table.names.ref); + projection.permitted = List.of(c); + projectedType.tsym = projection; + return projection; + } + private JavaFileObject writeClassInternal(ClassSymbol c) throws IOException, PoolOverflow, StringOverflow { @@ -1590,7 +1659,7 @@ public void writeClassFile(OutputStream out, ClassSymbol c) } else { databuf.appendChar(poolWriter.putClass(c)); } - databuf.appendChar(supertype.hasTag(CLASS) ? poolWriter.putClass((ClassSymbol)supertype.tsym) : 0); + databuf.appendChar(supertype.hasTag(CLASS) ? poolWriter.putClass(supertype) : 0); databuf.appendChar(interfaces.length()); for (List l = interfaces; l.nonEmpty(); l = l.tail) databuf.appendChar(poolWriter.putClass((ClassSymbol)l.head.tsym)); diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java index 4a3d4f08063..c0da0b39473 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java @@ -2275,8 +2275,8 @@ public void visitTypeCast(JCTypeCast tree) { // inline widening conversion is a nop, as the VM sees a subtyping relationship. if (!tree.clazz.type.isPrimitive() && !types.isSameType(tree.expr.type, tree.clazz.type) && - (!tree.clazz.type.tsym.isReferenceProjection() || tree.clazz.type.tsym.valueProjection() != tree.expr.type.tsym) && - types.asSuper(tree.expr.type, tree.clazz.type.tsym) == null) { + (!tree.clazz.type.isReferenceProjection() || !types.isSameType(tree.clazz.type.valueProjection(), tree.expr.type)) && + !types.isSubtype(tree.expr.type, tree.clazz.type)) { checkDimension(tree.pos(), tree.clazz.type); if (types.isPrimitiveClass(tree.clazz.type)) { code.emitop2(checkcast, new ConstantPoolQType(tree.clazz.type, types), PoolWriter::putClass); diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/PoolWriter.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/PoolWriter.java index 32ba0e6ced6..893aa0bb49a 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/PoolWriter.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/PoolWriter.java @@ -230,6 +230,9 @@ int putModule(ModuleSymbol mod) { * Enter an inner class into the `innerClasses' set. */ void enterInner(ClassSymbol c) { + if (c.isReferenceProjection()) { + c = c.valueProjection(); + } if (c.type.isCompound()) { throw new AssertionError("Unexpected intersection type: " + c.type); } @@ -375,6 +378,9 @@ void writeConstant(PoolConstant c) { Name name = ct.hasTag(ARRAY) ? typeSig(ct) : c instanceof ConstantPoolQType ? names.fromString("Q" + new String(externalize(ct.tsym.flatName())) + ";") : names.fromUtf(externalize(ct.tsym.flatName())); + if (ct.isReferenceProjection()) { + name = name.append('$', names.ref); + } poolbuf.appendByte(tag); poolbuf.appendChar(putName(name)); if (ct.hasTag(CLASS)) { diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/TransValues.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/TransValues.java index db8653bb865..fb4e1239b99 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/TransValues.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/TransValues.java @@ -34,6 +34,7 @@ import com.sun.tools.javac.code.Symbol.TypeSymbol; import com.sun.tools.javac.code.Symbol.VarSymbol; import com.sun.tools.javac.code.Symtab; +import com.sun.tools.javac.code.Type; import com.sun.tools.javac.code.Type.ClassType; import com.sun.tools.javac.code.Type.MethodType; import com.sun.tools.javac.code.Types; @@ -223,16 +224,6 @@ public void visitMethodDef(JCMethodDecl tree) { currentMethod.setType(factorySym.type); currentMethod.factoryProduct = product; currentClass.sym.members().remove(tree.sym); - ClassSymbol refProjection = currentClass.sym.projection; - if (refProjection != null) { - MethodSymbol projection = tree.sym.projection; - Assert.check(projection != null); - refProjection.members().remove(projection); - projection = factorySym.clone(refProjection); - projection.projection = factorySym; - factorySym.projection = projection; - refProjection.members().enter(projection); - } tree.sym = factorySym; currentClass.sym.members().enter(factorySym); tree.mods.flags |= STATIC; @@ -339,22 +330,20 @@ public void visitSelect(JCFieldAccess fieldAccess) { if (fieldAccess.name != names._class) { // TODO: this and super ?? Symbol sym = TreeInfo.symbol(fieldAccess); Symbol sitesym = TreeInfo.symbol(fieldAccess.selected); - TypeSymbol selectedType = fieldAccess.selected.type.tsym; + Type selectedType = fieldAccess.selected.type; if (selectedType.isReferenceProjection()) { switch (sym.kind) { case MTH: case VAR: if (sym.isStatic() && sitesym != null && sitesym.kind == TYP) { - fieldAccess.selected = make.Type(types.erasure(selectedType.valueProjection().type)); + fieldAccess.selected = make.Type(types.erasure(selectedType.valueProjection())); } else { fieldAccess.selected = - make.TypeCast(types.erasure(selectedType.valueProjection().type), fieldAccess.selected); - if (sym.owner.isReferenceProjection()) // is an empty class file. - TreeInfo.setSymbol(fieldAccess, sym.valueProjection()); + make.TypeCast(types.erasure(selectedType.valueProjection()), fieldAccess.selected); } break; case TYP: - fieldAccess.selected = make.Type(types.erasure(selectedType.valueProjection().type)); + fieldAccess.selected = make.Type(types.erasure(selectedType.valueProjection())); break; } } diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/model/JavacTypes.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/model/JavacTypes.java index e3e158a0725..3cfe8cd0769 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/model/JavacTypes.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/model/JavacTypes.java @@ -295,7 +295,7 @@ private DeclaredType getDeclaredType0(Type outer, public TypeMirror asMemberOf(DeclaredType containing, Element element) { Type site = (Type)containing; Symbol sym = (Symbol)element; - if (types.asSuper(site, sym.getEnclosingElement()) == null) + if (types.asSuper(site.referenceProjectionOrSelf(), sym.getEnclosingElement()) == null) throw new IllegalArgumentException(sym + "@" + site); return types.memberType(site, sym); } diff --git a/test/langtools/tools/javac/annotations/typeAnnotations/classfile/BridgeShouldHaveNoInteriorAnnotationsTest.java b/test/langtools/tools/javac/annotations/typeAnnotations/classfile/BridgeShouldHaveNoInteriorAnnotationsTest.java index 0ec1a790d72..cc0e4e660ef 100644 --- a/test/langtools/tools/javac/annotations/typeAnnotations/classfile/BridgeShouldHaveNoInteriorAnnotationsTest.java +++ b/test/langtools/tools/javac/annotations/typeAnnotations/classfile/BridgeShouldHaveNoInteriorAnnotationsTest.java @@ -71,17 +71,17 @@ public void remove() { }; - // Expected output can't be directly encoded into NestedLambdasCastedTest !!! + // Expected output can't be directly encoded into BridgeShouldHaveNoInteriorAnnotationsTest !!! static class OutputExpectedOnceHolder { public String[] outputs = { - "0: #120(): CAST, offset=1, type_index=0, location=[TYPE_ARGUMENT(0)]", - "1: #120(): LOCAL_VARIABLE, {start_pc=5, length=2, index=1}, location=[TYPE_ARGUMENT(0)]", + "0: #118(): CAST, offset=1, type_index=0, location=[TYPE_ARGUMENT(0)]", + "1: #118(): LOCAL_VARIABLE, {start_pc=2, length=2, index=1}, location=[TYPE_ARGUMENT(0)]", }; } static class OutputExpectedTwiceHolder { public String[] outputs = { - "0: #120(): METHOD_RETURN, location=[TYPE_ARGUMENT(0)]", + "0: #118(): METHOD_RETURN, location=[TYPE_ARGUMENT(0)]", }; } diff --git a/test/langtools/tools/javac/api/TestApisWithProjections.java b/test/langtools/tools/javac/api/TestApisWithProjections.java new file mode 100644 index 00000000000..cb04b60ba56 --- /dev/null +++ b/test/langtools/tools/javac/api/TestApisWithProjections.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* This test "covers"/verifies com.sun.tools.javac.model.JavacTypes#asMemberOf's calls + to asSuper work*properly with primitive types. +*/ + +/** + * @test + * @bug 8244712 + * @summary Test API usage with reference projection types. + * @library ./lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.code + * @build ToolTester + * @run main TestApisWithProjections + */ + +import java.io.*; +import javax.lang.model.element.Element; +import javax.lang.model.element.TypeElement; +import javax.lang.model.type.DeclaredType; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.util.ElementFilter; +import javax.lang.model.util.Elements; +import javax.lang.model.util.Types; +import javax.tools.*; + +import com.sun.tools.javac.api.JavacTaskImpl; + +public class TestApisWithProjections extends ToolTester { + public static void main(String... args) throws Exception { + try (TestApisWithProjections t = new TestApisWithProjections()) { + t.run(); + } + } + + void run() throws Exception { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + File file = new File(test_src, "TestApisWithProjections.java"); + final Iterable compilationUnits = + fm.getJavaFileObjects(new File[] {file}); + task = (JavacTaskImpl)tool.getTask(pw, fm, null, null, null, compilationUnits); + elements = task.getElements(); + types = task.getTypes(); + + Iterable toplevels; + toplevels = ElementFilter.typesIn(task.enter(task.parse())); + + for (TypeElement clazz : toplevels) { + System.out.format("Testing %s:%n%n", clazz.getSimpleName()); + testParseType(clazz); + } + + pw.close(); + + String out = sw.toString(); + System.out.println(out); + + if (out.contains("com.sun.tools.javac.util")) + throw new Exception("Unexpected output from compiler"); + } + + void testParseType(TypeElement clazz) { + DeclaredType type = (DeclaredType)task.parseType("PrimitiveClass", clazz); + for (Element member : elements.getAllMembers((TypeElement)type.asElement())) { + TypeMirror mt = types.asMemberOf(type, member); + System.out.format("%s : %s -> %s%n", member.getSimpleName(), member.asType(), mt); + } + } + + JavacTaskImpl task; + Elements elements; + Types types; +} + +abstract class Base { + void foo(T t) {} +} + +primitive class PrimitiveClass extends Base { +} diff --git a/test/langtools/tools/javac/valhalla/lworld-values/AsSuperTests.java b/test/langtools/tools/javac/valhalla/lworld-values/AsSuperTests.java new file mode 100644 index 00000000000..44451bda5fb --- /dev/null +++ b/test/langtools/tools/javac/valhalla/lworld-values/AsSuperTests.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8244712 + * @summary Javac should switch to reference projection before walking type hierarchy. + * @compile AsSuperTests.java + */ + +/* The following test "covers"/verifies that the asSuper calls in + com.sun.tools.javac.comp.Resolve#resolveSelf && + com.sun.tools.javac.comp.Lower#visitSelect + com.sun.tools.javac.comp.Resolve#mostSpecific + com.sun.tools.javac.comp.Attr#visitSelect + com.sun.tools.javac.comp.Resolve.UnboundMethodReferenceLookupHelper#UnboundMethodReferenceLookupHelper + work correctly with primitive types. +*/ + +interface I { + default void foo() { + System.out.println("I.foo"); + } +} + +abstract class Base { + static void goo() {} + void zoo() {} + interface SAM { + String m(Foo f); + } + + static void test() { + SAM s = Base::getX; + } + + String getX() { return null; } + + static primitive class Foo extends Base {} +} + +primitive class X extends Base implements I { + + static void goo() {} + + public void foo() { + I.super.foo(); + X.this.goo(); // covers the asSuper call in com.sun.tools.javac.comp.Resolve#mostSpecific + super.zoo(); // covers the asSuper call in com.sun.tools.javac.comp.Attr#visitSelect + } +} diff --git a/test/langtools/tools/javac/valhalla/lworld-values/AttributesTest.java b/test/langtools/tools/javac/valhalla/lworld-values/AttributesTest.java index 432ea576ab5..4ee6a3512b4 100644 --- a/test/langtools/tools/javac/valhalla/lworld-values/AttributesTest.java +++ b/test/langtools/tools/javac/valhalla/lworld-values/AttributesTest.java @@ -57,11 +57,11 @@ public static void main(String[] args) throws Exception { throw new AssertionError("Unexpected inner class attribute"); } String name = inners.classes[0].getInnerName(cls.constant_pool); - if (!name.equals("V$ref")) { + if (!name.equals("V")) { throw new AssertionError("Unexpected inner class " + name); } name = inners.classes[1].getInnerName(cls.constant_pool); - if (!name.equals("V")) { + if (!name.equals("V$ref")) { throw new AssertionError("Unexpected inner class " + name); } diff --git a/test/langtools/tools/javac/valhalla/lworld-values/CheckQuestionInMessages.out b/test/langtools/tools/javac/valhalla/lworld-values/CheckQuestionInMessages.out index 2152040f774..609bca6d944 100644 --- a/test/langtools/tools/javac/valhalla/lworld-values/CheckQuestionInMessages.out +++ b/test/langtools/tools/javac/valhalla/lworld-values/CheckQuestionInMessages.out @@ -1,3 +1,3 @@ -CheckQuestionInMessages.java:12:22: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.Object, java.util.List) -CheckQuestionInMessages.java:13:18: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.Object[], X$ref[]) +CheckQuestionInMessages.java:12:22: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.Object, java.util.List) +CheckQuestionInMessages.java:13:18: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.Object[], X.ref[]) 2 errors diff --git a/test/langtools/tools/javac/valhalla/lworld-values/ClassLiteralTypingNegativeTest.out b/test/langtools/tools/javac/valhalla/lworld-values/ClassLiteralTypingNegativeTest.out index 5cd9537b9ed..7f54c390659 100644 --- a/test/langtools/tools/javac/valhalla/lworld-values/ClassLiteralTypingNegativeTest.out +++ b/test/langtools/tools/javac/valhalla/lworld-values/ClassLiteralTypingNegativeTest.out @@ -1,9 +1,9 @@ -ClassLiteralTypingNegativeTest.java:14:51: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.Class, java.lang.Class) -ClassLiteralTypingNegativeTest.java:15:41: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.Class, java.lang.Class) -ClassLiteralTypingNegativeTest.java:17:30: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.Class, java.lang.Class) -ClassLiteralTypingNegativeTest.java:19:34: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.Class, java.lang.Class) -ClassLiteralTypingNegativeTest.java:31:51: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.Class, java.lang.Class) -ClassLiteralTypingNegativeTest.java:32:41: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.Class, java.lang.Class) -ClassLiteralTypingNegativeTest.java:34:30: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.Class, java.lang.Class) -ClassLiteralTypingNegativeTest.java:36:34: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.Class, java.lang.Class) +ClassLiteralTypingNegativeTest.java:14:51: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.Class, java.lang.Class) +ClassLiteralTypingNegativeTest.java:15:41: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.Class, java.lang.Class) +ClassLiteralTypingNegativeTest.java:17:30: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.Class, java.lang.Class) +ClassLiteralTypingNegativeTest.java:19:34: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.Class, java.lang.Class) +ClassLiteralTypingNegativeTest.java:31:51: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.Class, java.lang.Class) +ClassLiteralTypingNegativeTest.java:32:41: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.Class, java.lang.Class) +ClassLiteralTypingNegativeTest.java:34:30: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.Class, java.lang.Class) +ClassLiteralTypingNegativeTest.java:36:34: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.Class, java.lang.Class) 8 errors diff --git a/test/langtools/tools/javac/valhalla/lworld-values/ConditionalTypeTest.out b/test/langtools/tools/javac/valhalla/lworld-values/ConditionalTypeTest.out index d210b966319..9dd38b9fd08 100644 --- a/test/langtools/tools/javac/valhalla/lworld-values/ConditionalTypeTest.out +++ b/test/langtools/tools/javac/valhalla/lworld-values/ConditionalTypeTest.out @@ -1,6 +1,6 @@ ConditionalTypeTest.java:13:16: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.String, ConditionalTypeTest.I) ConditionalTypeTest.java:24:16: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.String, ConditionalTypeTest.Node) -ConditionalTypeTest.java:27:16: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.String, ConditionalTypeTest.Node$ref) +ConditionalTypeTest.java:27:16: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.String, ConditionalTypeTest.Node.ref) ConditionalTypeTest.java:30:16: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.String, ConditionalTypeTest.Node) ConditionalTypeTest.java:33:16: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.String, ConditionalTypeTest.Node) 5 errors diff --git a/test/langtools/tools/javac/valhalla/lworld-values/EnhancedForLoopTest.java b/test/langtools/tools/javac/valhalla/lworld-values/EnhancedForLoopTest.java index 1ab633ae756..ceac83224ff 100644 --- a/test/langtools/tools/javac/valhalla/lworld-values/EnhancedForLoopTest.java +++ b/test/langtools/tools/javac/valhalla/lworld-values/EnhancedForLoopTest.java @@ -25,7 +25,7 @@ /* * @test - * @bug 8244711 + * @bug 8244711 8244712 * @summary Test that inline types work well with enhanced for loop. * @run main EnhancedForLoopTest */ @@ -34,8 +34,36 @@ import java.util.List; import java.util.ArrayList; +/* This test covers/verifies that the asSuper calls in + + com.sun.tools.javac.comp.Lower.visitIterableForeachLoop + com.sun.tools.javac.comp.Attr#visitForeachLoop + + work properly with primitive class types. +*/ + public class EnhancedForLoopTest { + static primitive class PrimitiveIterator implements Iterator { + + Iterator iv; + + public PrimitiveIterator(List lv) { + this.iv = lv.iterator(); + } + + @Override + public boolean hasNext() { + return iv.hasNext(); + } + + @Override + public V next() { + return iv.next(); + } + + } + primitive static class Foo implements Iterable { List lv; @@ -48,8 +76,8 @@ public void add(V v) { lv.add(v); } - public Iterator iterator() { - return lv.iterator(); + public PrimitiveIterator iterator() { + return new PrimitiveIterator(lv); } } diff --git a/test/langtools/tools/javac/valhalla/lworld-values/GenericInlineTest.out b/test/langtools/tools/javac/valhalla/lworld-values/GenericInlineTest.out index 6aedeacac9b..d54f9c2a5af 100644 --- a/test/langtools/tools/javac/valhalla/lworld-values/GenericInlineTest.out +++ b/test/langtools/tools/javac/valhalla/lworld-values/GenericInlineTest.out @@ -2,7 +2,7 @@ GenericInlineTest.java:21:36: compiler.err.prob.found.req: (compiler.misc.inconv GenericInlineTest.java:27:35: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: GenericInlineTest, Mid) GenericInlineTest.java:29:35: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: GenericInlineTest, Low) GenericInlineTest.java:33:13: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: Low, GenericInlineTest) -GenericInlineTest.java:37:53: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: GenericInlineTest, GenericInlineTest$ref) -GenericInlineTest.java:40:13: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: GenericInlineTest$ref, GenericInlineTest) -GenericInlineTest.java:41:50: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: GenericInlineTest$ref, GenericInlineTest) +GenericInlineTest.java:37:53: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: GenericInlineTest, GenericInlineTest.ref) +GenericInlineTest.java:40:13: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: GenericInlineTest.ref, GenericInlineTest) +GenericInlineTest.java:41:50: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: GenericInlineTest.ref, GenericInlineTest) 7 errors diff --git a/test/langtools/tools/javac/valhalla/lworld-values/OverloadingPhaseTest.out b/test/langtools/tools/javac/valhalla/lworld-values/OverloadingPhaseTest.out index 0ad00fdecae..cf1de1fe46f 100644 --- a/test/langtools/tools/javac/valhalla/lworld-values/OverloadingPhaseTest.out +++ b/test/langtools/tools/javac/valhalla/lworld-values/OverloadingPhaseTest.out @@ -1,3 +1,3 @@ -OverloadingPhaseTest.java:26:24: compiler.err.ref.ambiguous: roo, kindname.method, roo(OverloadingPhaseTest.V$ref,int), OverloadingPhaseTest, kindname.method, roo(OverloadingPhaseTest.V$ref,java.lang.Integer), OverloadingPhaseTest -OverloadingPhaseTest.java:28:24: compiler.err.ref.ambiguous: roo, kindname.method, roo(OverloadingPhaseTest.V$ref,int), OverloadingPhaseTest, kindname.method, roo(OverloadingPhaseTest.V$ref,java.lang.Integer), OverloadingPhaseTest +OverloadingPhaseTest.java:26:24: compiler.err.ref.ambiguous: roo, kindname.method, roo(OverloadingPhaseTest.V.ref,int), OverloadingPhaseTest, kindname.method, roo(OverloadingPhaseTest.V.ref,java.lang.Integer), OverloadingPhaseTest +OverloadingPhaseTest.java:28:24: compiler.err.ref.ambiguous: roo, kindname.method, roo(OverloadingPhaseTest.V.ref,int), OverloadingPhaseTest, kindname.method, roo(OverloadingPhaseTest.V.ref,java.lang.Integer), OverloadingPhaseTest 2 errors diff --git a/test/langtools/tools/javac/valhalla/lworld-values/TypeRelationsNegativeTest.out b/test/langtools/tools/javac/valhalla/lworld-values/TypeRelationsNegativeTest.out index ea1dc29fd9f..7d6f9a1f9f6 100644 --- a/test/langtools/tools/javac/valhalla/lworld-values/TypeRelationsNegativeTest.out +++ b/test/langtools/tools/javac/valhalla/lworld-values/TypeRelationsNegativeTest.out @@ -1,4 +1,4 @@ TypeRelationsNegativeTest.java:11:39: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: compiler.misc.type.null, TypeRelationsNegativeTest) TypeRelationsNegativeTest.java:21:77: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: compiler.misc.type.null, TypeRelationsNegativeTest) -TypeRelationsNegativeTest.java:26:14: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: TypeRelationsNegativeTest$ref[], TypeRelationsNegativeTest[]) +TypeRelationsNegativeTest.java:26:14: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: TypeRelationsNegativeTest.ref[], TypeRelationsNegativeTest[]) 3 errors