Skip to content

Commit 52ea3cc

Browse files
committed
Merge pull request scala#1338 from scalamacros/ticket/5418
existentially typed macro expansions now work fine
2 parents 4db37e4 + 862a1ed commit 52ea3cc

File tree

6 files changed

+31
-3
lines changed

6 files changed

+31
-3
lines changed

src/compiler/scala/tools/nsc/typechecker/Macros.scala

+2-2
Original file line numberDiff line numberDiff line change
@@ -710,7 +710,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
710710
if (isNullaryInvocation(expandee)) expectedTpe = expectedTpe.finalResultType
711711
var typechecked = typecheck("macro def return type", expanded, expectedTpe)
712712
typechecked = typecheck("expected type", typechecked, pt)
713-
typechecked updateAttachment MacroExpansionAttachment(expandee)
713+
typechecked
714714
} finally {
715715
popMacroContext()
716716
}
@@ -776,7 +776,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
776776
macroLogLite("" + expanded.tree + "\n" + showRaw(expanded.tree))
777777
val freeSyms = expanded.tree.freeTerms ++ expanded.tree.freeTypes
778778
freeSyms foreach (sym => MacroFreeSymbolError(expandee, sym))
779-
Success(atPos(enclosingMacroPosition.focus)(expanded.tree))
779+
Success(atPos(enclosingMacroPosition.focus)(expanded.tree updateAttachment MacroExpansionAttachment(expandee)))
780780
case _ =>
781781
MacroExpansionIsNotExprError(expandee, expanded)
782782
}

src/compiler/scala/tools/nsc/typechecker/Typers.scala

+12-1
Original file line numberDiff line numberDiff line change
@@ -1197,7 +1197,7 @@ trait Typers extends Modes with Adaptations with Tags {
11971197

11981198
val found = tree.tpe
11991199
if (!found.isErroneous && !pt.isErroneous) {
1200-
if (!context.reportErrors && isPastTyper) {
1200+
if ((!context.reportErrors && isPastTyper) || tree.attachments.get[MacroExpansionAttachment].isDefined) {
12011201
val (bound, req) = pt match {
12021202
case ExistentialType(qs, tpe) => (qs, tpe)
12031203
case _ => (Nil, pt)
@@ -1230,6 +1230,17 @@ trait Typers extends Modes with Adaptations with Tags {
12301230
// to consistently transform skolems and fix 6029), I'd like to
12311231
// investigate ways to avoid skolems completely.
12321232
//
1233+
// upd. The same problem happens when we try to typecheck the result of macro expansion against its expected type
1234+
// (which is the return type of the macro definition instantiated in the context of expandee):
1235+
//
1236+
// Test.scala:2: error: type mismatch;
1237+
// found : $u.Expr[Class[_ <: Object]]
1238+
// required: reflect.runtime.universe.Expr[Class[?0(in value <local Test>)]] where type ?0(in value <local Test>) <: Object
1239+
// scala.reflect.runtime.universe.reify(new Object().getClass)
1240+
// ^
1241+
// Therefore following Martin's advice I use this logic to recover from skolem errors after macro expansions
1242+
// (by adding the ` || tree.attachments.get[MacroExpansionAttachment].isDefined` clause to the conditional above).
1243+
//
12331244
log("recovering from existential or skolem type error in tree \n" + tree + "\nwith type " + tree.tpe + "\n expected type = " + pt + "\n context = " + context.tree)
12341245
return adapt(tree, mode, deriveTypeWithWildcards(boundOrSkolems)(pt))
12351246
}

test/files/run/t5418a.check

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Expr[Class[_ <: java.lang.Object]](new Object().getClass())

test/files/run/t5418a.scala

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
object Test extends App {
2+
println(scala.reflect.runtime.universe.reify(new Object().getClass))
3+
}

test/files/run/t5418b.check

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
new Object().getClass()
2+
TypeRef(ThisType(java.lang), java.lang.Class, List(TypeRef(NoPrefix, newTypeName("?0"), List())))

test/files/run/t5418b.scala

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import scala.reflect.runtime.universe._
2+
import scala.reflect.runtime.{currentMirror => cm}
3+
import scala.tools.reflect.ToolBox
4+
5+
object Test extends App {
6+
val tb = cm.mkToolBox()
7+
val untyped = reify(new Object().getClass).tree
8+
val typed = tb.typeCheck(untyped)
9+
println(typed)
10+
println(showRaw(typed.tpe))
11+
}

0 commit comments

Comments
 (0)