Skip to content

Commit e4b421c

Browse files
authored
Merge pull request #13234 from dotty-staging/fix-13228
Don't export members that will be synthesized in case classes
2 parents 7945794 + db38c76 commit e4b421c

File tree

5 files changed

+29
-4
lines changed

5 files changed

+29
-4
lines changed

compiler/src/dotty/tools/dotc/core/Definitions.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1210,6 +1210,10 @@ class Definitions {
12101210
val AbstractFunctionClassPerRun: PerRun[Array[Symbol]] = new PerRun(AbstractFunctionType.map(_.symbol.asClass))
12111211
def AbstractFunctionClass(n: Int)(using Context): Symbol = AbstractFunctionClassPerRun()(using ctx)(n)
12121212

1213+
@tu lazy val caseClassSynthesized: List[Symbol] = List(
1214+
Any_hashCode, Any_equals, Any_toString, Product_canEqual, Product_productArity,
1215+
Product_productPrefix, Product_productElement, Product_productElementName)
1216+
12131217
val LazyHolder: PerRun[Map[Symbol, Symbol]] = new PerRun({
12141218
def holderImpl(holderType: String) = requiredClass("scala.runtime." + holderType)
12151219
Map[Symbol, Symbol](

compiler/src/dotty/tools/dotc/transform/SyntheticMembers.scala

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,7 @@ class SyntheticMembers(thisPhase: DenotTransformer) {
6363
private def initSymbols(using Context) =
6464
if (myValueSymbols.isEmpty) {
6565
myValueSymbols = List(defn.Any_hashCode, defn.Any_equals)
66-
myCaseSymbols = myValueSymbols ++ List(defn.Any_toString, defn.Product_canEqual,
67-
defn.Product_productArity, defn.Product_productPrefix, defn.Product_productElement,
68-
defn.Product_productElementName)
66+
myCaseSymbols = defn.caseClassSynthesized
6967
myCaseModuleSymbols = myCaseSymbols.filter(_ ne defn.Any_equals)
7068
myEnumValueSymbols = List(defn.Product_productPrefix)
7169
myNonJavaEnumValueSymbols = myEnumValueSymbols :+ defn.Any_toString

compiler/src/dotty/tools/dotc/typer/Namer.scala

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1156,10 +1156,15 @@ class Namer { typer: Typer =>
11561156

11571157
def addWildcardForwarders(seen: List[TermName], span: Span): Unit =
11581158
val nonContextual = mutable.HashSet(seen: _*)
1159+
val fromCaseClass = path.tpe.widen.classSymbols.exists(_.is(Case))
1160+
def isCaseClassSynthesized(mbr: Symbol) =
1161+
fromCaseClass && defn.caseClassSynthesized.contains(mbr)
11591162
for mbr <- path.tpe.membersBasedOnFlags(required = EmptyFlags, excluded = PrivateOrSynthetic) do
1160-
if !mbr.symbol.isSuperAccessor then
1163+
if !mbr.symbol.isSuperAccessor && !isCaseClassSynthesized(mbr.symbol) then
11611164
// Scala 2 superaccessors have neither Synthetic nor Artfact set, so we
11621165
// need to filter them out here (by contrast, Scala 3 superaccessors are Artifacts)
1166+
// Symbols from base traits of case classes that will get synthesized implementations
1167+
// at PostTyper are also excluded.
11631168
val alias = mbr.name.toTermName
11641169
if mbr.symbol.is(Given) then
11651170
if !seen.contains(alias) && mbr.matchesImportBound(givenBound) then

tests/run/i13228.check

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
RegisteredUser(Id,User(Name))
2+
false
3+
false
4+
false
5+
false

tests/run/i13228.scala

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
case class User(name: String)
2+
3+
case class RegisteredUser(id: String, data: User) {
4+
export data.*
5+
}
6+
7+
@main def Test() =
8+
println(RegisteredUser("Id", User("Name"))) // RegisteredUser(Name)
9+
println(RegisteredUser("Id", User("Name")).canEqual(User("Name"))) // True
10+
// The rest works as expected
11+
println(RegisteredUser("Id", User("Name")) == User("Name")) // False
12+
println(RegisteredUser("Id", User("Name")).hashCode == User("Name").hashCode) // False
13+
println(RegisteredUser("Id", User("Name")).productArity == User("Name").productArity) // False

0 commit comments

Comments
 (0)