diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 3b6e125fbeb4..96d8dbffccfb 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -684,25 +684,33 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer tree.withType(checkedType) checkLegalValue(toNotNullTermRef(tree1, pt), pt) - def isLocalExtensionMethodRef: Boolean = rawType match - case rawType: TermRef => - rawType.denot.hasAltWith(_.symbol.is(ExtensionMethod)) - && !pt.isExtensionApplyProto - && { + // extensionParam + def leadParamOf(m: SymDenotation): Symbol = + def leadParam(paramss: List[List[Symbol]]): Symbol = paramss match + case (param :: _) :: paramss if param.isType => leadParam(paramss) + case _ :: (param :: Nil) :: _ if m.name.isRightAssocOperatorName => param + case (param :: Nil) :: _ => param + case _ => NoSymbol + leadParam(m.rawParamss) + + val localExtensionSelection: untpd.Tree = + var select: untpd.Tree = EmptyTree + if ctx.mode.is(Mode.InExtensionMethod) then + rawType match + case rawType: TermRef + if rawType.denot.hasAltWith(_.symbol.is(ExtensionMethod)) && !pt.isExtensionApplyProto => val xmethod = ctx.owner.enclosingExtensionMethod - rawType.denot.hasAltWith { alt => - alt.symbol.is(ExtensionMethod) - && alt.symbol.extensionParam.span == xmethod.extensionParam.span - } - } - case _ => - false + val xparam = leadParamOf(xmethod) + if rawType.denot.hasAltWith: alt => + alt.symbol.is(ExtensionMethod) + && alt.symbol.extensionParam.span == xparam.span // forces alt.symbol (which might be xmethod) + then + select = untpd.cpy.Select(tree)(untpd.ref(xparam), name) + case _ => + select - if ctx.mode.is(Mode.InExtensionMethod) && isLocalExtensionMethodRef then - val xmethod = ctx.owner.enclosingExtensionMethod - val qualifier = untpd.ref(xmethod.extensionParam.termRef) - val selection = untpd.cpy.Select(tree)(qualifier, name) - typed(selection, pt) + if !localExtensionSelection.isEmpty then + typed(localExtensionSelection, pt) else if rawType.exists then val ref = setType(ensureAccessible(rawType, superAccess = false, tree.srcPos)) if ref.symbol.name != name then diff --git a/tests/pos/i18450.scala b/tests/pos/i18450.scala new file mode 100644 index 000000000000..42c4830a85e7 --- /dev/null +++ b/tests/pos/i18450.scala @@ -0,0 +1,15 @@ +//> using options -explain-cyclic -Ydebug-cyclic + +class C: + extension (s: String) + def f = "hello, world" + def g = f + + //def k = k // Overloaded or recursive method k needs return type + // if k is not forced, it fails with: + // value k is not a member of String. + // Extension methods were tried, ... + + def e = + import this.{f as hw} + hw // this.f