diff --git a/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala b/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala index f7ef86ee5cde..e98ff6c9d66d 100644 --- a/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala @@ -854,13 +854,13 @@ object JavaParsers { val accessors = (for (name, (tpt, annots)) <- fieldsByName yield - DefDef(name, Nil, tpt, unimplementedExpr) + DefDef(name, List(Nil), tpt, unimplementedExpr) .withMods(Modifiers(Flags.JavaDefined | Flags.Method | Flags.Synthetic)) ).toList // generate the canonical constructor val canonicalConstructor = - DefDef(nme.CONSTRUCTOR, joinParams(tparams, List(header)), TypeTree(), EmptyTree) + DefDef(nme.CONSTRUCTOR, joinParams(Nil, List(header)), TypeTree(), EmptyTree) .withMods(Modifiers(Flags.JavaDefined | Flags.Synthetic, mods.privateWithin)) // return the trees @@ -872,7 +872,7 @@ object JavaParsers { tparams = tparams, needsDummyConstr = true ) - ).withMods(mods) + ).withMods(mods.withFlags(Flags.JavaDefined | Flags.Final)) } addCompanionObject(statics, recordTypeDef) end recordDecl diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala index 819b43fcec2c..1e351067debf 100644 --- a/compiler/src/dotty/tools/dotc/typer/Namer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala @@ -879,6 +879,10 @@ class Namer { typer: Typer => * with a user-defined method in the same scope with a matching type. */ private def invalidateIfClashingSynthetic(denot: SymDenotation): Unit = + + def isJavaRecord(owner: Symbol) = + owner.is(JavaDefined) && owner.derivesFrom(defn.JavaRecordClass) + def isCaseClassOrCompanion(owner: Symbol) = owner.isClass && { if (owner.is(Module)) owner.linkedClass.is(CaseClass) @@ -902,9 +906,9 @@ class Namer { typer: Typer => && (definesMember || inheritsConcreteMember) ) || - // remove synthetic constructor of a java Record if it clashes with a non-synthetic constructor - (denot.isConstructor - && denot.owner.is(JavaDefined) && denot.owner.derivesFrom(defn.JavaRecordClass) + // remove synthetic constructor or method of a java Record if it clashes with a non-synthetic constructor + (isJavaRecord(denot.owner) + && denot.is(Method) && denot.owner.unforcedDecls.lookupAll(denot.name).exists(c => c != denot.symbol && c.info.matches(denot.info)) ) ) diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index c0b5ea19ec23..d51f51ea335a 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -2548,10 +2548,10 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer def canBeInvalidated(sym: Symbol): Boolean = sym.is(Synthetic) && (desugar.isRetractableCaseClassMethodName(sym.name) || - (sym.isConstructor && sym.owner.derivesFrom(defn.JavaRecordClass))) + (sym.owner.is(JavaDefined) && sym.owner.derivesFrom(defn.JavaRecordClass) && sym.is(Method))) if !sym.info.exists then - // it's a discarded method (synthetic case class method or synthetic java record constructor), drop it + // it's a discarded method (synthetic case class method or synthetic java record constructor or overriden member), drop it assert(canBeInvalidated(sym)) sym.owner.info.decls.openForMutations.unlink(sym) return EmptyTree diff --git a/tests/pos-java16+/i19386/FromScala.scala b/tests/pos-java16+/i19386/FromScala.scala new file mode 100644 index 000000000000..82b5835753a1 --- /dev/null +++ b/tests/pos-java16+/i19386/FromScala.scala @@ -0,0 +1,2 @@ +def test(r: R1): Unit = + val i: Int = r.i() diff --git a/tests/pos-java16+/i19386/R1.java b/tests/pos-java16+/i19386/R1.java new file mode 100644 index 000000000000..40837040d659 --- /dev/null +++ b/tests/pos-java16+/i19386/R1.java @@ -0,0 +1 @@ +public record R1(int i) {} diff --git a/tests/pos-java16+/java-records/FromScala.scala b/tests/pos-java16+/java-records/FromScala.scala index 67747e658432..8654f88f1835 100644 --- a/tests/pos-java16+/java-records/FromScala.scala +++ b/tests/pos-java16+/java-records/FromScala.scala @@ -1,4 +1,8 @@ object C: + + def useR0: Unit = + val r = R0() + def useR1: Unit = // constructor signature val r = R1(123, "hello") @@ -41,3 +45,7 @@ object C: val l2: Long = r3.l(43L, 44L) // supertype val isRecord: java.lang.Record = r3 + + def useR4: Unit = + val r4 = R4(1) + val i: Int = r4.t diff --git a/tests/pos-java16+/java-records/R0.java b/tests/pos-java16+/java-records/R0.java new file mode 100644 index 000000000000..ad43a2b22673 --- /dev/null +++ b/tests/pos-java16+/java-records/R0.java @@ -0,0 +1 @@ +public record R0() {} diff --git a/tests/pos-java16+/java-records/R4.java b/tests/pos-java16+/java-records/R4.java new file mode 100644 index 000000000000..b8a415480afd --- /dev/null +++ b/tests/pos-java16+/java-records/R4.java @@ -0,0 +1 @@ +public record R4(T t) {}