scala.reflect.macros.compiler.Errors.scala Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of scala-compiler Show documentation
Show all versions of scala-compiler Show documentation
Compiler for the SubScript extension of the Scala Programming Language
The newest version!
package scala.reflect.macros
package compiler
import scala.compat.Platform.EOL
import scala.reflect.macros.util.Traces
trait Errors extends Traces {
self: DefaultMacroCompiler =>
import global._
import analyzer._
import definitions._
import treeInfo._
import typer.infer.InferErrorGen._
import runDefinitions._
def globalSettings = global.settings
private def implRefError(message: String) = {
val Applied(culprit, _, _) = macroDdef.rhs
abort(culprit.pos, message)
}
private def bundleRefError(message: String) = {
val Applied(core, _, _) = macroDdef.rhs
val culprit = core match {
case Select(Applied(core, _, _), _) => core
case _ => core
}
abort(culprit.pos, message)
}
def MacroImplAmbiguousError() = implRefError(
"macro implementation reference is ambiguous: makes sense both as\n"+
"a macro bundle method reference and a vanilla object method reference")
def MacroBundleNonStaticError() = bundleRefError("macro bundles must be static")
def MacroBundleWrongShapeError() = bundleRefError("macro bundles must be concrete monomorphic classes having a single constructor with a `val c: Context` parameter")
trait Error {
self: MacroImplRefCompiler =>
// sanity check errors
def MacroImplReferenceWrongShapeError() = implRefError(
"macro implementation reference has wrong shape. required:\n"+
"macro [].[[]] or\n" +
"macro [].[[]]")
def MacroImplWrongNumberOfTypeArgumentsError() = {
val diagnostic = if (macroImpl.typeParams.length > targs.length) "has too few type arguments" else "has too many arguments"
implRefError(s"macro implementation reference $diagnostic for " + treeSymTypeMsg(macroImplRef))
}
private def macroImplementationWording =
if (isImplBundle) "bundle implementation"
else "macro implementation"
def MacroImplNotPublicError() = implRefError(s"${macroImplementationWording} must be public")
def MacroImplOverloadedError() = implRefError(s"${macroImplementationWording} cannot be overloaded")
def MacroImplNonTagImplicitParameters(params: List[Symbol]) = implRefError(s"${macroImplementationWording}s cannot have implicit parameters other than WeakTypeTag evidences")
// compatibility errors
// 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 = {
val coreAliases = List("WeakTypeTag", "Expr", "Tree")
coreAliases.foldLeft(s)((res, x) => res.replace("c.universe." + x, "c." + x))
}
private def showMeth(pss: List[List[Symbol]], restpe: Type, abbreviate: Boolean, untype: Boolean) = {
def preprocess(tpe: Type) = if (untype) untypeMetalevel(tpe) else tpe
var pssPart = (pss map (ps => ps map (p => p.defStringSeenAs(preprocess(p.info))) mkString ("(", ", ", ")"))).mkString
if (abbreviate) pssPart = abbreviateCoreAliases(pssPart)
var retPart = preprocess(restpe).toString
if (abbreviate || macroDdef.tpt.tpe == null) retPart = abbreviateCoreAliases(retPart)
pssPart + ": " + retPart
}
// not exactly an error generator, but very related
// and I dearly wanted to push it away from Macros.scala
private def checkConforms(slot: String, rtpe: Type, atpe: Type) = {
val verbose = macroDebugVerbose
def check(rtpe: Type, atpe: Type): Boolean = {
def success() = { if (verbose) println(rtpe + " <: " + atpe + "?" + EOL + "true"); true }
(rtpe, atpe) match {
case _ if rtpe eq atpe => success()
case (TypeRef(_, RepeatedParamClass, rtpe :: Nil), TypeRef(_, RepeatedParamClass, atpe :: Nil)) => check(rtpe, atpe)
case (ExprClassOf(_), TreeType()) if rtpe.prefix =:= atpe.prefix => success()
case (SubtreeType(), ExprClassOf(_)) if rtpe.prefix =:= atpe.prefix => success()
case _ => rtpe <:< atpe
}
}
val ok =
if (verbose) withTypesExplained(check(rtpe, atpe))
else check(rtpe, atpe)
if (!ok) {
if (!verbose) explainTypes(rtpe, atpe)
val msg = {
val ss = Seq(rtpe, atpe) map (this abbreviateCoreAliases _.toString)
s"type mismatch for $slot: ${ss(0)} does not conform to ${ss(1)}"
}
compatibilityError(msg)
}
}
private def compatibilityError(message: String) =
implRefError(
s"${macroImplementationWording} has incompatible shape:"+
"\n required: " + showMeth(rparamss, rret, abbreviate = true, untype = false) +
"\n or : " + showMeth(rparamss, rret, abbreviate = true, untype = true) +
"\n found : " + showMeth(aparamss, aret, abbreviate = false, untype = false) +
"\n" + message)
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) = checkConforms("parameter " + rparam.name, rparam.tpe, atpe)
def checkMacroImplResultTypeMismatch(atpe: Type, rret: Type) = checkConforms("return type", atpe, rret)
def MacroImplParamNameMismatchError(aparam: Symbol, rparam: Symbol) = compatibilityError("parameter names differ: " + rparam.name + " != " + aparam.name)
def MacroImplVarargMismatchError(aparam: Symbol, rparam: Symbol) = {
def fail(paramName: Name) = compatibilityError("types incompatible for parameter " + paramName + ": corresponding is not a vararg parameter")
if (isRepeated(rparam) && !isRepeated(aparam)) fail(rparam.name)
if (!isRepeated(rparam) && isRepeated(aparam)) fail(aparam.name)
}
def MacroImplTargMismatchError(atargs: List[Type], atparams: List[Symbol]) =
compatibilityError(NotWithinBoundsErrorMessage("", atargs, atparams, macroDebugVerbose || settings.explaintypes.value))
def MacroImplTparamInstantiationError(atparams: List[Symbol], e: NoInstance) = {
val badps = atparams map (_.defString) mkString ", "
compatibilityError(f"type parameters $badps cannot be instantiated%n${e.getMessage}")
}
}
}