diff options
author | Paul Phillips <paulp@improving.org> | 2013-06-15 14:28:23 -0400 |
---|---|---|
committer | Simon Ochsenreither <simon@ochsenreither.de> | 2013-07-17 23:38:28 +0200 |
commit | 4d6be05c28c95dcd26922059d773a8bfed6014ef (patch) | |
tree | 4cbb711d44ad2b073dd21d03811fdf3d7198b4d0 /src/compiler/scala/tools/nsc/typechecker/Implicits.scala | |
parent | aeb733147881d8da68d1e520b14112dc826a3977 (diff) | |
download | scala-4d6be05c28c95dcd26922059d773a8bfed6014ef.tar.gz scala-4d6be05c28c95dcd26922059d773a8bfed6014ef.tar.bz2 scala-4d6be05c28c95dcd26922059d773a8bfed6014ef.zip |
Make -Ytyper-debug output readable.
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker/Implicits.scala')
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Implicits.scala | 127 |
1 files changed, 41 insertions, 86 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index 8e79b56814..100112fec1 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -31,8 +31,8 @@ trait Implicits { import global._ import definitions._ import ImplicitsStats._ - import typeDebug.{ ptBlock, ptLine } - import global.typer.{ printTyping, deindentTyping, indentTyping, printInference } + import typingStack.{ printTyping } + import typeDebug._ def inferImplicit(tree: Tree, pt: Type, reportAmbiguous: Boolean, isView: Boolean, context: Context): SearchResult = inferImplicit(tree, pt, reportAmbiguous, isView, context, saveAmbiguousDivergent = true, tree.pos) @@ -60,25 +60,13 @@ trait Implicits { * @return A search result */ def inferImplicit(tree: Tree, pt: Type, reportAmbiguous: Boolean, isView: Boolean, context: Context, saveAmbiguousDivergent: Boolean, pos: Position): SearchResult = { - printInference("[infer %s] %s with pt=%s in %s".format( - if (isView) "view" else "implicit", - tree, pt, context.owner.enclClass) - ) - printTyping( - ptBlock("infer implicit" + (if (isView) " view" else ""), - "tree" -> tree, - "pt" -> pt, - "undetparams" -> context.outer.undetparams - ) - ) - indentTyping() - + val shouldPrint = printTypings && !context.undetparams.isEmpty val rawTypeStart = if (Statistics.canEnable) Statistics.startCounter(rawTypeImpl) else null val findMemberStart = if (Statistics.canEnable) Statistics.startCounter(findMemberImpl) else null val subtypeStart = if (Statistics.canEnable) Statistics.startCounter(subtypeImpl) else null val start = if (Statistics.canEnable) Statistics.startTimer(implicitNanos) else null - if (printInfers && !tree.isEmpty && !context.undetparams.isEmpty) - printTyping("typing implicit: %s %s".format(tree, context.undetparamsString)) + if (shouldPrint) + typingStack.printTyping(tree, "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 && saveAmbiguousDivergent && implicitSearchContext.hasErrors) { @@ -88,15 +76,13 @@ trait Implicits { }) debuglog("update buffer: " + implicitSearchContext.reportBuffer.errors) } - printInference("[infer implicit] inferred " + result) context.undetparams = context.undetparams filterNot result.subst.from.contains if (Statistics.canEnable) Statistics.stopTimer(implicitNanos, start) if (Statistics.canEnable) Statistics.stopCounter(rawTypeImpl, rawTypeStart) if (Statistics.canEnable) Statistics.stopCounter(findMemberImpl, findMemberStart) if (Statistics.canEnable) Statistics.stopCounter(subtypeImpl, subtypeStart) - deindentTyping() - printTyping("Implicit search yielded: "+ result) + result } @@ -143,6 +129,7 @@ trait Implicits { private val implicitsCache = new LinkedHashMap[Type, Infoss] private val infoMapCache = new LinkedHashMap[Symbol, InfoMap] private val improvesCache = perRunCaches.newMap[(ImplicitInfo, ImplicitInfo), Boolean]() + private val implicitSearchId = { var id = 1 ; () => try id finally id += 1 } private def isInvalidConversionTarget(tpe: Type): Boolean = tpe match { case Function1(_, out) => AnyRefClass.tpe <:< out @@ -325,18 +312,23 @@ trait Implicits { * (useful when we infer synthetic stuff and pass EmptyTree in the `tree` argument) * If it's set to NoPosition, then position-based services will use `tree.pos` */ - class ImplicitSearch(tree: Tree, pt: Type, isView: Boolean, context0: Context, pos0: Position = NoPosition) - extends Typer(context0) with ImplicitsContextErrors { - printTyping( - ptBlock("new ImplicitSearch", - "tree" -> tree, - "pt" -> pt, - "isView" -> isView, - "context0" -> context0, - "undetparams" -> context.outer.undetparams - ) - ) -// assert(tree.isEmpty || tree.pos.isDefined, tree) + class ImplicitSearch(tree: Tree, pt: Type, isView: Boolean, context0: Context, pos0: Position = NoPosition) extends Typer(context0) with ImplicitsContextErrors { + val searchId = implicitSearchId() + private def typingLog(what: String, msg: String) = + typingStack.printTyping(tree, f"[search #$searchId] $what $msg") + + import infer._ + if (Statistics.canEnable) Statistics.incCounter(implicitSearchCount) + + /** The type parameters to instantiate */ + val undetParams = if (isView) Nil else context.outer.undetparams + val wildPt = approximate(pt) + + def undet_s = if (undetParams.isEmpty) "" else undetParams.mkString(" inferring ", ", ", "") + def tree_s = typeDebug ptTree tree + def ctx_s = fullSiteString(context) + typingLog("start", s"`$tree_s`$undet_s, searching for adaptation to pt=$pt $ctx_s") + def pos = if (pos0 != NoPosition) pos0 else tree.pos def failure(what: Any, reason: String, pos: Position = this.pos): SearchResult = { @@ -344,8 +336,6 @@ trait Implicits { reporter.echo(pos, what+" is not a valid implicit value for "+pt+" because:\n"+reason) SearchFailure } - - import infer._ /** Is implicit info `info1` better than implicit info `info2`? */ def improves(info1: ImplicitInfo, info2: ImplicitInfo) = { @@ -418,14 +408,8 @@ trait Implicits { overlaps(dtor1, dted1) && (dtor1 =:= dted1 || complexity(dtor1) > complexity(dted1)) } - if (Statistics.canEnable) Statistics.incCounter(implicitSearchCount) - - /** The type parameters to instantiate */ - val undetParams = if (isView) List() else context.outer.undetparams - /** The expected type with all undetermined type parameters replaced with wildcards. */ def approximate(tp: Type) = deriveTypeWithWildcards(undetParams)(tp) - val wildPt = approximate(pt) /** Try to construct a typed tree from given implicit info with given * expected type. @@ -582,22 +566,12 @@ trait Implicits { private def typedImplicit0(info: ImplicitInfo, ptChecked: Boolean, isLocal: Boolean): SearchResult = { if (Statistics.canEnable) Statistics.incCounter(plausiblyCompatibleImplicits) - printTyping ( - ptBlock("typedImplicit0", - "info.name" -> info.name, - "ptChecked" -> ptChecked, - "pt" -> wildPt, - "orig" -> ptBlock("info", - "undetParams" -> undetParams, - "info.pre" -> info.pre - ).replaceAll("\\n", "\n ") - ) - ) - - if (ptChecked || matchesPt(info)) - typedImplicit1(info, isLocal) - else - SearchFailure + val ok = ptChecked || matchesPt(info) && { + def word = if (isLocal) "local " else "" + typingLog("match", s"$word$info") + true + } + if (ok) typedImplicit1(info, isLocal) else SearchFailure } private def typedImplicit1(info: ImplicitInfo, isLocal: Boolean): SearchResult = { @@ -618,9 +592,7 @@ trait Implicits { Select(gen.mkAttributedQualifier(info.pre), implicitMemberName) } } - printTyping("typedImplicit1 %s, pt=%s, from implicit %s:%s".format( - typeDebug.ptTree(itree), wildPt, info.name, info.tpe) - ) + typingLog("considering", typeDebug.ptTree(itree)) def fail(reason: String): SearchResult = failure(itree, reason) def fallback = typed1(itree, EXPRmode, wildPt) @@ -643,13 +615,10 @@ trait Implicits { if (Statistics.canEnable) Statistics.incCounter(typedImplicits) - printTyping("typed implicit %s:%s, pt=%s".format(itree1, itree1.tpe, wildPt)) val itree2 = if (isView) (itree1: @unchecked) match { case Apply(fun, _) => fun } else adapt(itree1, EXPRmode, wildPt) - printTyping("adapted implicit %s:%s to %s".format( - itree1.symbol, itree2.tpe, wildPt) - ) + typingStack.showAdapt(itree, itree2, pt, context) def hasMatchingSymbol(tree: Tree): Boolean = (tree.symbol == info.sym) || { tree match { @@ -669,15 +638,9 @@ trait Implicits { val tvars = undetParams map freshVar def ptInstantiated = pt.instantiateTypeParams(undetParams, tvars) - printInference("[search] considering %s (pt contains %s) trying %s against pt=%s".format( - if (undetParams.isEmpty) "no tparams" else undetParams.map(_.name).mkString(", "), - typeVarsInType(ptInstantiated) filterNot (_.isGround) match { case Nil => "no tvars" ; case tvs => tvs.mkString(", ") }, - itree2.tpe, pt - )) - if (matchesPt(itree2.tpe, ptInstantiated, undetParams)) { if (tvars.nonEmpty) - printTyping(ptLine("" + info.sym, "tvars" -> tvars, "tvars.constr" -> tvars.map(_.constr))) + typingLog("solve", ptLine("tvars" -> tvars, "tvars.constr" -> tvars.map(_.constr))) val targs = solvedTypes(tvars, undetParams, undetParams map varianceInType(pt), upper = false, lubDepth(List(itree2.tpe, pt))) @@ -729,7 +692,7 @@ trait Implicits { case None => val result = new SearchResult(itree2, subst) if (Statistics.canEnable) Statistics.incCounter(foundImplicits) - printInference("[success] found %s for pt %s".format(result, ptInstantiated)) + typingLog("success", s"inferred value of type $ptInstantiated is $result") result } } @@ -868,10 +831,7 @@ trait Implicits { matches sortBy (x => if (isView) -x.useCountView else -x.useCountArg) } if (eligible.nonEmpty) - printInference("[search%s] %s with pt=%s in %s, eligible:\n %s".format( - if (isView) " view" else "", - tree, pt, context.owner.enclClass, eligible.mkString("\n ")) - ) + printTyping(tree, eligible.size + s" eligible for pt=$pt at ${fullSiteString(context)}") /** Faster implicit search. Overall idea: * - prune aggressively @@ -898,10 +858,7 @@ trait Implicits { try improves(i, alt) catch { case e: CyclicReference => - if (printInfers) { - println(i+" discarded because cyclic reference occurred") - e.printStackTrace() - } + debugwarn(s"Discarding $i during implicit search due to cyclic reference") true } }) @@ -1044,9 +1001,7 @@ trait Implicits { tp match { case TypeRef(pre, sym, args) => if (sym.isClass) { - if (!((sym.name == tpnme.REFINE_CLASS_NAME) || - (sym.name startsWith tpnme.ANON_CLASS_NAME) || - (sym.name == tpnme.ROOT))) { + if (!sym.isAnonOrRefinementClass && !sym.isRoot) { if (sym.isStatic && !(pending contains sym)) infoMap ++= { infoMapCache get sym match { @@ -1060,7 +1015,7 @@ trait Implicits { } else getClassParts(tp) - args foreach (getParts(_)) + args foreach getParts } } else if (sym.isAliasType) { getParts(tp.normalize) // SI-7180 Normalize needed to expand HK type refs @@ -1088,9 +1043,9 @@ trait Implicits { val infoMap = new InfoMap getParts(tp)(infoMap, new mutable.HashSet(), Set()) - printInference( - ptBlock("companionImplicitMap " + tp, infoMap.toSeq.map({ case (k, v) => ("" + k, v.mkString(", ")) }): _*) - ) + if (infoMap.nonEmpty) + printTyping(tree, infoMap.size + " implicits in companion scope") + infoMap } |