Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

SI-5923 adapt macros when they are deferred

Amazingly enough, the fix for the "macro not expanded" problem was super
easy. (And I remember spending a day or two trying to find a quick fix
somewhen around Scala Days 2012!)

The problem was in the implementation of the macro expansion trigger,
which was buried in a chain of if-elif-elif. This meant that macro
expansion was mutually exclusive with a lot of important adaptations, e.g.
with `instantiate`.

More precisely, if an expandee contains an undetparam, its expansion
should be delayed until all its undetparams are inferred and then retried
later. Sometimes such inference can only happen upon a call to instantiate
in one of the elif's coming after the macro expansion elif. However this
elif would never be called for expandees, because control flow would always
enter the macro expansion branch preceding the inference branch.

Consequences of this fix are vast. First of all, we can get rid of the
"type parameter must be specified" hack. Secondly and most importantly,
we can now remove the `materializeImplicit` method from Implicits and
rely on implicit macros to materialize tags for us. (This is a tricky
change, and I'll do it later after we merge as much of my pending work
as possible). Finally, we learn that the current scheme of interaction
between macros, type inference and implicits is, in principle, sound!
  • Loading branch information...
commit fe6028476931b031e712c37d3e570125b1d034ae 1 parent 30e2e3a
@xeno-by xeno-by authored
View
6 src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala
@@ -77,11 +77,7 @@ abstract class Pickler extends SubComponent {
}
if (!t.isDef && t.hasSymbolField && t.symbol.isTermMacro) {
- unit.error(t.pos, t.symbol.typeParams.length match {
- case 0 => "macro has not been expanded"
- case 1 => "this type parameter must be specified"
- case _ => "these type parameters must be specified"
- })
+ unit.error(t.pos, "macro has not been expanded")
return
}
}
View
6 src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -1061,6 +1061,7 @@ trait Typers extends Modes with Adaptations with Tags {
instantiateToMethodType(mt)
case _ =>
+ def vanillaAdapt(tree: Tree) = {
def shouldInsertApply(tree: Tree) = inAllModes(mode, EXPRmode | FUNmode) && (tree.tpe match {
case _: MethodType | _: OverloadedType | _: PolyType => false
case _ => applyPossible
@@ -1076,8 +1077,6 @@ trait Typers extends Modes with Adaptations with Tags {
}
if (tree.isType)
adaptType()
- else if (inExprModeButNot(mode, FUNmode) && treeInfo.isMacroApplication(tree))
- macroExpandApply(this, tree, mode, pt)
else if (inAllModes(mode, PATTERNmode | FUNmode))
adaptConstrPattern()
else if (shouldInsertApply(tree))
@@ -1206,6 +1205,9 @@ trait Typers extends Modes with Adaptations with Tags {
}
fallBack
}
+ }
+ val tree1 = if (inExprModeButNot(mode, FUNmode) && treeInfo.isMacroApplication(tree)) macroExpandApply(this, tree, mode, pt) else tree
+ if (tree == tree1) vanillaAdapt(tree1) else tree1
}
}
View
2  test/files/neg/t5353.check
@@ -1,4 +1,4 @@
-t5353.scala:2: error: this type parameter must be specified
+t5353.scala:2: error: macro has not been expanded
def f(x: Boolean) = if (x) Array("abc") else Array()
^
one error found
View
0  test/files/neg/t5692a.check → test/files/pos/t5692a.check
File renamed without changes
View
0  test/files/neg/t5692a.flags → test/files/pos/t5692a.flags
File renamed without changes
View
0  test/files/neg/t5692a/Macros_1.scala → test/files/pos/t5692a/Macros_1.scala
File renamed without changes
View
0  test/files/neg/t5692b/Test_2.scala → test/files/pos/t5692a/Test_2.scala
File renamed without changes
View
0  test/files/neg/t5692b.check → test/files/pos/t5692b.check
File renamed without changes
View
0  test/files/neg/t5692b.flags → test/files/pos/t5692b.flags
File renamed without changes
View
0  test/files/neg/t5692b/Macros_1.scala → test/files/pos/t5692b/Macros_1.scala
File renamed without changes
View
0  test/files/neg/t5692a/Test_2.scala → test/files/pos/t5692b/Test_2.scala
File renamed without changes
Please sign in to comment.
Something went wrong with that request. Please try again.