1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
|
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 [<static object>].<method name>[[<type args>]] or\n" +
"macro [<macro bundle>].<method name>[[<type args>]]")
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}")
}
}
}
|