Skip to content

Commit

Permalink
Clarify ambiguous reference error message
Browse files Browse the repository at this point in the history
  • Loading branch information
som-snytt committed Feb 2, 2023
1 parent af95ceb commit 4ed780a
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 25 deletions.
30 changes: 19 additions & 11 deletions compiler/src/dotty/tools/dotc/reporting/messages.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1328,21 +1328,29 @@ 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.
|Note:
| - Definitions in an enclosing scope take precedence over inherited definitions
| - Definitions take precedence over imports
val precedent =
if newPrec == prevPrec then """two bindings of equal precedence
|were introduced in the same scope.""".stripMargin
else """a 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 bindings, from highest to lowest, is:
| - Definitions in an enclosing scope
| - Inherited definitions and top-level definitions in packages
| - Names introduced by imports
| - Named imports take precedence over wildcard imports
| - You may replace a name when imported using
| ${hl("import")} scala.{ $name => ${name.show + "Tick"} }
| - Definitions from packages in other files
|Note:
| - When importing, you can avoid naming conflicts by renaming:
| ${hl("import")} scala.{$name => ${name.show}Tick}
|"""
}

Expand Down
16 changes: 8 additions & 8 deletions tests/neg/ambiref.check
Original file line number Diff line number Diff line change
@@ -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`
45 changes: 45 additions & 0 deletions tests/neg/i12682.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
-- [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 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 bindings, from highest to lowest, is:
| - Definitions in an enclosing scope
| - Inherited definitions and top-level definitions in packages
| - Names introduced by imports
| - Named imports take precedence over wildcard imports
| - Definitions from packages in other files
| Note:
| - 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 bindings of equal precedence
| were introduced in the same scope.
|
| The precedence of the different kinds of bindings, from highest to lowest, is:
| - Definitions in an enclosing scope
| - Inherited definitions and top-level definitions in packages
| - Names introduced by imports
| - Named imports take precedence over wildcard imports
| - Definitions from packages in other files
| Note:
| - When importing, you can avoid naming conflicts by renaming:
| import scala.{m => mTick}
--------------------------------------------------------------------------------------------------------------------
13 changes: 13 additions & 0 deletions tests/neg/i12682.scala
Original file line number Diff line number Diff line change
@@ -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
8 changes: 4 additions & 4 deletions tests/neg/i13558.check
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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._
4 changes: 2 additions & 2 deletions tests/neg/i9803.check
Original file line number Diff line number Diff line change
@@ -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`

0 comments on commit 4ed780a

Please sign in to comment.