Skip to content
New issue

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

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

Already on GitHub? Sign in 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