Skip to content

Commit a577116

Browse files
Jannyboy11mbovel
andauthored
Improve error message for conflicting definitions (#23453)
Now includes the signature in the message also when emitted from the typer. Co-authored-by: Matthieu Bovel <[email protected]>
1 parent 665f6d7 commit a577116

18 files changed

+95
-45
lines changed

compiler/src/dotty/tools/dotc/reporting/messages.scala

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2333,7 +2333,9 @@ class DoubleDefinition(decl: Symbol, previousDecl: Symbol, base: Symbol)(using C
23332333
extends NamingMsg(DoubleDefinitionID) {
23342334
def msg(using Context) = {
23352335
def nameAnd = if (decl.name != previousDecl.name) " name and" else ""
2336-
def erasedType = if ctx.erasedTypes then i" ${decl.info}" else ""
2336+
def erasedType: Type =
2337+
if ctx.erasedTypes then decl.info
2338+
else TypeErasure.transformInfo(decl, decl.info)
23372339
def details(using Context): String =
23382340
if (decl.isRealMethod && previousDecl.isRealMethod) {
23392341
import Signature.MatchDegree.*
@@ -2361,7 +2363,7 @@ extends NamingMsg(DoubleDefinitionID) {
23612363
|Consider adding a @targetName annotation to one of the conflicting definitions
23622364
|for disambiguation."""
23632365
else ""
2364-
i"have the same$nameAnd type$erasedType after erasure.$hint"
2366+
i"have the same$nameAnd type $erasedType after erasure.$hint"
23652367
}
23662368
}
23672369
else ""
@@ -2374,7 +2376,7 @@ extends NamingMsg(DoubleDefinitionID) {
23742376
}
23752377
val clashDescription =
23762378
if (decl.owner eq previousDecl.owner)
2377-
"Double definition"
2379+
"Conflicting definitions"
23782380
else if ((decl.owner eq base) || (previousDecl eq base))
23792381
"Name clash between defined and inherited member"
23802382
else
@@ -3538,4 +3540,4 @@ final class NamedPatternNotApplicable(selectorType: Type)(using Context) extends
35383540
override protected def msg(using Context): String =
35393541
i"Named patterns cannot be used with $selectorType, because it is not a named tuple or case class"
35403542

3541-
override protected def explain(using Context): String = ""
3543+
override protected def explain(using Context): String = ""

compiler/test/dotc/neg-best-effort-unpickling.excludelist

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,6 @@ i22357a.scala
2121

2222
# `110 (of class java.lang.Integer)`
2323
context-function-syntax.scala
24+
25+
# Failure to disambiguate overloaded reference
26+
i23402b.scala

tests/neg/doubleDefinition.check

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,130 +1,130 @@
11
-- [E120] Naming Error: tests/neg/doubleDefinition.scala:14:5 ----------------------------------------------------------
22
14 | def foo(x: List[B]): Function1[B, B] = ??? // error: same jvm signature
33
| ^
4-
| Double definition:
4+
| Conflicting definitions:
55
| def foo(x: List[A]): A => A in class Test2 at line 13 and
66
| def foo(x: List[B]): B => B in class Test2 at line 14
7-
| have the same type after erasure.
7+
| have the same type (x: List): Function1 after erasure.
88
|
99
| Consider adding a @targetName annotation to one of the conflicting definitions
1010
| for disambiguation.
1111
-- [E120] Naming Error: tests/neg/doubleDefinition.scala:21:5 ----------------------------------------------------------
1212
21 | def foo(x: List[A]): Function2[B, B, B] = ??? // error
1313
| ^
14-
| Double definition:
14+
| Conflicting definitions:
1515
| def foo(x: List[A]): A => A in class Test3 at line 20 and
1616
| def foo(x: List[A]): (B, B) => B in class Test3 at line 21
1717
| have matching parameter types.
1818
-- [E120] Naming Error: tests/neg/doubleDefinition.scala:26:5 ----------------------------------------------------------
1919
26 | def foo = 2 // error
2020
| ^
21-
| Double definition:
21+
| Conflicting definitions:
2222
| val foo: Int in class Test4 at line 25 and
2323
| def foo: Int in class Test4 at line 26
2424
-- [E120] Naming Error: tests/neg/doubleDefinition.scala:31:5 ----------------------------------------------------------
2525
31 | val foo = 1 // error
2626
| ^
27-
| Double definition:
27+
| Conflicting definitions:
2828
| def foo: Int in class Test4b at line 30 and
2929
| val foo: Int in class Test4b at line 31
3030
-- [E120] Naming Error: tests/neg/doubleDefinition.scala:36:5 ----------------------------------------------------------
3131
36 | var foo = 1 // error
3232
| ^
33-
| Double definition:
33+
| Conflicting definitions:
3434
| def foo: Int in class Test4c at line 35 and
3535
| var foo: Int in class Test4c at line 36
3636
-- [E120] Naming Error: tests/neg/doubleDefinition.scala:41:5 ----------------------------------------------------------
3737
41 | def foo = 2 // error
3838
| ^
39-
| Double definition:
39+
| Conflicting definitions:
4040
| var foo: Int in class Test4d at line 40 and
4141
| def foo: Int in class Test4d at line 41
4242
-- [E120] Naming Error: tests/neg/doubleDefinition.scala:55:5 ----------------------------------------------------------
4343
55 | def foo(x: List[B]): Function1[B, B] = ??? // error: same jvm signature
4444
| ^
45-
| Double definition:
45+
| Conflicting definitions:
4646
| def foo(x: List[A]): A => A in trait Test6 at line 54 and
4747
| def foo(x: List[B]): B => B in trait Test6 at line 55
48-
| have the same type after erasure.
48+
| have the same type (x: List): Function1 after erasure.
4949
|
5050
| Consider adding a @targetName annotation to one of the conflicting definitions
5151
| for disambiguation.
5252
-- [E120] Naming Error: tests/neg/doubleDefinition.scala:62:5 ----------------------------------------------------------
5353
62 | def foo(x: List[A]): Function2[B, B, B] = ??? // error
5454
| ^
55-
| Double definition:
55+
| Conflicting definitions:
5656
| def foo(x: List[A]): A => A in trait Test7 at line 61 and
5757
| def foo(x: List[A]): (B, B) => B in trait Test7 at line 62
5858
| have matching parameter types.
5959
-- [E120] Naming Error: tests/neg/doubleDefinition.scala:67:5 ----------------------------------------------------------
6060
67 | def foo = 2 // error
6161
| ^
62-
| Double definition:
62+
| Conflicting definitions:
6363
| val foo: Int in class Test8 at line 66 and
6464
| def foo: Int in class Test8 at line 67
6565
-- [E120] Naming Error: tests/neg/doubleDefinition.scala:72:5 ----------------------------------------------------------
6666
72 | val foo = 1 // error
6767
| ^
68-
| Double definition:
68+
| Conflicting definitions:
6969
| def foo: Int in class Test8b at line 71 and
7070
| val foo: Int in class Test8b at line 72
7171
-- [E120] Naming Error: tests/neg/doubleDefinition.scala:77:5 ----------------------------------------------------------
7272
77 | var foo = 1 // error
7373
| ^
74-
| Double definition:
74+
| Conflicting definitions:
7575
| def foo: Int in class Test8c at line 76 and
7676
| var foo: Int in class Test8c at line 77
7777
-- [E120] Naming Error: tests/neg/doubleDefinition.scala:82:5 ----------------------------------------------------------
7878
82 | def foo = 2 // error
7979
| ^
80-
| Double definition:
80+
| Conflicting definitions:
8181
| var foo: Int in class Test8d at line 81 and
8282
| def foo: Int in class Test8d at line 82
8383
-- [E120] Naming Error: tests/neg/doubleDefinition.scala:88:5 ----------------------------------------------------------
8484
88 | def foo: String // error
8585
| ^
86-
| Double definition:
86+
| Conflicting definitions:
8787
| val foo: Int in class Test9 at line 87 and
8888
| def foo: String in class Test9 at line 88
8989
-- [E120] Naming Error: tests/neg/doubleDefinition.scala:92:5 ----------------------------------------------------------
9090
92 | def foo: Int // error
9191
| ^
92-
| Double definition:
92+
| Conflicting definitions:
9393
| val foo: Int in class Test10 at line 91 and
9494
| def foo: Int in class Test10 at line 92
9595
-- [E120] Naming Error: tests/neg/doubleDefinition.scala:96:5 ----------------------------------------------------------
9696
96 | def foo: String // error
9797
| ^
98-
| Double definition:
98+
| Conflicting definitions:
9999
| val foo: Int in class Test11 at line 95 and
100100
| def foo: String in class Test11 at line 96
101101
-- [E120] Naming Error: tests/neg/doubleDefinition.scala:100:5 ---------------------------------------------------------
102102
100 | def foo: Int // error
103103
| ^
104-
| Double definition:
104+
| Conflicting definitions:
105105
| val foo: Int in class Test12 at line 99 and
106106
| def foo: Int in class Test12 at line 100
107107
-- [E120] Naming Error: tests/neg/doubleDefinition.scala:104:5 ---------------------------------------------------------
108108
104 | def foo: String // error
109109
| ^
110-
| Double definition:
110+
| Conflicting definitions:
111111
| var foo: Int in class Test13 at line 103 and
112112
| def foo: String in class Test13 at line 104
113113
-- [E120] Naming Error: tests/neg/doubleDefinition.scala:108:5 ---------------------------------------------------------
114114
108 | def foo: Int // error
115115
| ^
116-
| Double definition:
116+
| Conflicting definitions:
117117
| var foo: Int in class Test14 at line 107 and
118118
| def foo: Int in class Test14 at line 108
119119
-- [E120] Naming Error: tests/neg/doubleDefinition.scala:112:5 ---------------------------------------------------------
120120
112 | def foo: String // error
121121
| ^
122-
| Double definition:
122+
| Conflicting definitions:
123123
| var foo: Int in class Test15 at line 111 and
124124
| def foo: String in class Test15 at line 112
125125
-- [E120] Naming Error: tests/neg/doubleDefinition.scala:116:5 ---------------------------------------------------------
126126
116 | def foo: Int // error
127127
| ^
128-
| Double definition:
128+
| Conflicting definitions:
129129
| var foo: Int in class Test16 at line 115 and
130130
| def foo: Int in class Test16 at line 116

tests/neg/exports.check

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,30 +15,30 @@
1515
-- [E120] Naming Error: tests/neg/exports.scala:23:33 ------------------------------------------------------------------
1616
23 | export printUnit.{stat => _, _} // error: double definition
1717
| ^
18-
| Double definition:
18+
| Conflicting definitions:
1919
| def status: List[String] in class Copier at line 28 and
2020
| final def status: List[String] in class Copier at line 23
21-
| have the same type after erasure.
21+
| have the same type (): List after erasure.
2222
|
2323
| Consider adding a @targetName annotation to one of the conflicting definitions
2424
| for disambiguation.
2525
-- [E120] Naming Error: tests/neg/exports.scala:24:20 ------------------------------------------------------------------
2626
24 | export scanUnit._ // error: double definition
2727
| ^
28-
| Double definition:
28+
| Conflicting definitions:
2929
| final def status: List[String] in class Copier at line 23 and
3030
| final def status: List[String] in class Copier at line 24
31-
| have the same type after erasure.
31+
| have the same type (): List after erasure.
3232
|
3333
| Consider adding a @targetName annotation to one of the conflicting definitions
3434
| for disambiguation.
3535
-- [E120] Naming Error: tests/neg/exports.scala:26:21 ------------------------------------------------------------------
3636
26 | export printUnit.status // error: double definition
3737
| ^
38-
| Double definition:
38+
| Conflicting definitions:
3939
| final def status: List[String] in class Copier at line 24 and
4040
| final def status: List[String] in class Copier at line 26
41-
| have the same type after erasure.
41+
| have the same type (): List after erasure.
4242
|
4343
| Consider adding a @targetName annotation to one of the conflicting definitions
4444
| for disambiguation.
@@ -55,7 +55,7 @@
5555
-- [E120] Naming Error: tests/neg/exports.scala:46:15 ------------------------------------------------------------------
5656
46 | export bar._ // error: double definition
5757
| ^
58-
| Double definition:
58+
| Conflicting definitions:
5959
| val bar: Bar in class Baz at line 45 and
6060
| final def bar: (Baz.this.bar.bar : => (Baz.this.bar.baz.bar : Bar)) in class Baz at line 46
6161
-- [E083] Type Error: tests/neg/exports.scala:57:11 --------------------------------------------------------------------

tests/neg/i14966a.check

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
-- [E120] Naming Error: tests/neg/i14966a.scala:3:6 --------------------------------------------------------------------
22
3 | def f(x: List[Int]): String = ??? // error
33
| ^
4-
| Double definition:
4+
| Conflicting definitions:
55
| def f[X <: String](x: List[X]): String in class Test at line 2 and
66
| def f(x: List[Int]): String in class Test at line 3
77
| have the same type (x: scala.collection.immutable.List): String after erasure.

tests/neg/i19809.check

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
-- [E120] Naming Error: tests/neg/i19809.scala:3:6 ---------------------------------------------------------------------
22
3 | def x_=(x: Int): Unit // error
33
| ^
4-
| Double definition:
4+
| Conflicting definitions:
55
| def x_=(x$1: Int): Unit in trait <refinement> at line 2 and
66
| def x_=(x: Int): Unit in trait <refinement> at line 3
7-
| have the same type after erasure.
7+
| have the same type (x: Int): Unit after erasure.
88
|
99
| Consider adding a @targetName annotation to one of the conflicting definitions
1010
| for disambiguation.

tests/neg/i23402.check

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
-- [E120] Naming Error: tests/neg/i23402.scala:4:5 ---------------------------------------------------------------------
2+
4 | def apply(p1: String)(p2: Int): A = A(p1, p2) // error
3+
| ^
4+
| Conflicting definitions:
5+
| def apply(p1: String, p2: Int): A in object A at line 3 and
6+
| def apply(p1: String)(p2: Int): A in object A at line 4
7+
| have the same type (p1: String, p2: Int): A after erasure.
8+
|
9+
| Consider adding a @targetName annotation to one of the conflicting definitions
10+
| for disambiguation.

tests/neg/i23402.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
class A(p1: String, p2: Int)
2+
object A {
3+
def apply(p1: String, p2: Int): A = A(p1, p2)
4+
def apply(p1: String)(p2: Int): A = A(p1, p2) // error
5+
}

tests/neg/i23402b.check

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
-- [E120] Naming Error: tests/neg/i23402b.scala:4:5 --------------------------------------------------------------------
2+
4 | def apply[T](p1: String)(p2: Int): A = A(p1, p2) // error
3+
| ^
4+
| Conflicting definitions:
5+
| def apply[T](p1: String, p2: Int): A in object A at line 3 and
6+
| def apply[T](p1: String)(p2: Int): A in object A at line 4
7+
| have the same type (p1: String, p2: Int): A after erasure.
8+
|
9+
| Consider adding a @targetName annotation to one of the conflicting definitions
10+
| for disambiguation.

tests/neg/i23402b.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
class A(p1: String, p2: Int)
2+
object A {
3+
def apply[T](p1: String, p2: Int): A = A(p1, p2)
4+
def apply[T](p1: String)(p2: Int): A = A(p1, p2) // error
5+
}

tests/neg/i23402c.check

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
-- [E120] Naming Error: tests/neg/i23402c.scala:4:5 --------------------------------------------------------------------
2+
4 | def apply[T](p1: String)(p2: Int): A = A(p1, p2) // error
3+
| ^
4+
| Conflicting definitions:
5+
| def apply(p1: String, p2: Int): A in object A at line 3 and
6+
| def apply[T](p1: String)(p2: Int): A in object A at line 4
7+
| have the same type (p1: String, p2: Int): A after erasure.
8+
|
9+
| Consider adding a @targetName annotation to one of the conflicting definitions
10+
| for disambiguation.

tests/neg/i23402c.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
class A(p1: String, p2: Int)
2+
object A {
3+
def apply(p1: String, p2: Int): A = A(p1, p2)
4+
def apply[T](p1: String)(p2: Int): A = A(p1, p2) // error
5+
}

tests/neg/i7359-f.check

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
| Name clash between inherited members:
55
| def equals[T >: Boolean <: Boolean](obj: Any): T in trait SAMTrait at line 3 and
66
| def equals(x$0: Any): Boolean in class Any
7-
| have the same type after erasure.
7+
| have the same type (x$0: Object): Boolean after erasure.
88
|
99
| Consider adding a @targetName annotation to one of the conflicting definitions
1010
| for disambiguation.

tests/neg/into-override.check

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
| Name clash between defined and inherited member:
55
| def f(x: X): Unit in trait A at line 11 and
66
| override def f(x: Conversion.into[X]): Unit in trait C at line 17
7-
| have the same type after erasure.
7+
| have the same type (x: Object): Unit after erasure.
88
|
99
| Consider adding a @targetName annotation to one of the conflicting definitions
1010
| for disambiguation.
@@ -14,7 +14,7 @@
1414
| Name clash between inherited members:
1515
| override def f(x: X): Unit in trait B at line 14 and
1616
| override def f(x: Conversion.into[X]): Unit in trait C at line 17
17-
| have the same type after erasure.
17+
| have the same type (x: Object): Unit after erasure.
1818
|
1919
| Consider adding a @targetName annotation to one of the conflicting definitions
2020
| for disambiguation.
@@ -24,7 +24,7 @@
2424
| Name clash between defined and inherited member:
2525
| override def f(x: Conversion.into[X]): Unit in trait C at line 17 and
2626
| override def f(x: X): Unit in trait E at line 22
27-
| have the same type after erasure.
27+
| have the same type (x: Object): Unit after erasure.
2828
|
2929
| Consider adding a @targetName annotation to one of the conflicting definitions
3030
| for disambiguation.

tests/neg/mixin-forwarder-clash1.check

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
| Name clash between inherited members:
55
| def concat(suffix: Int): X in trait One at line 4 and
66
| def concat[Dummy](suffix: Int): Y in trait Two at line 8
7-
| have the same type after erasure.
7+
| have the same type (suffix: Int): Object after erasure.
88
|
99
| Consider adding a @targetName annotation to one of the conflicting definitions
1010
| for disambiguation.

tests/neg/mixin-forwarder-clash2.check

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
| Name clash between inherited members:
66
| def concat(suffix: Int): X in trait One at line 4 and
77
| def concat[Dummy](suffix: Int): Y in trait Two at line 8
8-
| have the same type after erasure.
8+
| have the same type (suffix: Int): Object after erasure.
99
|
1010
| Consider adding a @targetName annotation to one of the conflicting definitions
1111
| for disambiguation.

tests/neg/override-erasure-clash.check

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@
44
| Name clash between defined and inherited member:
55
| def f(): Int in class A at line 3 and
66
| def g(): Int in class B at line 5
7-
| have the same name and type after erasure.
7+
| have the same name and type (): Int after erasure.

tests/neg/type-params.check

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,10 @@
5252
-- [E120] Naming Error: tests/neg/type-params.scala:44:6 ---------------------------------------------------------------
5353
44 | def a = (p: A) => () // error
5454
| ^
55-
| Double definition:
55+
| Conflicting definitions:
5656
| def a: () => Unit in trait t278 at line 43 and
5757
| def a: t278.this.A => Unit in trait t278 at line 44
58-
| have the same type after erasure.
58+
| have the same type (): Function1 after erasure.
5959
|
6060
| Consider adding a @targetName annotation to one of the conflicting definitions
6161
| for disambiguation.

0 commit comments

Comments
 (0)