Skip to content

Commit ca36ff2

Browse files
committed
Infer missing implicit args in using clause
If there are some missing arguments in a using argument clause, infer them with implicit search.
1 parent a162b7b commit ca36ff2

File tree

3 files changed

+42
-12
lines changed

3 files changed

+42
-12
lines changed

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

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,10 @@ trait Applications extends Compatibility {
543543
else identity
544544
}
545545

546+
def addTypedAndSubstitute(arg: Arg, formal: Type): List[Type] =
547+
val substParam = addTyped(arg, formal)
548+
formals1.mapconserve(substParam)
549+
546550
def missingArg(n: Int): Unit = {
547551
val pname = methodType.paramNames(n)
548552
fail(
@@ -553,7 +557,7 @@ trait Applications extends Compatibility {
553557
def tryDefault(n: Int, args1: List[Arg]): Unit = {
554558
val sym = methRef.symbol
555559

556-
val defaultExpr =
560+
def defaultExpr =
557561
if (isJavaAnnotConstr(sym)) {
558562
val cinfo = sym.owner.asClass.classInfo
559563
val pname = methodType.paramNames(n)
@@ -580,12 +584,16 @@ trait Applications extends Compatibility {
580584
EmptyTree
581585
}
582586

583-
if (!defaultExpr.isEmpty) {
584-
val substParam = addTyped(treeToArg(defaultExpr), formal)
585-
matchArgs(args1, formals1.mapconserve(substParam), n + 1)
586-
}
587+
def implicitArg = implicitArgTree(formal, appPos.span)
588+
589+
if methodType.isContextualMethod && ctx.mode.is(Mode.ImplicitsEnabled) then
590+
matchArgs(args1, addTypedAndSubstitute(treeToArg(implicitArg), formal), n + 1)
587591
else
588-
missingArg(n)
592+
val defaultArg = defaultExpr
593+
if !defaultArg.isEmpty then
594+
matchArgs(args1, addTypedAndSubstitute(treeToArg(defaultArg), formal), n + 1)
595+
else
596+
missingArg(n)
589597
}
590598

591599
if (formal.isRepeatedParam)
@@ -605,8 +613,7 @@ trait Applications extends Compatibility {
605613
case EmptyTree :: args1 =>
606614
tryDefault(n, args1)
607615
case arg :: args1 =>
608-
val substParam = addTyped(arg, formal)
609-
matchArgs(args1, formals1.mapconserve(substParam), n + 1)
616+
matchArgs(args1, addTypedAndSubstitute(arg, formal), n + 1)
610617
case nil =>
611618
tryDefault(n, args)
612619
}
@@ -1674,10 +1681,7 @@ trait Applications extends Compatibility {
16741681
pt match
16751682
case pt: FunProto =>
16761683
if pt.applyKind == ApplyKind.Using then
1677-
val alts0 = alts.filterConserve { alt =>
1678-
val mt = alt.widen.stripPoly
1679-
mt.isImplicitMethod || mt.isContextualMethod
1680-
}
1684+
val alts0 = alts.filterConserve(_.widen.stripPoly.isImplicitMethod)
16811685
if alts0 ne alts then return resolve(alts0)
16821686
else if alts.exists(_.widen.stripPoly.isContextualMethod) then
16831687
return resolveMapped(alts, alt => stripImplicit(alt.widen), pt)

tests/run/extra-implicits.check

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
A(explicit)
2+
B(default)
3+
A(explicit)
4+
B(default)
5+
A(default)
6+
B(explicit)
7+
A(explicit)
8+
B(explicit)

tests/run/extra-implicits.scala

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
2+
case class A(x: String)
3+
case class B(x: String)
4+
given a1 as A("default")
5+
given b1 as B("default")
6+
val a2 = A("explicit")
7+
val b2 = B("explicit")
8+
9+
def f(using a: A, b: B): Unit =
10+
println(a)
11+
println(b)
12+
13+
@main def Test =
14+
f(using a2)
15+
f(using a = a2)
16+
f(using b = b2)
17+
f(using b = b2, a = a2)
18+

0 commit comments

Comments
 (0)