Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Fix Java record problems (#19578) and (#19386) #19583

Merged
merged 6 commits into from
Feb 9, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -872,7 +872,7 @@ object JavaParsers {
tparams = tparams,
needsDummyConstr = true
)
).withMods(mods)
).withMods(mods.withFlags(Flags.JavaDefined | Flags.Final))
}
addCompanionObject(statics, recordTypeDef)
end recordDecl
Expand Down
10 changes: 7 additions & 3 deletions compiler/src/dotty/tools/dotc/typer/Namer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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.isConstructor || definesMember)
&& denot.owner.unforcedDecls.lookupAll(denot.name).exists(c => c != denot.symbol && c.info.matches(denot.info))
noti0na1 marked this conversation as resolved.
Show resolved Hide resolved
)
)
Expand Down
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/typer/Typer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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)))

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
Expand Down
2 changes: 2 additions & 0 deletions tests/pos-java16+/i19386/FromScala.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
def test(r: R1): Unit =
val i: Int = r.i()
1 change: 1 addition & 0 deletions tests/pos-java16+/i19386/R1.java
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
public record R1(int i) {}
8 changes: 8 additions & 0 deletions tests/pos-java16+/java-records/FromScala.scala
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
object C:

def useR0: Unit =
val r = R0()

def useR1: Unit =
// constructor signature
val r = R1(123, "hello")
Expand Down Expand Up @@ -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
1 change: 1 addition & 0 deletions tests/pos-java16+/java-records/R0.java
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
public record R0() {}
1 change: 1 addition & 0 deletions tests/pos-java16+/java-records/R4.java
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
public record R4<T>(T t) {}
Loading