diff --git a/compiler/src/dotty/tools/dotc/reporting/messages.scala b/compiler/src/dotty/tools/dotc/reporting/messages.scala index d7920e1f1b36..a82e49a048ab 100644 --- a/compiler/src/dotty/tools/dotc/reporting/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/messages.scala @@ -1328,21 +1328,32 @@ class AmbiguousReference(name: Name, newPrec: BindingPrec, prevPrec: BindingPrec } def msg(using Context) = - i"""|Reference to $name is ambiguous, - |it is both ${bindingString(newPrec, ctx)} + i"""|Reference to $name is ambiguous. + |It is both ${bindingString(newPrec, ctx)} |and ${bindingString(prevPrec, prevCtx, " subsequently")}""" def explain(using Context) = - i"""|The compiler can't decide which of the possible choices you - |are referencing with $name: A definition of lower precedence - |in an inner scope, or a definition with higher precedence in - |an outer scope. + val precedent = + if newPrec == prevPrec then """two name bindings of equal precedence + |were introduced in the same scope.""".stripMargin + else """a name binding of lower precedence + |in an inner scope cannot shadow a binding with higher precedence in + |an outer scope.""".stripMargin + + i"""|The identifier $name is ambiguous because $precedent + | + |The precedence of the different kinds of name bindings, from highest to lowest, is: + | - Definitions in an enclosing scope + | - Inherited definitions and top-level definitions in packages + | - Names introduced by import of a specific name + | - Names introduced by wildcard import + | - Definitions from packages in other files |Note: - | - Definitions in an enclosing scope take precedence over inherited definitions - | - Definitions take precedence over imports - | - Named imports take precedence over wildcard imports - | - You may replace a name when imported using - | ${hl("import")} scala.{ $name => ${name.show + "Tick"} } + | - As a rule, definitions take precedence over imports. + | - Definitions in an enclosing scope take precedence over inherited definitions, + | which can result in ambiguities in nested classes. + | - When importing, you can avoid naming conflicts by renaming: + | ${hl("import")} scala.{$name => ${name.show}Tick} |""" } diff --git a/tests/neg/ambiref.check b/tests/neg/ambiref.check index 95b542c7aae3..5d701b3b3b71 100644 --- a/tests/neg/ambiref.check +++ b/tests/neg/ambiref.check @@ -1,32 +1,32 @@ -- [E049] Reference Error: tests/neg/ambiref.scala:8:14 ---------------------------------------------------------------- 8 | println(x) // error | ^ - | Reference to x is ambiguous, - | it is both defined in object Test + | Reference to x is ambiguous. + | It is both defined in object Test | and inherited subsequently in class D | | longer explanation available when compiling with `-explain` -- [E049] Reference Error: tests/neg/ambiref.scala:10:14 --------------------------------------------------------------- 10 | println(x) // error | ^ - | Reference to x is ambiguous, - | it is both defined in object Test + | Reference to x is ambiguous. + | It is both defined in object Test | and inherited subsequently in anonymous class test1.C {...} | | longer explanation available when compiling with `-explain` -- [E049] Reference Error: tests/neg/ambiref.scala:17:14 --------------------------------------------------------------- 17 | println(y) // error | ^ - | Reference to y is ambiguous, - | it is both defined in method c + | Reference to y is ambiguous. + | It is both defined in method c | and inherited subsequently in anonymous class D {...} | | longer explanation available when compiling with `-explain` -- [E049] Reference Error: tests/neg/ambiref.scala:25:16 --------------------------------------------------------------- 25 | println(y) // error | ^ - | Reference to y is ambiguous, - | it is both defined in method c + | Reference to y is ambiguous. + | It is both defined in method c | and inherited subsequently in class E | | longer explanation available when compiling with `-explain` diff --git a/tests/neg/i12682.check b/tests/neg/i12682.check new file mode 100644 index 000000000000..605414938529 --- /dev/null +++ b/tests/neg/i12682.check @@ -0,0 +1,51 @@ +-- [E049] Reference Error: tests/neg/i12682.scala:6:12 ----------------------------------------------------------------- +6 | val x = m(1) // error + | ^ + | Reference to m is ambiguous. + | It is both defined in object C + | and inherited subsequently in object T + |--------------------------------------------------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | The identifier m is ambiguous because a name binding of lower precedence + | in an inner scope cannot shadow a binding with higher precedence in + | an outer scope. + | + | The precedence of the different kinds of name bindings, from highest to lowest, is: + | - Definitions in an enclosing scope + | - Inherited definitions and top-level definitions in packages + | - Names introduced by import of a specific name + | - Names introduced by wildcard import + | - Definitions from packages in other files + | Note: + | - As a rule, definitions take precedence over imports. + | - Definitions in an enclosing scope take precedence over inherited definitions, + | which can result in ambiguities in nested classes. + | - When importing, you can avoid naming conflicts by renaming: + | import scala.{m => mTick} + --------------------------------------------------------------------------------------------------------------------- +-- [E049] Reference Error: tests/neg/i12682.scala:13:10 ---------------------------------------------------------------- +13 | def d = m(42) // error + | ^ + | Reference to m is ambiguous. + | It is both imported by import X._ + | and imported subsequently by import Y._ + |-------------------------------------------------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | The identifier m is ambiguous because two name bindings of equal precedence + | were introduced in the same scope. + | + | The precedence of the different kinds of name bindings, from highest to lowest, is: + | - Definitions in an enclosing scope + | - Inherited definitions and top-level definitions in packages + | - Names introduced by import of a specific name + | - Names introduced by wildcard import + | - Definitions from packages in other files + | Note: + | - As a rule, definitions take precedence over imports. + | - Definitions in an enclosing scope take precedence over inherited definitions, + | which can result in ambiguities in nested classes. + | - When importing, you can avoid naming conflicts by renaming: + | import scala.{m => mTick} + -------------------------------------------------------------------------------------------------------------------- diff --git a/tests/neg/i12682.scala b/tests/neg/i12682.scala new file mode 100644 index 000000000000..0b37816ef0df --- /dev/null +++ b/tests/neg/i12682.scala @@ -0,0 +1,13 @@ +// scalac: -explain + +object C: + def m(x: Int) = 1 + object T extends K: + val x = m(1) // error +class K: + def m(i: Int) = 2 +object X extends K +object Y extends K +object D: + import X.*, Y.* + def d = m(42) // error diff --git a/tests/neg/i13558.check b/tests/neg/i13558.check index ab10a42cdd32..7b4b5215a0a3 100644 --- a/tests/neg/i13558.check +++ b/tests/neg/i13558.check @@ -8,8 +8,8 @@ | | failed with: | - | Reference to id is ambiguous, - | it is both imported by import testcode.ExtensionB._ + | Reference to id is ambiguous. + | It is both imported by import testcode.ExtensionB._ | and imported subsequently by import testcode.ExtensionA._ -- [E008] Not Found Error: tests/neg/i13558.scala:29:14 ---------------------------------------------------------------- 29 | println(a.id) // error @@ -21,6 +21,6 @@ | | failed with: | - | Reference to id is ambiguous, - | it is both imported by import testcode.ExtensionA._ + | Reference to id is ambiguous. + | It is both imported by import testcode.ExtensionA._ | and imported subsequently by import testcode.ExtensionB._ diff --git a/tests/neg/i9803.check b/tests/neg/i9803.check index cc7d56d585b0..20225f1f5bc5 100644 --- a/tests/neg/i9803.check +++ b/tests/neg/i9803.check @@ -1,8 +1,8 @@ -- [E049] Reference Error: tests/neg/i9803.scala:15:10 ----------------------------------------------------------------- 15 | println(f421()) // error | ^^^^ - | Reference to f421 is ambiguous, - | it is both imported by name by import bugs.shadowing.x.f421 + | Reference to f421 is ambiguous. + | It is both imported by name by import bugs.shadowing.x.f421 | and imported by name subsequently by import bugs.shadowing.y.f421 | | longer explanation available when compiling with `-explain`