diff options
author | Eugene Burmako <xeno.by@gmail.com> | 2013-02-23 14:34:29 +0100 |
---|---|---|
committer | Eugene Burmako <xeno.by@gmail.com> | 2013-05-11 18:37:11 +0200 |
commit | 3edde2727bad9b00cbaf5475f5bf234f08c26cbd (patch) | |
tree | 417c7e1b2ed785bcf01ee7d1b8e42fbdaa4a6d92 | |
parent | b4da864247ccaaee4f987fbf433b312e1d744a8f (diff) | |
download | scala-3edde2727bad9b00cbaf5475f5bf234f08c26cbd.tar.gz scala-3edde2727bad9b00cbaf5475f5bf234f08c26cbd.tar.bz2 scala-3edde2727bad9b00cbaf5475f5bf234f08c26cbd.zip |
[nomaster] SI-7166 catches DivergentImplicit in c.inferImplicitXXX
Despite inferImplicit usually being nice and buffering errors, apparently
it can also throw DivergentImplicit exception. This patch catches it and
only reports it if silent is set to false.
NOTE: we no longer have the DivergentImplicit exception in master,
so this commit only makes sense in 2.10.x.
-rw-r--r-- | src/compiler/scala/reflect/macros/runtime/Typers.scala | 29 | ||||
-rw-r--r-- | src/compiler/scala/tools/reflect/ToolBoxFactory.scala | 29 | ||||
-rw-r--r-- | test/files/neg/t7166.check | 4 | ||||
-rw-r--r-- | test/files/neg/t7166/Impls_Macros_1.scala | 26 | ||||
-rw-r--r-- | test/files/neg/t7166/Test_2.scala | 3 |
5 files changed, 71 insertions, 20 deletions
diff --git a/src/compiler/scala/reflect/macros/runtime/Typers.scala b/src/compiler/scala/reflect/macros/runtime/Typers.scala index 7cfee2041c..2823a8300d 100644 --- a/src/compiler/scala/reflect/macros/runtime/Typers.scala +++ b/src/compiler/scala/reflect/macros/runtime/Typers.scala @@ -46,19 +46,28 @@ trait Typers { private def inferImplicit(tree: Tree, pt: Type, isView: Boolean, silent: Boolean, withMacrosDisabled: Boolean, pos: Position): Tree = { import universe.analyzer.SearchResult + import scala.tools.nsc.typechecker.DivergentImplicit val context = callsiteTyper.context val wrapper1 = if (!withMacrosDisabled) (context.withMacrosEnabled[SearchResult] _) else (context.withMacrosDisabled[SearchResult] _) def wrapper (inference: => SearchResult) = wrapper1(inference) - wrapper(universe.analyzer.inferImplicit(tree, pt, reportAmbiguous = true, isView = isView, context = context, saveAmbiguousDivergent = !silent, pos = pos)) match { - case failure if failure.tree.isEmpty => - macroLogVerbose("implicit search has failed. to find out the reason, turn on -Xlog-implicits") - if (!silent) { - if (context.hasErrors) throw new TypecheckException(context.errBuffer.head.errPos, context.errBuffer.head.errMsg) - else throw new TypecheckException(pos, "implicit search has failed. to find out the reason, turn on -Xlog-implicits") - } - universe.EmptyTree - case success => - success.tree + def fail(reason: Option[String]) = { + macroLogVerbose("implicit search has failed. to find out the reason, turn on -Xlog-implicits") + if (!silent) { + if (context.hasErrors) throw new TypecheckException(context.errBuffer.head.errPos, context.errBuffer.head.errMsg) + else throw new TypecheckException(pos, reason getOrElse "implicit search has failed. to find out the reason, turn on -Xlog-implicits") + } + universe.EmptyTree + } + try { + wrapper(universe.analyzer.inferImplicit(tree, pt, reportAmbiguous = true, isView = isView, context = context, saveAmbiguousDivergent = !silent, pos = pos)) match { + case failure if failure.tree.isEmpty => fail(None) + case success => success.tree + } + } catch { + case ex: DivergentImplicit => + if (universe.settings.Xdivergence211.value) + universe.debuglog("this shouldn't happen. DivergentImplicit exception has been thrown with -Xdivergence211 turned on: "+ex) + fail(Some("divergent implicit expansion")) } } diff --git a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala index acfc86c1ac..b9968eedef 100644 --- a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala +++ b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala @@ -180,18 +180,27 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => def inferImplicit(tree: Tree, pt: Type, isView: Boolean, silent: Boolean, withMacrosDisabled: Boolean, pos: Position): Tree = transformDuringTyper(tree, withImplicitViewsDisabled = false, withMacrosDisabled = withMacrosDisabled)( (currentTyper, tree) => { + import scala.tools.nsc.typechecker.DivergentImplicit trace("inferring implicit %s (macros = %s): ".format(if (isView) "view" else "value", !withMacrosDisabled))(showAttributed(pt, true, true, settings.Yshowsymkinds.value)) val context = currentTyper.context - analyzer.inferImplicit(tree, pt, reportAmbiguous = true, isView = isView, context = context, saveAmbiguousDivergent = !silent, pos = pos) match { - case failure if failure.tree.isEmpty => - trace("implicit search has failed. to find out the reason, turn on -Xlog-implicits: ")(failure.tree) - if (!silent) { - if (context.hasErrors) throw ToolBoxError("reflective implicit search has failed: %s".format(context.errBuffer.head.errMsg)) - else throw new ToolBoxError("reflective implicit search has failed. to find out the reason, turn on -Xlog-implicits") - } - EmptyTree - case success => - success.tree + def fail(reason: Option[String]) = { + debuglog("reflective implicit search has failed. to find out the reason, turn on -Xlog-implicits") + if (!silent) { + if (context.hasErrors) throw ToolBoxError("reflective implicit search has failed: %s".format(context.errBuffer.head.errMsg)) + else throw ToolBoxError(reason getOrElse "reflective implicit search has failed. to find out the reason, turn on -Xlog-implicits") + } + EmptyTree + } + try { + analyzer.inferImplicit(tree, pt, reportAmbiguous = true, isView = isView, context = context, saveAmbiguousDivergent = !silent, pos = pos) match { + case failure if failure.tree.isEmpty => fail(None) + case success => success.tree + } + } catch { + case ex: DivergentImplicit => + if (settings.Xdivergence211.value) + debuglog("this shouldn't happen. DivergentImplicit exception has been thrown with -Xdivergence211 turned on: "+ex) + fail(Some("divergent implicit expansion")) } }) diff --git a/test/files/neg/t7166.check b/test/files/neg/t7166.check new file mode 100644 index 0000000000..c87198cb27 --- /dev/null +++ b/test/files/neg/t7166.check @@ -0,0 +1,4 @@ +Test_2.scala:2: error: silent = true does work! + println(implicitly[Complex[Foo]]) + ^ +one error found diff --git a/test/files/neg/t7166/Impls_Macros_1.scala b/test/files/neg/t7166/Impls_Macros_1.scala new file mode 100644 index 0000000000..62a15657c3 --- /dev/null +++ b/test/files/neg/t7166/Impls_Macros_1.scala @@ -0,0 +1,26 @@ +import scala.reflect.macros.Context +import language.experimental.macros + +trait Complex[T] + +class Foo + +object Complex { + def impl[T: c.WeakTypeTag](c: Context): c.Expr[Complex[T]] = { + import c.universe._ + def shout(msg: String) = { + val cannotShutMeUp = c.asInstanceOf[scala.reflect.macros.runtime.Context].universe.currentRun.currentUnit.error _ + cannotShutMeUp(c.enclosingPosition.asInstanceOf[scala.reflect.internal.util.Position], msg) + } + try { + val complexOfT = appliedType(typeOf[Complex[_]], List(weakTypeOf[T])) + val infiniteRecursion = c.inferImplicitValue(complexOfT, silent = true) + shout("silent = true does work!") + } catch { + case ex: Exception => shout(ex.toString) + } + c.literalNull + } + + implicit def genComplex[T]: Complex[T] = macro impl[T] +} diff --git a/test/files/neg/t7166/Test_2.scala b/test/files/neg/t7166/Test_2.scala new file mode 100644 index 0000000000..dcc4593335 --- /dev/null +++ b/test/files/neg/t7166/Test_2.scala @@ -0,0 +1,3 @@ +object Test extends App { + println(implicitly[Complex[Foo]]) +}
\ No newline at end of file |