From 8510bafc2b80ab3526932a053ca574f9f68b5ea6 Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Tue, 25 Jan 2022 15:44:30 +0100 Subject: [PATCH] Avoid unnecessary under-constrained implicit searches In some situations we only call `constrainResult` for its side-effects and ignore its result, but `constrainResult` calls `necessarilyCompatible` which will call `viewExists` as a last-try. Since `viewExists` doesn't have side-effects we might as well skip it, and it turns out that using `NoViewsAllowed.constrainResult` does exactly that. This leads to a significant speed-up (from ~8s to sub-second with a hot compiler) with the test case from #14333 (most likely this is because at the point where we call `constrainResult` we haven't accumulated any constraint from the arguments of the application, so implicit search is free to go on a wild goose chase). I also removed obsolete comments in this method. Fixes #14333. --- .../dotty/tools/dotc/typer/Applications.scala | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index 180ff505e76c..6592afe03da5 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -433,15 +433,18 @@ trait Applications extends Compatibility { protected def init(): Unit = methType match { case methType: MethodType => - // apply the result type constraint, unless method type is dependent val resultApprox = resultTypeApprox(methType) - if (!constrainResult(methRef.symbol, resultApprox, resultType)) - if (ctx.typerState.isCommittable) - // defer the problem until after the application; - // it might be healed by an implicit conversion - () - else - fail(TypeMismatch(methType.resultType, resultType, None)) + val sym = methRef.symbol + if ctx.typerState.isCommittable then + // Here we call `resultType` only to accumulate constraints (even if + // it fails, we might be able to heal the expression to conform to the + // result type) so don't check for views since `viewExists` doesn't + // have any side-effect and would only slow the compiler down (cf #14333). + NoViewsAllowed.constrainResult(sym, resultApprox, resultType) + else if !constrainResult(sym, resultApprox, resultType) then + // Here we actually record that this alternative failed so that + // overloading resolution might prune it. + fail(TypeMismatch(methType.resultType, resultType, None)) // match all arguments with corresponding formal parameters matchArgs(orderedArgs, methType.paramInfos, 0)