Skip to content

Port remaining Desugar and Applications errors to the new scheme #8263

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Feb 18, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 18 additions & 14 deletions compiler/src/dotty/tools/dotc/ast/Desugar.scala
Original file line number Diff line number Diff line change
Expand Up @@ -558,7 +558,7 @@ object desugar {
else if (originalTparams.isEmpty)
appliedRef(enumClassRef)
else {
ctx.error(i"explicit extends clause needed because both enum case and enum class have type parameters"
ctx.error(TypedCaseDoesNotExplicitlyExtendTypedEnum(enumClass, cdef)
, cdef.sourcePos.startPos)
appliedTypeTree(enumClassRef, constrTparams map (_ => anyRef))
}
Expand Down Expand Up @@ -930,22 +930,27 @@ object desugar {

def makeExtensionDef(mdef: Tree, tparams: List[TypeDef], leadingParams: List[ValDef],
givenParamss: List[List[ValDef]])(using ctx: Context): Tree = {
val allowed = "allowed here, since collective parameters are given"
mdef match {
case mdef: DefDef =>
if (mdef.mods.is(Extension)) {
ctx.error(em"No extension method $allowed", mdef.sourcePos)
ctx.error(NoExtensionMethodAllowed(mdef), mdef.sourcePos)
mdef
} else {
if (tparams.nonEmpty && mdef.tparams.nonEmpty) then
ctx.error(ExtensionMethodCannotHaveTypeParams(mdef), mdef.tparams.head.sourcePos)
mdef
else cpy.DefDef(mdef)(
tparams = tparams ++ mdef.tparams,
vparamss = leadingParams :: givenParamss ::: mdef.vparamss
).withMods(mdef.mods | Extension)
}
else cpy.DefDef(mdef)(
tparams = tparams ++ mdef.tparams,
vparamss = leadingParams :: givenParamss ::: mdef.vparamss
).withMods(mdef.mods | Extension)
case mdef: Import =>
mdef
case mdef =>
ctx.error(em"Only methods $allowed", mdef.sourcePos)
case mdef if !mdef.isEmpty => {
ctx.error(ExtensionCanOnlyHaveDefs(mdef), mdef.sourcePos)
mdef
}
case mdef => mdef
}
}

Expand Down Expand Up @@ -979,7 +984,7 @@ object desugar {
if (name.isEmpty) name = name.likeSpaced(inventGivenOrExtensionName(impl))
if (ctx.owner == defn.ScalaPackageClass && defn.reservedScalaClassNames.contains(name.toTypeName)) {
def kind = if (name.isTypeName) "class" else "object"
ctx.error(em"illegal redefinition of standard $kind $name", mdef.sourcePos)
ctx.error(IllegalRedefinitionOfStandardKind(kind, name), mdef.sourcePos)
name = name.errorName
}
name
Expand All @@ -998,7 +1003,7 @@ object desugar {
case Some(DefDef(name, _, (vparam :: _) :: _, _, _)) =>
s"extension_${name}_${inventTypeName(vparam.tpt)}"
case _ =>
ctx.error(i"anonymous instance must implement a type or have at least one extension method", impl.sourcePos)
ctx.error(AnonymousInstanceCannotBeEmpty(impl), impl.sourcePos)
nme.ERROR.toString
else
impl.parents.map(inventTypeName(_)).mkString("given_", "_", "")
Expand Down Expand Up @@ -1170,10 +1175,9 @@ object desugar {
def checkModifiers(tree: Tree)(implicit ctx: Context): Tree = tree match {
case tree: MemberDef =>
var tested: MemberDef = tree
def fail(msg: String) = ctx.error(msg, tree.sourcePos)
def checkApplicable(flag: Flag, test: MemberDefTest): Unit =
if (tested.mods.is(flag) && !test.applyOrElse(tree, (md: MemberDef) => false)) {
fail(i"modifier `${flag.flagsString}` is not allowed for this definition")
ctx.error(ModifierNotAllowedForDefinition(flag), tree.sourcePos)
tested = tested.withMods(tested.mods.withoutFlags(flag))
}
checkApplicable(Opaque, legalOpaque)
Expand Down Expand Up @@ -1795,7 +1799,7 @@ object desugar {
def traverse(tree: untpd.Tree)(implicit ctx: Context): Unit = tree match {
case Splice(expr) => collect(expr)
case TypSplice(expr) =>
ctx.error("Type splices cannot be used in val patterns. Consider using `match` instead.", tree.sourcePos)
ctx.error(TypeSpliceInValPattern(expr), tree.sourcePos)
case _ => traverseChildren(tree)
}
}.traverse(expr)
Expand Down
12 changes: 0 additions & 12 deletions compiler/src/dotty/tools/dotc/parsing/Parsers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3470,17 +3470,6 @@ object Parsers {
Template(constr, parents, Nil, EmptyValDef, Nil)
}

def checkExtensionMethod(tparams: List[Tree], stat: Tree): Unit = stat match {
case stat: DefDef =>
if stat.mods.is(Extension) then
syntaxError(i"no extension method allowed here since leading parameter was already given", stat.span)
else if tparams.nonEmpty && stat.tparams.nonEmpty then
syntaxError(i"extension method cannot have type parameters since some were already given previously",
stat.tparams.head.span)
case stat =>
syntaxError(i"extension clause can only define methods", stat.span)
}

/** GivenDef ::= [GivenSig] [‘_’ ‘<:’] Type ‘=’ Expr
* | [GivenSig] ConstrApps [TemplateBody]
* GivenSig ::= [id] [DefTypeParamClause] {UsingParamClauses} ‘as’
Expand Down Expand Up @@ -3541,7 +3530,6 @@ object Parsers {
possibleTemplateStart()
if !in.isNestedStart then syntaxError("Extension without extension methods")
val templ = templateBodyOpt(makeConstructor(tparams, extParams :: givenParamss), Nil, Nil)
templ.body.foreach(checkExtensionMethod(tparams, _))
val edef = ModuleDef(name, templ)
finalizeDef(edef, addFlag(mods, Given), start)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,16 @@ enum ErrorMessageID extends java.lang.Enum[ErrorMessageID] {
CaseClassMissingNonImplicitParamListID,
EnumerationsShouldNotBeEmptyID,
AbstractCannotBeUsedForObjectsID,
ModifierRedundantForObjectsID
ModifierRedundantForObjectsID,
TypedCaseDoesNotExplicitlyExtendTypedEnumID,
IllegalRedefinitionOfStandardKindID,
NoExtensionMethodAllowedID,
ExtensionMethodCannotHaveTypeParamsID,
ExtensionCanOnlyHaveDefsID,
UnexpectedPatternForSummonFromID,
AnonymousInstanceCannotBeEmptyID,
TypeSpliceInValPatternID,
ModifierNotAllowedForDefinitionID

def errorNumber = ordinal - 2
}
113 changes: 113 additions & 0 deletions compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2443,4 +2443,117 @@ object messages {
| ${hl("object")} ${mdef.name} { }
|""".stripMargin
}

case class TypedCaseDoesNotExplicitlyExtendTypedEnum(enumDef: Symbol, caseDef: untpd.TypeDef)(implicit ctx: Context)
extends Message(TypedCaseDoesNotExplicitlyExtendTypedEnumID) {
val kind: String = "Syntax"
val msg: String = i"explicit extends clause needed because both enum case and enum class have type parameters"

val explanation: String =
em"""Enumerations where the enum class as well as the enum case have type parameters need
|an explicit extends.
|for example:
| ${hl("enum")} ${enumDef.name}[T] {
| ${hl("case")} ${caseDef.name}[U](u: U) ${hl("extends")} ${enumDef.name}[U]
| }
|""".stripMargin
}

case class IllegalRedefinitionOfStandardKind(kindType: String, name: Name)(implicit ctx: Context)
extends Message(IllegalRedefinitionOfStandardKindID) {
val kind: String = "Syntax"
val msg: String = em"illegal redefinition of standard $kindType $name"

val explanation: String =
em"""| "$name" is a standard Scala core `$kindType`
| Please choose a different name to avoid conflicts
|""".stripMargin
}

case class NoExtensionMethodAllowed(mdef: untpd.DefDef)(implicit ctx: Context)
extends Message(NoExtensionMethodAllowedID) {
val kind: String = "Syntax"
val msg: String = em"No extension method allowed here, since collective parameters are given"

val explanation: String =
em"""|Extension method:
| `${mdef}`
|is defined inside an extension clause which has collective parameters.
|""".stripMargin
}

case class ExtensionMethodCannotHaveTypeParams(mdef: untpd.DefDef)(implicit ctx: Context)
extends Message(ExtensionMethodCannotHaveTypeParamsID) {
val kind: String = "Syntax"
val msg: String = i"Extension method cannot have type parameters since some were already given previously"

val explanation: String =
em"""|Extension method:
| `${mdef}`
|has type parameters `[${mdef.tparams.map(_.show).mkString(",")}]`, while the extension clause has
|it's own type parameters. Please consider moving these to the extension clause's type parameter list.
|""".stripMargin
}

case class ExtensionCanOnlyHaveDefs(mdef: untpd.Tree)(implicit ctx: Context)
extends Message(ExtensionCanOnlyHaveDefsID) {
val kind: String = "Syntax"
val msg: String = em"Only methods allowed here, since collective parameters are given"

val explanation: String =
em"""Extension clauses can only have `def`s
| `${mdef.show}` is not a valid expression here.
|""".stripMargin
}

case class UnexpectedPatternForSummonFrom(tree: Tree[_])(implicit ctx: Context)
extends Message(UnexpectedPatternForSummonFromID) {
val kind: String = "Syntax"
val msg: String = em"Unexpected pattern for summonFrom. Expected ${hl("`x: T`")} or ${hl("`_`")}"

val explanation: String =
em"""|The pattern "${tree.show}" provided in the ${hl("case")} expression of the ${hl("summonFrom")},
| needs to be of the form ${hl("`x: T`")} or ${hl("`_`")}.
|
| Example usage:
| inline def a = summonFrom {
| case x: T => ???
| }
|
| or
| inline def a = summonFrom {
| case _ => ???
| }
|""".stripMargin
}

case class AnonymousInstanceCannotBeEmpty(impl: untpd.Template)(implicit ctx: Context)
extends Message(AnonymousInstanceCannotBeEmptyID) {
val kind: String = "Syntax"
val msg: String = i"anonymous instance must implement a type or have at least one extension method"

val explanation: String =
em"""|Anonymous instances cannot be defined with an empty body. The block
|`${impl.show}` should either contain an implemented type or at least one extension method.
|""".stripMargin
}

case class TypeSpliceInValPattern(expr: untpd.Tree)(implicit ctx: Context)
extends Message(TypeSpliceInValPatternID) {
val kind: String = "Syntax"
val msg: String = "Type splices cannot be used in val patterns. Consider using `match` instead."

val explanation: String =
em"""|Type splice: `$$${expr.show}` cannot be used in a `val` pattern. Consider rewriting the `val` pattern
|as a `match` with a corresponding `case` to replace the `val`.
|""".stripMargin
}

case class ModifierNotAllowedForDefinition(flag: Flag)(implicit ctx: Context)
extends Message(ModifierNotAllowedForDefinitionID) {
val kind: String = "Syntax"
val msg: String = s"Modifier `${flag.flagsString}` is not allowed for this definition"

val explanation: String = ""
}
}
7 changes: 4 additions & 3 deletions compiler/src/dotty/tools/dotc/typer/Applications.scala
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ import collection.mutable
import config.Printers.{overload, typr, unapp}
import TypeApplications._

import reporting.diagnostic.{Message, messages}
import reporting.diagnostic.Message
import reporting.diagnostic.messages.{UnexpectedPatternForSummonFrom, NotAMember}
import reporting.trace
import Constants.{Constant, IntTag, LongTag}
import dotty.tools.dotc.reporting.diagnostic.messages.{UnapplyInvalidReturnType, NotAnExtractor, UnapplyInvalidNumberOfArguments}
Expand Down Expand Up @@ -916,7 +917,7 @@ trait Applications extends Compatibility {
case CaseDef(Bind(_, Typed(_: Ident, _)), _, _) => // OK
case CaseDef(Ident(name), _, _) if name == nme.WILDCARD => // Ok
case CaseDef(pat, _, _) =>
ctx.error("Unexpected pattern for summonFrom. Expected `x: T` or `_`", pat.sourcePos)
ctx.error(UnexpectedPatternForSummonFrom(pat), pat.sourcePos)
}
typed(untpd.InlineMatch(EmptyTree, cases).withSpan(arg.span), pt)
case _ =>
Expand Down Expand Up @@ -1075,7 +1076,7 @@ trait Applications extends Compatibility {
msgs match
case msg :: Nil =>
msg.contained match
case messages.NotAMember(_, nme.unapply, _, _) => return notAnExtractor(tree)
case NotAMember(_, nme.unapply, _, _) => return notAnExtractor(tree)
case _ =>
case _ =>
msgs.foreach(ctx.reporter.report)
Expand Down
Loading