changeset 56807:7fa5bdf1b954 patterns-deconstruction

manual merge with records branch
author vromero
date Thu, 20 Jun 2019 12:08:09 -0400
parents c365fc1be242 ed1f7c1d4ff3
children 5137dd14728a
files src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties
diffstat 5 files changed, 69 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java	Tue Jun 18 21:30:50 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java	Thu Jun 20 12:08:09 2019 -0400
@@ -1132,6 +1132,44 @@
          *  to the symbol table.
          */
         private void addRecordMembersIfNeeded(JCClassDecl tree, Env<AttrContext> env, boolean defaultConstructorGenerated) {
+            if (!defaultConstructorGenerated) {
+                // let's check if there is a constructor with exactly the same arguments as the record components
+                List<Type> recordComponentTypes = TreeInfo.recordFields(tree).map(vd -> vd.sym.type);
+                List<Type> erasedTypes = types.erasure(recordComponentTypes);
+                JCMethodDecl canonicalDecl = null;
+                for (JCTree def : tree.defs) {
+                    if (TreeInfo.isConstructor(def)) {
+                        JCMethodDecl mdecl = (JCMethodDecl)def;
+                        if (types.isSameTypes(mdecl.sym.type.getParameterTypes(), erasedTypes)) {
+                            canonicalDecl = mdecl;
+                            break;
+                        }
+                    }
+                }
+                if (canonicalDecl != null && !types.isSameTypes(erasedTypes, recordComponentTypes)) {
+                    // error we found a constructor with the same erasure as the canonical constructor
+                    log.error(canonicalDecl, Errors.ConstructorWithSameErasureAsCanonical);
+                }
+                MethodSymbol canonicalInit = canonicalDecl == null ?
+                        null :
+                        canonicalDecl.sym;
+                if (canonicalInit == null) {
+                    RecordConstructorHelper helper = new RecordConstructorHelper(tree.sym, TreeInfo.recordFields(tree).map(vd -> vd.sym));
+                    JCTree constrDef = defaultConstructor(make.at(tree.pos), helper);
+                    tree.defs = tree.defs.prepend(constrDef);
+                    defaultConstructorGenerated = true;
+                } else {
+                    /* there is an explicit constructor that match the canonical constructor by type
+                       let's check that the match is also by name
+                    */
+                    List<Name> recordComponentNames = TreeInfo.recordFields(tree).map(vd -> vd.sym.name);
+                    List<Name> initParamNames = canonicalInit.params.map(p -> p.name);
+                    if (!initParamNames.equals(recordComponentNames)) {
+                        log.error(canonicalDecl, Errors.CanonicalWithNameMismatch);
+                    }
+                }
+            }
+
             if (lookupMethod(tree.sym, names.toString, List.nil()) == null) {
                 // public String toString() { return ???; }
                 JCMethodDecl toString = make.
@@ -1208,7 +1246,7 @@
                 LowerSignatureGenerator sg = new LowerSignatureGenerator();
                 sg.assembleSig(typeList);
                 return sg.toString();
-            }
+        }
 
             /**
              * Signature Generation
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties	Tue Jun 18 21:30:50 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties	Thu Jun 20 12:08:09 2019 -0400
@@ -3461,12 +3461,18 @@
 # 0: name
 compiler.err.record.not.allowed=\
     ''{0}'' not allowed here\n\
-    as of release 10, ''{0}'' is a restricted type name and cannot be used for type declarations
+    as of release 14, ''{0}'' is a restricted type name and cannot be used for type declarations
 
 # 0: name
 compiler.err.method.must.be.public=\
     method: {0}(), must be public
 
+compiler.err.canonical.with.name.mismatch=\
+    constructor with same signature as canonical does not match by parameter names
+
+compiler.err.constructor.with.same.erasure.as.canonical=\
+    constructor with same erasure as canonical constructor
+
 ############################################
 # messages previouly at javac.properties
 
--- a/test/langtools/tools/javac/records/mandated_members/canonical_constructor/BadCanonicalConstructorTest.java	Tue Jun 18 21:30:50 2019 +0200
+++ b/test/langtools/tools/javac/records/mandated_members/canonical_constructor/BadCanonicalConstructorTest.java	Thu Jun 20 12:08:09 2019 -0400
@@ -1,6 +1,6 @@
 /*
  * @test /nodynamiccopyright/
- * @summary check that a datum can inherit from DataClass or an abstract datum class
+ * @summary check that the compiler doesn't accept canonical constructors with wrong accessibility
  * @compile/fail/ref=BadCanonicalConstructorTest.out -XDrawDiagnostics BadCanonicalConstructorTest.java
  */
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/records/mandated_members/canonical_constructor/MismatchTest.java	Thu Jun 20 12:08:09 2019 -0400
@@ -0,0 +1,17 @@
+/*
+ * @test /nodynamiccopyright/
+ * @summary check that the compiler doesn't accept canonical constructors with name mismatch
+ * @compile/fail/ref=MismatchTest.out -XDrawDiagnostics MismatchTest.java
+ */
+
+import java.util.*;
+
+public class MismatchTest {
+    record R1(int i, int j) {
+        public R1(int j, int i) {} // doesn't match by name
+    }
+
+    record R2(int i, List<String> ls) {
+        public R2(int i, List ls) {}
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/records/mandated_members/canonical_constructor/MismatchTest.out	Thu Jun 20 12:08:09 2019 -0400
@@ -0,0 +1,5 @@
+MismatchTest.java:11:16: compiler.err.canonical.with.name.mismatch
+MismatchTest.java:15:16: compiler.err.constructor.with.same.erasure.as.canonical
+- compiler.note.unchecked.filename: MismatchTest.java
+- compiler.note.unchecked.recompile
+2 errors