From 789145cfbb078b30b6c3242627af29c95950fb25 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Wed, 18 Oct 2023 10:01:24 +0200 Subject: [PATCH 1/2] Keep qualifier of Ident when selecting setter We already keep the qualifier as a typed splice if the prefix is an explicit Select. Fixes #18713 --- .../src/dotty/tools/dotc/typer/Typer.scala | 14 +++++++++++++- tests/pos/i18713.scala | 18 ++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 tests/pos/i18713.scala diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 9f6bf8c7dee5..ac90664ddddf 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -1119,7 +1119,19 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer case Apply(fn, _) if fn.symbol.is(ExtensionMethod) => def toSetter(fn: Tree): untpd.Tree = fn match case fn @ Ident(name: TermName) => - untpd.cpy.Ident(fn)(name.setterName) + // We need to make sure that the prefix of this extension getter is + // retained when we transform it into a setter. Otherwise, we could + // end up resoving an unrelated setter from another extension. We + // transform the `Ident` into a `Select` to ensure that the prefix + // is retained with a `TypedSplice` (see `case Select` bellow). + // See tests/pos/i18713.scala for an example. + fn.tpe match + case TermRef(qual: TermRef, _) => + toSetter(ref(qual).select(fn.symbol).withSpan(fn.span)) + case TermRef(qual: ThisType, _) => + toSetter(This(qual.cls).select(fn.symbol).withSpan(fn.span)) + case TermRef(NoPrefix, _) => + untpd.cpy.Ident(fn)(name.setterName) case fn @ Select(qual, name: TermName) => untpd.cpy.Select(fn)(untpd.TypedSplice(qual), name.setterName) case fn @ TypeApply(fn1, targs) => diff --git a/tests/pos/i18713.scala b/tests/pos/i18713.scala new file mode 100644 index 000000000000..0c406aa09d2e --- /dev/null +++ b/tests/pos/i18713.scala @@ -0,0 +1,18 @@ +import language.experimental.relaxedExtensionImports + +class A +object AA: + extension (a: A) + def f = ??? + def f_=(x: String) = ??? + +object BB: + extension (b: Long) + def f = ??? + def f_=(x: String) = ??? + +def test(a: A) = + import AA.* + import BB.* + a.f + a.f = "aa" From e0f036cd744bfc7e034000bc3fef94e18ce2a2b8 Mon Sep 17 00:00:00 2001 From: odersky Date: Mon, 13 Nov 2023 18:26:52 +0100 Subject: [PATCH 2/2] Update compiler/src/dotty/tools/dotc/typer/Typer.scala --- compiler/src/dotty/tools/dotc/typer/Typer.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index ac90664ddddf..bd83fbd864e0 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -1121,7 +1121,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer case fn @ Ident(name: TermName) => // We need to make sure that the prefix of this extension getter is // retained when we transform it into a setter. Otherwise, we could - // end up resoving an unrelated setter from another extension. We + // end up resolving an unrelated setter from another extension. We // transform the `Ident` into a `Select` to ensure that the prefix // is retained with a `TypedSplice` (see `case Select` bellow). // See tests/pos/i18713.scala for an example.