Skip to content

Commit 9506ac4

Browse files
authored
Merge pull request #475 from scala/backport-lts-3.3-23439
Backport "Avoid forcing extension on check of local select" to 3.3 LTS
2 parents bdef0bc + 3d955be commit 9506ac4

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
@@ -639,25 +639,33 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
639639
checkLegalValue(tree2, pt)
640640
tree2
641641

642-
def isLocalExtensionMethodRef: Boolean = rawType match
643-
case rawType: TermRef =>
644-
rawType.denot.hasAltWith(_.symbol.is(ExtensionMethod))
645-
&& !pt.isExtensionApplyProto
646-
&& {
642+
// extensionParam
643+
def leadParamOf(m: SymDenotation): Symbol =
644+
def leadParam(paramss: List[List[Symbol]]): Symbol = paramss match
645+
case (param :: _) :: paramss if param.isType => leadParam(paramss)
646+
case _ :: (param :: Nil) :: _ if m.name.isRightAssocOperatorName => param
647+
case (param :: Nil) :: _ => param
648+
case _ => NoSymbol
649+
leadParam(m.rawParamss)
650+
651+
val localExtensionSelection: untpd.Tree =
652+
var select: untpd.Tree = EmptyTree
653+
if ctx.mode.is(Mode.InExtensionMethod) then
654+
rawType match
655+
case rawType: TermRef
656+
if rawType.denot.hasAltWith(_.symbol.is(ExtensionMethod)) && !pt.isExtensionApplyProto =>
647657
val xmethod = ctx.owner.enclosingExtensionMethod
648-
rawType.denot.hasAltWith { alt =>
649-
alt.symbol.is(ExtensionMethod)
650-
&& alt.symbol.extensionParam.span == xmethod.extensionParam.span
651-
}
652-
}
653-
case _ =>
654-
false
658+
val xparam = leadParamOf(xmethod)
659+
if rawType.denot.hasAltWith: alt =>
660+
alt.symbol.is(ExtensionMethod)
661+
&& alt.symbol.extensionParam.span == xparam.span // forces alt.symbol (which might be xmethod)
662+
then
663+
select = untpd.cpy.Select(tree)(untpd.ref(xparam), name)
664+
case _ =>
665+
select
655666

656-
if ctx.mode.is(Mode.InExtensionMethod) && isLocalExtensionMethodRef then
657-
val xmethod = ctx.owner.enclosingExtensionMethod
658-
val qualifier = untpd.ref(xmethod.extensionParam.termRef)
659-
val selection = untpd.cpy.Select(tree)(qualifier, name)
660-
typed(selection, pt)
667+
if !localExtensionSelection.isEmpty then
668+
typed(localExtensionSelection, pt)
661669
else if rawType.exists then
662670
val ref = setType(ensureAccessible(rawType, superAccess = false, tree.srcPos))
663671
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)