From 7a78bfd403fa6df2b4ce03cc994f50cd1523fb06 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Wed, 18 Oct 2023 10:01:24 +0200 Subject: [PATCH 1/3] 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 [Cherry-picked 789145cfbb078b30b6c3242627af29c95950fb25] --- .../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 b073d8d413e0..5d114325ad42 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -1098,7 +1098,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 99dd85da78eca785b215b666d05ed67b3554856d Mon Sep 17 00:00:00 2001 From: odersky Date: Mon, 13 Nov 2023 18:26:52 +0100 Subject: [PATCH 2/3] Update compiler/src/dotty/tools/dotc/typer/Typer.scala [Cherry-picked e0f036cd744bfc7e034000bc3fef94e18ce2a2b8] --- 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 5d114325ad42..864a52c8c538 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -1100,7 +1100,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. From 8fa14e50270a5d1e8e30f7495ceee46aed2c197a Mon Sep 17 00:00:00 2001 From: Wojciech Mazur Date: Sun, 23 Jun 2024 01:33:14 +0200 Subject: [PATCH 3/3] Supress false-positive match exhastivity warning --- compiler/src/dotty/tools/dotc/typer/Typer.scala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 864a52c8c538..a74f6dc32668 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -1104,13 +1104,14 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer // 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 + (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) + ): @annotation.nowarn // false-positive match exhastivity warning case fn @ Select(qual, name: TermName) => untpd.cpy.Select(fn)(untpd.TypedSplice(qual), name.setterName) case fn @ TypeApply(fn1, targs) =>