diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2013-05-17 17:01:20 +0200 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2013-05-17 11:16:39 -0700 |
commit | b7c352a57f65458c66c78a368f75aaaa4a08e443 (patch) | |
tree | 4b2b7fcea439948c5de65b05a392091a66eea0a4 /src/compiler/scala/tools/nsc/typechecker/Implicits.scala | |
parent | 4f8c306aca703c63282295c9f74f0cb35f9f85d4 (diff) | |
parent | be405eed9bef9736f0142d6ddf53b6bf8af08696 (diff) | |
download | scala-b7c352a57f65458c66c78a368f75aaaa4a08e443.tar.gz scala-b7c352a57f65458c66c78a368f75aaaa4a08e443.tar.bz2 scala-b7c352a57f65458c66c78a368f75aaaa4a08e443.zip |
Merge v2.10.1-326-g4f8c306' into merge/v2.10.1-326-g4f8c306-to-master
================================================================
Merge commit 'v2.10.1-326-g4f8c306' into merge/v2.10.1-326-g4f8c306-to-master
Conflicts:
src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
src/reflect/scala/reflect/runtime/JavaMirrors.scala
================================================================
Merge -s ours 4e64a27 ([nomaster commit range])
================================================================
Merge commit '0ae7e55' into merge/v2.10.1-326-g4f8c306-to-master
Conflicts:
src/compiler/scala/tools/nsc/typechecker/Macros.scala
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker/Implicits.scala')
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Implicits.scala | 285 |
1 files changed, 104 insertions, 181 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index 770aef5d61..4acda12dc0 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -8,7 +8,8 @@ //todo: disallow C#D in superclass //todo: treat :::= correctly -package scala.tools.nsc +package scala +package tools.nsc package typechecker import scala.annotation.tailrec @@ -30,11 +31,11 @@ trait Implicits { import global._ import definitions._ import ImplicitsStats._ - import typeDebug.{ ptTree, ptBlock, ptLine } + import typeDebug.{ ptBlock, ptLine } import global.typer.{ printTyping, deindentTyping, indentTyping, printInference } def inferImplicit(tree: Tree, pt: Type, reportAmbiguous: Boolean, isView: Boolean, context: Context): SearchResult = - inferImplicit(tree, pt, reportAmbiguous, isView, context, true, tree.pos) + inferImplicit(tree, pt, reportAmbiguous, isView, context, saveAmbiguousDivergent = true, tree.pos) def inferImplicit(tree: Tree, pt: Type, reportAmbiguous: Boolean, isView: Boolean, context: Context, saveAmbiguousDivergent: Boolean): SearchResult = inferImplicit(tree, pt, reportAmbiguous, isView, context, saveAmbiguousDivergent, tree.pos) @@ -80,9 +81,12 @@ trait Implicits { printTyping("typing implicit: %s %s".format(tree, context.undetparamsString)) val implicitSearchContext = context.makeImplicit(reportAmbiguous) val result = new ImplicitSearch(tree, pt, isView, implicitSearchContext, pos).bestImplicit - if ((result.isFailure || !settings.Xdivergence211.value) && saveAmbiguousDivergent && implicitSearchContext.hasErrors) { - context.updateBuffer(implicitSearchContext.errBuffer.filter(err => err.kind == ErrorKinds.Ambiguous || err.kind == ErrorKinds.Divergent)) - debugwarn("update buffer: " + implicitSearchContext.errBuffer) + if (result.isFailure && saveAmbiguousDivergent && implicitSearchContext.hasErrors) { + context.updateBuffer(implicitSearchContext.reportBuffer.errors.collect { + case dte: DivergentImplicitTypeError => dte + case ate: AmbiguousImplicitTypeError => ate + }) + debuglog("update buffer: " + implicitSearchContext.reportBuffer.errors) } printInference("[infer implicit] inferred " + result) context.undetparams = context.undetparams filterNot result.subst.from.contains @@ -101,24 +105,14 @@ trait Implicits { def inferImplicit(tree: Tree, pt: Type, isView: Boolean, context: Context, silent: Boolean, withMacrosDisabled: Boolean, pos: Position, onError: (Position, String) => Unit): Tree = { val wrapper1 = if (!withMacrosDisabled) (context.withMacrosEnabled[SearchResult] _) else (context.withMacrosDisabled[SearchResult] _) def wrapper(inference: => SearchResult) = wrapper1(inference) - def fail(reason: Option[String]) = { - if (!silent) { - if (context.hasErrors) onError(context.errBuffer.head.errPos, context.errBuffer.head.errMsg) - else onError(pos, reason getOrElse "implicit search has failed. to find out the reason, turn on -Xlog-implicits") - } - EmptyTree - } - try { - wrapper(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) - debugwarn("this shouldn't happen. DivergentImplicit exception has been thrown with -Xdivergence211 turned on: "+ex) - fail(Some("divergent implicit expansion")) + val result = wrapper(inferImplicit(tree, pt, reportAmbiguous = true, isView = isView, context = context, saveAmbiguousDivergent = !silent, pos = pos)) + if (result.isFailure && !silent) { + val err = context.firstError + val errPos = err.map(_.errPos).getOrElse(pos) + val errMsg = err.map(_.errMsg).getOrElse("implicit search has failed. to find out the reason, turn on -Xlog-implicits") + onError(errPos, errMsg) } + result.tree } /** Find all views from type `tp` (in which `tpars` are free) @@ -137,7 +131,7 @@ trait Implicits { val tvars = tpars map (TypeVar untouchable _) val tpSubsted = tp.subst(tpars, tvars) - val search = new ImplicitSearch(EmptyTree, functionType(List(tpSubsted), AnyClass.tpe), true, context.makeImplicit(false)) + val search = new ImplicitSearch(EmptyTree, functionType(List(tpSubsted), AnyClass.tpe), true, context.makeImplicit(reportAmbiguousErrors = false)) search.allImplicitsPoly(tvars) } @@ -157,7 +151,7 @@ trait Implicits { } /* Map a polytype to one in which all type parameters and argument-dependent types are replaced by wildcards. - * Consider `implicit def b(implicit x: A): x.T = error("")`. We need to approximate DebruijnIndex types + * Consider `implicit def b(implicit x: A): x.T = error("")`. We need to approximate debruijn index types * when checking whether `b` is a valid implicit, as we haven't even searched a value for the implicit arg `x`, * so we have to approximate (otherwise it is excluded a priori). */ @@ -177,7 +171,6 @@ trait Implicits { def isFailure = false def isAmbiguousFailure = false - // only used when -Xdivergence211 is turned on def isDivergent = false final def isSuccess = !isFailure } @@ -186,7 +179,6 @@ trait Implicits { override def isFailure = true } - // only used when -Xdivergence211 is turned on lazy val DivergentSearchFailure = new SearchResult(EmptyTree, EmptyTreeTypeSubstituter) { override def isFailure = true override def isDivergent = true @@ -231,15 +223,7 @@ trait Implicits { tp.isError } - /** Todo reconcile with definition of stability given in Types.scala */ - private def isStable(tp: Type): Boolean = tp match { - case TypeRef(pre, sym, _) => - sym.isPackageClass || - sym.isModuleClass && isStable(pre) /*|| - sym.isAliasType && isStable(tp.normalize)*/ - case _ => tp.isStable - } - def isStablePrefix = isStable(pre) + def isStablePrefix = pre.isStable override def equals(other: Any) = other match { case that: ImplicitInfo => @@ -249,7 +233,10 @@ trait Implicits { case _ => false } override def hashCode = name.## + pre.## + sym.## - override def toString = name + ": " + tpe + override def toString = ( + if (tpeCache eq null) name + ": ?" + else name + ": " + tpe + ) } /** A class which is used to track pending implicits to prevent infinite implicit searches. @@ -281,11 +268,7 @@ trait Implicits { object HasMember { private val hasMemberCache = perRunCaches.newMap[Name, Type]() def apply(name: Name): Type = hasMemberCache.getOrElseUpdate(name, memberWildcardType(name, WildcardType)) - def unapply(pt: Type): Option[Name] = pt match { - case RefinedType(List(WildcardType), Scope(sym)) if sym.tpe == WildcardType => Some(sym.name) - case _ => None } - } /** An extractor for types of the form ? { name: (? >: argtpe <: Any*)restp } */ @@ -317,7 +300,7 @@ trait Implicits { */ object Function1 { val Sym = FunctionClass(1) - def unapply(tp: Type) = tp match { + def unapply(tp: Type) = tp baseType Sym match { case TypeRef(_, Sym, arg1 :: arg2 :: _) => Some((arg1, arg2)) case _ => None } @@ -347,7 +330,7 @@ trait Implicits { def pos = if (pos0 != NoPosition) pos0 else tree.pos def failure(what: Any, reason: String, pos: Position = this.pos): SearchResult = { - if (settings.XlogImplicits.value) + if (settings.XlogImplicits) reporter.echo(pos, what+" is not a valid implicit value for "+pt+" because:\n"+reason) SearchFailure } @@ -360,7 +343,7 @@ trait Implicits { (info2 == NoImplicitInfo) || (info1 != NoImplicitInfo) && { if (info1.sym.isStatic && info2.sym.isStatic) { - improvesCache get (info1, info2) match { + improvesCache get ((info1, info2)) match { case Some(b) => if (Statistics.canEnable) Statistics.incCounter(improvesCachedCount); b case None => val result = isStrictlyMoreSpecific(info1.tpe, info2.tpe, info1.sym, info2.sym) @@ -388,7 +371,7 @@ trait Implicits { * if one or both are intersection types with a pair of overlapping parent types. */ private def dominates(dtor: Type, dted: Type): Boolean = { - def core(tp: Type): Type = tp.normalize match { + def core(tp: Type): Type = tp.dealiasWiden match { case RefinedType(parents, defs) => intersectionType(parents map core, tp.typeSymbol.owner) case AnnotatedType(annots, tp, selfsym) => core(tp) case ExistentialType(tparams, result) => core(result).subst(tparams, tparams map (t => core(t.info.bounds.hi))) @@ -403,11 +386,11 @@ trait Implicits { deriveTypeWithWildcards(syms.distinct)(tp) } def sum(xs: List[Int]) = (0 /: xs)(_ + _) - def complexity(tp: Type): Int = tp.normalize match { + def complexity(tp: Type): Int = tp.dealiasWiden match { case NoPrefix => 0 case SingleType(pre, sym) => - if (sym.isPackage) 0 else complexity(tp.normalize.widen) + if (sym.isPackage) 0 else complexity(tp.dealiasWiden) case TypeRef(pre, sym, args) => complexity(pre) + sum(args map complexity) + 1 case RefinedType(parents, _) => @@ -458,45 +441,21 @@ trait Implicits { (context.openImplicits find { case OpenImplicit(info, tp, tree1) => !info.sym.isMacro && tree1.symbol == tree.symbol && dominates(pt, tp)}) match { case Some(pending) => //println("Pending implicit "+pending+" dominates "+pt+"/"+undetParams) //@MDEBUG - if (settings.Xdivergence211.value) DivergentSearchFailure - else throw DivergentImplicit + DivergentSearchFailure case None => - def pre211DivergenceLogic() = { try { context.openImplicits = OpenImplicit(info, pt, tree) :: context.openImplicits // println(" "*context.openImplicits.length+"typed implicit "+info+" for "+pt) //@MDEBUG - typedImplicit0(info, ptChecked, isLocal) - } catch { - case ex: DivergentImplicit => + val result = typedImplicit0(info, ptChecked, isLocal) + if (result.isDivergent) { //println("DivergentImplicit for pt:"+ pt +", open implicits:"+context.openImplicits) //@MDEBUG - if (context.openImplicits.tail.isEmpty) { - if (!pt.isErroneous && !info.sym.isMacro) - DivergingImplicitExpansionError(tree, pt, info.sym)(context) - SearchFailure - } else { - throw DivergentImplicit - } + if (context.openImplicits.tail.isEmpty && !pt.isErroneous) + DivergingImplicitExpansionError(tree, pt, info.sym)(context) + } + result } finally { context.openImplicits = context.openImplicits.tail } - } - def post211DivergenceLogic() = { - try { - context.openImplicits = OpenImplicit(info, pt, tree) :: context.openImplicits - // println(" "*context.openImplicits.length+"typed implicit "+info+" for "+pt) //@MDEBUG - val result = typedImplicit0(info, ptChecked, isLocal) - if (result.isDivergent) { - //println("DivergentImplicit for pt:"+ pt +", open implicits:"+context.openImplicits) //@MDEBUG - if (context.openImplicits.tail.isEmpty && !pt.isErroneous) - DivergingImplicitExpansionError(tree, pt, info.sym)(context) - } - result - } finally { - context.openImplicits = context.openImplicits.tail - } - } - if (settings.Xdivergence211.value) post211DivergenceLogic() - else pre211DivergenceLogic() } } @@ -512,10 +471,8 @@ trait Implicits { val start = if (Statistics.canEnable) Statistics.startTimer(matchesPtNanos) else null val result = normSubType(tp, pt) || isView && { pt match { - case TypeRef(_, Function1.Sym, arg1 :: arg2 :: Nil) => - matchesPtView(tp, arg1, arg2, undet) - case _ => - false + case Function1(arg1, arg2) => matchesPtView(tp, arg1, arg2, undet) + case _ => false } } if (Statistics.canEnable) Statistics.stopTimer(matchesPtNanos, start) @@ -656,21 +613,23 @@ trait Implicits { ) def fail(reason: String): SearchResult = failure(itree, reason) + def fallback = typed1(itree, EXPRmode, wildPt) try { - val itree1 = - if (isView) { - val arg1 :: arg2 :: _ = pt.typeArgs + val itree1 = if (!isView) fallback else pt match { + case Function1(arg1, arg2) => typed1( atPos(itree.pos)(Apply(itree, List(Ident("<argument>") setType approximate(arg1)))), EXPRmode, approximate(arg2) ) - } - else - typed1(itree, EXPRmode, wildPt) - - if (context.hasErrors) - return fail(context.errBuffer.head.errMsg) + case _ => fallback + } + context.firstError match { // using match rather than foreach to avoid non local return. + case Some(err) => + log("implicit adapt failed: " + err.errMsg) + return fail(err.errMsg) + case None => + } if (Statistics.canEnable) Statistics.incCounter(typedImplicits) @@ -692,7 +651,7 @@ trait Implicits { } if (context.hasErrors) - fail("hasMatchingSymbol reported error: " + context.errBuffer.head.errMsg) + fail("hasMatchingSymbol reported error: " + context.firstError.get.errMsg) else if (isLocal && !hasMatchingSymbol(itree1)) fail("candidate implicit %s is shadowed by %s".format( info.sym.fullLocationString, itree1.symbol.fullLocationString)) @@ -711,12 +670,15 @@ trait Implicits { printTyping(ptLine("" + info.sym, "tvars" -> tvars, "tvars.constr" -> tvars.map(_.constr))) val targs = solvedTypes(tvars, undetParams, undetParams map varianceInType(pt), - false, lubDepth(List(itree2.tpe, pt))) + upper = false, lubDepth(List(itree2.tpe, pt))) // #2421: check that we correctly instantiated type parameters outside of the implicit tree: checkBounds(itree2, NoPrefix, NoSymbol, undetParams, targs, "inferred ") - if (context.hasErrors) - return fail("type parameters weren't correctly instantiated outside of the implicit tree: " + context.errBuffer.head.errMsg) + context.firstError match { + case Some(err) => + return fail("type parameters weren't correctly instantiated outside of the implicit tree: " + err.errMsg) + case None => + } // filter out failures from type inference, don't want to remove them from undetParams! // we must be conservative in leaving type params in undetparams @@ -741,23 +703,24 @@ trait Implicits { // duplicating the code here, but this is probably a // hotspot (and you can't just call typed, need to force // re-typecheck) - // TODO: the return tree is ignored. This seems to make - // no difference, but it's bad practice regardless. - - - val checked = itree2 match { + // + // 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 case t => t } - if (context.hasErrors) - fail("typing TypeApply reported errors for the implicit tree: " + context.errBuffer.head.errMsg) - else { - val result = new SearchResult(itree2, subst) - if (Statistics.canEnable) Statistics.incCounter(foundImplicits) - printInference("[success] found %s for pt %s".format(result, ptInstantiated)) - result + context.firstError match { + case Some(err) => + fail("typing TypeApply reported errors for the implicit tree: " + err.errMsg) + case None => + val result = new SearchResult(itree2, subst) + if (Statistics.canEnable) Statistics.incCounter(foundImplicits) + printInference("[success] found %s for pt %s".format(result, ptInstantiated)) + result } } else fail("incompatible: %s does not match expected type %s".format(itree2.tpe, ptInstantiated)) @@ -865,26 +828,6 @@ trait Implicits { /** Preventing a divergent implicit from terminating implicit search, * so that if there is a best candidate it can still be selected. - * - * The old way of handling divergence. - * Only enabled when -Xdivergence211 is turned off. - */ - private var divergence = false - private val divergenceHandler: PartialFunction[Throwable, SearchResult] = { - var remaining = 1; - { case x: DivergentImplicit if remaining > 0 => - remaining -= 1 - divergence = true - log("discarding divergent implicit during implicit search") - SearchFailure - } - } - - /** Preventing a divergent implicit from terminating implicit search, - * so that if there is a best candidate it can still be selected. - * - * The new way of handling divergence. - * Only enabled when -Xdivergence211 is turned on. */ object DivergentImplicitRecovery { // symbol of the implicit that caused the divergence. @@ -928,24 +871,15 @@ trait Implicits { @tailrec private def rankImplicits(pending: Infos, acc: Infos): Infos = pending match { case Nil => acc case i :: is => - def pre211tryImplicitInfo(i: ImplicitInfo) = - try typedImplicit(i, ptChecked = true, isLocal) - catch divergenceHandler - - def post211tryImplicitInfo(i: ImplicitInfo) = - DivergentImplicitRecovery(typedImplicit(i, ptChecked = true, isLocal), i) - - { - if (settings.Xdivergence211.value) post211tryImplicitInfo(i) - else pre211tryImplicitInfo(i) - } match { - // only used if -Xdivergence211 is turned on + DivergentImplicitRecovery(typedImplicit(i, ptChecked = true, isLocal), i) match { case sr if sr.isDivergent => Nil case sr if sr.isFailure => // We don't want errors that occur during checking implicit info // to influence the check of further infos. - context.condBufferFlush(_.kind != ErrorKinds.Divergent) + context.reportBuffer.retainErrors { + case err: DivergentImplicitTypeError => true + } rankImplicits(is, acc) case newBest => best = newBest @@ -990,12 +924,11 @@ trait Implicits { } if (best.isFailure) { - /** If there is no winner, and we witnessed and caught divergence, - * now we can throw it for the error message. + /* If there is no winner, and we witnessed and caught divergence, + * now we can throw it for the error message. */ - if (divergence || DivergentImplicitRecovery.sym != null) { - if (settings.Xdivergence211.value) DivergingImplicitExpansionError(tree, pt, DivergentImplicitRecovery.sym)(context) - else throw DivergentImplicit + if (DivergentImplicitRecovery.sym != null) { + DivergingImplicitExpansionError(tree, pt, DivergentImplicitRecovery.sym)(context) } else invalidImplicits take 1 foreach { sym => def isSensibleAddendum = pt match { case Function1(_, out) => out <:< sym.tpe.finalResultType @@ -1060,8 +993,8 @@ trait Implicits { */ private def companionImplicitMap(tp: Type): InfoMap = { - /** Populate implicit info map by traversing all parts of type `tp`. - * Parameters as for `getParts`. + /* Populate implicit info map by traversing all parts of type `tp`. + * Parameters as for `getParts`. */ def getClassParts(tp: Type)(implicit infoMap: InfoMap, seen: mutable.Set[Type], pending: Set[Symbol]) = tp match { case TypeRef(pre, sym, args) => @@ -1093,13 +1026,13 @@ trait Implicits { } } - /** Populate implicit info map by traversing all parts of type `tp`. - * This method is performance critical. - * @param tp The type for which we want to traverse parts - * @param infoMap The infoMap in which implicit infos corresponding to parts are stored - * @param seen The types that were already visited previously when collecting parts for the given infoMap - * @param pending The set of static symbols for which we are currently trying to collect their parts - * in order to cache them in infoMapCache + /* Populate implicit info map by traversing all parts of type `tp`. + * This method is performance critical. + * @param tp The type for which we want to traverse parts + * @param infoMap The infoMap in which implicit infos corresponding to parts are stored + * @param seen The types that were already visited previously when collecting parts for the given infoMap + * @param pending The set of static symbols for which we are currently trying to collect their parts + * in order to cache them in infoMapCache */ def getParts(tp: Type)(implicit infoMap: InfoMap, seen: mutable.Set[Type], pending: Set[Symbol]) { if (seen(tp)) @@ -1117,7 +1050,7 @@ trait Implicits { case Some(imap) => imap case None => val result = new InfoMap - getClassParts(sym.tpe)(result, new mutable.HashSet(), pending + sym) + getClassParts(sym.tpeHK)(result, new mutable.HashSet(), pending + sym) infoMapCache(sym) = result result } @@ -1211,8 +1144,10 @@ trait Implicits { try { val tree1 = typedPos(pos.focus)(arg) - if (context.hasErrors) processMacroExpansionError(context.errBuffer.head.errPos, context.errBuffer.head.errMsg) - else new SearchResult(tree1, EmptyTreeTypeSubstituter) + context.firstError match { + case Some(err) => processMacroExpansionError(err.errPos, err.errMsg) + case None => new SearchResult(tree1, EmptyTreeTypeSubstituter) + } } catch { case ex: TypeError => processMacroExpansionError(ex.pos, ex.msg) @@ -1229,7 +1164,7 @@ trait Implicits { case ThisType(thisSym) => gen.mkAttributedThis(thisSym) case _ => - // if ``pre'' is not a PDT, e.g. if someone wrote + // if `pre` is not a PDT, e.g. if someone wrote // implicitly[scala.reflect.macros.Context#TypeTag[Int]] // then we need to fail, because we don't know the prefix to use during type reification // upd. we also need to fail silently, because this is a very common situation @@ -1243,8 +1178,8 @@ trait Implicits { } ) // todo. migrate hardcoded materialization in Implicits to corresponding implicit macros - var materializer = atPos(pos.focus)(gen.mkMethodCall(TagMaterializers(tagClass), List(tp), if (prefix != EmptyTree) List(prefix) else List())) - if (settings.XlogImplicits.value) reporter.echo(pos, "materializing requested %s.%s[%s] using %s".format(pre, tagClass.name, tp, materializer)) + val materializer = atPos(pos.focus)(gen.mkMethodCall(TagMaterializers(tagClass), List(tp), if (prefix != EmptyTree) List(prefix) else List())) + if (settings.XlogImplicits) reporter.echo(pos, "materializing requested %s.%s[%s] using %s".format(pre, tagClass.name, tp, materializer)) if (context.macrosEnabled) success(materializer) // don't call `failure` here. if macros are disabled, we just fail silently // otherwise -Xlog-implicits will spam the long with zillions of "macros are disabled" @@ -1262,23 +1197,23 @@ trait Implicits { val full = flavor == FullManifestClass val opt = flavor == OptManifestClass - /** Creates a tree that calls the factory method called constructor in object scala.reflect.Manifest */ + /* Creates a tree that calls the factory method called constructor in object scala.reflect.Manifest */ def manifestFactoryCall(constructor: String, tparg: Type, args: Tree*): Tree = if (args contains EmptyTree) EmptyTree else typedPos(tree.pos.focus) { val mani = gen.mkManifestFactoryCall(full, constructor, tparg, args.toList) - if (settings.debug.value) println("generated manifest: "+mani) // DEBUG + if (settings.debug) println("generated manifest: "+mani) // DEBUG mani } - /** Creates a tree representing one of the singleton manifests.*/ + /* Creates a tree representing one of the singleton manifests.*/ def findSingletonManifest(name: String) = typedPos(tree.pos.focus) { Select(gen.mkAttributedRef(FullManifestModule), name) } - /** Re-wraps a type in a manifest before calling inferImplicit on the result */ + /* Re-wraps a type in a manifest before calling inferImplicit on the result */ def findManifest(tp: Type, manifestClass: Symbol = if (full) FullManifestClass else PartialManifestClass) = - inferImplicit(tree, appliedType(manifestClass, tp), true, false, context).tree + inferImplicit(tree, appliedType(manifestClass, tp), reportAmbiguous = true, isView = false, context).tree def findSubManifest(tp: Type) = findManifest(tp, if (full) FullManifestClass else OptManifestClass) def mot(tp0: Type, from: List[Symbol], to: List[Type]): SearchResult = { @@ -1413,7 +1348,7 @@ trait Implicits { val failstart = if (Statistics.canEnable) Statistics.startTimer(inscopeFailNanos) else null val succstart = if (Statistics.canEnable) Statistics.startTimer(inscopeSucceedNanos) else null - var result = searchImplicit(context.implicitss, true) + var result = searchImplicit(context.implicitss, isLocal = true) if (result.isFailure) { if (Statistics.canEnable) Statistics.stopTimer(inscopeFailNanos, failstart) @@ -1431,23 +1366,18 @@ trait Implicits { // `materializeImplicit` does some preprocessing for `pt` // is it only meant for manifests/tags or we need to do the same for `implicitsOfExpectedType`? - if (result.isFailure) result = searchImplicit(implicitsOfExpectedType, false) + if (result.isFailure && !wasAmbigious) result = searchImplicit(implicitsOfExpectedType, isLocal = false) if (result.isFailure) { context.updateBuffer(previousErrs) if (Statistics.canEnable) Statistics.stopTimer(oftypeFailNanos, failstart) } else { - if (wasAmbigious && settings.lint.value) - reporter.warning(tree.pos, - "Search of in-scope implicits was ambiguous, and the implicit scope was searched. In Scala 2.11.0, this code will not compile. See SI-6667. \n" + - previousErrs.map(_.errMsg).mkString("\n")) - if (Statistics.canEnable) Statistics.stopTimer(oftypeSucceedNanos, succstart) if (Statistics.canEnable) Statistics.incCounter(oftypeImplicitHits) } } - if (result.isFailure && settings.debug.value) + if (result.isFailure && settings.debug) log("no implicits found for "+pt+" "+pt.typeSymbol.info.baseClasses+" "+implicitsOfExpectedType) result @@ -1455,7 +1385,7 @@ trait Implicits { def allImplicits: List[SearchResult] = { def search(iss: Infoss, isLocal: Boolean) = applicableInfos(iss, isLocal).values - (search(context.implicitss, true) ++ search(implicitsOfExpectedType, false)).toList.filter(_.tree ne EmptyTree) + (search(context.implicitss, isLocal = true) ++ search(implicitsOfExpectedType, isLocal = false)).toList.filter(_.tree ne EmptyTree) } // find all implicits for some type that contains type variables @@ -1516,7 +1446,6 @@ trait Implicits { interpolate(msg, Map((typeParamNames zip typeArgs): _*)) // TODO: give access to the name and type of the implicit argument, etc? def validate: Option[String] = { - import scala.util.matching.Regex; import scala.collection.breakOut // is there a shorter way to avoid the intermediate toList? val refs = """\$\{([^}]+)\}""".r.findAllIn(msg).matchData.map(_ group 1).toSet val decls = typeParamNames.toSet @@ -1542,9 +1471,7 @@ object ImplicitsStats { val subtypeImpl = Statistics.newSubCounter(" of which in implicit", subtypeCount) val findMemberImpl = Statistics.newSubCounter(" of which in implicit", findMemberCount) val subtypeAppInfos = Statistics.newSubCounter(" of which in app impl", subtypeCount) - val subtypeImprovCount = Statistics.newSubCounter(" of which in improves", subtypeCount) val implicitSearchCount = Statistics.newCounter ("#implicit searches", "typer") - val triedImplicits = Statistics.newSubCounter(" #tried", implicitSearchCount) val plausiblyCompatibleImplicits = Statistics.newSubCounter(" #plausibly compatible", implicitSearchCount) val matchingImplicits = Statistics.newSubCounter(" #matching", implicitSearchCount) @@ -1564,7 +1491,3 @@ object ImplicitsStats { val implicitCacheAccs = Statistics.newCounter ("implicit cache accesses", "typer") val implicitCacheHits = Statistics.newSubCounter("implicit cache hits", implicitCacheAccs) } - -// only used when -Xdivergence211 is turned off -class DivergentImplicit extends Exception -object DivergentImplicit extends DivergentImplicit |