Skip to content

Commit d204179

Browse files
authored
Merge pull request #2484 from ennru/ennru_MoveToErrorCaseClassesFriday
Move to error case classes (Friday)
2 parents 730e50b + 74eb841 commit d204179

File tree

6 files changed

+375
-27
lines changed

6 files changed

+375
-27
lines changed

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,20 @@ public enum ErrorMessageID {
6363
TypeDoesNotTakeParametersID,
6464
ParameterizedTypeLacksArgumentsID,
6565
VarValParametersMayNotBeCallByNameID,
66+
MissingTypeParameterForID,
67+
DoesNotConformToBoundID,
68+
DoesNotConformToSelfTypeID,
69+
DoesNotConformToSelfTypeCantBeInstantiatedID,
70+
AbstractMemberMayNotHaveModifierID,
71+
TopLevelCantBeImplicitID,
72+
TypesAndTraitsCantBeImplicitID,
73+
OnlyClassesCanBeAbstractID,
74+
AbstractOverrideOnlyInTraitsID,
75+
TraitsMayNotBeFinalID,
76+
NativeMembersMayNotHaveImplementationID,
77+
OnlyClassesCanHaveDeclaredButUndefinedMembersID,
78+
CannotExtendAnyValID,
79+
CannotHaveSameNameAsID,
6680
;
6781

6882
public int errorNumber() {

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

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import printing.Formatting
2020
import ErrorMessageID._
2121
import Denotations.SingleDenotation
2222
import dotty.tools.dotc.ast.Trees
23+
import dotty.tools.dotc.core.Flags.{FlagSet, Mutable}
2324
import dotty.tools.dotc.core.SymDenotations.SymDenotation
2425

2526
object messages {
@@ -1351,4 +1352,133 @@ object messages {
13511352
| ${"}"}
13521353
|"""
13531354
}
1355+
1356+
case class MissingTypeParameterFor(tpe: Type)(implicit ctx: Context)
1357+
extends Message(MissingTypeParameterForID) {
1358+
val msg = hl"missing type parameter for ${tpe}"
1359+
val kind = "Syntax"
1360+
val explanation = ""
1361+
}
1362+
1363+
case class DoesNotConformToBound(tpe: Type, which: String, bound: Type)(
1364+
err: typer.ErrorReporting.Errors)(implicit ctx: Context)
1365+
extends Message(DoesNotConformToBoundID) {
1366+
val msg = hl"Type argument ${tpe} does not conform to $which bound $bound ${err.whyNoMatchStr(tpe, bound)}"
1367+
val kind = "Type Mismatch"
1368+
val explanation = ""
1369+
}
1370+
1371+
case class DoesNotConformToSelfType(category: String, selfType: Type, cls: Symbol,
1372+
otherSelf: Type, relation: String, other: Symbol)(
1373+
implicit ctx: Context)
1374+
extends Message(DoesNotConformToSelfTypeID) {
1375+
val msg = hl"""$category: self type $selfType of $cls does not conform to self type $otherSelf
1376+
|of $relation $other"""
1377+
val kind = "Type Mismatch"
1378+
val explanation =
1379+
hl"""You mixed in $other which requires self type $otherSelf, but $cls has self type
1380+
|$selfType and does not inherit from $otherSelf.
1381+
|
1382+
|Note: Self types are indicated with the notation
1383+
| ${s"class "}$other ${"{ this: "}$otherSelf${" => "}
1384+
"""
1385+
}
1386+
1387+
case class DoesNotConformToSelfTypeCantBeInstantiated(tp: Type, selfType: Type)(
1388+
implicit ctx: Context)
1389+
extends Message(DoesNotConformToSelfTypeCantBeInstantiatedID) {
1390+
val msg = hl"""$tp does not conform to its self type $selfType; cannot be instantiated"""
1391+
val kind = "Type Mismatch"
1392+
val explanation =
1393+
hl"""To create an instance of $tp it needs to inherit $selfType in some way.
1394+
|
1395+
|Note: Self types are indicated with the notation
1396+
| ${s"class "}$tp ${"{ this: "}$selfType${" => "}
1397+
|"""
1398+
}
1399+
1400+
case class AbstractMemberMayNotHaveModifier(sym: Symbol, flag: FlagSet)(
1401+
implicit ctx: Context)
1402+
extends Message(AbstractMemberMayNotHaveModifierID) {
1403+
val msg = hl"""${"abstract"} $sym may not have `$flag' modifier"""
1404+
val kind = "Syntax"
1405+
val explanation = ""
1406+
}
1407+
1408+
case class TopLevelCantBeImplicit(sym: Symbol)(
1409+
implicit ctx: Context)
1410+
extends Message(TopLevelCantBeImplicitID) {
1411+
val msg = hl"""${"implicit"} modifier cannot be used for top-level definitions"""
1412+
val kind = "Syntax"
1413+
val explanation = ""
1414+
}
1415+
1416+
case class TypesAndTraitsCantBeImplicit(sym: Symbol)(
1417+
implicit ctx: Context)
1418+
extends Message(TypesAndTraitsCantBeImplicitID) {
1419+
val msg = hl"""${"implicit"} modifier cannot be used for types or traits"""
1420+
val kind = "Syntax"
1421+
val explanation = ""
1422+
}
1423+
1424+
case class OnlyClassesCanBeAbstract(sym: Symbol)(
1425+
implicit ctx: Context)
1426+
extends Message(OnlyClassesCanBeAbstractID) {
1427+
val msg = hl"""${"abstract"} modifier can be used only for classes; it should be omitted for abstract members"""
1428+
val kind = "Syntax"
1429+
val explanation = ""
1430+
}
1431+
1432+
case class AbstractOverrideOnlyInTraits(sym: Symbol)(
1433+
implicit ctx: Context)
1434+
extends Message(AbstractOverrideOnlyInTraitsID) {
1435+
val msg = hl"""${"abstract override"} modifier only allowed for members of traits"""
1436+
val kind = "Syntax"
1437+
val explanation = ""
1438+
}
1439+
1440+
case class TraitsMayNotBeFinal(sym: Symbol)(
1441+
implicit ctx: Context)
1442+
extends Message(TraitsMayNotBeFinalID) {
1443+
val msg = hl"""$sym may not be ${"final"}"""
1444+
val kind = "Syntax"
1445+
val explanation =
1446+
"A trait can never be final since it is abstract and must be extended to be useful."
1447+
}
1448+
1449+
case class NativeMembersMayNotHaveImplementation(sym: Symbol)(
1450+
implicit ctx: Context)
1451+
extends Message(NativeMembersMayNotHaveImplementationID) {
1452+
val msg = hl"""${"@native"} members may not have an implementation"""
1453+
val kind = "Syntax"
1454+
val explanation = ""
1455+
}
1456+
1457+
case class OnlyClassesCanHaveDeclaredButUndefinedMembers(sym: Symbol)(
1458+
implicit ctx: Context)
1459+
extends Message(OnlyClassesCanHaveDeclaredButUndefinedMembersID) {
1460+
1461+
private val varNote =
1462+
if (sym.is(Mutable)) "Note that variables need to be initialized to be defined."
1463+
else ""
1464+
val msg = hl"""only classes can have declared but undefined members"""
1465+
val kind = "Syntax"
1466+
val explanation = s"$varNote"
1467+
}
1468+
1469+
case class CannotExtendAnyVal(sym: Symbol)(implicit ctx: Context)
1470+
extends Message(CannotExtendAnyValID) {
1471+
val msg = hl"""$sym cannot extend ${"AnyVal"}"""
1472+
val kind = "Syntax"
1473+
val explanation = ""
1474+
}
1475+
1476+
case class CannotHaveSameNameAs(sym: Symbol, cls: Symbol)(implicit ctx: Context)
1477+
extends Message(CannotHaveSameNameAsID) {
1478+
val msg = hl"""$sym cannot have the same name as ${cls.showLocated} -- class definitions cannot be overridden"""
1479+
val kind = "Syntax"
1480+
val explanation = ""
1481+
}
1482+
1483+
13541484
}

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

Lines changed: 22 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,21 @@ import Constants._
1818
import Scopes._
1919
import CheckRealizable._
2020
import ErrorReporting.errorTree
21+
2122
import annotation.unchecked
2223
import util.Positions._
23-
import util.{Stats, SimpleMap}
24+
import util.{SimpleMap, Stats}
2425
import util.common._
2526
import transform.SymUtils._
2627
import Decorators._
2728
import Uniques._
2829
import ErrorReporting.{err, errorType}
2930
import config.Printers.typr
31+
3032
import collection.mutable
3133
import SymDenotations.NoCompleter
32-
import dotty.tools.dotc.reporting.diagnostic.messages.CantInstantiateAbstractClassOrTrait
34+
import dotty.tools.dotc.reporting.diagnostic.{ErrorMessageID, Message}
35+
import dotty.tools.dotc.reporting.diagnostic.messages._
3336
import dotty.tools.dotc.transform.ValueClasses._
3437

3538
object Checking {
@@ -42,11 +45,12 @@ object Checking {
4245
def checkBounds(args: List[tpd.Tree], boundss: List[TypeBounds], instantiate: (Type, List[Type]) => Type)(implicit ctx: Context): Unit = {
4346
(args, boundss).zipped.foreach { (arg, bound) =>
4447
if (!bound.isHK && arg.tpe.isHK)
48+
// see MissingTypeParameterFor
4549
ctx.error(ex"missing type parameter(s) for $arg", arg.pos)
4650
}
4751
for ((arg, which, bound) <- ctx.boundsViolations(args, boundss, instantiate))
4852
ctx.error(
49-
ex"Type argument ${arg.tpe} does not conform to $which bound $bound ${err.whyNoMatchStr(arg.tpe, bound)}",
53+
DoesNotConformToBound(arg.tpe, which, bound)(err),
5054
arg.pos.focus)
5155
}
5256

@@ -111,18 +115,16 @@ object Checking {
111115
val stp = SkolemType(tp)
112116
val selfType = tref.givenSelfType.asSeenFrom(stp, cls)
113117
if (selfType.exists && !(stp <:< selfType))
114-
ctx.error(ex"$tp does not conform to its self type $selfType; cannot be instantiated")
118+
ctx.error(DoesNotConformToSelfTypeCantBeInstantiated(tp, selfType), pos)
115119
}
116120
case _ =>
117121
}
118122

119123
/** Check that type `tp` is realizable. */
120124
def checkRealizable(tp: Type, pos: Position)(implicit ctx: Context): Unit = {
121125
val rstatus = realizability(tp)
122-
if (rstatus ne Realizable) {
123-
def msg = em"$tp is not a legal path\n since it${rstatus.msg}"
124-
if (ctx.scala2Mode) ctx.migrationWarning(msg, pos) else ctx.error(msg, pos)
125-
}
126+
if (rstatus ne Realizable)
127+
ctx.errorOrMigrationWarning(em"$tp is not a legal path\n since it${rstatus.msg}", pos)
126128
}
127129

128130
/** A type map which checks that the only cycles in a type are F-bounds
@@ -304,50 +306,46 @@ object Checking {
304306

305307
/** Check that symbol's definition is well-formed. */
306308
def checkWellFormed(sym: Symbol)(implicit ctx: Context): Unit = {
307-
//println(i"check wf $sym with flags ${sym.flags}")
308-
def fail(msg: String) = ctx.error(msg, sym.pos)
309-
def varNote =
310-
if (sym.is(Mutable)) "\n(Note that variables need to be initialized to be defined)"
311-
else ""
309+
def fail(msg: Message) = ctx.error(msg, sym.pos)
312310

313311
def checkWithDeferred(flag: FlagSet) =
314312
if (sym.is(flag))
315-
fail(i"abstract member may not have `$flag' modifier")
313+
fail(AbstractMemberMayNotHaveModifier(sym, flag))
316314
def checkNoConflict(flag1: FlagSet, flag2: FlagSet) =
317315
if (sym.is(allOf(flag1, flag2)))
318316
fail(i"illegal combination of modifiers: $flag1 and $flag2 for: $sym")
319317

320318
if (sym.is(ImplicitCommon)) {
321319
if (sym.owner.is(Package))
322-
fail(i"`implicit' modifier cannot be used for top-level definitions")
320+
fail(TopLevelCantBeImplicit(sym))
323321
if (sym.isType)
324-
fail(i"`implicit' modifier cannot be used for types or traits")
322+
fail(TypesAndTraitsCantBeImplicit(sym))
325323
}
326324
if (!sym.isClass && sym.is(Abstract))
327-
fail(i"`abstract' modifier can be used only for classes; it should be omitted for abstract members")
325+
fail(OnlyClassesCanBeAbstract(sym))
328326
if (sym.is(AbsOverride) && !sym.owner.is(Trait))
329-
fail(i"`abstract override' modifier only allowed for members of traits")
327+
fail(AbstractOverrideOnlyInTraits(sym))
330328
if (sym.is(Trait) && sym.is(Final))
331-
fail(i"$sym may not be `final'")
329+
fail(TraitsMayNotBeFinal(sym))
332330
if (sym.hasAnnotation(defn.NativeAnnot)) {
333331
if (!sym.is(Deferred))
334-
fail(i"`@native' members may not have implementation")
332+
fail(NativeMembersMayNotHaveImplementation(sym))
335333
}
336334
else if (sym.is(Deferred, butNot = Param) && !sym.isType && !sym.isSelfSym) {
337335
if (!sym.owner.isClass || sym.owner.is(Module) || sym.owner.isAnonymousClass)
338-
fail(i"only classes can have declared but undefined members$varNote")
336+
fail(OnlyClassesCanHaveDeclaredButUndefinedMembers(sym))
339337
checkWithDeferred(Private)
340338
checkWithDeferred(Final)
341339
checkWithDeferred(Inline)
342340
}
343341
if (sym.isValueClass && sym.is(Trait) && !sym.isRefinementClass)
344-
fail(i"$sym cannot extend AnyVal")
342+
fail(CannotExtendAnyVal(sym))
345343
checkNoConflict(Final, Sealed)
346344
checkNoConflict(Private, Protected)
347345
checkNoConflict(Abstract, Override)
348346
if (sym.isType && !sym.is(Deferred))
349347
for (cls <- sym.allOverriddenSymbols.filter(_.isClass)) {
350-
fail(i"$sym cannot have the same name as ${cls.showLocated} -- class definitions cannot be overridden")
348+
fail(CannotHaveSameNameAs(sym, cls))
351349
sym.setFlag(Private) // break the overriding relationship by making sym Private
352350
}
353351
}
@@ -610,7 +608,7 @@ trait Checking {
610608
if (tpt.tpe.isHK && !ctx.compilationUnit.isJava) {
611609
// be more lenient with missing type params in Java,
612610
// needed to make pos/java-interop/t1196 work.
613-
errorTree(tpt, ex"missing type parameter for ${tpt.tpe}")
611+
errorTree(tpt, MissingTypeParameterFor(tpt.tpe))
614612
}
615613
else tpt
616614

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,8 @@ object RefChecks {
9797
def checkSelfConforms(other: TypeRef, category: String, relation: String) = {
9898
val otherSelf = other.givenSelfType.asSeenFrom(cls.thisType, other.classSymbol)
9999
if (otherSelf.exists && !(cinfo.selfType <:< otherSelf))
100-
ctx.error(ex"$category: self type ${cinfo.selfType} of $cls does not conform to self type $otherSelf of $relation ${other.classSymbol}", cls.pos)
100+
ctx.error(DoesNotConformToSelfType(category, cinfo.selfType, cls, otherSelf, relation, other.classSymbol),
101+
cls.pos)
101102
}
102103
for (parent <- cinfo.classParents)
103104
checkSelfConforms(parent, "illegal inheritance", "parent")

0 commit comments

Comments
 (0)