Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 28 additions & 10 deletions compiler/src/dotty/tools/dotc/reporting/messages.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2364,7 +2364,7 @@ class SymbolIsNotAValue(symbol: Symbol)(using Context) extends TypeMsg(SymbolIsN
}

class DoubleDefinition(decl: Symbol, previousDecl: Symbol, base: Symbol)(using Context)
extends NamingMsg(DoubleDefinitionID) {
extends NamingMsg(DoubleDefinitionID):
import Signature.MatchDegree.*

private def erasedType: Type =
Expand Down Expand Up @@ -2426,6 +2426,25 @@ extends NamingMsg(DoubleDefinitionID) {
} + details
}
def explain(using Context) =
def givenAddendum =
def isGivenName(sym: Symbol) = sym.name.startsWith("given_") // Desugar.inventGivenName
def print(tpe: Type): String =
def addParams(tpe: Type): List[String] = tpe match
case tpe: MethodType =>
val s = if tpe.isContextualMethod then i"(${tpe.paramInfos}%, %) =>" else ""
s :: addParams(tpe.resType)
case tpe: PolyType =>
i"[${tpe.paramNames}%, %] =>" :: addParams(tpe.resType)
case tpe =>
i"$tpe" :: Nil
addParams(tpe).mkString(" ")
if decl.is(Given) && previousDecl.is(Given) && isGivenName(decl) && isGivenName(previousDecl) then
i"""| Provide an explicit, unique name to given definitions,
| since the names assigned to anonymous givens may clash. For example:
|
| given myGiven: ${print(atPhase(typerPhase)(decl.info))}
|"""
else ""
decl.signature.matchDegree(previousDecl.signature) match
case FullMatch =>
i"""
Expand All @@ -2439,30 +2458,29 @@ extends NamingMsg(DoubleDefinitionID) {
|
|In your code the two declarations
|
| ${previousDecl.showDcl}
| ${decl.showDcl}
| ${atPhase(typerPhase)(previousDecl.showDcl)}
| ${atPhase(typerPhase)(decl.showDcl)}
|
|erase to the identical signature
|
| ${erasedType}
|
|so the compiler cannot keep both: the generated bytecode symbols would collide.
|
|To fix this error, you need to disambiguate the two definitions. You can either:
|To fix this error, you must disambiguate the two definitions by doing one of the following:
|
|1. Rename one of the definitions, or
|1. Rename one of the definitions.$givenAddendum
|2. Keep the same names in source but give one definition a distinct
| bytecode-level name via `@targetName` for example:
| bytecode-level name via `@targetName`; for example:
|
| @targetName("${decl.name.show}_2")
| ${decl.showDcl}
| ${atPhase(typerPhase)(decl.showDcl)}
|
|Choose the `@targetName` argument carefully: it is the name that will be used
|when calling the method externally, so it should be unique and descriptive.
"""
|"""
case _ => ""

}
end DoubleDefinition

class ImportedTwice(sel: Name)(using Context) extends SyntaxMsg(ImportedTwiceID) {
def msg(using Context) = s"${sel.show} is imported twice on the same import line."
Expand Down
7 changes: 3 additions & 4 deletions tests/neg/i23350.check
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,15 @@
|
| so the compiler cannot keep both: the generated bytecode symbols would collide.
|
| To fix this error, you need to disambiguate the two definitions. You can either:
| To fix this error, you must disambiguate the two definitions by doing one of the following:
|
| 1. Rename one of the definitions, or
| 1. Rename one of the definitions.
| 2. Keep the same names in source but give one definition a distinct
| bytecode-level name via `@targetName` for example:
| bytecode-level name via `@targetName`; for example:
|
| @targetName("apply_2")
| def apply(a: UndefOr2[String]): Unit
|
| Choose the `@targetName` argument carefully: it is the name that will be used
| when calling the method externally, so it should be unique and descriptive.
|
---------------------------------------------------------------------------------------------------------------------
7 changes: 3 additions & 4 deletions tests/neg/i23402.check
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,15 @@
|
| so the compiler cannot keep both: the generated bytecode symbols would collide.
|
| To fix this error, you need to disambiguate the two definitions. You can either:
| To fix this error, you must disambiguate the two definitions by doing one of the following:
|
| 1. Rename one of the definitions, or
| 1. Rename one of the definitions.
| 2. Keep the same names in source but give one definition a distinct
| bytecode-level name via `@targetName` for example:
| bytecode-level name via `@targetName`; for example:
|
| @targetName("apply_2")
| def apply(p1: String)(p2: Int): A
|
| Choose the `@targetName` argument carefully: it is the name that will be used
| when calling the method externally, so it should be unique and descriptive.
|
---------------------------------------------------------------------------------------------------------------------
45 changes: 45 additions & 0 deletions tests/neg/i23832a.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
-- [E120] Naming Error: tests/neg/i23832a.scala:9:8 --------------------------------------------------------------------
9 | given Special[Option[Int]] = ??? // error
| ^
| Conflicting definitions:
| final lazy given val given_Special_Option: Special[Option[Long]] in object syntax at line 8 and
| final lazy given val given_Special_Option: Special[Option[Int]] in object syntax at line 9
|---------------------------------------------------------------------------------------------------------------------
| Explanation (enabled by `-explain`)
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
| As part of the Scala compilation pipeline every type is reduced to its erased
| (runtime) form. In this phase, among other transformations, generic parameters
| disappear and separate parameter-list boundaries are flattened.
|
| For example, both `f[T](x: T)(y: String): Unit` and `f(x: Any, z: String): Unit`
| erase to the same runtime signature `f(x: Object, y: String): Unit`. Note that
| parameter names are irrelevant.
|
| In your code the two declarations
|
| final lazy given val given_Special_Option: Special[Option[Long]]
| final lazy given val given_Special_Option: Special[Option[Int]]
|
| erase to the identical signature
|
| Special
|
| so the compiler cannot keep both: the generated bytecode symbols would collide.
|
| To fix this error, you must disambiguate the two definitions by doing one of the following:
|
| 1. Rename one of the definitions. Provide an explicit, unique name to given definitions,
| since the names assigned to anonymous givens may clash. For example:
|
| given myGiven: Special[Option[Int]]
|
| 2. Keep the same names in source but give one definition a distinct
| bytecode-level name via `@targetName`; for example:
|
| @targetName("given_Special_Option_2")
| final lazy given val given_Special_Option: Special[Option[Int]]
|
| Choose the `@targetName` argument carefully: it is the name that will be used
| when calling the method externally, so it should be unique and descriptive.
---------------------------------------------------------------------------------------------------------------------
9 changes: 9 additions & 0 deletions tests/neg/i23832a.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
//> using options -explain

// follow-up to neg/i23402*.scala

trait Special[A]

object syntax:
given Special[Option[Long]] = ???
given Special[Option[Int]] = ??? // error
45 changes: 45 additions & 0 deletions tests/neg/i23832b.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
-- [E120] Naming Error: tests/neg/i23832b.scala:9:8 --------------------------------------------------------------------
9 | given [A] => Special[Option[A]] = ??? // error
| ^
| Conflicting definitions:
| final lazy given val given_Special_Option: Special[Option[Long]] in object syntax at line 8 and
| final given def given_Special_Option[A]: Special[Option[A]] in object syntax at line 9
|---------------------------------------------------------------------------------------------------------------------
| Explanation (enabled by `-explain`)
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
| As part of the Scala compilation pipeline every type is reduced to its erased
| (runtime) form. In this phase, among other transformations, generic parameters
| disappear and separate parameter-list boundaries are flattened.
|
| For example, both `f[T](x: T)(y: String): Unit` and `f(x: Any, z: String): Unit`
| erase to the same runtime signature `f(x: Object, y: String): Unit`. Note that
| parameter names are irrelevant.
|
| In your code the two declarations
|
| final lazy given val given_Special_Option: Special[Option[Long]]
| final given def given_Special_Option[A]: Special[Option[A]]
|
| erase to the identical signature
|
| (): Special
|
| so the compiler cannot keep both: the generated bytecode symbols would collide.
|
| To fix this error, you must disambiguate the two definitions by doing one of the following:
|
| 1. Rename one of the definitions. Provide an explicit, unique name to given definitions,
| since the names assigned to anonymous givens may clash. For example:
|
| given myGiven: [A] => Special[Option[A]]
|
| 2. Keep the same names in source but give one definition a distinct
| bytecode-level name via `@targetName`; for example:
|
| @targetName("given_Special_Option_2")
| final given def given_Special_Option[A]: Special[Option[A]]
|
| Choose the `@targetName` argument carefully: it is the name that will be used
| when calling the method externally, so it should be unique and descriptive.
---------------------------------------------------------------------------------------------------------------------
9 changes: 9 additions & 0 deletions tests/neg/i23832b.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
//> using options -explain

// follow-up to neg/i23402*.scala

trait Special[A]

object syntax:
given Special[Option[Long]] = ???
given [A] => Special[Option[A]] = ??? // error
Loading