From e21096f5ccbb27587bedbf238b18661d158995e1 Mon Sep 17 00:00:00 2001 From: Adriaan Moors Date: Mon, 4 Aug 2014 17:24:45 +0200 Subject: Separate statistics from functional code; optimize. --- .../scala/tools/nsc/typechecker/Implicits.scala | 77 +++++++++++++--------- 1 file changed, 45 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index d56f4a7ce8..b85c8e6d42 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -1342,36 +1342,47 @@ trait Implicits { * If all fails return SearchFailure */ def bestImplicit: SearchResult = { - val failstart = if (Statistics.canEnable) Statistics.startTimer(inscopeFailNanos) else null - val succstart = if (Statistics.canEnable) Statistics.startTimer(inscopeSucceedNanos) else null + val stats = Statistics.canEnable + val failstart = if (stats) Statistics.startTimer(inscopeFailNanos) else null + val succstart = if (stats) Statistics.startTimer(inscopeSucceedNanos) else null var result = searchImplicit(context.implicitss, isLocalToCallsite = true) - if (result.isFailure) { - if (Statistics.canEnable) Statistics.stopTimer(inscopeFailNanos, failstart) - } else { - if (Statistics.canEnable) Statistics.stopTimer(inscopeSucceedNanos, succstart) - if (Statistics.canEnable) Statistics.incCounter(inscopeImplicitHits) + if (stats) { + if (result.isFailure) Statistics.stopTimer(inscopeFailNanos, failstart) + else { + Statistics.stopTimer(inscopeSucceedNanos, succstart) + Statistics.incCounter(inscopeImplicitHits) + } } + if (result.isFailure) { + val failstart = if (stats) Statistics.startTimer(oftypeFailNanos) else null + val succstart = if (stats) Statistics.startTimer(oftypeSucceedNanos) else null + + // SI-6667, never search companions after an ambiguous error in in-scope implicits + val wasAmbigious = result.isAmbiguousFailure + + // TODO: encapsulate val previousErrs = context.reporter.errors context.reporter.clearAllErrors() - val failstart = if (Statistics.canEnable) Statistics.startTimer(oftypeFailNanos) else null - val succstart = if (Statistics.canEnable) Statistics.startTimer(oftypeSucceedNanos) else null - val wasAmbigious = result.isAmbiguousFailure // SI-6667, never search companions after an ambiguous error in in-scope implicits result = materializeImplicit(pt) + // `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 && !wasAmbigious) result = searchImplicit(implicitsOfExpectedType, isLocalToCallsite = false) - if (result.isFailure) { + if (result.isFailure) context.reporter ++= previousErrs - if (Statistics.canEnable) Statistics.stopTimer(oftypeFailNanos, failstart) - } else { - if (Statistics.canEnable) Statistics.stopTimer(oftypeSucceedNanos, succstart) - if (Statistics.canEnable) Statistics.incCounter(oftypeImplicitHits) + + if (stats) { + if (result.isFailure) Statistics.stopTimer(oftypeFailNanos, failstart) + else { + Statistics.stopTimer(oftypeSucceedNanos, succstart) + Statistics.incCounter(oftypeImplicitHits) + } } } if (result.isSuccess && isView) { @@ -1384,12 +1395,13 @@ trait Implicits { } pt match { case Function1(_, out) => - def prohibit(sym: Symbol) = if (sym.tpe <:< out) { - maybeInvalidConversionError(s"the result type of an implicit conversion must be more specific than ${sym.name}") - result = SearchFailure + // must inline to avoid capturing result + def prohibit(sym: Symbol) = (sym.tpe <:< out) && { + maybeInvalidConversionError(s"the result type of an implicit conversion must be more specific than ${sym.name}") + true } - prohibit(AnyRefClass) - if (settings.isScala211) prohibit(AnyValClass) + if (prohibit(AnyRefClass) || (settings.isScala211 && prohibit(AnyValClass))) + result = SearchFailure case _ => false } if (settings.isScala211 && isInvalidConversionSource(pt)) { @@ -1397,8 +1409,9 @@ trait Implicits { result = SearchFailure } } - if (result.isFailure) - debuglog("no implicits found for "+pt+" "+pt.typeSymbol.info.baseClasses+" "+implicitsOfExpectedType) + + if (result.isFailure && settings.debug) // debuglog is not inlined for some reason + log("no implicits found for "+pt+" "+pt.typeSymbol.info.baseClasses+" "+implicitsOfExpectedType) result } @@ -1420,19 +1433,19 @@ trait Implicits { val eligible = new ImplicitComputation(iss, isLocalToCallsite).eligible eligible.toList.flatMap { (ii: ImplicitInfo) => - // each ImplicitInfo contributes a distinct set of constraints (generated indirectly by typedImplicit) - // thus, start each type var off with a fresh for every typedImplicit - resetTVars() - // any previous errors should not affect us now - context.reporter.clearAllErrors() - val res = typedImplicit(ii, ptChecked = false, isLocalToCallsite) - if (res.tree ne EmptyTree) List((res, tvars map (_.constr))) - else Nil + // each ImplicitInfo contributes a distinct set of constraints (generated indirectly by typedImplicit) + // thus, start each type var off with a fresh for every typedImplicit + resetTVars() + // any previous errors should not affect us now + context.reporter.clearAllErrors() + val res = typedImplicit(ii, ptChecked = false, isLocalToCallsite) + if (res.tree ne EmptyTree) List((res, tvars map (_.constr))) + else Nil + } } - } eligibleInfos(context.implicitss, isLocalToCallsite = true) ++ eligibleInfos(implicitsOfExpectedType, isLocalToCallsite = false) - } + } } object ImplicitNotFoundMsg { -- cgit v1.2.3