scala / bug

Scala 2 bug reports only. Please, no questions — proper bug reports only.
https://scala-lang.org
230 stars 21 forks source link

Stabilizer causes type error in combination with type member #12987

Closed lrytz closed 1 month ago

lrytz commented 2 months ago

This fails to compile on 2.13:

// class Foo[FT] {
class Foo {
  type FT
  class I
  def m(b: FT, o: Option[I]): Int = 0
}

object Test {
  // def f[T]: Foo[FT] = ???
  def f[T]: Foo { type FT = T } = ???
  def t = {
    val b: Any = ???
    f.m(b, None)
  }
}

The compiler inserts a stabilizer (https://github.com/scala/scala/pull/5999) because the signature of f.m refers to Foo.this.I:

        <synthetic> <stable> <artifact> val stabilizer$1: Foo{type FT = T} = Test.this.f[T];
        stabilizer$1.m(b, None)

The T in the stabilizer's type is a reference to the type param of f. The type error is

A.scala:11: error: type mismatch;
 found   : Any
 required: T
    f.m(b, None)
        ^

The variant (in comments) using a type parameter FT instead of a type member compiles correctly.

The difference is how the parameter type FT is represented in the method stabilizer$1.m (after asSeenFrom):

Now the issue is that instantiateTypeParams and inferMethodInstance use substSym to replace references to the type param T, but that leaves the AliasNoArgsTypeRef(stabilizer$1.type, FT) untouched.


I think this is specific to stabilizers, because the compiler inserts a stable val but leaves some type params of its rhs undetermined. That's not possible to write in source, val stabilizer$1: Foo{type FT = T} would need a concrete type for T.

So maybe there's some workaround we can do when creating the stabilizer. Changing methods like substSym / instantiateTypeParams / inferMethodInstance for AliasTypeRefs would likely break things (normalize gives the relativeInfo, but that probably drops too much information if we call it that widely).