Skip to content

Extensions declared next to opaque types warn that they won't be used even though when used externally they will be used #21190

Closed
@Ichoran

Description

@Ichoran

Compiler version

3.5.0-RC3 or 3.6 nightly

Minimized code

//> using scala 3.nightly
//> using mainClass reproduction.opaqueoverwarning.Main

package reproduction.opaqueoverwarning

opaque type FromEnd = Int
object FromEnd:
  inline def apply(i: Int): FromEnd = i
  extension (fe: FromEnd)
    inline def value: Int = fe

// Warning appears when extension is in same namespace as opaque type
// under 3.5.0-RC3 (and 3.6.0 nightly)
extension [A](a: Array[A])
  inline def apply(fe: FromEnd): A =
    a(a.length - 1 - FromEnd.value(fe))
    
object Main:
  def run(): Unit =
    val xs = Array(1, 2, 3)

    println(s"First element = ${xs(0)}")
    println(s"Last element = ${xs(FromEnd(0))}")

  def main(args: Array[String]): Unit =
    run()

Output

[warn] ./Reproduction.scala:15:14
[warn] Extension method apply will never be selected
[warn] because Array already has a member with the same name and compatible parameter types.
[warn]   inline def apply(fe: FromEnd): A =
[warn]              ^
First element = 1
Last element = 3

Expectation

First element = 1
Last element = 3

because, obviously, the extension method apply was selected, so it certainly isn't the case that it will "never be selected".

If we want to retain the warning in case someone wants to try to use the extension within the same file, at least it should go away when the full path is used (e.g. reproduction.opaqueoverwarning.FromEnd) as a signal that you are taking the external rather than the privileged view of the opaque type.

(Note that there are a number of cases where the full path has to be used already in order to get the desired behavior--in inline matches, for example.)

The warning doesn't happen if the opaque type and extension method are inside an object (see e.g. https://scastie.scala-lang.org/SHWSAqOPSVGV7gdA80WJTA and contrast to https://scastie.scala-lang.org/fes52gRsSmiFpSlHP7r7QA).

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions