< prev index next >

src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java

Print this page
@@ -758,10 +758,35 @@
              return (t.hasTag(TYPEVAR))
                                      ? diags.fragment(Fragments.TypeParameter(t))
                                      : t;
          }
  
+     void checkConstraintsOfValueClass(JCClassDecl tree, ClassSymbol c) {
+         DiagnosticPosition pos = tree.pos();
+         for (Type st : types.closure(c.type)) {
+             if (st == null || st.tsym == null || st.tsym.kind == ERR)
+                 continue;
+             if  (st.tsym == syms.objectType.tsym || st.tsym == syms.recordType.tsym || st.isInterface())
+                 continue;
+             if (!st.tsym.isAbstract()) {
+                 if (c != st.tsym) {
+                     log.error(pos, Errors.ConcreteSupertypeForValueClass(c, st));
+                 }
+                 continue;
+             }
+             // dealing with an abstract value or value super class below.
+             for (Symbol s : st.tsym.members().getSymbols(NON_RECURSIVE)) {
+                 if (s.kind == MTH) {
+                     if ((s.flags() & (SYNCHRONIZED | STATIC)) == SYNCHRONIZED) {
+                         log.error(pos, Errors.SuperClassMethodCannotBeSynchronized(s, c, st));
+                     }
+                     break;
+                 }
+             }
+         }
+     }
+ 
      /** Check that type is a valid qualifier for a constructor reference expression
       */
      Type checkConstructorRefType(DiagnosticPosition pos, Type t) {
          t = checkClassOrArrayType(pos, t);
          if (t.hasTag(CLASS)) {

@@ -815,10 +840,36 @@
              return typeTagError(pos,
                                  diags.fragment(Fragments.TypeReqRef),
                                  t);
      }
  
+     /** Check that type is an identity type, i.e. not a value type.
+      *  When not discernible statically, give it the benefit of doubt
+      *  and defer to runtime.
+      *
+      *  @param pos           Position to be used for error reporting.
+      *  @param t             The type to be checked.
+      */
+     boolean checkIdentityType(DiagnosticPosition pos, Type t) {
+         if (t.hasTag(TYPEVAR)) {
+             t = types.skipTypeVars(t, false);
+         }
+         if (t.isIntersection()) {
+             IntersectionClassType ict = (IntersectionClassType)t;
+             boolean result = true;
+             for (Type component : ict.getExplicitComponents()) {
+                 result &= checkIdentityType(pos, component);
+             }
+             return result;
+         }
+         if (t.isPrimitive() || (t.isValueClass() && !t.tsym.isAbstract())) {
+             typeTagError(pos, diags.fragment(Fragments.TypeReqIdentity), t);
+             return false;
+         }
+         return true;
+     }
+ 
      /** Check that each type is a reference type, i.e. a class, interface or array type
       *  or a type variable.
       *  @param trees         Original trees, used for error reporting.
       *  @param types         The types to be checked.
       */

@@ -1205,12 +1256,17 @@
                  mask = ReceiverParamFlags;
              else if (sym.owner.kind != TYP)
                  mask = LocalVarFlags;
              else if ((sym.owner.flags_field & INTERFACE) != 0)
                  mask = implicit = InterfaceVarFlags;
-             else
-                 mask = VarFlags;
+             else {
+                 boolean isInstanceFieldOfValueClass = sym.owner.type.isValueClass() && (flags & STATIC) == 0;
+                 mask = !isInstanceFieldOfValueClass ? VarFlags : ExtendedVarFlags;
+                 if (isInstanceFieldOfValueClass) {
+                     implicit |= FINAL | STRICT;
+                 }
+             }
              break;
          case MTH:
              if (sym.name == names.init) {
                  if ((sym.owner.flags_field & ENUM) != 0) {
                      // enum constructors cannot be declared public or

@@ -1232,13 +1288,16 @@
                      }
                  } else {
                      mask = implicit = InterfaceMethodFlags;
                  }
              } else if ((sym.owner.flags_field & RECORD) != 0) {
-                 mask = RecordMethodFlags;
+                 mask = ((sym.owner.flags_field & VALUE_CLASS) != 0 && (flags & Flags.STATIC) == 0) ?
+                         RecordMethodFlags & ~SYNCHRONIZED : RecordMethodFlags;
              } else {
-                 mask = MethodFlags;
+                 // value objects do not have an associated monitor/lock
+                 mask = ((sym.owner.flags_field & VALUE_CLASS) != 0 && (flags & Flags.STATIC) == 0) ?
+                         MethodFlags & ~SYNCHRONIZED : MethodFlags;
              }
              if ((flags & STRICTFP) != 0) {
                  warnOnExplicitStrictfp(pos);
              }
              // Imply STRICTFP if owner has STRICTFP set.

@@ -1251,11 +1310,11 @@
                      (sym.isDirectlyOrIndirectlyLocal() && (flags & ANNOTATION) != 0)) {
                  boolean implicitlyStatic = !sym.isAnonymous() &&
                          ((flags & RECORD) != 0 || (flags & ENUM) != 0 || (flags & INTERFACE) != 0);
                  boolean staticOrImplicitlyStatic = (flags & STATIC) != 0 || implicitlyStatic;
                  // local statics are allowed only if records are allowed too
-                 mask = staticOrImplicitlyStatic && allowRecords && (flags & ANNOTATION) == 0 ? StaticLocalFlags : LocalClassFlags;
+                 mask = staticOrImplicitlyStatic && allowRecords && (flags & ANNOTATION) == 0 ? ExtendedStaticLocalClassFlags : ExtendedLocalClassFlags;
                  implicit = implicitlyStatic ? STATIC : implicit;
              } else if (sym.owner.kind == TYP) {
                  // statics in inner classes are allowed only if records are allowed too
                  mask = ((flags & STATIC) != 0) && allowRecords && (flags & ANNOTATION) == 0 ? ExtendedMemberStaticClassFlags : ExtendedMemberClassFlags;
                  if (sym.owner.owner.kind == PCK ||

@@ -1270,13 +1329,17 @@
                  mask = ExtendedClassFlags;
              }
              // Interfaces are always ABSTRACT
              if ((flags & INTERFACE) != 0) implicit |= ABSTRACT;
  
+             if ((flags & (INTERFACE | VALUE_CLASS)) == 0) {
+                 implicit |= IDENTITY_TYPE;
+             }
+ 
              if ((flags & ENUM) != 0) {
-                 // enums can't be declared abstract, final, sealed or non-sealed
-                 mask &= ~(ABSTRACT | FINAL | SEALED | NON_SEALED);
+                 // enums can't be declared abstract, final, sealed or non-sealed or value
+                 mask &= ~(ABSTRACT | FINAL | SEALED | NON_SEALED | VALUE_CLASS);
                  implicit |= implicitEnumFinalFlag(tree);
              }
              if ((flags & RECORD) != 0) {
                  // records can't be declared abstract
                  mask &= ~ABSTRACT;

@@ -1285,10 +1348,18 @@
              if ((flags & STRICTFP) != 0) {
                  warnOnExplicitStrictfp(pos);
              }
              // Imply STRICTFP if owner has STRICTFP set.
              implicit |= sym.owner.flags_field & STRICTFP;
+ 
+             // concrete value classes are implicitly final
+             if ((flags & (ABSTRACT | INTERFACE | VALUE_CLASS)) == VALUE_CLASS) {
+                 implicit |= FINAL;
+             }
+ 
+             // TYPs can't be declared synchronized
+             mask &= ~SYNCHRONIZED;
              break;
          default:
              throw new AssertionError();
          }
          long illegal = flags & ExtendedStandardFlags & ~mask;

@@ -1315,19 +1386,23 @@
                   &&
                   checkDisjoint(pos, flags,
                                 ABSTRACT | INTERFACE,
                                 FINAL | NATIVE | SYNCHRONIZED)
                   &&
+                  checkDisjoint(pos, flags,
+                         INTERFACE,
+                         VALUE_CLASS)
+                  &&
                   checkDisjoint(pos, flags,
                                 PUBLIC,
                                 PRIVATE | PROTECTED)
                   &&
                   checkDisjoint(pos, flags,
                                 PRIVATE,
                                 PUBLIC | PROTECTED)
                   &&
-                  checkDisjoint(pos, flags,
+                  checkDisjoint(pos, (flags | implicit), // complain against volatile & implcitly final entities too.
                                 FINAL,
                                 VOLATILE)
                   &&
                   (sym.kind == TYP ||
                    checkDisjoint(pos, flags,

@@ -1339,11 +1414,20 @@
                   && checkDisjoint(pos, flags,
                                  SEALED,
                             FINAL | NON_SEALED)
                   && checkDisjoint(pos, flags,
                                  SEALED,
-                                 ANNOTATION)) {
+                                 ANNOTATION)
+                 && checkDisjoint(pos, flags,
+                                 VALUE_CLASS,
+                                 ANNOTATION)
+                 && checkDisjoint(pos, flags,
+                                 VALUE_CLASS,
+                                 NON_SEALED)
+                 && checkDisjoint(pos, flags,
+                                 VALUE_CLASS,
+                                 INTERFACE) ) {
              // skip
          }
          return flags & (mask | ~ExtendedStandardFlags) | implicit;
      }
  

@@ -2584,10 +2668,25 @@
              for (List<Type> m = supertypes; m != l; m = m.tail)
                  if (!checkCompatibleAbstracts(pos, l.head, m.head, c))
                      return;
          }
          checkCompatibleConcretes(pos, c);
+ 
+         boolean cIsValue = (c.tsym.flags() & VALUE_CLASS) != 0;
+         Type identitySuper = null, valueSuper = null;
+         for (Type t : types.closure(c)) {
+             if (t != c) {
+                 if ((t.tsym.flags() & IDENTITY_TYPE) != 0 && (t.tsym.flags() & VALUE_BASED) == 0)
+                     identitySuper = t;
+                 else if ((t.tsym.flags() & VALUE_CLASS) != 0)
+                     valueSuper = t;
+                 if (cIsValue && identitySuper != null && identitySuper.tsym != syms.objectType.tsym) { // Object is special
+                     log.error(pos, Errors.ValueTypeHasIdentitySuperType(c, identitySuper));
+                     break;
+                 }
+             }
+         }
      }
  
      /** Check that all non-override equivalent methods accessible from 'site'
       *  are mutually compatible (JLS 8.4.8/9.4.1).
       *

@@ -4058,13 +4157,16 @@
                  if (initCall != null) {
                      log.error(apply.pos(), Errors.RedundantSuperclassInit);
                      break;
                  }
  
+                 // valhalla is using this feature so commenting this code for now so that the
+                 // build doesn't depend on preview code
                  // If super()/this() isn't first, require "statements before super()" feature
-                 if (!firstStatement)
+                 /*if (!firstStatement) {
                      preview.checkSourceLevel(apply.pos(), Feature.SUPER_INIT);
+                 }*/
  
                  // We found a legitimate super()/this() call; remember it
                  initCall = methodName;
              } while (false);
  
< prev index next >