summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Implicits.scala41
-rw-r--r--src/reflect/scala/reflect/macros/Enclosures.scala12
-rw-r--r--src/reflect/scala/reflect/macros/Typers.scala21
-rw-r--r--src/reflect/scala/reflect/macros/WhiteboxContext.scala33
-rw-r--r--test/files/neg/macro-blackbox-dynamic-materialization.check4
-rw-r--r--test/files/neg/macro-blackbox-dynamic-materialization/Macros_1.scala25
-rw-r--r--test/files/neg/macro-blackbox-dynamic-materialization/Test_2.scala4
-rw-r--r--test/files/neg/macro-blackbox-fundep-materialization.check6
-rw-r--r--test/files/neg/macro-divergence-controlled/Impls_Macros_1.scala4
-rw-r--r--test/files/run/macro-sip19-revised/Impls_Macros_1.scala4
-rw-r--r--test/files/run/macro-sip19/Impls_Macros_1.scala4
-rw-r--r--test/files/run/macro-whitebox-dynamic-materialization.check2
-rw-r--r--test/files/run/macro-whitebox-dynamic-materialization/Macros_1.scala25
-rw-r--r--test/files/run/macro-whitebox-dynamic-materialization/Test_2.scala4
14 files changed, 125 insertions, 64 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
index c9dbdb93ff..01acbb8cc2 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
@@ -596,7 +596,7 @@ trait Implicits {
// workaround for deficient context provided by ModelFactoryImplicitSupport#makeImplicitConstraints
val isScalaDoc = context.tree == EmptyTree
- val itree = atPos(pos.focus) {
+ val itree0 = atPos(pos.focus) {
if (isLocal && !isScalaDoc) {
// SI-4270 SI-5376 Always use an unattributed Ident for implicits in the local scope,
// rather than an attributed Select, to detect shadowing.
@@ -608,15 +608,16 @@ trait Implicits {
Select(gen.mkAttributedQualifier(info.pre), implicitMemberName)
}
}
- typingLog("considering", typeDebug.ptTree(itree))
+ val itree1 = if (isBlackbox(info.sym)) suppressMacroExpansion(itree0) else itree0
+ typingLog("considering", typeDebug.ptTree(itree1))
- def fail(reason: String): SearchResult = failure(itree, reason)
- def fallback = typed1(itree, EXPRmode, wildPt)
+ def fail(reason: String): SearchResult = failure(itree0, reason)
+ def fallback = typed1(itree1, EXPRmode, wildPt)
try {
- val itree1 = if (!isView) fallback else pt match {
+ val itree2 = if (!isView) fallback else pt match {
case Function1(arg1, arg2) =>
typed1(
- atPos(itree.pos)(Apply(itree, List(Ident("<argument>") setType approximate(arg1)))),
+ atPos(itree0.pos)(Apply(itree1, List(Ident("<argument>") setType approximate(arg1)))),
EXPRmode,
approximate(arg2)
) match {
@@ -647,10 +648,10 @@ trait Implicits {
if (Statistics.canEnable) Statistics.incCounter(typedImplicits)
- val itree2 = if (isView) treeInfo.dissectApplied(itree1).callee
- else adapt(itree1, EXPRmode, wildPt)
+ val itree3 = if (isView) treeInfo.dissectApplied(itree2).callee
+ else adapt(itree2, EXPRmode, wildPt)
- typingStack.showAdapt(itree, itree2, pt, context)
+ typingStack.showAdapt(itree0, itree3, pt, context)
def hasMatchingSymbol(tree: Tree): Boolean = (tree.symbol == info.sym) || {
tree match {
@@ -663,21 +664,21 @@ trait Implicits {
if (context.hasErrors)
fail("hasMatchingSymbol reported error: " + context.firstError.get.errMsg)
- else if (isLocal && !hasMatchingSymbol(itree1))
+ else if (isLocal && !hasMatchingSymbol(itree2))
fail("candidate implicit %s is shadowed by %s".format(
- info.sym.fullLocationString, itree1.symbol.fullLocationString))
+ info.sym.fullLocationString, itree2.symbol.fullLocationString))
else {
val tvars = undetParams map freshVar
def ptInstantiated = pt.instantiateTypeParams(undetParams, tvars)
- if (matchesPt(itree2.tpe, ptInstantiated, undetParams)) {
+ if (matchesPt(itree3.tpe, ptInstantiated, undetParams)) {
if (tvars.nonEmpty)
typingLog("solve", ptLine("tvars" -> tvars, "tvars.constr" -> tvars.map(_.constr)))
- val targs = solvedTypes(tvars, undetParams, undetParams map varianceInType(pt), upper = false, lubDepth(itree2.tpe :: pt :: Nil))
+ val targs = solvedTypes(tvars, undetParams, undetParams map varianceInType(pt), upper = false, lubDepth(itree3.tpe :: pt :: Nil))
// #2421: check that we correctly instantiated type parameters outside of the implicit tree:
- checkBounds(itree2, NoPrefix, NoSymbol, undetParams, targs, "inferred ")
+ checkBounds(itree3, NoPrefix, NoSymbol, undetParams, targs, "inferred ")
context.firstError match {
case Some(err) =>
return fail("type parameters weren't correctly instantiated outside of the implicit tree: " + err.errMsg)
@@ -693,7 +694,7 @@ trait Implicits {
if (okParams.isEmpty) EmptyTreeTypeSubstituter
else {
val subst = new TreeTypeSubstituter(okParams, okArgs)
- subst traverse itree2
+ subst traverse itree3
notifyUndetparamsInferred(okParams, okArgs)
subst
}
@@ -711,9 +712,9 @@ trait Implicits {
// This is just called for the side effect of error detection,
// see SI-6966 to see what goes wrong if we use the result of this
// as the SearchResult.
- itree2 match {
- case TypeApply(fun, args) => typedTypeApply(itree2, EXPRmode, fun, args)
- case Apply(TypeApply(fun, args), _) => typedTypeApply(itree2, EXPRmode, fun, args) // t2421c
+ itree3 match {
+ case TypeApply(fun, args) => typedTypeApply(itree3, EXPRmode, fun, args)
+ case Apply(TypeApply(fun, args), _) => typedTypeApply(itree3, EXPRmode, fun, args) // t2421c
case t => t
}
@@ -721,13 +722,13 @@ trait Implicits {
case Some(err) =>
fail("typing TypeApply reported errors for the implicit tree: " + err.errMsg)
case None =>
- val result = new SearchResult(itree2, subst)
+ val result = new SearchResult(unsuppressMacroExpansion(itree3), subst)
if (Statistics.canEnable) Statistics.incCounter(foundImplicits)
typingLog("success", s"inferred value of type $ptInstantiated is $result")
result
}
}
- else fail("incompatible: %s does not match expected type %s".format(itree2.tpe, ptInstantiated))
+ else fail("incompatible: %s does not match expected type %s".format(itree3.tpe, ptInstantiated))
}
}
catch {
diff --git a/src/reflect/scala/reflect/macros/Enclosures.scala b/src/reflect/scala/reflect/macros/Enclosures.scala
index c3d019ccf3..31905c4739 100644
--- a/src/reflect/scala/reflect/macros/Enclosures.scala
+++ b/src/reflect/scala/reflect/macros/Enclosures.scala
@@ -45,18 +45,6 @@ trait Enclosures {
*/
def enclosingMacros: List[BlackboxContext]
- /** Information about one of the currently considered implicit candidates.
- * Candidates are used in plural form, because implicit parameters may themselves have implicit parameters,
- * hence implicit searches can recursively trigger other implicit searches.
- *
- * Can be useful to get information about an application with an implicit parameter that is materialized during current macro expansion.
- * If we're in an implicit macro being expanded, it's included in this list.
- *
- * Unlike `openImplicits`, this is a val, which means that it gets initialized when the context is created
- * and always stays the same regardless of whatever happens during macro expansion.
- */
- def enclosingImplicits: List[ImplicitCandidate]
-
/** Tries to guess a position for the enclosing application.
* But that is simple, right? Just dereference `pos` of `macroApplication`? Not really.
* If we're in a synthetic macro expansion (no positions), we must do our best to infer the position of something that triggerd this expansion.
diff --git a/src/reflect/scala/reflect/macros/Typers.scala b/src/reflect/scala/reflect/macros/Typers.scala
index ec90ee8fe6..29c1af110b 100644
--- a/src/reflect/scala/reflect/macros/Typers.scala
+++ b/src/reflect/scala/reflect/macros/Typers.scala
@@ -23,27 +23,6 @@ trait Typers {
*/
def openMacros: List[BlackboxContext]
- /** Information about one of the currently considered implicit candidates.
- * Candidates are used in plural form, because implicit parameters may themselves have implicit parameters,
- * hence implicit searches can recursively trigger other implicit searches.
- *
- * `pre` and `sym` provide information about the candidate itself.
- * `pt` and `tree` store the parameters of the implicit search the candidate is participating in.
- */
- case class ImplicitCandidate(pre: Type, sym: Symbol, pt: Type, tree: Tree)
-
- /** Information about one of the currently considered implicit candidates.
- * Candidates are used in plural form, because implicit parameters may themselves have implicit parameters,
- * hence implicit searches can recursively trigger other implicit searches.
- *
- * Can be useful to get information about an application with an implicit parameter that is materialized during current macro expansion.
- * If we're in an implicit macro being expanded, it's included in this list.
- *
- * Unlike `enclosingImplicits`, this is a def, which means that it gets recalculated on every invocation,
- * so it might change depending on what is going on during macro expansion.
- */
- def openImplicits: List[ImplicitCandidate]
-
/** Typechecks the provided tree against the expected type `pt` in the macro callsite context.
*
* If `silent` is false, `TypecheckException` will be thrown in case of a typecheck error.
diff --git a/src/reflect/scala/reflect/macros/WhiteboxContext.scala b/src/reflect/scala/reflect/macros/WhiteboxContext.scala
index 76bc17746c..9d65a5c16e 100644
--- a/src/reflect/scala/reflect/macros/WhiteboxContext.scala
+++ b/src/reflect/scala/reflect/macros/WhiteboxContext.scala
@@ -40,4 +40,37 @@ trait WhiteboxContext extends BlackboxContext {
/** @inheritdoc
*/
def enclosingMacros: List[WhiteboxContext]
+
+ /** Information about one of the currently considered implicit candidates.
+ * Candidates are used in plural form, because implicit parameters may themselves have implicit parameters,
+ * hence implicit searches can recursively trigger other implicit searches.
+ *
+ * `pre` and `sym` provide information about the candidate itself.
+ * `pt` and `tree` store the parameters of the implicit search the candidate is participating in.
+ */
+ case class ImplicitCandidate(pre: Type, sym: Symbol, pt: Type, tree: Tree)
+
+ /** Information about one of the currently considered implicit candidates.
+ * Candidates are used in plural form, because implicit parameters may themselves have implicit parameters,
+ * hence implicit searches can recursively trigger other implicit searches.
+ *
+ * Can be useful to get information about an application with an implicit parameter that is materialized during current macro expansion.
+ * If we're in an implicit macro being expanded, it's included in this list.
+ *
+ * Unlike `enclosingImplicits`, this is a def, which means that it gets recalculated on every invocation,
+ * so it might change depending on what is going on during macro expansion.
+ */
+ def openImplicits: List[ImplicitCandidate]
+
+ /** Information about one of the currently considered implicit candidates.
+ * Candidates are used in plural form, because implicit parameters may themselves have implicit parameters,
+ * hence implicit searches can recursively trigger other implicit searches.
+ *
+ * Can be useful to get information about an application with an implicit parameter that is materialized during current macro expansion.
+ * If we're in an implicit macro being expanded, it's included in this list.
+ *
+ * Unlike `openImplicits`, this is a val, which means that it gets initialized when the context is created
+ * and always stays the same regardless of whatever happens during macro expansion.
+ */
+ def enclosingImplicits: List[ImplicitCandidate]
} \ No newline at end of file
diff --git a/test/files/neg/macro-blackbox-dynamic-materialization.check b/test/files/neg/macro-blackbox-dynamic-materialization.check
new file mode 100644
index 0000000000..f6c73f7edb
--- /dev/null
+++ b/test/files/neg/macro-blackbox-dynamic-materialization.check
@@ -0,0 +1,4 @@
+Test_2.scala:2: error: I don't like classes that contain integers
+ println(implicitly[Foo[C1]])
+ ^
+one error found
diff --git a/test/files/neg/macro-blackbox-dynamic-materialization/Macros_1.scala b/test/files/neg/macro-blackbox-dynamic-materialization/Macros_1.scala
new file mode 100644
index 0000000000..a00d195005
--- /dev/null
+++ b/test/files/neg/macro-blackbox-dynamic-materialization/Macros_1.scala
@@ -0,0 +1,25 @@
+import scala.reflect.macros.BlackboxContext
+import scala.language.experimental.macros
+
+trait Foo[T]
+
+class C1(val x: Int)
+class C2(val x: String)
+
+trait LowPriority {
+ implicit def lessSpecific[T]: Foo[T] = null
+}
+
+object Foo extends LowPriority {
+ implicit def moreSpecific[T]: Foo[T] = macro Macros.impl[T]
+}
+
+object Macros {
+ def impl[T: c.WeakTypeTag](c: BlackboxContext) = {
+ import c.universe._
+ val tpe = weakTypeOf[T]
+ if (tpe.members.exists(_.typeSignature =:= typeOf[Int]))
+ c.abort(c.enclosingPosition, "I don't like classes that contain integers")
+ q"new Foo[$tpe]{ override def toString = ${tpe.toString} }"
+ }
+} \ No newline at end of file
diff --git a/test/files/neg/macro-blackbox-dynamic-materialization/Test_2.scala b/test/files/neg/macro-blackbox-dynamic-materialization/Test_2.scala
new file mode 100644
index 0000000000..bf19209ab7
--- /dev/null
+++ b/test/files/neg/macro-blackbox-dynamic-materialization/Test_2.scala
@@ -0,0 +1,4 @@
+object Test extends App {
+ println(implicitly[Foo[C1]])
+ println(implicitly[Foo[C2]])
+} \ No newline at end of file
diff --git a/test/files/neg/macro-blackbox-fundep-materialization.check b/test/files/neg/macro-blackbox-fundep-materialization.check
index a5a9b9a206..3c03064a2d 100644
--- a/test/files/neg/macro-blackbox-fundep-materialization.check
+++ b/test/files/neg/macro-blackbox-fundep-materialization.check
@@ -1,12 +1,8 @@
-Test_2.scala:7: Iso.materializeIso is not a valid implicit value for Iso[Test.Foo,L] because:
-hasMatchingSymbol reported error: type mismatch;
+Test_2.scala:7: 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-divergence-controlled/Impls_Macros_1.scala b/test/files/neg/macro-divergence-controlled/Impls_Macros_1.scala
index 23fcdd6445..9fb374800b 100644
--- a/test/files/neg/macro-divergence-controlled/Impls_Macros_1.scala
+++ b/test/files/neg/macro-divergence-controlled/Impls_Macros_1.scala
@@ -1,4 +1,4 @@
-import scala.reflect.macros.BlackboxContext
+import scala.reflect.macros.WhiteboxContext
import language.experimental.macros
trait Complex[T]
@@ -6,7 +6,7 @@ trait Complex[T]
class Foo(val foo: Foo)
object Complex {
- def impl[T: c.WeakTypeTag](c: BlackboxContext): c.Expr[Complex[T]] = {
+ def impl[T: c.WeakTypeTag](c: WhiteboxContext): c.Expr[Complex[T]] = {
import c.universe._
val tpe = weakTypeOf[T]
for (f <- tpe.declarations.collect{case f: TermSymbol if f.isParamAccessor && !f.isMethod => f}) {
diff --git a/test/files/run/macro-sip19-revised/Impls_Macros_1.scala b/test/files/run/macro-sip19-revised/Impls_Macros_1.scala
index 870930c7e5..3acc52dbe0 100644
--- a/test/files/run/macro-sip19-revised/Impls_Macros_1.scala
+++ b/test/files/run/macro-sip19-revised/Impls_Macros_1.scala
@@ -1,7 +1,7 @@
-import scala.reflect.macros.BlackboxContext
+import scala.reflect.macros.WhiteboxContext
object Macros {
- def impl(c: BlackboxContext) = {
+ def impl(c: WhiteboxContext) = {
import c.universe._
val inscope = c.inferImplicitValue(c.mirror.staticClass("SourceLocation").toType)
diff --git a/test/files/run/macro-sip19/Impls_Macros_1.scala b/test/files/run/macro-sip19/Impls_Macros_1.scala
index 72a3c2568d..f830d2af0d 100644
--- a/test/files/run/macro-sip19/Impls_Macros_1.scala
+++ b/test/files/run/macro-sip19/Impls_Macros_1.scala
@@ -1,7 +1,7 @@
-import scala.reflect.macros.BlackboxContext
+import scala.reflect.macros.WhiteboxContext
object Macros {
- def impl(c: BlackboxContext) = {
+ def impl(c: WhiteboxContext) = {
import c.universe._
val Apply(fun, args) = c.enclosingImplicits(0).tree
val fileName = fun.pos.source.file.file.getName
diff --git a/test/files/run/macro-whitebox-dynamic-materialization.check b/test/files/run/macro-whitebox-dynamic-materialization.check
new file mode 100644
index 0000000000..ccec8e5b25
--- /dev/null
+++ b/test/files/run/macro-whitebox-dynamic-materialization.check
@@ -0,0 +1,2 @@
+null
+C2
diff --git a/test/files/run/macro-whitebox-dynamic-materialization/Macros_1.scala b/test/files/run/macro-whitebox-dynamic-materialization/Macros_1.scala
new file mode 100644
index 0000000000..87cd310b09
--- /dev/null
+++ b/test/files/run/macro-whitebox-dynamic-materialization/Macros_1.scala
@@ -0,0 +1,25 @@
+import scala.reflect.macros.WhiteboxContext
+import scala.language.experimental.macros
+
+trait Foo[T]
+
+class C1(val x: Int)
+class C2(val x: String)
+
+trait LowPriority {
+ implicit def lessSpecific[T]: Foo[T] = null
+}
+
+object Foo extends LowPriority {
+ implicit def moreSpecific[T]: Foo[T] = macro Macros.impl[T]
+}
+
+object Macros {
+ def impl[T: c.WeakTypeTag](c: WhiteboxContext) = {
+ import c.universe._
+ val tpe = weakTypeOf[T]
+ if (tpe.members.exists(_.typeSignature =:= typeOf[Int]))
+ c.abort(c.enclosingPosition, "I don't like classes that contain integers")
+ q"new Foo[$tpe]{ override def toString = ${tpe.toString} }"
+ }
+} \ No newline at end of file
diff --git a/test/files/run/macro-whitebox-dynamic-materialization/Test_2.scala b/test/files/run/macro-whitebox-dynamic-materialization/Test_2.scala
new file mode 100644
index 0000000000..bf19209ab7
--- /dev/null
+++ b/test/files/run/macro-whitebox-dynamic-materialization/Test_2.scala
@@ -0,0 +1,4 @@
+object Test extends App {
+ println(implicitly[Foo[C1]])
+ println(implicitly[Foo[C2]])
+} \ No newline at end of file