OpenJDK / amber / amber
changeset 56805:ed1f7c1d4ff3 records-and-sealed
improving generation and error detection on canonical constructors
author | vromero |
---|---|
date | Thu, 20 Jun 2019 11:05:50 -0400 |
parents | a7ed37b357b7 |
children | fa374e622161 7fa5bdf1b954 aafd62d33c39 |
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 test/langtools/tools/javac/records/mandated_members/canonical_constructor/BadCanonicalConstructorTest.java test/langtools/tools/javac/records/mandated_members/canonical_constructor/MismatchTest.java test/langtools/tools/javac/records/mandated_members/canonical_constructor/MismatchTest.out |
diffstat | 5 files changed, 68 insertions(+), 3 deletions(-) [+] |
line wrap: on
line diff
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java Tue Jun 18 15:27:02 2019 -0400 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java Thu Jun 20 11:05:50 2019 -0400 @@ -1130,6 +1130,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. @@ -1191,7 +1229,6 @@ } } } - } private Symbol lookupMethod(TypeSymbol tsym, Name name, List<Type> argtypes) {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties Tue Jun 18 15:27:02 2019 -0400 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties Thu Jun 20 11:05:50 2019 -0400 @@ -3448,12 +3448,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 15:27:02 2019 -0400 +++ b/test/langtools/tools/javac/records/mandated_members/canonical_constructor/BadCanonicalConstructorTest.java Thu Jun 20 11:05:50 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 11:05:50 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 11:05:50 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