Skip to content

Commit f728134

Browse files
Merge pull request #3465 from maseev/iss1589-trait-is-expected
Add an error message class for a case where a trait is expected
2 parents 8b78497 + 2036126 commit f728134

File tree

4 files changed

+52
-2
lines changed

4 files changed

+52
-2
lines changed

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,8 @@ public enum ErrorMessageID {
110110
MissingEmptyArgumentListID,
111111
DuplicateNamedTypeParameterID,
112112
UndefinedNamedTypeParameterID,
113-
IllegalStartOfStatementID
113+
IllegalStartOfStatementID,
114+
TraitIsExpectedID,
114115
;
115116

116117
public int errorNumber() {

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

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1888,4 +1888,32 @@ object messages {
18881888
}
18891889
val explanation = "A statement is either an import, a definition or an expression."
18901890
}
1891+
1892+
case class TraitIsExpected(symbol: Symbol)(implicit ctx: Context) extends Message(TraitIsExpectedID) {
1893+
val kind = "Syntax"
1894+
val msg = hl"$symbol is not a trait"
1895+
val explanation = {
1896+
val errorCodeExample =
1897+
"""class A
1898+
|class B
1899+
|
1900+
|val a = new A with B // will fail with a compile error - class B is not a trait""".stripMargin
1901+
val codeExample =
1902+
"""class A
1903+
|trait B
1904+
|
1905+
|val a = new A with B // compiles normally""".stripMargin
1906+
1907+
hl"""Only traits can be mixed into classes using a ${"with"} keyword.
1908+
|Consider the following example:
1909+
|
1910+
|$errorCodeExample
1911+
|
1912+
|The example mentioned above would fail because B is not a trait.
1913+
|But if you make B a trait it will be compiled without any errors:
1914+
|
1915+
|$codeExample
1916+
|"""
1917+
}
1918+
}
18911919
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -548,7 +548,7 @@ trait Checking {
548548
def checkClassType(tp: Type, pos: Position, traitReq: Boolean, stablePrefixReq: Boolean)(implicit ctx: Context): Type =
549549
tp.underlyingClassRef(refinementOK = false) match {
550550
case tref: TypeRef =>
551-
if (traitReq && !(tref.symbol is Trait)) ctx.error(ex"$tref is not a trait", pos)
551+
if (traitReq && !(tref.symbol is Trait)) ctx.error(TraitIsExpected(tref.symbol), pos)
552552
if (stablePrefixReq && ctx.phase <= ctx.refchecksPhase) checkStable(tref.prefix, pos)
553553
tp
554554
case _ =>

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

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1151,4 +1151,25 @@ class ErrorMessagesTests extends ErrorMessagesTest {
11511151
assertEquals(IllegalStartOfStatement(isModifier = false), err)
11521152
assertEquals(IllegalStartOfStatement(isModifier = true), errWithModifier)
11531153
}
1154+
1155+
@Test def traitIsExpected =
1156+
checkMessagesAfter("frontend") {
1157+
"""
1158+
|class A
1159+
|class B
1160+
|
1161+
|object Test {
1162+
| def main(args: Array[String]): Unit = {
1163+
| val a = new A with B
1164+
| }
1165+
|}
1166+
""".stripMargin
1167+
}
1168+
.expect { (ictx, messages) =>
1169+
implicit val ctx: Context = ictx
1170+
1171+
assertMessageCount(1, messages)
1172+
val TraitIsExpected(symbol) :: Nil = messages
1173+
assertEquals("class B", symbol.show)
1174+
}
11541175
}

0 commit comments

Comments
 (0)