< prev index next >

src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java

Print this page

        

@@ -91,10 +91,12 @@
     final Symtab syms;
     final JavacMessages messages;
     final Names names;
     final boolean allowDefaultMethods;
     final boolean mapCapturesToBounds;
+    final boolean allowValueBasedClasses;
+    final boolean nonCovariantValueArrays;
     final Check chk;
     final Enter enter;
     JCDiagnostic.Factory diags;
     List<Warner> warnStack = List.nil();
     final Name capturedName;

@@ -120,10 +122,13 @@
         enter = Enter.instance(context);
         capturedName = names.fromString("<captured wildcard>");
         messages = JavacMessages.instance(context);
         diags = JCDiagnostic.Factory.instance(context);
         noWarnings = new Warner(null);
+        Options options = Options.instance(context);
+        allowValueBasedClasses = options.isSet("allowValueBasedClasses");
+        nonCovariantValueArrays = options.isSet("nonCovariantValueArrays");
     }
     // </editor-fold>
 
     // <editor-fold defaultstate="collapsed" desc="bounds">
     /**

@@ -599,10 +604,11 @@
      */
     public boolean isConvertible(Type t, Type s, Warner warn) {
         if (t.hasTag(ERROR)) {
             return true;
         }
+
         boolean tPrimitive = t.isPrimitive();
         boolean sPrimitive = s.isPrimitive();
         if (tPrimitive == sPrimitive) {
             return isSubtypeUnchecked(t, s, warn);
         }

@@ -992,10 +998,51 @@
                    !overridesObjectMethod(origin, sym) &&
                    (interfaceCandidates(origin.type, (MethodSymbol)sym).head.flags() & DEFAULT) == 0;
        }
     }
 
+    public boolean isValue(Type t) {
+        return t != null && t.tsym != null && (t.tsym.flags() & Flags.VALUE) != 0;
+    }
+
+    public boolean isValueBased(Type t) {
+        return allowValueBasedClasses && t != null && t.tsym != null && (t.tsym.flags() & Flags.VALUEBASED) != 0;
+    }
+
+    private final HashMap<ClassSymbol, ClassSymbol> nullableProjectionsMap = new HashMap<>();
+
+    public ClassSymbol projectedNullableType(ClassSymbol c) {
+        if (!c.isValue() || !c.type.hasTag(CLASS))
+            return null;
+        ClassSymbol lox = nullableProjectionsMap.get(c);
+        if (lox != null)
+            return lox;
+
+        ClassType ct = (ClassType) c.type;
+        ClassType loxType = new ClassType(ct.getEnclosingType(), ct.typarams_field, null);
+        loxType.allparams_field = ct.allparams_field;
+        loxType.supertype_field = ct.supertype_field;
+        loxType.interfaces_field = ct.interfaces_field;
+        loxType.all_interfaces_field = ct.all_interfaces_field;
+        lox = new ClassSymbol((c.flags() & ~VALUE), c.name, loxType, c.owner) {
+            @Override
+            public boolean isProjectedNullable() {
+                return true;
+            }
+
+            @Override
+            public ClassSymbol nullFreeTypeSymbol() {
+                return c;
+            }
+        };
+        lox.members_field = c.members();
+        loxType.tsym = lox;
+
+        nullableProjectionsMap.put(c, lox);
+        return lox;
+    }
+
     // <editor-fold defaultstate="collapsed" desc="isSubtype">
     /**
      * Is t an unchecked subtype of s?
      */
     public boolean isSubtypeUnchecked(Type t, Type s) {

@@ -1015,11 +1062,20 @@
         private boolean isSubtypeUncheckedInternal(Type t, Type s, boolean capture, Warner warn) {
             if (t.hasTag(ARRAY) && s.hasTag(ARRAY)) {
                 if (((ArrayType)t).elemtype.isPrimitive()) {
                     return isSameType(elemtype(t), elemtype(s));
                 } else {
-                    return isSubtypeUncheckedInternal(elemtype(t), elemtype(s), false, warn);
+                    Type et = elemtype(t);
+                    Type es = elemtype(s);
+                    if (!isSubtypeUncheckedInternal(et, es, false, warn))
+                        return false;
+                    if (nonCovariantValueArrays) {
+                        if (isValue(et) || isValue(es)) {
+                            return isSameType(erasure(et), erasure(es));
+                        }
+                    }
+                    return true;
                 }
             } else if (isSubtype(t, s, capture)) {
                 return true;
             } else if (t.hasTag(TYPEVAR)) {
                 return isSubtypeUncheckedInternal(t.getUpperBound(), s, false, warn);

@@ -1112,11 +1168,11 @@
                      return t.hasTag(s.getTag());
                  case TYPEVAR:
                      return isSubtypeNoCapture(t.getUpperBound(), s);
                  case BOT:
                      return
-                         s.hasTag(BOT) || s.hasTag(CLASS) ||
+                         s.hasTag(BOT) || (s.hasTag(CLASS) && (!isValue(s) || isValueBased(s))) ||
                          s.hasTag(ARRAY) || s.hasTag(TYPEVAR);
                  case WILDCARD: //we shouldn't be here - avoids crash (see 7034495)
                  case NONE:
                      return false;
                  default:

@@ -1681,11 +1737,11 @@
                 return isCastable(wildUpperBound(t), s, warnStack.head);
             }
 
             @Override
             public Boolean visitClassType(ClassType t, Type s) {
-                if (s.hasTag(ERROR) || s.hasTag(BOT))
+                if (s.hasTag(ERROR) || (s.hasTag(BOT) && !isValue(t)))
                     return true;
 
                 if (s.hasTag(TYPEVAR)) {
                     if (isCastable(t, s.getUpperBound(), noWarnings)) {
                         warnStack.head.warn(LintCategory.UNCHECKED);

@@ -1805,11 +1861,20 @@
                     return isSubtype(t, s);
                 case ARRAY:
                     if (elemtype(t).isPrimitive() || elemtype(s).isPrimitive()) {
                         return elemtype(t).hasTag(elemtype(s).getTag());
                     } else {
-                        return visit(elemtype(t), elemtype(s));
+                        Type et = elemtype(t);
+                        Type es = elemtype(s);
+                        if (!visit(et, es))
+                            return false;
+                        if (nonCovariantValueArrays) {
+                            if (isValue(et) || isValue(es)) {
+                                return isSameType(erasure(et), erasure(es));
+                            }
+                        }
+                        return true;
                     }
                 default:
                     return false;
                 }
             }

@@ -2122,10 +2187,17 @@
             @Override
             public Type visitClassType(ClassType t, Symbol sym) {
                 if (t.tsym == sym)
                     return t;
 
+                /* For inline types, the wired in super type is j.l.O.
+                   So we need a special check for V <: V?
+                */
+                if (t.tsym == sym.nullFreeTypeSymbol()) {
+                    return new ClassType(t.getEnclosingType(), t.getTypeArguments(), (TypeSymbol)sym, t.getMetadata());
+                }
+
                 Type st = supertype(t);
                 if (st.hasTag(CLASS) || st.hasTag(TYPEVAR)) {
                     Type x = asSuper(st, sym);
                     if (x != null)
                         return x;

@@ -4815,14 +4887,20 @@
      * A wrapper for a type that allows use in sets.
      */
     public static class UniqueType {
         public final Type type;
         final Types types;
+        private boolean encodeTypeSig;
 
-        public UniqueType(Type type, Types types) {
+        public UniqueType(Type type, Types types, boolean encodeTypeSig) {
             this.type = type;
             this.types = types;
+            this.encodeTypeSig = encodeTypeSig;
+        }
+
+        public UniqueType(Type type, Types types) {
+            this(type, types, true);
         }
 
         public int hashCode() {
             return types.hashCode(type);
         }

@@ -4830,10 +4908,14 @@
         public boolean equals(Object obj) {
             return (obj instanceof UniqueType) &&
                 types.isSameType(type, ((UniqueType)obj).type);
         }
 
+        public boolean encodeTypeSig() {
+            return encodeTypeSig;
+        }
+
         public String toString() {
             return type.toString();
         }
 
     }

@@ -5062,11 +5144,14 @@
                     break;
                 case CLASS:
                     if (type.isCompound()) {
                         reportIllegalSignature(type);
                     }
-                    append('L');
+                    if (types.isValue(type))
+                        append('Q');
+                    else
+                        append('L');
                     assembleClassSig(type);
                     append(';');
                     break;
                 case ARRAY:
                     ArrayType at = (ArrayType) type;
< prev index next >