diff --git a/spec/02-identifiers-names-and-scopes.md b/spec/02-identifiers-names-and-scopes.md index 8ae89aec117..63ca8b21d78 100644 --- a/spec/02-identifiers-names-and-scopes.md +++ b/spec/02-identifiers-names-and-scopes.md @@ -17,11 +17,9 @@ which are collectively called _bindings_. Bindings of each kind are assigned a precedence which determines whether one binding can shadow another: -1. Definitions and declarations in lexical scope that are not [top-level](09-top-level-definitions.html) - have the highest precedence. -1. Definitions and declarations that are either inherited, - or made available by a package clause and also defined in the same compilation unit as the reference to them, - have the next highest precedence. +1. Definitions and declarations that are local, inherited, or made + available by a package clause and also defined in the same compilation unit + as the reference to them, have the highest precedence. 1. Explicit imports have the next highest precedence. 1. Wildcard imports have the next highest precedence. 1. Bindings made available by a package clause, @@ -39,6 +37,11 @@ in some inner scope _shadows_ bindings of lower precedence in the same scope as well as bindings of the same or lower precedence in outer scopes. +It is an error if an identifier x is available as an inherited member in an inner scope +and the same name x is defined in an outer scope in the same source file, unless +the inherited member (has an overloaded alternative that) coincides with +(an overloaded alternative of) the definition x. + Note that shadowing is only a partial order. In the following example, neither binding of `x` shadows the other. Consequently, the reference to `x` in the last line of the block is ambiguous. diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala index a439b111a98..09af2a01615 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala @@ -1607,7 +1607,7 @@ trait Contexts { self: Analyzer => val wasFoundInSuper = foundInSuper val foundCompetingSymbol: () => Boolean = if (foreignDefined) () => !foreignDefined - else () => !defSym.isTopLevel && !defSym.owner.isPackageObjectOrClass && !foundInSuper && !foreignDefined + else () => !defSym.owner.isPackageObjectOrClass && !foundInSuper && !foreignDefined while ((cx ne NoContext) && cx.depth >= symbolDepth) cx = cx.outer if (wasFoundInSuper) while ((cx ne NoContext) && (cx.owner eq cx0.owner)) cx = cx.outer diff --git a/test/files/neg/t11921b.check b/test/files/neg/t11921b.check index 0e2e2391d34..045f13ffb9a 100644 --- a/test/files/neg/t11921b.check +++ b/test/files/neg/t11921b.check @@ -29,6 +29,13 @@ Such references are ambiguous in Scala 3. To continue using the inherited symbol Or use `-Wconf:msg=legacy-binding:s` to silence this warning. println(y) // error ^ +t11921b.scala:65: warning: reference to global is ambiguous; +it is both defined in the enclosing package and inherited in the enclosing object D as value global (defined in class C) +In Scala 2, symbols inherited from a superclass shadow symbols defined in an outer scope. +Such references are ambiguous in Scala 3. To continue using the inherited symbol, write `this.global`. +Or use `-Wconf:msg=legacy-binding:s` to silence this warning. + println(global) // error + ^ t11921b.scala:75: warning: reference to x is ambiguous; it is both defined in the enclosing object Uhu and inherited in the enclosing class C as value x (defined in class A, inherited through parent class B) In Scala 2, symbols inherited from a superclass shadow symbols defined in an outer scope. @@ -50,5 +57,5 @@ Such references are ambiguous in Scala 3. To continue using the inherited symbol Or use `-Wconf:msg=legacy-binding:s` to silence this warning. def v = t(lo) // error ^ -7 warnings +8 warnings 1 error diff --git a/test/files/neg/t11921b.scala b/test/files/neg/t11921b.scala index 93447b5e0a5..ef3b53ae472 100644 --- a/test/files/neg/t11921b.scala +++ b/test/files/neg/t11921b.scala @@ -62,7 +62,7 @@ class C { val global = 42 } object D extends C { - println(global) // OK, since global is defined in package (https://github.com/scala/scala/pull/10220/files#r1109773904) + println(global) // error } object test5 { @@ -136,3 +136,10 @@ object test10 { def v = t(lo) // error } } + +package scala { + trait P { trait Option[+A] } + class C extends P { + def t = new Option[String] {} // OK, competing scala.Option is not defined in the same compilation unit + } +}