Skip to content

Commit 48ed5d7

Browse files
Fix #7793: Account for context params preceding normal ones in overloading
1 parent 84ea41a commit 48ed5d7

File tree

2 files changed

+49
-12
lines changed

2 files changed

+49
-12
lines changed

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

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,7 @@ trait Applications extends Compatibility {
339339
else
340340
args
341341

342-
protected def init(): Unit = methType match {
342+
protected def initWith(mt: Type): Unit = mt match {
343343
case methType: MethodType =>
344344
// apply the result type constraint, unless method type is dependent
345345
val resultApprox = resultTypeApprox(methType)
@@ -358,6 +358,28 @@ trait Applications extends Compatibility {
358358
else fail(s"$methString does not take parameters")
359359
}
360360

361+
protected def reset(): Unit =
362+
ok = true
363+
364+
/**
365+
* This function tests whether a given method is applicable to the
366+
* given arguments. Context parameters that precede the normal parameters
367+
* pose problems for such a test. E.g.:
368+
369+
* def f(using String)(g: Int => String): Int
370+
* f(x => "2")
371+
* f(using summon[String])(x => "2")
372+
373+
* At the first call site, the context parameter is omitted. For the
374+
* applicability test to pass in that case, we should also test
375+
* the function `f` with its context parameters dropped.
376+
*/
377+
protected def init(): Unit =
378+
initWith(methType)
379+
if !success then
380+
reset()
381+
initWith(stripImplicit(methType))
382+
361383
/** The application was successful */
362384
def success: Boolean = ok
363385

@@ -688,6 +710,12 @@ trait Applications extends Compatibility {
688710
private var typedArgBuf = new mutable.ListBuffer[Tree]
689711
private var liftedDefs: mutable.ListBuffer[Tree] = null
690712
private var myNormalizedFun: Tree = fun
713+
override protected def reset(): Unit =
714+
super.reset()
715+
typedArgBuf = new mutable.ListBuffer[Tree]
716+
liftedDefs = null
717+
myNormalizedFun = fun
718+
691719
init()
692720

693721
def addArg(arg: Tree, formal: Type): Unit =
@@ -1299,6 +1327,16 @@ trait Applications extends Compatibility {
12991327
}
13001328
}
13011329

1330+
/** Drop any implicit parameter section */
1331+
def stripImplicit(tp: Type)(using Context): Type = tp match {
1332+
case mt: MethodType if mt.isImplicitMethod =>
1333+
stripImplicit(resultTypeApprox(mt))
1334+
case pt: PolyType =>
1335+
pt.derivedLambdaType(pt.paramNames, pt.paramInfos, stripImplicit(pt.resultType))
1336+
case _ =>
1337+
tp
1338+
}
1339+
13021340
/** Compare owner inheritance level.
13031341
* @param sym1 The first owner
13041342
* @param sym2 The second owner
@@ -1466,16 +1504,6 @@ trait Applications extends Compatibility {
14661504
else tp
14671505
}
14681506

1469-
/** Drop any implicit parameter section */
1470-
def stripImplicit(tp: Type): Type = tp match {
1471-
case mt: MethodType if mt.isImplicitMethod =>
1472-
stripImplicit(resultTypeApprox(mt))
1473-
case pt: PolyType =>
1474-
pt.derivedLambdaType(pt.paramNames, pt.paramInfos, stripImplicit(pt.resultType))
1475-
case _ =>
1476-
tp
1477-
}
1478-
14791507
def compareWithTypes(tp1: Type, tp2: Type) = {
14801508
val ownerScore = compareOwner(alt1.symbol.maybeOwner, alt2.symbol.maybeOwner)
14811509
def winsType1 = isAsSpecific(alt1, tp1, alt2, tp2)
@@ -1901,7 +1929,7 @@ trait Applications extends Compatibility {
19011929
recur(altFormals.map(_.tail), args1)
19021930
case _ =>
19031931
}
1904-
recur(alts.map(_.widen.firstParamTypes), pt.args)
1932+
recur(alts.map(alt => stripImplicit(alt.widen).firstParamTypes), pt.args)
19051933
}
19061934

19071935
private def harmonizeWith[T <: AnyRef](ts: List[T])(tpe: T => Type, adapt: (T, Type) => T)(implicit ctx: Context): List[T] = {

tests/pos/i7793.scala

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
trait Foo:
2+
def g(f: Int => Int): Int = 1
3+
def g(using String)(f: Int => String): String = "2"
4+
5+
@main def Test =
6+
val m: Foo = ???
7+
given String = "foo"
8+
m.g(x => "2")
9+
m.g(using summon[String])(x => "2")

0 commit comments

Comments
 (0)