Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stabilizer causes type error in combination with type member #12987

Closed
lrytz opened this issue Apr 19, 2024 · 0 comments · Fixed by scala/scala#10760
Closed

Stabilizer causes type error in combination with type member #12987

lrytz opened this issue Apr 19, 2024 · 0 comments · Fixed by scala/scala#10760
Assignees
Milestone

Comments

@lrytz
Copy link
Member

lrytz commented Apr 19, 2024

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 (scala/scala#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 FT is a type param, stabilizer$1.m has parameter type TypeRef to T, the undetermined type param of f. FT is substituted.
  • when FT is a type member, m's parameter type is an AliasNoArgsTypeRef with prefix stabilizer$1.type and symbol FT (it's not substitued). It's relativeInfo indeed points to T, the undetermined type param of f.

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).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants