Skip to content

Commit 6ebb4c2

Browse files
Fallback to alts before skipParamClause if empty in resolveCandidates
`resolvedMapped` applies `resolveOverloaded(resolve)`, _not_ `resolve` directly. This benefits from the insertion of implicit parameters, apply methods, etc. But there are still some adaptations, e.g. auto-tupling, that are not performed at this stage. In those cases, it is possible that we find that no alternatives are applicable. So we fallback to the `alts` we had before considering the next parameter clause. Resolution will succeed (only) if narrowMostSpecific finds an unambiguous alternative by considering (only) the prior argument lists, after which adaptation can be performed. See tests/run/tupled-function-extension-method.scala for an example. We only do this for resolveCandidates and not resolveOverloaded2, because in the latter causes some cases where there are indeed no good alternatives to be reported as ambiguous instead, which is unideal for error messages.
1 parent fab9bbf commit 6ebb4c2

File tree

1 file changed

+13
-1
lines changed

1 file changed

+13
-1
lines changed

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

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2228,7 +2228,9 @@ trait Applications extends Compatibility {
22282228
trace(i"resolve over $alts%, %, pt = $pt", typr, show = true):
22292229
record(s"resolveOverloaded1", alts.length)
22302230

2231-
def isDetermined(alts: List[TermRef]) = alts.isEmpty || alts.tail.isEmpty
2231+
extension (self: List[TermRef])
2232+
def isDetermined: Boolean = self.isEmpty || self.tail.isEmpty
2233+
inline def fallbackTo(inline alts: List[TermRef]) = if self.nonEmpty then self else alts
22322234

22332235
/** The shape of given tree as a type; cannot handle named arguments. */
22342236
def typeShape(tree: untpd.Tree): Type = tree match {
@@ -2287,6 +2289,15 @@ trait Applications extends Compatibility {
22872289
case resType =>
22882290
// try to narrow further with snd argument list
22892291
resolveMapped(skipParamClause(Nil), resolve)(alts, resType)
2292+
2293+
// Note that `resolvedMapped` applies `resolveOverloaded(resolve)`, _not_ `resolve` directly.
2294+
// This benefits from the insertion of implicit parameters, apply methods, etc.
2295+
// But there are still some adaptations, e.g. auto-tupling, that are not performed at this stage.
2296+
// In those cases, it is possible that we find that no alternatives are applicable.
2297+
// So, in resolveCandidates, we fallback to the `alts` we had before considering the next parameter clause.
2298+
// Resolution will succeed (only) if narrowMostSpecific finds an unambiguous alternative
2299+
// by considering (only) the prior argument lists, after which adaptation can be performed.
2300+
// See tests/run/tupled-function-extension-method.scala for an example.
22902301
end narrowByNextParamClause
22912302

22922303
/** Normalization steps before checking arguments:
@@ -2405,6 +2416,7 @@ trait Applications extends Compatibility {
24052416
resultType.deepenProto match
24062417
case resultType: FunOrPolyProto =>
24072418
narrowByNextParamClause(resolveCandidates)(alts3, pt.typedArgs(), resultType)
2419+
.fallbackTo(alts3) // see comment in narrowByNextParamClause
24082420
case _ =>
24092421
alts3
24102422

0 commit comments

Comments
 (0)