Skip to content

Commit 43612f9

Browse files
authored
Merge pull request #2012 from ennru/ennru_CantInstantiateAbstract
Change 'is abstract; cannot be instantiated' to Message
2 parents a0c2e55 + 3c2b09f commit 43612f9

File tree

4 files changed

+63
-2
lines changed

4 files changed

+63
-2
lines changed

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,9 @@ public enum ErrorMessageID {
4949
OverridesNothingButNameExistsID,
5050
ForwardReferenceExtendsOverDefinitionID,
5151
ExpectedTokenButFoundID,
52-
MixedLeftAndRightAssociativeOpsID;
52+
MixedLeftAndRightAssociativeOpsID,
53+
CantInstantiateAbstractClassOrTraitID,
54+
;
5355

5456
public int errorNumber() {
5557
return ordinal() - 2;

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

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1127,4 +1127,23 @@ object messages {
11271127
|""".stripMargin
11281128
}
11291129

1130+
case class CantInstantiateAbstractClassOrTrait(cls: Symbol, isTrait: Boolean)(implicit ctx: Context)
1131+
extends Message(CantInstantiateAbstractClassOrTraitID) {
1132+
val kind = "Usage"
1133+
private val traitOrAbstract = if (isTrait) hl"a trait" else hl"abstract"
1134+
val msg = hl"""${cls.name} is ${traitOrAbstract}; it cannot be instantiated"""
1135+
val explanation =
1136+
hl"""|Abstract classes and traits need to be extended by a concrete class or object
1137+
|to make their functionality accessible.
1138+
|
1139+
|You may want to create an anonymous class extending ${cls.name} with
1140+
| ${s"class ${cls.name} { }"}
1141+
|
1142+
|or add a companion object with
1143+
| ${s"object ${cls.name} extends ${cls.name}"}
1144+
|
1145+
|You need to implement any abstract members in both cases.
1146+
|""".stripMargin
1147+
}
1148+
11301149
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import ErrorReporting.{err, errorType}
2929
import config.Printers.typr
3030
import collection.mutable
3131
import SymDenotations.NoCompleter
32+
import dotty.tools.dotc.reporting.diagnostic.messages.CantInstantiateAbstractClassOrTrait
3233
import dotty.tools.dotc.transform.ValueClasses._
3334

3435
object Checking {
@@ -103,7 +104,7 @@ object Checking {
103104
case tref: TypeRef =>
104105
val cls = tref.symbol
105106
if (cls.is(AbstractOrTrait))
106-
ctx.error(em"$cls is abstract; cannot be instantiated", pos)
107+
ctx.error(CantInstantiateAbstractClassOrTrait(cls, isTrait = cls.is(Trait)), pos)
107108
if (!cls.is(Module)) {
108109
// Create a synthetic singleton type instance, and check whether
109110
// it conforms to the self type of the class as seen from that instance.

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

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,4 +159,43 @@ class ErrorMessagesTests extends ErrorMessagesTest {
159159
assertEquals("+:", op2.show)
160160
assertFalse(op2LeftAssoc)
161161
}
162+
163+
@Test def cantInstantiateAbstract =
164+
checkMessagesAfter("refchecks") {
165+
"""
166+
|object Scope {
167+
| abstract class Concept
168+
| new Concept()
169+
|}
170+
""".stripMargin
171+
}
172+
.expect { (ictx, messages) =>
173+
implicit val ctx: Context = ictx
174+
val defn = ictx.definitions
175+
176+
assertMessageCount(1, messages)
177+
val CantInstantiateAbstractClassOrTrait(cls, isTrait) :: Nil = messages
178+
assertEquals("Concept", cls.name.show)
179+
assertFalse("expected class", isTrait)
180+
}
181+
182+
@Test def cantInstantiateTrait =
183+
checkMessagesAfter("refchecks") {
184+
"""
185+
|object Scope {
186+
| trait Concept
187+
| new Concept()
188+
|}
189+
""".stripMargin
190+
}
191+
.expect { (ictx, messages) =>
192+
implicit val ctx: Context = ictx
193+
val defn = ictx.definitions
194+
195+
assertMessageCount(1, messages)
196+
val CantInstantiateAbstractClassOrTrait(cls, isTrait) :: Nil = messages
197+
assertEquals("Concept", cls.name.show)
198+
assertTrue("expected trait", isTrait)
199+
}
200+
162201
}

0 commit comments

Comments
 (0)