Skip to content

Commit aefdbd3

Browse files
committed
Merge pull request scala#2622 from scalamacros/pullrequest/paradise
Backport from paradise/macros
2 parents 5312d63 + a45d3e5 commit aefdbd3

File tree

11 files changed

+107
-57
lines changed

11 files changed

+107
-57
lines changed

src/compiler/scala/reflect/macros/util/Helpers.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ trait Helpers {
5454
*
5555
* @see Metalevels.scala for more information and examples about metalevels
5656
*/
57-
def increaseMetalevel(pre: Type, tp: Type): Type = dealiasAndRewrap(tp) {
57+
def increaseMetalevel(pre: Type, tp: Type): Type = transparentShallowTransform(RepeatedParamClass, tp) {
5858
case tp => typeRef(pre, MacroContextExprClass, List(tp))
5959
}
6060

@@ -64,8 +64,8 @@ trait Helpers {
6464
*
6565
* @see Metalevels.scala for more information and examples about metalevels
6666
*/
67-
def decreaseMetalevel(tp: Type): Type = dealiasAndRewrap(tp) {
67+
def decreaseMetalevel(tp: Type): Type = transparentShallowTransform(RepeatedParamClass, tp) {
6868
case ExprClassOf(runtimeType) => runtimeType
69-
case _ => AnyClass.tpe // so that macro impls with rhs = ??? don't screw up our inference
69+
case _ => AnyTpe // so that macro impls with rhs = ??? don't screw up our inference
7070
}
7171
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -782,7 +782,7 @@ trait ContextErrors {
782782
}
783783

784784
def MacroExpansionHasInvalidTypeError(expandee: Tree, expanded: Any) = {
785-
val expected = "expr"
785+
val expected = "expr or tree"
786786
val isPathMismatch = expanded != null && expanded.isInstanceOf[scala.reflect.api.Exprs#Expr[_]]
787787
macroExpansionError(expandee,
788788
s"macro must return a compiler-specific $expected; returned value is " + (

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

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -92,11 +92,12 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers {
9292
methName: String,
9393
// flattens the macro impl's parameter lists having symbols replaced with their fingerprints
9494
// currently fingerprints are calculated solely from types of the symbols:
95-
// * c.Expr[T] => IMPLPARAM_EXPR
96-
// * c.WeakTypeTag[T] => index of the type parameter corresponding to that type tag
97-
// * everything else (e.g. scala.reflect.macros.Context) => IMPLPARAM_OTHER
95+
// * c.Expr[T] => LiftedTyped
96+
// * c.Tree => LiftedUntyped
97+
// * c.WeakTypeTag[T] => Tagged(index of the type parameter corresponding to that type tag)
98+
// * everything else (e.g. scala.reflect.macros.Context) => Other
9899
// f.ex. for: def impl[T: WeakTypeTag, U, V: WeakTypeTag](c: Context)(x: c.Expr[T], y: c.Tree): (U, V) = ???
99-
// `signature` will be equal to List(List(Other), List(Lifted, Other), List(Tagged(0), Tagged(2)))
100+
// `signature` will be equal to List(List(Other), List(LiftedTyped, LiftedUntyped), List(Tagged(0), Tagged(2)))
100101
signature: List[List[Fingerprint]],
101102
// type arguments part of a macro impl ref (the right-hand side of a macro definition)
102103
// these trees don't refer to a macro impl, so we can pickle them as is
@@ -124,7 +125,7 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers {
124125
* "className" = "Macros$"))
125126
*/
126127
object MacroImplBinding {
127-
val versionFormat = 4.0
128+
val versionFormat = 5.0
128129

129130
def pickleAtom(obj: Any): Tree =
130131
obj match {
@@ -164,7 +165,8 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers {
164165
def signature: List[List[Fingerprint]] = {
165166
def fingerprint(tpe: Type): Fingerprint = tpe.dealiasWiden match {
166167
case TypeRef(_, RepeatedParamClass, underlying :: Nil) => fingerprint(underlying)
167-
case ExprClassOf(_) => Lifted
168+
case ExprClassOf(_) => LiftedTyped
169+
case TreeType() => LiftedUntyped
168170
case _ => Other
169171
}
170172

@@ -388,7 +390,8 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers {
388390
val wrappedArgs = mapWithIndex(args)((arg, j) => {
389391
val fingerprint = implParams(min(j, implParams.length - 1))
390392
fingerprint match {
391-
case Lifted => context.Expr[Nothing](arg)(TypeTag.Nothing) // TODO: SI-5752
393+
case LiftedTyped => context.Expr[Nothing](arg)(TypeTag.Nothing) // TODO: SI-5752
394+
case LiftedUntyped => arg
392395
case _ => abort(s"unexpected fingerprint $fingerprint in $binding with paramss being $paramss " +
393396
s"corresponding to arg $arg in $argss")
394397
}
@@ -690,6 +693,7 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers {
690693
}
691694
expanded match {
692695
case expanded: Expr[_] if expandee.symbol.isTermMacro => validateResultingTree(expanded.tree)
696+
case expanded: Tree if expandee.symbol.isTermMacro => validateResultingTree(expanded)
693697
case _ => MacroExpansionHasInvalidTypeError(expandee, expanded)
694698
}
695699
} catch {
@@ -804,16 +808,19 @@ class Fingerprint(val value: Int) extends AnyVal {
804808
def paramPos = { assert(isTag, this); value }
805809
def isTag = value >= 0
806810
def isOther = this == Other
807-
def isExpr = this == Lifted
811+
def isExpr = this == LiftedTyped
812+
def isTree = this == LiftedUntyped
808813
override def toString = this match {
809814
case Other => "Other"
810-
case Lifted => "Expr"
815+
case LiftedTyped => "Expr"
816+
case LiftedUntyped => "Tree"
811817
case _ => s"Tag($value)"
812818
}
813819
}
814820

815821
object Fingerprint {
816822
def Tagged(tparamPos: Int) = new Fingerprint(tparamPos)
817823
val Other = new Fingerprint(-1)
818-
val Lifted = new Fingerprint(-2)
824+
val LiftedTyped = new Fingerprint(-2)
825+
val LiftedUntyped = new Fingerprint(-3)
819826
}

src/reflect/scala/reflect/internal/Definitions.scala

Lines changed: 9 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -409,10 +409,6 @@ trait Definitions extends api.StandardDefinitions {
409409
lazy val JavaRepeatedParamClass = specialPolyClass(tpnme.JAVA_REPEATED_PARAM_CLASS_NAME, COVARIANT)(tparam => arrayType(tparam.tpe))
410410
lazy val RepeatedParamClass = specialPolyClass(tpnme.REPEATED_PARAM_CLASS_NAME, COVARIANT)(tparam => seqType(tparam.tpe))
411411

412-
def dropByName(tp: Type): Type = tp match {
413-
case TypeRef(_, ByNameParamClass, arg :: Nil) => arg
414-
case _ => tp
415-
}
416412
def isByNameParamType(tp: Type) = tp.typeSymbol == ByNameParamClass
417413
def isScalaRepeatedParamType(tp: Type) = tp.typeSymbol == RepeatedParamClass
418414
def isJavaRepeatedParamType(tp: Type) = tp.typeSymbol == JavaRepeatedParamClass
@@ -433,29 +429,15 @@ trait Definitions extends api.StandardDefinitions {
433429
case _ => false
434430
}
435431

436-
def repeatedToSingle(tp: Type): Type = tp match {
437-
case TypeRef(_, RepeatedParamClass, arg :: Nil) => arg
438-
case _ => tp
439-
}
440-
441-
def repeatedToSeq(tp: Type): Type = (tp baseType RepeatedParamClass) match {
442-
case TypeRef(_, RepeatedParamClass, arg :: Nil) => seqType(arg)
443-
case _ => tp
444-
}
445-
446-
def seqToRepeated(tp: Type): Type = (tp baseType SeqClass) match {
447-
case TypeRef(_, SeqClass, arg :: Nil) => scalaRepeatedType(arg)
448-
case _ => tp
449-
}
450-
451-
def isReferenceArray(tp: Type) = tp match {
452-
case TypeRef(_, ArrayClass, arg :: Nil) => arg <:< AnyRefTpe
453-
case _ => false
454-
}
455-
def isArrayOfSymbol(tp: Type, elem: Symbol) = tp match {
456-
case TypeRef(_, ArrayClass, arg :: Nil) => arg.typeSymbol == elem
457-
case _ => false
458-
}
432+
// wrapping and unwrapping
433+
def dropByName(tp: Type): Type = elementExtract(ByNameParamClass, tp) orElse tp
434+
def repeatedToSingle(tp: Type): Type = elementExtract(RepeatedParamClass, tp) orElse tp
435+
def repeatedToSeq(tp: Type): Type = elementTransform(RepeatedParamClass, tp)(seqType) orElse tp
436+
def seqToRepeated(tp: Type): Type = elementTransform(SeqClass, tp)(scalaRepeatedType) orElse tp
437+
def isReferenceArray(tp: Type) = elementTest(ArrayClass, tp)(_ <:< AnyRefTpe)
438+
def isArrayOfSymbol(tp: Type, elem: Symbol) = elementTest(ArrayClass, tp)(_.typeSymbol == elem)
439+
def elementType(container: Symbol, tp: Type): Type = elementExtract(container, tp)
440+
object ExprClassOf { def unapply(tp: Type): Option[Type] = elementExtractOption(ExprClass, tp) }
459441

460442
// collections classes
461443
lazy val ConsClass = requiredClass[scala.collection.immutable.::[_]]
@@ -514,13 +496,6 @@ trait Definitions extends api.StandardDefinitions {
514496
lazy val ExprClass = ExprsClass.map(sym => getMemberClass(sym, tpnme.Expr))
515497
def ExprSplice = ExprClass.map(sym => getMemberMethod(sym, nme.splice))
516498
def ExprValue = ExprClass.map(sym => getMemberMethod(sym, nme.value))
517-
object ExprClassOf {
518-
def unapply(tpe: Type): Option[Type] = tpe.dealias match {
519-
case ExistentialType(_, underlying) => unapply(underlying)
520-
case TypeRef(_, ExprClass, t :: Nil) => Some(t)
521-
case _ => None
522-
}
523-
}
524499

525500
lazy val ClassTagModule = requiredModule[scala.reflect.ClassTag[_]]
526501
lazy val ClassTagClass = requiredClass[scala.reflect.ClassTag[_]]
@@ -709,11 +684,6 @@ trait Definitions extends api.StandardDefinitions {
709684
(sym eq PartialFunctionClass) || (sym eq AbstractPartialFunctionClass)
710685
}
711686

712-
def elementType(container: Symbol, tp: Type): Type = tp match {
713-
case TypeRef(_, `container`, arg :: Nil) => arg
714-
case _ => NoType
715-
}
716-
717687
def arrayType(arg: Type) = appliedType(ArrayClass, arg)
718688
def byNameType(arg: Type) = appliedType(ByNameParamClass, arg)
719689
def iteratorOfType(tp: Type) = appliedType(IteratorClass, tp)

src/reflect/scala/reflect/internal/TreeInfo.scala

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -837,11 +837,12 @@ abstract class TreeInfo {
837837

838838
def unapply(tree: Tree) = refPart(tree) match {
839839
case ref: RefTree => {
840-
val isBundle = definitions.isMacroBundleType(ref.qualifier.tpe)
840+
val qual = ref.qualifier
841+
val isBundle = definitions.isMacroBundleType(qual.tpe)
841842
val owner =
842-
if (isBundle) ref.qualifier.tpe.typeSymbol
843+
if (isBundle) qual.tpe.typeSymbol
843844
else {
844-
val sym = ref.qualifier.symbol
845+
val sym = if (qual.hasSymbolField) qual.symbol else NoSymbol
845846
if (sym.isModule) sym.moduleClass else sym
846847
}
847848
Some((isBundle, owner, ref.symbol, dissectApplied(tree).targs))

src/reflect/scala/reflect/internal/Types.scala

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2455,6 +2455,7 @@ trait Types
24552455
else
24562456
super.prefixString
24572457
)
2458+
def copy(pre: Type = this.pre, sym: Symbol = this.sym, args: List[Type] = this.args) = TypeRef(pre, sym, args)
24582459
override def kind = "TypeRef"
24592460
}
24602461

@@ -3718,6 +3719,43 @@ trait Types
37183719
object unwrapToStableClass extends ClassUnwrapper(existential = false) { }
37193720
object unwrapWrapperTypes extends TypeUnwrapper(true, true, true, true) { }
37203721

3722+
def elementExtract(container: Symbol, tp: Type): Type = {
3723+
assert(!container.isAliasType, container)
3724+
unwrapWrapperTypes(tp baseType container).dealiasWiden match {
3725+
case TypeRef(_, `container`, arg :: Nil) => arg
3726+
case _ => NoType
3727+
}
3728+
}
3729+
def elementExtractOption(container: Symbol, tp: Type): Option[Type] = {
3730+
elementExtract(container, tp) match {
3731+
case NoType => None
3732+
case tp => Some(tp)
3733+
}
3734+
}
3735+
def elementTest(container: Symbol, tp: Type)(f: Type => Boolean): Boolean = {
3736+
elementExtract(container, tp) match {
3737+
case NoType => false
3738+
case tp => f(tp)
3739+
}
3740+
}
3741+
def elementTransform(container: Symbol, tp: Type)(f: Type => Type): Type = {
3742+
elementExtract(container, tp) match {
3743+
case NoType => NoType
3744+
case tp => f(tp)
3745+
}
3746+
}
3747+
3748+
def transparentShallowTransform(container: Symbol, tp: Type)(f: Type => Type): Type = {
3749+
def loop(tp: Type): Type = tp match {
3750+
case tp @ AnnotatedType(_, underlying, _) => tp.copy(underlying = loop(underlying))
3751+
case tp @ ExistentialType(_, underlying) => tp.copy(underlying = loop(underlying))
3752+
case tp @ PolyType(_, resultType) => tp.copy(resultType = loop(resultType))
3753+
case tp @ NullaryMethodType(resultType) => tp.copy(resultType = loop(resultType))
3754+
case tp => elementTransform(container, tp)(el => appliedType(container, f(el))).orElse(f(tp))
3755+
}
3756+
loop(tp)
3757+
}
3758+
37213759
/** Repack existential types, otherwise they sometimes get unpacked in the
37223760
* wrong location (type inference comes up with an unexpected skolem)
37233761
*/

test/files/neg/macro-invalidshape.check

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,9 @@ Macros_Test_2.scala:4: error: missing arguments for method foo in object Impls;
1212
follow this method with `_' if you want to treat it as a partially applied function
1313
def foo3(x: Any) = macro {2; Impls.foo}
1414
^
15-
three errors found
15+
Macros_Test_2.scala:7: error: macro implementation reference has wrong shape. required:
16+
macro [<static object>].<method name>[[<type args>]] or
17+
macro [<macro bundle>].<method name>[[<type args>]]
18+
def foo = macro impl
19+
^
20+
four errors found

test/files/neg/macro-invalidshape/Macros_Test_2.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@ object Macros {
22
def foo1(x: Any) = macro 2
33
def foo2(x: Any) = macro Impls.foo(null)(null)
44
def foo3(x: Any) = macro {2; Impls.foo}
5+
{
6+
def impl(c: scala.reflect.macros.Context) = c.literalUnit
7+
def foo = macro impl
8+
foo
9+
}
510
}
611

712
object Test extends App {
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
2
2+
2
3+
2
4+
2
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import language.experimental.macros
2+
import scala.reflect.macros.Context
3+
4+
object Macros {
5+
def implUU(c: Context)(x: c.Tree): c.Tree = x
6+
def implTU(c: Context)(x: c.Expr[Int]): c.Tree = x.tree
7+
def implUT(c: Context)(x: c.Tree): c.Expr[Int] = c.Expr[Int](x)
8+
def implTT(c: Context)(x: c.Expr[Int]): c.Expr[Int] = x
9+
10+
def fooUU(x: Int): Int = macro implUU
11+
def fooTU(x: Int): Int = macro implTU
12+
def fooUT(x: Int): Int = macro implUT
13+
def fooTT(x: Int): Int = macro implTT
14+
}

0 commit comments

Comments
 (0)