Skip to content

Commit 0a8bb4b

Browse files
authored
Merge pull request #10926 from dotty-staging/fix-#10866
Don't generate case class method if it clashes with inherited concret…
2 parents d932af9 + 5204f13 commit 0a8bb4b

File tree

3 files changed

+36
-13
lines changed

3 files changed

+36
-13
lines changed

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

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -766,23 +766,33 @@ class Namer { typer: Typer =>
766766
* `denot` is a compiler generated case class method that clashes
767767
* with a user-defined method in the same scope with a matching type.
768768
*/
769-
private def invalidateIfClashingSynthetic(denot: SymDenotation): Unit = {
770-
def isCaseClass(owner: Symbol) =
769+
private def invalidateIfClashingSynthetic(denot: SymDenotation): Unit =
770+
771+
def isCaseClassOrCompanion(owner: Symbol) =
771772
owner.isClass && {
772773
if (owner.is(Module)) owner.linkedClass.is(CaseClass)
773774
else owner.is(CaseClass)
774775
}
775-
val isClashingSynthetic =
776-
denot.is(Synthetic) &&
777-
desugar.isRetractableCaseClassMethodName(denot.name) &&
778-
isCaseClass(denot.owner) &&
776+
777+
def definesMember =
779778
denot.owner.info.decls.lookupAll(denot.name).exists(alt =>
780779
alt != denot.symbol && alt.info.matchesLoosely(denot.info))
781-
if (isClashingSynthetic) {
780+
781+
def inheritsConcreteMember =
782+
denot.owner.asClass.classParents.exists(parent =>
783+
parent.member(denot.name).hasAltWith(sd =>
784+
!sd.symbol.is(Deferred) && sd.matches(denot)))
785+
786+
val isClashingSynthetic =
787+
denot.is(Synthetic, butNot = ConstructorProxy)
788+
&& desugar.isRetractableCaseClassMethodName(denot.name)
789+
&& isCaseClassOrCompanion(denot.owner)
790+
&& (definesMember || inheritsConcreteMember)
791+
792+
if isClashingSynthetic then
782793
typr.println(i"invalidating clashing $denot in ${denot.owner}")
783794
denot.markAbsent()
784-
}
785-
}
795+
end invalidateIfClashingSynthetic
786796

787797
/** If completed symbol is an enum value or a named class, register it as a child
788798
* in all direct parent classes which are sealed.

tests/neg/i4564a.scala

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
2-
class BaseCP[T] {
3-
def apply(x: T): ClashPoly = if (???) ClashPoly(1) else ???
1+
abstract class BaseCP[T] {
2+
def apply(x: T): ClashPoly
43
}
5-
object ClashPoly extends BaseCP[Int]
4+
object ClashPoly extends BaseCP[Int] // error: object creation impossible
65
case class ClashPoly private(x: Int) // error: private method apply cannot override method apply in class BaseCP

tests/run/i10866.scala

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
abstract class B{
2+
def unapply(arg:A)={println ("Unapply from B"); true}
3+
}
4+
5+
case class A()
6+
7+
object A extends B
8+
9+
object Test extends App {
10+
println("Test")
11+
A() match {
12+
case A() => println("done")
13+
}
14+
}

0 commit comments

Comments
 (0)