scala/scala3

Extension method isn't resolved but can be called directly

Opened this issue · 2 comments

Compiler version

3.3.5 LTS, 3.6.3

Minimized code

enum Child:
  case Son(name: String)

extension [A](x: A)(using Child <:< A) def boo: Unit = println("")
// extension [A >: Child](x: A) def boo: Unit = println("") // works

boo(Child.Son("bob"))  // compiling
(Child.Son("bob")).boo // not compiling

val x = Child.Son("bob")
x.boo // compiling

Output

Compiler error:

value boo is not a member of Playground.Child.Son

Expectation

According the following rule from the doc about extension methods:

The selection is rewritten to m[Ts](e) and typechecked, using the following slight modification of the name resolution rules...

I expect that the behavior for direct call and as-field would be the same.

I understand, that there is a difference in type inference: compiler infers type Son in second case. But type Son is very specific, I feel like it shouldn't be inferred for enum:

Generally, the type of a enum case constructor application will be widened to the underlying enum type, unless a more specific type is expected.

Simpler example:

trait TCl[A]

enum Child:
  case Son(name: String)

given TCl[Child] = new TCl[Child] {}

extension [A: TCl](x: A) def boo: Unit = println("")

boo(Child.Son("bob"))

Child.Son("bob").boo // doesn't compile

val x = Child.Son("bob")
x.boo

https://scastie.scala-lang.org/road21/a2KV87ICTr29S4zBeBTkbQ/8

Conversely,

extension (x: Child.Son) def boob: Unit = println("boob")
Child.Son("bob").boob

The other rule is "add variance until it typechecks".

trait TCl[-A]