Skip to content

Commit be5cbda

Browse files
oderskytgodzik
authored andcommitted
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 scala#23610
1 parent 1baf2b8 commit be5cbda

File tree

1 file changed

+22
-17
lines changed

1 file changed

+22
-17
lines changed

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

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3836,6 +3836,12 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
38363836

38373837
def addImplicitArgs(using Context) =
38383838
def hasDefaultParams = methPart(tree).symbol.hasDefaultParams
3839+
def findDefaultArgument(argIndex: Int): Tree =
3840+
def appPart(t: Tree): Tree = t match
3841+
case Block(_, expr) => appPart(expr)
3842+
case Inlined(_, _, expr) => appPart(expr)
3843+
case t => t
3844+
defaultArgument(appPart(tree), n = argIndex, testOnly = false)
38393845
def implicitArgs(formals: List[Type], argIndex: Int, pt: Type): List[Tree] = formals match
38403846
case Nil => Nil
38413847
case formal :: formals1 =>
@@ -3851,11 +3857,17 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
38513857

38523858
val arg = inferImplicitArg(formal, tree.span.endPos)
38533859

3860+
lazy val defaultArg = findDefaultArgument(argIndex)
3861+
.showing(i"default argument: for $formal, $tree, $argIndex = $result", typr)
3862+
def argHasDefault = hasDefaultParams && !defaultArg.isEmpty
3863+
38543864
def canProfitFromMoreConstraints =
38553865
arg.tpe.isInstanceOf[AmbiguousImplicits]
3856-
// ambiguity could be decided by more constraints
3857-
|| !isFullyDefined(formal, ForceDegree.none)
3858-
// more context might constrain type variables which could make implicit scope larger
3866+
// Ambiguity could be decided by more constraints
3867+
|| !isFullyDefined(formal, ForceDegree.none) && !argHasDefault
3868+
// More context might constrain type variables which could make implicit scope larger.
3869+
// But in this case we should search with additional arguments typed only if there
3870+
// is no default argument.
38593871

38603872
arg.tpe match
38613873
case failed: SearchFailureType if canProfitFromMoreConstraints =>
@@ -3868,20 +3880,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
38683880
case failed: AmbiguousImplicits =>
38693881
arg :: implicitArgs(formals1, argIndex + 1, pt)
38703882
case failed: SearchFailureType =>
3871-
lazy val defaultArg =
3872-
def appPart(t: Tree): Tree = t match
3873-
case Block(stats, expr) => appPart(expr)
3874-
case Inlined(_, _, expr) => appPart(expr)
3875-
case _ => t
3876-
defaultArgument(appPart(tree), argIndex, testOnly = false)
3877-
.showing(i"default argument: for $formal, $tree, $argIndex = $result", typr)
3878-
if !hasDefaultParams || defaultArg.isEmpty then
3879-
// no need to search further, the adapt fails in any case
3880-
// the reason why we continue inferring arguments in case of an AmbiguousImplicits
3881-
// is that we need to know whether there are further errors.
3882-
// If there are none, we have to propagate the ambiguity to the caller.
3883-
arg :: formals1.map(dummyArg)
3884-
else
3883+
if argHasDefault then
38853884
// This is tricky. On the one hand, we need the defaultArg to
38863885
// correctly type subsequent formal parameters in the same using
38873886
// clause in case there are parameter dependencies. On the other hand,
@@ -3892,6 +3891,12 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
38923891
// `if propFail.exists` where we re-type the whole using clause with named
38933892
// arguments for all implicits that were found.
38943893
arg :: inferArgsAfter(defaultArg)
3894+
else
3895+
// no need to search further, the adapt fails in any case
3896+
// the reason why we continue inferring arguments in case of an AmbiguousImplicits
3897+
// is that we need to know whether there are further errors.
3898+
// If there are none, we have to propagate the ambiguity to the caller.
3899+
arg :: formals1.map(dummyArg)
38953900
case _ =>
38963901
arg :: inferArgsAfter(arg)
38973902
end implicitArgs

0 commit comments

Comments
 (0)