From 4a480822ca26e919c41339bdd8b6cbad6dd94126 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Tue, 15 Nov 2022 11:37:25 +0100 Subject: [PATCH] don't report type / term aliases as ambiguous --- .../tools/nsc/typechecker/Contexts.scala | 10 +++-- test/files/neg/t11921-alias.check | 15 +++++++ test/files/neg/t11921-alias.scala | 39 +++++++++++++++++++ 3 files changed, 61 insertions(+), 3 deletions(-) create mode 100644 test/files/neg/t11921-alias.check create mode 100644 test/files/neg/t11921-alias.scala diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala index 91e8b730101f..d97e8dff047e 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala @@ -1455,7 +1455,7 @@ trait Contexts { self: Analyzer => } // cx.scope eq null arises during FixInvalidSyms in Duplicators - def nextDefinition(): Unit = { + def nextDefinition(lastDef: Symbol, lastPre: Type): Unit = { var inPrefix = false defSym = NoSymbol while (defSym == NoSymbol && (cx ne NoContext) && (cx.scope ne null)) { @@ -1466,10 +1466,14 @@ trait Contexts { self: Analyzer => } if (!defSym.exists) cx = cx.outer // push further outward } + if ((defSym.isAliasType || lastDef.isAliasType) && pre.memberType(defSym) =:= lastPre.memberType(lastDef)) + defSym = NoSymbol + if (defSym.isStable && lastDef.isStable && singleType(pre, defSym) =:= singleType(lastPre, lastDef)) + defSym = NoSymbol foundInPrefix = inPrefix && defSym.exists foundInSuper = foundInPrefix && defSym.owner != cx.owner } - nextDefinition() + nextDefinition(NoSymbol, NoPrefix) if (symbolDepth < 0) symbolDepth = cx.depth @@ -1581,7 +1585,7 @@ trait Contexts { self: Analyzer => while ((cx ne NoContext) && (cx.owner eq cx0.owner)) cx = cx.outer var done = false while (!done) { - nextDefinition() + nextDefinition(defSym0, pre0) done = (cx eq NoContext) || defSym.exists && foundCompetingSymbol() if (!done && (cx ne NoContext)) cx = cx.outer } diff --git a/test/files/neg/t11921-alias.check b/test/files/neg/t11921-alias.check new file mode 100644 index 000000000000..847486c35489 --- /dev/null +++ b/test/files/neg/t11921-alias.check @@ -0,0 +1,15 @@ +t11921-alias.scala:16: error: reference to TT is ambiguous; +it is both defined in object O and available as type TT in class C +Since 2.13.11, symbols inherited from a superclass no longer shadow symbols defined in an outer scope. +If shadowing was intended, write `this.TT`. +Or use `-Ylegacy-binding` to enable the previous behavior everywhere. + def n(x: TT) = x // ambiguous + ^ +t11921-alias.scala:36: error: reference to c is ambiguous; +it is both defined in class B and available as value c in class A +Since 2.13.11, symbols inherited from a superclass no longer shadow symbols defined in an outer scope. +If shadowing was intended, write `this.c`. +Or use `-Ylegacy-binding` to enable the previous behavior everywhere. + def n = c // ambiguous + ^ +2 errors diff --git a/test/files/neg/t11921-alias.scala b/test/files/neg/t11921-alias.scala new file mode 100644 index 000000000000..5cbbaac6168c --- /dev/null +++ b/test/files/neg/t11921-alias.scala @@ -0,0 +1,39 @@ +object t1 { + class C[T] { type TT = T } + object O { + type TT = String + class D extends C[TT] { + def n(x: TT) = x // OK + } + } +} + +object t2 { + class C[T] { type TT <: T } + object O { + type TT = String + class D extends C[TT] { + def n(x: TT) = x // ambiguous + } + } +} + +object t3 { + trait Context + class A[C <: Context](val c: C) + class B(val c: Context) { b => + val a = new A[c.type](c) { + def n = c // OK + } + } +} + +object t4 { + trait Context + class A[C <: Context](val c: C) + class B(val c: Context) { b => + val a = new A(c) { + def n = c // ambiguous + } + } +}