summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
diff options
context:
space:
mode:
authorEugene Burmako <xeno.by@gmail.com>2013-06-03 11:08:50 -0700
committerEugene Burmako <xeno.by@gmail.com>2013-06-03 11:08:50 -0700
commit69887ddd682057c4787e2e4377830390faf8ecf1 (patch)
tree1158f24dd50dac397e867a6d2d861171e7335c4f /src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
parentc1cd65bb5276b715141df6d09fc95b0c44d2b4c2 (diff)
parent82f0925b69db8b5f9a3b10f58926c574433ca423 (diff)
downloadscala-69887ddd682057c4787e2e4377830390faf8ecf1.tar.gz
scala-69887ddd682057c4787e2e4377830390faf8ecf1.tar.bz2
scala-69887ddd682057c4787e2e4377830390faf8ecf1.zip
Merge pull request #2577 from scalamacros/pullrequest/paradise
Backport from paradise/macros
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala162
1 files changed, 16 insertions, 146 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
index dbcb6c19a0..fe1607c631 100644
--- a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
@@ -460,7 +460,7 @@ trait ContextErrors {
def AbstractionFromVolatileTypeError(vd: ValDef) =
issueNormalTypeError(vd, "illegal abstraction from value with volatile type "+vd.symbol.tpe)
- private[ContextErrors] def TypedApplyWrongNumberOfTpeParametersErrorMessage(fun: Tree) =
+ private[scala] def TypedApplyWrongNumberOfTpeParametersErrorMessage(fun: Tree) =
"wrong number of type parameters for "+treeSymTypeMsg(fun)
def TypedApplyWrongNumberOfTpeParametersError(tree: Tree, fun: Tree) = {
@@ -476,7 +476,7 @@ trait ContextErrors {
// doTypeApply
//tryNamesDefaults
def NamedAndDefaultArgumentsNotSupportedForMacros(tree: Tree, fun: Tree) =
- NormalTypeError(tree, "macros application do not support named and/or default arguments")
+ NormalTypeError(tree, "macro applications do not support named and/or default arguments")
def TooManyArgsNamesDefaultsError(tree: Tree, fun: Tree) =
NormalTypeError(tree, "too many arguments for "+treeSymTypeMsg(fun))
@@ -571,7 +571,7 @@ trait ContextErrors {
//adapt
def MissingArgsForMethodTpeError(tree: Tree, meth: Symbol) = {
val message =
- if (meth.isMacro) MacroPartialApplicationErrorMessage
+ if (meth.isMacro) MacroTooFewArgumentListsMessage
else "missing arguments for " + meth.fullLocationString + (
if (meth.isConstructor) ""
else ";\nfollow this method with `_' if you want to treat it as a partially applied function"
@@ -692,7 +692,6 @@ trait ContextErrors {
issueNormalTypeError(expandee, s"macro in $role role can only expand into $allowedExpansions")
}
- // same reason as for MacroBodyTypecheckException
case object MacroExpansionException extends Exception with scala.util.control.ControlThrowable
protected def macroExpansionError(expandee: Tree, msg: String, pos: Position = NoPosition) = {
@@ -703,15 +702,24 @@ trait ContextErrors {
throw MacroExpansionException
}
- def MacroPartialApplicationErrorMessage = "macros cannot be partially applied"
- def MacroPartialApplicationError(expandee: Tree) = {
+ private def macroExpansionError2(expandee: Tree, msg: String) = {
// macroExpansionError won't work => swallows positions, hence needed to do issueTypeError
// kinda contradictory to the comment in `macroExpansionError`, but this is how it works
- issueNormalTypeError(expandee, MacroPartialApplicationErrorMessage)
+ issueNormalTypeError(expandee, msg)
setError(expandee)
throw MacroExpansionException
}
+ private def MacroTooFewArgumentListsMessage = "too few argument lists for macro invocation"
+ def MacroTooFewArgumentListsError(expandee: Tree) = macroExpansionError2(expandee, MacroTooFewArgumentListsMessage)
+
+ private def MacroTooManyArgumentListsMessage = "too many argument lists for macro invocation"
+ def MacroTooManyArgumentListsError(expandee: Tree) = macroExpansionError2(expandee, MacroTooManyArgumentListsMessage)
+
+ def MacroTooFewArgumentsError(expandee: Tree) = macroExpansionError2(expandee, "too few arguments for macro invocation")
+
+ def MacroTooManyArgumentsError(expandee: Tree) = macroExpansionError2(expandee, "too many arguments for macro invocation")
+
def MacroGeneratedAbort(expandee: Tree, ex: AbortMacroException) = {
// errors have been reported by the macro itself, so we do nothing here
macroLogVerbose("macro expansion has been aborted")
@@ -917,7 +925,7 @@ trait ContextErrors {
kindErrors.toList.mkString("\n", ", ", ""))
}
- private[ContextErrors] def NotWithinBoundsErrorMessage(prefix: String, targs: List[Type], tparams: List[Symbol], explaintypes: Boolean) = {
+ private[scala] def NotWithinBoundsErrorMessage(prefix: String, targs: List[Type], tparams: List[Symbol], explaintypes: Boolean) = {
if (explaintypes) {
val bounds = tparams map (tp => tp.info.instantiateTypeParams(tparams, targs).bounds)
(targs, bounds).zipped foreach ((targ, bound) => explainTypes(bound.lo, targ))
@@ -1224,142 +1232,4 @@ trait ContextErrors {
setError(arg)
}
}
-
- // using an exception here is actually a good idea
- // because the lifespan of this exception is extremely small and controlled
- // moreover exceptions let us avoid an avalanche of "if (!hasError) do stuff" checks
- case object MacroBodyTypecheckException extends Exception with scala.util.control.ControlThrowable
-
- trait MacroErrors {
- self: MacroTyper =>
-
- private implicit val context0 = typer.context
- val context = typer.context
-
- // helpers
-
- private def lengthMsg(flavor: String, violation: String, extra: Symbol) = {
- val noun = if (flavor == "value") "parameter" else "type parameter"
- val message = noun + " lists have different length, " + violation + " extra " + noun
- val suffix = if (extra ne NoSymbol) " " + extra.defString else ""
- message + suffix
- }
-
- private def abbreviateCoreAliases(s: String): String = List("WeakTypeTag", "Expr").foldLeft(s)((res, x) => res.replace("c.universe." + x, "c." + x))
-
- private def showMeth(pss: List[List[Symbol]], restpe: Type, abbreviate: Boolean) = {
- var argsPart = (pss map (ps => ps map (_.defString) mkString ("(", ", ", ")"))).mkString
- if (abbreviate) argsPart = abbreviateCoreAliases(argsPart)
- var retPart = restpe.toString
- if (abbreviate || macroDdef.tpt.tpe == null) retPart = abbreviateCoreAliases(retPart)
- argsPart + ": " + retPart
- }
-
- // not exactly an error generator, but very related
- // and I dearly wanted to push it away from Macros.scala
- private def checkSubType(slot: String, rtpe: Type, atpe: Type) = {
- val ok = if (macroDebugVerbose) {
- withTypesExplained(rtpe <:< atpe)
- } else rtpe <:< atpe
- if (!ok) {
- if (!macroDebugVerbose)
- explainTypes(rtpe, atpe)
- compatibilityError("type mismatch for %s: %s does not conform to %s".format(slot, abbreviateCoreAliases(rtpe.toString), abbreviateCoreAliases(atpe.toString)))
- }
- }
-
- // errors
-
- private def fail() = {
- // need to set the IS_ERROR flag to prohibit spurious expansions
- if (macroDef != null) macroDef setFlag IS_ERROR
- // not setting ErrorSymbol as in `infer.setError`, because we still need to know that it's a macro
- // otherwise assignTypeToTree in Namers might fail if macroDdef.tpt == EmptyTree
- macroDdef setType ErrorType
- throw MacroBodyTypecheckException
- }
-
- private def genericError(tree: Tree, message: String) = {
- issueNormalTypeError(tree, message)
- fail()
- }
-
- private def implRefError(message: String) = {
- val treeInfo.Applied(implRef, _, _) = macroDdef.rhs
- genericError(implRef, message)
- }
-
- private def compatibilityError(message: String) =
- implRefError(
- "macro implementation has wrong shape:"+
- "\n required: " + showMeth(rparamss, rret, abbreviate = true) +
- "\n found : " + showMeth(aparamss, aret, abbreviate = false) +
- "\n" + message)
-
- // Phase I: sanity checks
-
- def MacroDefIsFastTrack() = {
- macroLogVerbose("typecheck terminated unexpectedly: macro is fast track")
- assert(!macroDdef.tpt.isEmpty, "fast track macros must provide result type")
- throw MacroBodyTypecheckException // don't call fail, because we don't need IS_ERROR
- }
-
- def MacroDefIsQmarkQmarkQmark() = {
- macroLogVerbose("typecheck terminated unexpectedly: macro is ???")
- throw MacroBodyTypecheckException
- }
-
- def MacroFeatureNotEnabled() = {
- macroLogVerbose("typecheck terminated unexpectedly: language.experimental.macros feature is not enabled")
- fail()
- }
-
- // Phase II: typecheck the right-hand side of the macro def
-
- // do nothing, just fail. relevant typecheck errors have already been reported
- def MacroDefUntypeableBodyError() = fail()
-
- def MacroDefInvalidBodyError() = genericError(macroDdef, "macro body has wrong shape:\n required: macro [<implementation object>].<method name>[[<type args>]]")
-
- def MacroImplNotPublicError() = implRefError("macro implementation must be public")
-
- def MacroImplOverloadedError() = implRefError("macro implementation cannot be overloaded")
-
- def MacroImplWrongNumberOfTypeArgumentsError(macroImplRef: Tree) = implRefError(typer.TyperErrorGen.TypedApplyWrongNumberOfTpeParametersErrorMessage(macroImplRef))
-
- def MacroImplNotStaticError() = implRefError("macro implementation must be in statically accessible object")
-
- // Phase III: check compatibility between the macro def and its macro impl
- // aXXX (e.g. aparams) => characteristics of the macro impl ("a" stands for "actual")
- // rXXX (e.g. rparams) => characteristics of a reference macro impl signature synthesized from the macro def ("r" stands for "reference")
-
- def MacroImplNonTagImplicitParameters(params: List[Symbol]) = compatibilityError("macro implementations cannot have implicit parameters other than WeakTypeTag evidences")
-
- def MacroImplParamssMismatchError() = compatibilityError("number of parameter sections differ")
-
- def MacroImplExtraParamsError(aparams: List[Symbol], rparams: List[Symbol]) = compatibilityError(lengthMsg("value", "found", aparams(rparams.length)))
-
- def MacroImplMissingParamsError(aparams: List[Symbol], rparams: List[Symbol]) = compatibilityError(abbreviateCoreAliases(lengthMsg("value", "required", rparams(aparams.length))))
-
- def checkMacroImplParamTypeMismatch(atpe: Type, rparam: Symbol) = checkSubType("parameter " + rparam.name, rparam.tpe, atpe)
-
- def checkMacroImplResultTypeMismatch(atpe: Type, rret: Type) = checkSubType("return type", atpe, rret)
-
- def MacroImplParamNameMismatchError(aparam: Symbol, rparam: Symbol) = compatibilityError("parameter names differ: " + rparam.name + " != " + aparam.name)
-
- def MacroImplVarargMismatchError(aparam: Symbol, rparam: Symbol) = {
- if (isRepeated(rparam) && !isRepeated(aparam))
- compatibilityError("types incompatible for parameter " + rparam.name + ": corresponding is not a vararg parameter")
- if (!isRepeated(rparam) && isRepeated(aparam))
- compatibilityError("types incompatible for parameter " + aparam.name + ": corresponding is not a vararg parameter")
- }
-
- def MacroImplTargMismatchError(atargs: List[Type], atparams: List[Symbol]) =
- compatibilityError(typer.infer.InferErrorGen.NotWithinBoundsErrorMessage("", atargs, atparams, macroDebugVerbose || settings.explaintypes))
-
- def MacroImplTparamInstantiationError(atparams: List[Symbol], ex: NoInstance) =
- compatibilityError(
- "type parameters "+(atparams map (_.defString) mkString ", ")+" cannot be instantiated\n"+
- ex.getMessage)
- }
}