@@ -2225,7 +2225,7 @@ trait Applications extends Compatibility {
22252225 * implicits and SAM conversions enabled, and once without.
22262226 */
22272227 private def resolveOverloaded1 (alts : List [TermRef ], pt : Type , srcPos : SrcPos )(using Context ): List [TermRef ] =
2228- trace(i " resolve over $alts%, %, pt = $pt" , typr, show = true ) {
2228+ trace(i " resolve over $alts%, %, pt = $pt" , typr, show = true ):
22292229 record(s " resolveOverloaded1 " , alts.length)
22302230
22312231 val sv = Feature .sourceVersion
@@ -2378,7 +2378,10 @@ trait Applications extends Compatibility {
23782378 case _ => arg
23792379 end normArg
23802380
2381- val candidates = pt match {
2381+ // Note it is important not to capture the outer ctx, for when it is passed to resolveMapped
2382+ // (through narrowByNextParamClause) which retracts the Mode.SynthesizeExtMethodReceiver from the ctx
2383+ // before continuing to `resolveCandidates`.
2384+ def resolveCandidates (alts : List [TermRef ], pt : Type , srcPos : SrcPos )(using Context ): List [TermRef ] = pt match
23822385 case pt @ FunProto (args, resultType) =>
23832386 val numArgs = args.length
23842387 def sizeFits (alt : TermRef ): Boolean = alt.widen.stripPoly match {
@@ -2430,7 +2433,13 @@ trait Applications extends Compatibility {
24302433 else
24312434 record(" resolveOverloaded.narrowedByShape" , alts2.length)
24322435 pretypeArgs(alts2, pt)
2433- narrowByTrees(alts2, pt.typedArgs(normArg(alts2, _, _)), resultType)
2436+ val alts3 = narrowByTrees(alts2, pt.typedArgs(normArg(alts2, _, _)), resultType)
2437+
2438+ resultType.deepenProto match
2439+ case resultType : FunOrPolyProto =>
2440+ narrowByNextParamClause(resolveCandidates)(alts3, pt.typedArgs(), resultType)
2441+ case _ =>
2442+ alts3
24342443
24352444 case pt @ PolyProto (targs1, pt1) =>
24362445 val alts1 = alts.filterConserve(pt.canInstantiate)
@@ -2441,7 +2450,7 @@ trait Applications extends Compatibility {
24412450 TypeOps .boundsViolations(targs1, tp.paramInfos, _.substParams(tp, _), NoType ).isEmpty
24422451 val alts2 = alts1.filter(withinBounds)
24432452 if isDetermined(alts2) then alts2
2444- else resolveMapped(_.widen.appliedTo(targs1.tpes))(alts1, pt1, srcPos)
2453+ else resolveMapped(_.widen.appliedTo(targs1.tpes), resolveCandidates )(alts1, pt1, srcPos)
24452454
24462455 case pt =>
24472456 val compat = alts.filterConserve(normalizedCompatible(_, pt, keepConstraint = false ))
@@ -2465,48 +2474,58 @@ trait Applications extends Compatibility {
24652474 normalize(alt, IgnoredProto (pt)).widenSingleton.isInstanceOf [MethodType ])
24662475 if convertible.length == 1 then convertible else compat
24672476 else compat
2468- }
2477+ end resolveCandidates
24692478
24702479 def resultIsMethod (tp : Type ): Boolean = tp.widen.stripPoly match
24712480 case tp : MethodType => stripInferrable(tp.resultType).isInstanceOf [MethodType ]
24722481 case _ => false
24732482
2474- record(" resolveOverloaded.narrowedApplicable" , candidates.length)
2475- if pt.unusableForInference then
2476- // `pt` might have become erroneous by typing arguments of FunProtos.
2477- // If `pt` is erroneous, don't try to go further; report the error in `pt` instead.
2478- candidates
2479- else
2480- val found = narrowMostSpecific(candidates)
2481- if isDetermined(found) then found
2483+ // Like resolveCandidates, we should not capture the outer ctx parameter.
2484+ def resolveOverloaded2 (candidates : List [TermRef ], pt : Type , srcPos : SrcPos )(using Context ): List [TermRef ] =
2485+ if pt.unusableForInference then
2486+ // `pt` might have become erroneous by typing arguments of FunProtos.
2487+ // If `pt` is erroneous, don't try to go further; report the error in `pt` instead.
2488+ candidates
24822489 else
2483- val deepPt = pt.deepenProto
2484- deepPt match
2485- case pt @ FunProto (_, resType : FunOrPolyProto ) =>
2486- warnOnPriorityChange(candidates, found):
2487- narrowByNextParamClause(resolveOverloaded1)(_, pt.typedArgs(), resType)
2488- case _ =>
2489- // prefer alternatives that need no eta expansion
2490- val noCurried = alts.filterConserve(! resultIsMethod(_))
2491- val noCurriedCount = noCurried.length
2492- if noCurriedCount == 1 then
2493- noCurried
2494- else if noCurriedCount > 1 && noCurriedCount < alts.length then
2495- resolveOverloaded1(noCurried, pt, srcPos)
2496- else
2497- // prefer alternatves that match without default parameters
2498- val noDefaults = alts.filterConserve(! _.symbol.hasDefaultParams)
2499- val noDefaultsCount = noDefaults.length
2500- if noDefaultsCount == 1 then
2501- noDefaults
2502- else if noDefaultsCount > 1 && noDefaultsCount < alts.length then
2503- resolveOverloaded1(noDefaults, pt, srcPos)
2504- else if deepPt ne pt then
2505- // try again with a deeper known expected type
2506- resolveOverloaded1(alts, deepPt, srcPos)
2490+ val found = narrowMostSpecific(candidates)
2491+ if isDetermined(found) then found
2492+ else
2493+ val deepPt = pt.deepenProto
2494+ deepPt match
2495+ case pt @ FunProto (_, resType : FunOrPolyProto ) =>
2496+ warnOnPriorityChange(candidates, found):
2497+ narrowByNextParamClause(resolveOverloaded1)(_, pt.typedArgs(), resType)
2498+ case _ =>
2499+ // prefer alternatives that need no eta expansion
2500+ val noCurried = alts.filterConserve(! resultIsMethod(_))
2501+ val noCurriedCount = noCurried.length
2502+ if noCurriedCount == 1 then
2503+ noCurried
2504+ else if noCurriedCount > 1 && noCurriedCount < alts.length then
2505+ resolveOverloaded1(noCurried, pt, srcPos)
25072506 else
2508- candidates
2509- }
2507+ // prefer alternatves that match without default parameters
2508+ val noDefaults = alts.filterConserve(! _.symbol.hasDefaultParams)
2509+ val noDefaultsCount = noDefaults.length
2510+ if noDefaultsCount == 1 then
2511+ noDefaults
2512+ else if noDefaultsCount > 1 && noDefaultsCount < alts.length then
2513+ resolveOverloaded1(noDefaults, pt, srcPos)
2514+ else if deepPt ne pt then
2515+ // try again with a deeper known expected type
2516+ resolveOverloaded1(alts, deepPt, srcPos)
2517+ else
2518+ candidates
2519+ end resolveOverloaded2
2520+
2521+ // First, we find the candidates by considering all parameter clauses.
2522+ // Second, we determine the most specific again by considering all parameter clauses;
2523+ // but restarting from the 1st argument list.
2524+ // In both cases, considering subsequent argument lists only narrows the set of alternatives
2525+ // (i.e. we do retry from the complete list of alternative mapped onto there next param clause).
2526+ val candidates = resolveCandidates(alts, pt, srcPos)
2527+ record(" resolveOverloaded.narrowedApplicable" , candidates.length)
2528+ resolveOverloaded2(candidates, pt, srcPos)
25102529 end resolveOverloaded1
25112530
25122531 /** Is `formal` a product type which is elementwise compatible with `params`? */
0 commit comments