Skip to content

Commit 76caf35

Browse files
Merge pull request #8263 from ausmarton/ticket/1589
Port remaining Desugar and Applications errors to the new scheme
2 parents e8fa408 + 6caa732 commit 76caf35

25 files changed

+423
-34
lines changed

compiler/src/dotty/tools/dotc/ast/Desugar.scala

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -558,7 +558,7 @@ object desugar {
558558
else if (originalTparams.isEmpty)
559559
appliedRef(enumClassRef)
560560
else {
561-
ctx.error(i"explicit extends clause needed because both enum case and enum class have type parameters"
561+
ctx.error(TypedCaseDoesNotExplicitlyExtendTypedEnum(enumClass, cdef)
562562
, cdef.sourcePos.startPos)
563563
appliedTypeTree(enumClassRef, constrTparams map (_ => anyRef))
564564
}
@@ -930,22 +930,27 @@ object desugar {
930930

931931
def makeExtensionDef(mdef: Tree, tparams: List[TypeDef], leadingParams: List[ValDef],
932932
givenParamss: List[List[ValDef]])(using ctx: Context): Tree = {
933-
val allowed = "allowed here, since collective parameters are given"
934933
mdef match {
935934
case mdef: DefDef =>
936935
if (mdef.mods.is(Extension)) {
937-
ctx.error(em"No extension method $allowed", mdef.sourcePos)
936+
ctx.error(NoExtensionMethodAllowed(mdef), mdef.sourcePos)
938937
mdef
938+
} else {
939+
if (tparams.nonEmpty && mdef.tparams.nonEmpty) then
940+
ctx.error(ExtensionMethodCannotHaveTypeParams(mdef), mdef.tparams.head.sourcePos)
941+
mdef
942+
else cpy.DefDef(mdef)(
943+
tparams = tparams ++ mdef.tparams,
944+
vparamss = leadingParams :: givenParamss ::: mdef.vparamss
945+
).withMods(mdef.mods | Extension)
939946
}
940-
else cpy.DefDef(mdef)(
941-
tparams = tparams ++ mdef.tparams,
942-
vparamss = leadingParams :: givenParamss ::: mdef.vparamss
943-
).withMods(mdef.mods | Extension)
944947
case mdef: Import =>
945948
mdef
946-
case mdef =>
947-
ctx.error(em"Only methods $allowed", mdef.sourcePos)
949+
case mdef if !mdef.isEmpty => {
950+
ctx.error(ExtensionCanOnlyHaveDefs(mdef), mdef.sourcePos)
948951
mdef
952+
}
953+
case mdef => mdef
949954
}
950955
}
951956

@@ -979,7 +984,7 @@ object desugar {
979984
if (name.isEmpty) name = name.likeSpaced(inventGivenOrExtensionName(impl))
980985
if (ctx.owner == defn.ScalaPackageClass && defn.reservedScalaClassNames.contains(name.toTypeName)) {
981986
def kind = if (name.isTypeName) "class" else "object"
982-
ctx.error(em"illegal redefinition of standard $kind $name", mdef.sourcePos)
987+
ctx.error(IllegalRedefinitionOfStandardKind(kind, name), mdef.sourcePos)
983988
name = name.errorName
984989
}
985990
name
@@ -998,7 +1003,7 @@ object desugar {
9981003
case Some(DefDef(name, _, (vparam :: _) :: _, _, _)) =>
9991004
s"extension_${name}_${inventTypeName(vparam.tpt)}"
10001005
case _ =>
1001-
ctx.error(i"anonymous instance must implement a type or have at least one extension method", impl.sourcePos)
1006+
ctx.error(AnonymousInstanceCannotBeEmpty(impl), impl.sourcePos)
10021007
nme.ERROR.toString
10031008
else
10041009
impl.parents.map(inventTypeName(_)).mkString("given_", "_", "")
@@ -1170,10 +1175,9 @@ object desugar {
11701175
def checkModifiers(tree: Tree)(implicit ctx: Context): Tree = tree match {
11711176
case tree: MemberDef =>
11721177
var tested: MemberDef = tree
1173-
def fail(msg: String) = ctx.error(msg, tree.sourcePos)
11741178
def checkApplicable(flag: Flag, test: MemberDefTest): Unit =
11751179
if (tested.mods.is(flag) && !test.applyOrElse(tree, (md: MemberDef) => false)) {
1176-
fail(i"modifier `${flag.flagsString}` is not allowed for this definition")
1180+
ctx.error(ModifierNotAllowedForDefinition(flag), tree.sourcePos)
11771181
tested = tested.withMods(tested.mods.withoutFlags(flag))
11781182
}
11791183
checkApplicable(Opaque, legalOpaque)
@@ -1795,7 +1799,7 @@ object desugar {
17951799
def traverse(tree: untpd.Tree)(implicit ctx: Context): Unit = tree match {
17961800
case Splice(expr) => collect(expr)
17971801
case TypSplice(expr) =>
1798-
ctx.error("Type splices cannot be used in val patterns. Consider using `match` instead.", tree.sourcePos)
1802+
ctx.error(TypeSpliceInValPattern(expr), tree.sourcePos)
17991803
case _ => traverseChildren(tree)
18001804
}
18011805
}.traverse(expr)

compiler/src/dotty/tools/dotc/parsing/Parsers.scala

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3470,17 +3470,6 @@ object Parsers {
34703470
Template(constr, parents, Nil, EmptyValDef, Nil)
34713471
}
34723472

3473-
def checkExtensionMethod(tparams: List[Tree], stat: Tree): Unit = stat match {
3474-
case stat: DefDef =>
3475-
if stat.mods.is(Extension) then
3476-
syntaxError(i"no extension method allowed here since leading parameter was already given", stat.span)
3477-
else if tparams.nonEmpty && stat.tparams.nonEmpty then
3478-
syntaxError(i"extension method cannot have type parameters since some were already given previously",
3479-
stat.tparams.head.span)
3480-
case stat =>
3481-
syntaxError(i"extension clause can only define methods", stat.span)
3482-
}
3483-
34843473
/** GivenDef ::= [GivenSig] [‘_’ ‘<:’] Type ‘=’ Expr
34853474
* | [GivenSig] ConstrApps [TemplateBody]
34863475
* GivenSig ::= [id] [DefTypeParamClause] {UsingParamClauses} ‘as’
@@ -3541,7 +3530,6 @@ object Parsers {
35413530
possibleTemplateStart()
35423531
if !in.isNestedStart then syntaxError("Extension without extension methods")
35433532
val templ = templateBodyOpt(makeConstructor(tparams, extParams :: givenParamss), Nil, Nil)
3544-
templ.body.foreach(checkExtensionMethod(tparams, _))
35453533
val edef = ModuleDef(name, templ)
35463534
finalizeDef(edef, addFlag(mods, Given), start)
35473535
}

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

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,16 @@ enum ErrorMessageID extends java.lang.Enum[ErrorMessageID] {
155155
CaseClassMissingNonImplicitParamListID,
156156
EnumerationsShouldNotBeEmptyID,
157157
AbstractCannotBeUsedForObjectsID,
158-
ModifierRedundantForObjectsID
158+
ModifierRedundantForObjectsID,
159+
TypedCaseDoesNotExplicitlyExtendTypedEnumID,
160+
IllegalRedefinitionOfStandardKindID,
161+
NoExtensionMethodAllowedID,
162+
ExtensionMethodCannotHaveTypeParamsID,
163+
ExtensionCanOnlyHaveDefsID,
164+
UnexpectedPatternForSummonFromID,
165+
AnonymousInstanceCannotBeEmptyID,
166+
TypeSpliceInValPatternID,
167+
ModifierNotAllowedForDefinitionID
159168

160169
def errorNumber = ordinal - 2
161170
}

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

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2443,4 +2443,117 @@ object messages {
24432443
| ${hl("object")} ${mdef.name} { }
24442444
|""".stripMargin
24452445
}
2446+
2447+
case class TypedCaseDoesNotExplicitlyExtendTypedEnum(enumDef: Symbol, caseDef: untpd.TypeDef)(implicit ctx: Context)
2448+
extends Message(TypedCaseDoesNotExplicitlyExtendTypedEnumID) {
2449+
val kind: String = "Syntax"
2450+
val msg: String = i"explicit extends clause needed because both enum case and enum class have type parameters"
2451+
2452+
val explanation: String =
2453+
em"""Enumerations where the enum class as well as the enum case have type parameters need
2454+
|an explicit extends.
2455+
|for example:
2456+
| ${hl("enum")} ${enumDef.name}[T] {
2457+
| ${hl("case")} ${caseDef.name}[U](u: U) ${hl("extends")} ${enumDef.name}[U]
2458+
| }
2459+
|""".stripMargin
2460+
}
2461+
2462+
case class IllegalRedefinitionOfStandardKind(kindType: String, name: Name)(implicit ctx: Context)
2463+
extends Message(IllegalRedefinitionOfStandardKindID) {
2464+
val kind: String = "Syntax"
2465+
val msg: String = em"illegal redefinition of standard $kindType $name"
2466+
2467+
val explanation: String =
2468+
em"""| "$name" is a standard Scala core `$kindType`
2469+
| Please choose a different name to avoid conflicts
2470+
|""".stripMargin
2471+
}
2472+
2473+
case class NoExtensionMethodAllowed(mdef: untpd.DefDef)(implicit ctx: Context)
2474+
extends Message(NoExtensionMethodAllowedID) {
2475+
val kind: String = "Syntax"
2476+
val msg: String = em"No extension method allowed here, since collective parameters are given"
2477+
2478+
val explanation: String =
2479+
em"""|Extension method:
2480+
| `${mdef}`
2481+
|is defined inside an extension clause which has collective parameters.
2482+
|""".stripMargin
2483+
}
2484+
2485+
case class ExtensionMethodCannotHaveTypeParams(mdef: untpd.DefDef)(implicit ctx: Context)
2486+
extends Message(ExtensionMethodCannotHaveTypeParamsID) {
2487+
val kind: String = "Syntax"
2488+
val msg: String = i"Extension method cannot have type parameters since some were already given previously"
2489+
2490+
val explanation: String =
2491+
em"""|Extension method:
2492+
| `${mdef}`
2493+
|has type parameters `[${mdef.tparams.map(_.show).mkString(",")}]`, while the extension clause has
2494+
|it's own type parameters. Please consider moving these to the extension clause's type parameter list.
2495+
|""".stripMargin
2496+
}
2497+
2498+
case class ExtensionCanOnlyHaveDefs(mdef: untpd.Tree)(implicit ctx: Context)
2499+
extends Message(ExtensionCanOnlyHaveDefsID) {
2500+
val kind: String = "Syntax"
2501+
val msg: String = em"Only methods allowed here, since collective parameters are given"
2502+
2503+
val explanation: String =
2504+
em"""Extension clauses can only have `def`s
2505+
| `${mdef.show}` is not a valid expression here.
2506+
|""".stripMargin
2507+
}
2508+
2509+
case class UnexpectedPatternForSummonFrom(tree: Tree[_])(implicit ctx: Context)
2510+
extends Message(UnexpectedPatternForSummonFromID) {
2511+
val kind: String = "Syntax"
2512+
val msg: String = em"Unexpected pattern for summonFrom. Expected ${hl("`x: T`")} or ${hl("`_`")}"
2513+
2514+
val explanation: String =
2515+
em"""|The pattern "${tree.show}" provided in the ${hl("case")} expression of the ${hl("summonFrom")},
2516+
| needs to be of the form ${hl("`x: T`")} or ${hl("`_`")}.
2517+
|
2518+
| Example usage:
2519+
| inline def a = summonFrom {
2520+
| case x: T => ???
2521+
| }
2522+
|
2523+
| or
2524+
| inline def a = summonFrom {
2525+
| case _ => ???
2526+
| }
2527+
|""".stripMargin
2528+
}
2529+
2530+
case class AnonymousInstanceCannotBeEmpty(impl: untpd.Template)(implicit ctx: Context)
2531+
extends Message(AnonymousInstanceCannotBeEmptyID) {
2532+
val kind: String = "Syntax"
2533+
val msg: String = i"anonymous instance must implement a type or have at least one extension method"
2534+
2535+
val explanation: String =
2536+
em"""|Anonymous instances cannot be defined with an empty body. The block
2537+
|`${impl.show}` should either contain an implemented type or at least one extension method.
2538+
|""".stripMargin
2539+
}
2540+
2541+
case class TypeSpliceInValPattern(expr: untpd.Tree)(implicit ctx: Context)
2542+
extends Message(TypeSpliceInValPatternID) {
2543+
val kind: String = "Syntax"
2544+
val msg: String = "Type splices cannot be used in val patterns. Consider using `match` instead."
2545+
2546+
val explanation: String =
2547+
em"""|Type splice: `$$${expr.show}` cannot be used in a `val` pattern. Consider rewriting the `val` pattern
2548+
|as a `match` with a corresponding `case` to replace the `val`.
2549+
|""".stripMargin
2550+
}
2551+
2552+
case class ModifierNotAllowedForDefinition(flag: Flag)(implicit ctx: Context)
2553+
extends Message(ModifierNotAllowedForDefinitionID) {
2554+
val kind: String = "Syntax"
2555+
val msg: String = s"Modifier `${flag.flagsString}` is not allowed for this definition"
2556+
2557+
val explanation: String = ""
2558+
}
24462559
}

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ import collection.mutable
2828
import config.Printers.{overload, typr, unapp}
2929
import TypeApplications._
3030

31-
import reporting.diagnostic.{Message, messages}
31+
import reporting.diagnostic.Message
32+
import reporting.diagnostic.messages.{UnexpectedPatternForSummonFrom, NotAMember}
3233
import reporting.trace
3334
import Constants.{Constant, IntTag, LongTag}
3435
import dotty.tools.dotc.reporting.diagnostic.messages.{UnapplyInvalidReturnType, NotAnExtractor, UnapplyInvalidNumberOfArguments}
@@ -916,7 +917,7 @@ trait Applications extends Compatibility {
916917
case CaseDef(Bind(_, Typed(_: Ident, _)), _, _) => // OK
917918
case CaseDef(Ident(name), _, _) if name == nme.WILDCARD => // Ok
918919
case CaseDef(pat, _, _) =>
919-
ctx.error("Unexpected pattern for summonFrom. Expected `x: T` or `_`", pat.sourcePos)
920+
ctx.error(UnexpectedPatternForSummonFrom(pat), pat.sourcePos)
920921
}
921922
typed(untpd.InlineMatch(EmptyTree, cases).withSpan(arg.span), pt)
922923
case _ =>
@@ -1075,7 +1076,7 @@ trait Applications extends Compatibility {
10751076
msgs match
10761077
case msg :: Nil =>
10771078
msg.contained match
1078-
case messages.NotAMember(_, nme.unapply, _, _) => return notAnExtractor(tree)
1079+
case NotAMember(_, nme.unapply, _, _) => return notAnExtractor(tree)
10791080
case _ =>
10801081
case _ =>
10811082
msgs.foreach(ctx.reporter.report)

0 commit comments

Comments
 (0)