Skip to content

Commit 9d191c8

Browse files
authored
Avoid forcing extension on check of local select (#23439)
Fixes #18450 Uses a non-forcing version of `extensionParam` for the enclosing extension.
2 parents 6aaff88 + 8988848 commit 9d191c8

File tree

2 files changed

+40
-17
lines changed

2 files changed

+40
-17
lines changed

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

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -684,25 +684,33 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
684684
tree.withType(checkedType)
685685
checkLegalValue(toNotNullTermRef(tree1, pt), pt)
686686

687-
def isLocalExtensionMethodRef: Boolean = rawType match
688-
case rawType: TermRef =>
689-
rawType.denot.hasAltWith(_.symbol.is(ExtensionMethod))
690-
&& !pt.isExtensionApplyProto
691-
&& {
687+
// extensionParam
688+
def leadParamOf(m: SymDenotation): Symbol =
689+
def leadParam(paramss: List[List[Symbol]]): Symbol = paramss match
690+
case (param :: _) :: paramss if param.isType => leadParam(paramss)
691+
case _ :: (param :: Nil) :: _ if m.name.isRightAssocOperatorName => param
692+
case (param :: Nil) :: _ => param
693+
case _ => NoSymbol
694+
leadParam(m.rawParamss)
695+
696+
val localExtensionSelection: untpd.Tree =
697+
var select: untpd.Tree = EmptyTree
698+
if ctx.mode.is(Mode.InExtensionMethod) then
699+
rawType match
700+
case rawType: TermRef
701+
if rawType.denot.hasAltWith(_.symbol.is(ExtensionMethod)) && !pt.isExtensionApplyProto =>
692702
val xmethod = ctx.owner.enclosingExtensionMethod
693-
rawType.denot.hasAltWith { alt =>
694-
alt.symbol.is(ExtensionMethod)
695-
&& alt.symbol.extensionParam.span == xmethod.extensionParam.span
696-
}
697-
}
698-
case _ =>
699-
false
703+
val xparam = leadParamOf(xmethod)
704+
if rawType.denot.hasAltWith: alt =>
705+
alt.symbol.is(ExtensionMethod)
706+
&& alt.symbol.extensionParam.span == xparam.span // forces alt.symbol (which might be xmethod)
707+
then
708+
select = untpd.cpy.Select(tree)(untpd.ref(xparam), name)
709+
case _ =>
710+
select
700711

701-
if ctx.mode.is(Mode.InExtensionMethod) && isLocalExtensionMethodRef then
702-
val xmethod = ctx.owner.enclosingExtensionMethod
703-
val qualifier = untpd.ref(xmethod.extensionParam.termRef)
704-
val selection = untpd.cpy.Select(tree)(qualifier, name)
705-
typed(selection, pt)
712+
if !localExtensionSelection.isEmpty then
713+
typed(localExtensionSelection, pt)
706714
else if rawType.exists then
707715
val ref = setType(ensureAccessible(rawType, superAccess = false, tree.srcPos))
708716
if ref.symbol.name != name then

tests/pos/i18450.scala

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//> using options -explain-cyclic -Ydebug-cyclic
2+
3+
class C:
4+
extension (s: String)
5+
def f = "hello, world"
6+
def g = f
7+
8+
//def k = k // Overloaded or recursive method k needs return type
9+
// if k is not forced, it fails with:
10+
// value k is not a member of String.
11+
// Extension methods were tried, ...
12+
13+
def e =
14+
import this.{f as hw}
15+
hw // this.f

0 commit comments

Comments
 (0)