bug
bug copied to clipboard
Stabilizer causes type error in combination with type member
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):
- when
FTis a type param,m's parameter type is aTypeReftoT, the undetermined type param off - when
FTis a type member,m's parameter type is anAliasNoArgsTypeRefwith prefixstabilizer$1.typeand symbolFT. It'srelativeInfoindeed points toT, the undetermined type param off.
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).