Skip to content

Commit 975c988

Browse files
committed
Use more context for implicit search only if no default argument
After an "implicit not found", we type additional arguments to get more context which might give a larger implicit scope to search. With this commit we do that only if there is no default argument for the implicit. This might fix #23610
1 parent e4b8f3c commit 975c988

File tree

1 file changed

+16
-12
lines changed

1 file changed

+16
-12
lines changed

compiler/src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4362,11 +4362,17 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
43624362

43634363
val arg = inferImplicitArg(formal, tree.span.endPos)
43644364

4365+
lazy val defaultArg = findDefaultArgument(argIndex)
4366+
.showing(i"default argument: for $formal, $tree, $argIndex = $result", typr)
4367+
def argHasDefault = hasDefaultParams && !defaultArg.isEmpty
4368+
43654369
def canProfitFromMoreConstraints =
43664370
arg.tpe.isInstanceOf[AmbiguousImplicits]
4367-
// ambiguity could be decided by more constraints
4368-
|| !isFullyDefined(formal, ForceDegree.none)
4369-
// more context might constrain type variables which could make implicit scope larger
4371+
// Ambiguity could be decided by more constraints
4372+
|| !isFullyDefined(formal, ForceDegree.none) && !argHasDefault
4373+
// More context might constrain type variables which could make implicit scope larger.
4374+
// But in this case we should search with additional arguments typed only if there
4375+
// is no default argument.
43704376

43714377
// Try to constrain the result using `pt1`, but back out if a BadTyperStateAssertion
43724378
// is thrown. TODO Find out why the bad typer state arises and prevent it. The try-catch
@@ -4388,15 +4394,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
43884394
case failed: AmbiguousImplicits =>
43894395
arg :: implicitArgs(formals1, argIndex + 1, pt)
43904396
case failed: SearchFailureType =>
4391-
lazy val defaultArg = findDefaultArgument(argIndex)
4392-
.showing(i"default argument: for $formal, $tree, $argIndex = $result", typr)
4393-
if !hasDefaultParams || defaultArg.isEmpty then
4394-
// no need to search further, the adapt fails in any case
4395-
// the reason why we continue inferring arguments in case of an AmbiguousImplicits
4396-
// is that we need to know whether there are further errors.
4397-
// If there are none, we have to propagate the ambiguity to the caller.
4398-
arg :: formals1.map(dummyArg)
4399-
else
4397+
if argHasDefault then
44004398
// This is tricky. On the one hand, we need the defaultArg to
44014399
// correctly type subsequent formal parameters in the same using
44024400
// clause in case there are parameter dependencies. On the other hand,
@@ -4407,6 +4405,12 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
44074405
// `if propFail.exists` where we re-type the whole using clause with named
44084406
// arguments for all implicits that were found.
44094407
arg :: inferArgsAfter(defaultArg)
4408+
else
4409+
// no need to search further, the adapt fails in any case
4410+
// the reason why we continue inferring arguments in case of an AmbiguousImplicits
4411+
// is that we need to know whether there are further errors.
4412+
// If there are none, we have to propagate the ambiguity to the caller.
4413+
arg :: formals1.map(dummyArg)
44104414
case _ =>
44114415
arg :: inferArgsAfter(arg)
44124416
end implicitArgs

0 commit comments

Comments
 (0)