Skip to content

Incorrect type inference for F-bounds #11234

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

Closed
liufengyun opened this issue Jan 27, 2021 · 0 comments · Fixed by #11237
Closed

Incorrect type inference for F-bounds #11234

liufengyun opened this issue Jan 27, 2021 · 0 comments · Fixed by #11237

Comments

@liufengyun
Copy link
Contributor

Compiler version

M3

Minimized code

trait Foo[A <: Foo[A]]
trait FooCreator[A <: Foo[A]] {
  def createFoo(): A
}

trait FooWrapper {
  type A <: Foo[A]
  def foo: A
}

object FooWrapper {
  def apply[A0 <: Foo[A0]](toWrap: A0): FooWrapper { type A = A0 } = new FooWrapper {
    type A = A0
    def foo: A0 = toWrap
  }
}

def error(fooWrapper: FooWrapper, processor: [A <: Foo[A]] => A => A): FooWrapper =
  FooWrapper(processor(fooWrapper.foo))

Output

Compiler reports an error with a huge type. It's impossible to see what's wrong.

The following code compiles without any problem:

def error(fooWrapper: FooWrapper, processor: [A <: Foo[A]] => A => A): FooWrapper =
-  FooWrapper(processor(fooWrapper.foo))
+  FooWrapper[fooWrapper.A](processor(fooWrapper.foo))

Expectation

Compiles without error.

This is another issue reported in #11078. As the fix is different, thus it better to handle it in a different issue.

@liufengyun liufengyun self-assigned this Jan 27, 2021
liufengyun added a commit to dotty-staging/dotty that referenced this issue Jan 28, 2021
**Note**: this is a trial as `Constraints` should be immutable.

In tests/pos/11234.scala, we have the following F-bounded constraints:

    bounds =
	A0 <: Foo[LazyRef(A0)]
	A <: Foo[LazyRef(A)]
    ordering =
	A <: A0

As `Foo[T]` is non-variant, at some point we will add `A0 <: A`, it
will trigger unification of `A0` and `A`. The unification will call
`Foo[A0].&(Foo[A])`, which in turn calls `TypeComparer.glb(Foo[A0],
Foo[A])`.  The call `glb(Foo[A0], Foo[A])` in a fresh TypeComparer
will in turn add `A0 <: A` thus trigger the unification again.

We break the loop by remembering the unification pair and use the
knowledge in subtyping.
liufengyun added a commit to dotty-staging/dotty that referenced this issue Jan 28, 2021
**Note**: this is a trial as `Constraints` should be immutable.

In tests/pos/11234.scala, we have the following F-bounded constraints:

    bounds =
	A0 <: Foo[LazyRef(A0)]
	A <: Foo[LazyRef(A)]
    ordering =
	A <: A0

As `Foo[T]` is non-variant, at some point we will add `A0 <: A`, it
will trigger unification of `A0` and `A`. The unification will call
`Foo[A0].&(Foo[A])`, which in turn calls `TypeComparer.glb(Foo[A0],
Foo[A])`.  The call `glb(Foo[A0], Foo[A])` in a fresh TypeComparer
will in turn add `A0 <: A` thus trigger the unification again.

We break the loop by remembering the unification pair and use the
knowledge in subtyping.
liufengyun added a commit to dotty-staging/dotty that referenced this issue Mar 4, 2021
In tests/pos/11234.scala, we have the following F-bounded constraints:

    bounds =
	A0 <: Foo[LazyRef(A0)]
	A <: Foo[LazyRef(A)]
    ordering =
	A <: A0

As `Foo[T]` is non-variant, at some point we will add `A0 <: A`, it
will trigger unification of `A0` and `A`. The unification will call
`Foo[A0].&(Foo[A])`, which in turn calls `TypeComparer.glb(Foo[A0],
Foo[A])`.  The call `glb(Foo[A0], Foo[A])` in a fresh TypeComparer
will in turn add `A0 <: A` thus trigger the unification again.

We need to perform substitution before merge the bounds.
odersky added a commit that referenced this issue Mar 4, 2021
Fix #11234: Avoid cycles in unifying F-bounded type parameters
@Kordyjan Kordyjan added this to the 3.0.0 milestone Aug 2, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants