summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEugene Burmako <xeno.by@gmail.com>2012-09-18 15:04:20 +0200
committerEugene Burmako <xeno.by@gmail.com>2012-09-18 15:07:49 +0200
commitfce3f8b2e351494dd8c110b896f731931ae2805e (patch)
tree0ba835180642d9e3683fcb2d2531a192a079a900 /src
parent66603a2c003852d39faec20a9763fb0e25049cf4 (diff)
downloadscala-fce3f8b2e351494dd8c110b896f731931ae2805e.tar.gz
scala-fce3f8b2e351494dd8c110b896f731931ae2805e.tar.bz2
scala-fce3f8b2e351494dd8c110b896f731931ae2805e.zip
existentially typed expansions now work fine
If one tries to compile the following code with the parent of this commit: ru.reify(new Object().getClass) then the following error will occur: Test.scala:2: error: type mismatch; found : $u.Expr[Class[_ <: Object]] required: reflect.runtime.universe.Expr[Class[?0(in value <local Test>)]] where type ?0(in value <local Test>) <: Object ru.reify(new Object().getClass) ^ This happens because macro expansions are always typechecked against the return type of their macro definitions instantiated in the context of expandee. In this case the expected type contains skolems which are incompatible with wildcards in the type of the expansion. I tried all the incantations I could think of - without any success. Luckily I met Martin who pointed me at the same problem solved in adapt (see the diff w.r.t Typers.scala).
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Macros.scala4
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala13
2 files changed, 14 insertions, 3 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Macros.scala b/src/compiler/scala/tools/nsc/typechecker/Macros.scala
index 9adf86e44b..f9a35ba9a0 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Macros.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Macros.scala
@@ -710,7 +710,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
if (isNullaryInvocation(expandee)) expectedTpe = expectedTpe.finalResultType
var typechecked = typecheck("macro def return type", expanded, expectedTpe)
typechecked = typecheck("expected type", typechecked, pt)
- typechecked updateAttachment MacroExpansionAttachment(expandee)
+ typechecked
} finally {
popMacroContext()
}
@@ -776,7 +776,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
macroLogLite("" + expanded.tree + "\n" + showRaw(expanded.tree))
val freeSyms = expanded.tree.freeTerms ++ expanded.tree.freeTypes
freeSyms foreach (sym => MacroFreeSymbolError(expandee, sym))
- Success(atPos(enclosingMacroPosition.focus)(expanded.tree))
+ Success(atPos(enclosingMacroPosition.focus)(expanded.tree updateAttachment MacroExpansionAttachment(expandee)))
case _ =>
MacroExpansionIsNotExprError(expandee, expanded)
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 089245e124..de9a56c99c 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -1198,7 +1198,7 @@ trait Typers extends Modes with Adaptations with Tags {
val found = tree.tpe
if (!found.isErroneous && !pt.isErroneous) {
- if (!context.reportErrors && isPastTyper) {
+ if ((!context.reportErrors && isPastTyper) || tree.attachments.get[MacroExpansionAttachment].isDefined) {
val (bound, req) = pt match {
case ExistentialType(qs, tpe) => (qs, tpe)
case _ => (Nil, pt)
@@ -1231,6 +1231,17 @@ trait Typers extends Modes with Adaptations with Tags {
// to consistently transform skolems and fix 6029), I'd like to
// investigate ways to avoid skolems completely.
//
+ // upd. The same problem happens when we try to typecheck the result of macro expansion against its expected type
+ // (which is the return type of the macro definition instantiated in the context of expandee):
+ //
+ // Test.scala:2: error: type mismatch;
+ // found : $u.Expr[Class[_ <: Object]]
+ // required: reflect.runtime.universe.Expr[Class[?0(in value <local Test>)]] where type ?0(in value <local Test>) <: Object
+ // scala.reflect.runtime.universe.reify(new Object().getClass)
+ // ^
+ // Therefore following Martin's advice I use this logic to recover from skolem errors after macro expansions
+ // (by adding the ` || tree.attachments.get[MacroExpansionAttachment].isDefined` clause to the conditional above).
+ //
log("recovering from existential or skolem type error in tree \n" + tree + "\nwith type " + tree.tpe + "\n expected type = " + pt + "\n context = " + context.tree)
return adapt(tree, mode, deriveTypeWithWildcards(boundOrSkolems)(pt))
}