Skip to content

Commit 0438e48

Browse files
rsoeldnerallanrenucci
authored andcommitted
Add error message for companion and class/module name clash (#3361)
1 parent 4dc4bd6 commit 0438e48

File tree

4 files changed

+40
-5
lines changed

4 files changed

+40
-5
lines changed

compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ public enum ErrorMessageID {
103103
ExtendFinalClassID,
104104
EnumCaseDefinitionInNonEnumOwnerID,
105105
ExpectedTypeBoundOrEqualsID,
106+
ClassAndCompanionNameClashID,
106107
;
107108

108109
public int errorNumber() {

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1804,4 +1804,17 @@ object messages {
18041804
|refers to a subtype of type ${"A"}.
18051805
|"""
18061806
}
1807+
1808+
case class ClassAndCompanionNameClash(cls: Symbol, other: Symbol)(implicit ctx: Context)
1809+
extends Message(ClassAndCompanionNameClashID) {
1810+
val kind = "Naming"
1811+
val msg = hl"Name clash: both ${cls.owner} and its companion object defines ${cls.name}"
1812+
val explanation = {
1813+
val kind = if (cls.owner.is(Flags.Trait)) "trait" else "class"
1814+
1815+
hl"""|A $kind and its companion object cannot both define a ${"class"}, ${"trait"} or ${"object"} with the same name:
1816+
| - ${cls.owner} defines ${cls}
1817+
| - ${other.owner} defines ${other}"""
1818+
}
1819+
}
18071820
}

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

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -113,11 +113,9 @@ object RefChecks {
113113
*/
114114
private def checkCompanionNameClashes(cls: Symbol)(implicit ctx: Context): Unit =
115115
if (!(cls.owner is ModuleClass)) {
116-
val other = cls.owner.linkedClass.info.decl(cls.name)
117-
if (other.symbol.isClass)
118-
ctx.error(s"name clash: ${cls.owner} defines $cls" + "\n" +
119-
s"and its companion ${cls.owner.companionModule} also defines $other",
120-
cls.pos)
116+
val other = cls.owner.linkedClass.info.decl(cls.name).symbol
117+
if (other.isClass)
118+
ctx.error(ClassAndCompanionNameClash(cls, other), cls.pos)
121119
}
122120

123121
// Override checking ------------------------------------------------------------

compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1038,4 +1038,27 @@ class ErrorMessagesTests extends ErrorMessagesTest {
10381038
val ExpectedTypeBoundOrEquals(found) :: Nil = messages
10391039
assertEquals(Tokens.IDENTIFIER, found)
10401040
}
1041+
1042+
@Test def classAndCompanionNameClash =
1043+
checkMessagesAfter("refchecks") {
1044+
"""
1045+
|class T {
1046+
| class G
1047+
|}
1048+
|object T {
1049+
| trait G
1050+
|}
1051+
""".stripMargin
1052+
}.expect { (ictx, messages) =>
1053+
implicit val ctx: Context = ictx
1054+
1055+
assertMessageCount(1, messages)
1056+
val ClassAndCompanionNameClash(cls, other) :: Nil = messages
1057+
1058+
assertEquals("class T", cls.owner.show)
1059+
assertEquals("class G", cls.show)
1060+
assertEquals("object T", other.owner.show)
1061+
assertEquals("trait G", other.show)
1062+
1063+
}
10411064
}

0 commit comments

Comments
 (0)