summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Macros.scala11
-rw-r--r--test/files/neg/macro-blackbox-fundep-materialization.check12
-rw-r--r--test/files/neg/macro-blackbox-fundep-materialization.flags1
-rw-r--r--test/files/neg/macro-blackbox-fundep-materialization/Macros_1.scala39
-rw-r--r--test/files/neg/macro-blackbox-fundep-materialization/Test_2.scala (renamed from test/files/run/t5923c/Test_2.scala)0
-rw-r--r--test/files/run/macro-blackbox-materialization.check3
-rw-r--r--test/files/run/macro-blackbox-materialization/Macros_1.scala16
-rw-r--r--test/files/run/macro-blackbox-materialization/Test_2.scala5
-rw-r--r--test/files/run/macro-whitebox-fundep-materialization.check (renamed from test/files/run/t5923c.check)0
-rw-r--r--test/files/run/macro-whitebox-fundep-materialization/Macros_1.scala (renamed from test/files/run/t5923c/Macros_1.scala)2
-rw-r--r--test/files/run/macro-whitebox-fundep-materialization/Test_2.scala12
-rw-r--r--test/files/run/t5923c.scala4
12 files changed, 100 insertions, 5 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Macros.scala b/src/compiler/scala/tools/nsc/typechecker/Macros.scala
index 57358f72f5..27920dbd74 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Macros.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Macros.scala
@@ -678,7 +678,7 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers {
// e.g. for Foo it will be Int :: String :: Boolean :: HNil), there's no way to convey this information
// to the typechecker. Therefore the typechecker will infer Nothing for L, which is hardly what we want.
//
- // =========== THE SOLUTION ===========
+ // =========== THE SOLUTION (ENABLED ONLY FOR WHITEBOX MACROS) ===========
//
// To give materializers a chance to say their word before vanilla inference kicks in,
// we infer as much as possible (e.g. in the example above even though L is hopeless, C still can be inferred to Foo)
@@ -686,9 +686,12 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers {
// Thanks to that the materializer can take a look at what's going on and react accordingly.
val shouldInstantiate = typer.context.undetparams.nonEmpty && !mode.inPolyMode
if (shouldInstantiate) {
- forced += delayed
- typer.infer.inferExprInstance(delayed, typer.context.extractUndetparams(), pt, keepNothings = false)
- macroExpandApply(typer, delayed, mode, pt)
+ if (isBlackbox(expandee)) typer.instantiatePossiblyExpectingUnit(delayed, mode, pt)
+ else {
+ forced += delayed
+ typer.infer.inferExprInstance(delayed, typer.context.extractUndetparams(), pt, keepNothings = false)
+ macroExpandApply(typer, delayed, mode, pt)
+ }
} else delayed
}
}
diff --git a/test/files/neg/macro-blackbox-fundep-materialization.check b/test/files/neg/macro-blackbox-fundep-materialization.check
new file mode 100644
index 0000000000..a5a9b9a206
--- /dev/null
+++ b/test/files/neg/macro-blackbox-fundep-materialization.check
@@ -0,0 +1,12 @@
+Test_2.scala:7: Iso.materializeIso is not a valid implicit value for Iso[Test.Foo,L] because:
+hasMatchingSymbol reported error: type mismatch;
+ found : Iso[Test.Foo,(Int, String, Boolean)]
+ required: Iso[Test.Foo,Nothing]
+Note: (Int, String, Boolean) >: Nothing, but trait Iso is invariant in type U.
+You may wish to define U as -U instead. (SLS 4.5)
+ val equiv = foo(Foo(23, "foo", true))
+ ^
+Test_2.scala:7: error: could not find implicit value for parameter iso: Iso[Test.Foo,L]
+ val equiv = foo(Foo(23, "foo", true))
+ ^
+one error found
diff --git a/test/files/neg/macro-blackbox-fundep-materialization.flags b/test/files/neg/macro-blackbox-fundep-materialization.flags
new file mode 100644
index 0000000000..4c6cdb71e2
--- /dev/null
+++ b/test/files/neg/macro-blackbox-fundep-materialization.flags
@@ -0,0 +1 @@
+-Xlog-implicits \ No newline at end of file
diff --git a/test/files/neg/macro-blackbox-fundep-materialization/Macros_1.scala b/test/files/neg/macro-blackbox-fundep-materialization/Macros_1.scala
new file mode 100644
index 0000000000..6bddef4b9d
--- /dev/null
+++ b/test/files/neg/macro-blackbox-fundep-materialization/Macros_1.scala
@@ -0,0 +1,39 @@
+import scala.language.experimental.macros
+import scala.reflect.macros.BlackboxContext
+
+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: BlackboxContext): 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/neg/macro-blackbox-fundep-materialization/Test_2.scala
index a00f4ed7db..a00f4ed7db 100644
--- a/test/files/run/t5923c/Test_2.scala
+++ b/test/files/neg/macro-blackbox-fundep-materialization/Test_2.scala
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/t5923c.check b/test/files/run/macro-whitebox-fundep-materialization.check
index bed7429108..bed7429108 100644
--- a/test/files/run/t5923c.check
+++ b/test/files/run/macro-whitebox-fundep-materialization.check
diff --git a/test/files/run/t5923c/Macros_1.scala b/test/files/run/macro-whitebox-fundep-materialization/Macros_1.scala
index c86e14966b..671a4fff4e 100644
--- a/test/files/run/t5923c/Macros_1.scala
+++ b/test/files/run/macro-whitebox-fundep-materialization/Macros_1.scala
@@ -1,4 +1,4 @@
-import language.experimental.macros
+import scala.language.experimental.macros
import scala.reflect.macros.WhiteboxContext
trait Iso[T, U] {
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.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