Skip to content

Commit

Permalink
Merge pull request #8263 from ausmarton/ticket/1589
Browse files Browse the repository at this point in the history
Port remaining Desugar and Applications errors to the new scheme
  • Loading branch information
anatoliykmetyuk committed Feb 18, 2020
2 parents e8fa408 + 6caa732 commit 76caf35
Show file tree
Hide file tree
Showing 25 changed files with 423 additions and 34 deletions.
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

0 comments on commit 76caf35

Please sign in to comment.