From 6038bac3513a834e67ab4074c2c7b03aac11b1b3 Mon Sep 17 00:00:00 2001 From: Eugene Burmako Date: Wed, 2 Oct 2013 17:21:55 +0200 Subject: blackbox restriction #2: can't guide type inference MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When an application of a blackbox macro still has undetermined type parameters after Scala’s type inference algorithm has finished working, these type parameters are inferred forcedly, in exactly the same manner as type inference happens for normal methods. This makes it impossible for blackbox macros to influence type inference, prohibiting fundep materialization. --- .../files/run/macro-blackbox-materialization.check | 3 ++ .../macro-blackbox-materialization/Macros_1.scala | 16 +++++++++ .../macro-blackbox-materialization/Test_2.scala | 5 +++ .../macro-whitebox-fundep-materialization.check | 1 + .../Macros_1.scala | 39 ++++++++++++++++++++++ .../Test_2.scala | 12 +++++++ test/files/run/t5923c.check | 1 - test/files/run/t5923c.scala | 4 +++ test/files/run/t5923c/Macros_1.scala | 39 ---------------------- test/files/run/t5923c/Test_2.scala | 12 ------- 10 files changed, 80 insertions(+), 52 deletions(-) create mode 100644 test/files/run/macro-blackbox-materialization.check create mode 100644 test/files/run/macro-blackbox-materialization/Macros_1.scala create mode 100644 test/files/run/macro-blackbox-materialization/Test_2.scala create mode 100644 test/files/run/macro-whitebox-fundep-materialization.check create mode 100644 test/files/run/macro-whitebox-fundep-materialization/Macros_1.scala create mode 100644 test/files/run/macro-whitebox-fundep-materialization/Test_2.scala delete mode 100644 test/files/run/t5923c.check create mode 100644 test/files/run/t5923c.scala delete mode 100644 test/files/run/t5923c/Macros_1.scala delete mode 100644 test/files/run/t5923c/Test_2.scala (limited to 'test/files/run') diff --git a/test/files/run/macro-blackbox-materialization.check b/test/files/run/macro-blackbox-materialization.check new file mode 100644 index 0000000000..7165b734ac --- /dev/null +++ b/test/files/run/macro-blackbox-materialization.check @@ -0,0 +1,3 @@ +C(Int) +C(String) +C(Nothing) diff --git a/test/files/run/macro-blackbox-materialization/Macros_1.scala b/test/files/run/macro-blackbox-materialization/Macros_1.scala new file mode 100644 index 0000000000..7c31dd7dc2 --- /dev/null +++ b/test/files/run/macro-blackbox-materialization/Macros_1.scala @@ -0,0 +1,16 @@ +// For the full version of the test, take a look at run/t5923a + +import scala.reflect.macros.BlackboxContext +import language.experimental.macros + +case class C[T](t: String) +object C { + implicit def foo[T]: C[T] = macro Macros.impl[T] +} + +object Macros { + def impl[T: c.WeakTypeTag](c: BlackboxContext) = { + import c.universe._ + reify(C[T](c.literal(weakTypeOf[T].toString).splice)) + } +} \ No newline at end of file diff --git a/test/files/run/macro-blackbox-materialization/Test_2.scala b/test/files/run/macro-blackbox-materialization/Test_2.scala new file mode 100644 index 0000000000..001ff9aea8 --- /dev/null +++ b/test/files/run/macro-blackbox-materialization/Test_2.scala @@ -0,0 +1,5 @@ +object Test extends App { + println(implicitly[C[Int]]) + println(implicitly[C[String]]) + println(implicitly[C[Nothing]]) +} \ No newline at end of file diff --git a/test/files/run/macro-whitebox-fundep-materialization.check b/test/files/run/macro-whitebox-fundep-materialization.check new file mode 100644 index 0000000000..bed7429108 --- /dev/null +++ b/test/files/run/macro-whitebox-fundep-materialization.check @@ -0,0 +1 @@ +(23,foo,true) diff --git a/test/files/run/macro-whitebox-fundep-materialization/Macros_1.scala b/test/files/run/macro-whitebox-fundep-materialization/Macros_1.scala new file mode 100644 index 0000000000..671a4fff4e --- /dev/null +++ b/test/files/run/macro-whitebox-fundep-materialization/Macros_1.scala @@ -0,0 +1,39 @@ +import scala.language.experimental.macros +import scala.reflect.macros.WhiteboxContext + +trait Iso[T, U] { + def to(t : T) : U + // def from(u : U) : T +} + +object Iso { + implicit def materializeIso[T, U]: Iso[T, U] = macro impl[T, U] + def impl[T: c.WeakTypeTag, U: c.WeakTypeTag](c: WhiteboxContext): c.Expr[Iso[T, U]] = { + import c.universe._ + import definitions._ + import Flag._ + + val sym = c.weakTypeOf[T].typeSymbol + if (!sym.isClass || !sym.asClass.isCaseClass) c.abort(c.enclosingPosition, s"$sym is not a case class") + val fields = sym.typeSignature.declarations.toList.collect{ case x: TermSymbol if x.isVal && x.isCaseAccessor => x } + + def mkTpt() = { + val core = Ident(TupleClass(fields.length) orElse UnitClass) + if (fields.length == 0) core + else AppliedTypeTree(core, fields map (f => TypeTree(f.typeSignature))) + } + + def mkFrom() = { + if (fields.length == 0) Literal(Constant(Unit)) + else Apply(Ident(newTermName("Tuple" + fields.length)), fields map (f => Select(Ident(newTermName("f")), newTermName(f.name.toString.trim)))) + } + + val evidenceClass = ClassDef(Modifiers(FINAL), newTypeName("$anon"), List(), Template( + List(AppliedTypeTree(Ident(newTypeName("Iso")), List(Ident(sym), mkTpt()))), + emptyValDef, + List( + DefDef(Modifiers(), nme.CONSTRUCTOR, List(), List(List()), TypeTree(), Block(List(Apply(Select(Super(This(tpnme.EMPTY), tpnme.EMPTY), nme.CONSTRUCTOR), List())), Literal(Constant(())))), + DefDef(Modifiers(), newTermName("to"), List(), List(List(ValDef(Modifiers(PARAM), newTermName("f"), Ident(sym), EmptyTree))), TypeTree(), mkFrom())))) + c.Expr[Iso[T, U]](Block(List(evidenceClass), Apply(Select(New(Ident(newTypeName("$anon"))), nme.CONSTRUCTOR), List()))) + } +} diff --git a/test/files/run/macro-whitebox-fundep-materialization/Test_2.scala b/test/files/run/macro-whitebox-fundep-materialization/Test_2.scala new file mode 100644 index 0000000000..a00f4ed7db --- /dev/null +++ b/test/files/run/macro-whitebox-fundep-materialization/Test_2.scala @@ -0,0 +1,12 @@ +// see the comments for macroExpandApply.onDelayed for an explanation of what's tested here +object Test extends App { + case class Foo(i: Int, s: String, b: Boolean) + def foo[C, L](c: C)(implicit iso: Iso[C, L]): L = iso.to(c) + + { + val equiv = foo(Foo(23, "foo", true)) + def typed[T](t: => T) {} + typed[(Int, String, Boolean)](equiv) + println(equiv) + } +} \ No newline at end of file diff --git a/test/files/run/t5923c.check b/test/files/run/t5923c.check deleted file mode 100644 index bed7429108..0000000000 --- a/test/files/run/t5923c.check +++ /dev/null @@ -1 +0,0 @@ -(23,foo,true) diff --git a/test/files/run/t5923c.scala b/test/files/run/t5923c.scala new file mode 100644 index 0000000000..956b256785 --- /dev/null +++ b/test/files/run/t5923c.scala @@ -0,0 +1,4 @@ +// see neg/macro-blackbox-fundep-materialization and run/macro-whitebox-fundep-materialization +object Test extends App { + // do nothing +} \ No newline at end of file diff --git a/test/files/run/t5923c/Macros_1.scala b/test/files/run/t5923c/Macros_1.scala deleted file mode 100644 index c86e14966b..0000000000 --- a/test/files/run/t5923c/Macros_1.scala +++ /dev/null @@ -1,39 +0,0 @@ -import language.experimental.macros -import scala.reflect.macros.WhiteboxContext - -trait Iso[T, U] { - def to(t : T) : U - // def from(u : U) : T -} - -object Iso { - implicit def materializeIso[T, U]: Iso[T, U] = macro impl[T, U] - def impl[T: c.WeakTypeTag, U: c.WeakTypeTag](c: WhiteboxContext): c.Expr[Iso[T, U]] = { - import c.universe._ - import definitions._ - import Flag._ - - val sym = c.weakTypeOf[T].typeSymbol - if (!sym.isClass || !sym.asClass.isCaseClass) c.abort(c.enclosingPosition, s"$sym is not a case class") - val fields = sym.typeSignature.declarations.toList.collect{ case x: TermSymbol if x.isVal && x.isCaseAccessor => x } - - def mkTpt() = { - val core = Ident(TupleClass(fields.length) orElse UnitClass) - if (fields.length == 0) core - else AppliedTypeTree(core, fields map (f => TypeTree(f.typeSignature))) - } - - def mkFrom() = { - if (fields.length == 0) Literal(Constant(Unit)) - else Apply(Ident(newTermName("Tuple" + fields.length)), fields map (f => Select(Ident(newTermName("f")), newTermName(f.name.toString.trim)))) - } - - val evidenceClass = ClassDef(Modifiers(FINAL), newTypeName("$anon"), List(), Template( - List(AppliedTypeTree(Ident(newTypeName("Iso")), List(Ident(sym), mkTpt()))), - emptyValDef, - List( - DefDef(Modifiers(), nme.CONSTRUCTOR, List(), List(List()), TypeTree(), Block(List(Apply(Select(Super(This(tpnme.EMPTY), tpnme.EMPTY), nme.CONSTRUCTOR), List())), Literal(Constant(())))), - DefDef(Modifiers(), newTermName("to"), List(), List(List(ValDef(Modifiers(PARAM), newTermName("f"), Ident(sym), EmptyTree))), TypeTree(), mkFrom())))) - c.Expr[Iso[T, U]](Block(List(evidenceClass), Apply(Select(New(Ident(newTypeName("$anon"))), nme.CONSTRUCTOR), List()))) - } -} diff --git a/test/files/run/t5923c/Test_2.scala b/test/files/run/t5923c/Test_2.scala deleted file mode 100644 index a00f4ed7db..0000000000 --- a/test/files/run/t5923c/Test_2.scala +++ /dev/null @@ -1,12 +0,0 @@ -// see the comments for macroExpandApply.onDelayed for an explanation of what's tested here -object Test extends App { - case class Foo(i: Int, s: String, b: Boolean) - def foo[C, L](c: C)(implicit iso: Iso[C, L]): L = iso.to(c) - - { - val equiv = foo(Foo(23, "foo", true)) - def typed[T](t: => T) {} - typed[(Int, String, Boolean)](equiv) - println(equiv) - } -} \ No newline at end of file -- cgit v1.2.3