Skip to content

Imprecise type inferred with polymorphic type alias #6693

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
fhackett opened this issue Jun 16, 2019 · 2 comments
Closed

Imprecise type inferred with polymorphic type alias #6693

fhackett opened this issue Jun 16, 2019 · 2 comments
Assignees

Comments

@fhackett
Copy link
Contributor

Trying to compile this code yields an error I can't make sense of:

package towers.computes

import quoted._

sealed abstract class Computes[T]

object Computes {

  opaque type Opaque[T] = Int

  implicit class ComputesApplication1[T : Type](fn : Computes[Opaque[T]]) {
    def apply[A](arg1 : Computes[A]) : Computes[T] = ???
  }

  def let[V, T : Type](value : Computes[V], body : Computes[Opaque[T]]) : Computes[T] = body(value)
}

The error is:

[error] -- [E007] Type Mismatch Error: /home/finn/programming/polyparse/src/main/scala/Computes.scala:15:92
[error] 15 |  def let[V, T : Type](value : Computes[V], body : Computes[Opaque[T]]) : Computes[T] = body(value)
[error]    |                                                                                        ^^^^^^^^^^^
[error]    |                             Found:    towers.computes.Computes[Nothing]
[error]    |                             Required: towers.computes.Computes[T]

For some reason, the .apply method on ComputesApplication1 is determined to yield Computes[Nothing] instead of Computes[T] as the signature dictates.

While trying to minimise my example, here are some variations I tried:

  • Removing the : Type implicits prevents the bug from occurring.
  • Replacing Type with a trait declared trait SomeImplicit[T] does not cause the same issue
  • Removing only the : Type in the let method changes nothing, while it should fail because the ComputesApplication1 would then be missing an implicit it needs.
  • Removing the Computes[...] and just leaving Opaque[...] causes what's left to just compile normally
@hrhino

This comment has been minimized.

@nicolasstucki
Copy link
Contributor

nicolasstucki commented Jun 17, 2019

It can be minimized as

sealed abstract class Computes[T]

object Computes {

  type Type[Y]

  type Foo[T] = Int

  class ComputesApplication1[T: Type](fn : Computes[Foo[T]]) {
    def apply() : Computes[T] = ???
  }

  def let[X : Type](body : Computes[Foo[X]]) : Computes[X] = {
    implicit val x: Type[Nothing] = ??? // Should not be needed, looked for as ComputesApplication1[Nothing] requires it
    new ComputesApplication1(body).apply()
  }
}

Therefore it has nothing to do with opaque types, the issue is more general.
For ComputesApplication1 we are inferring the bounds Nothing <:< T <:< X and then choose the lower bound as it is the most precise one.

@nicolasstucki nicolasstucki changed the title Unexplainable interaction between opaque types and implicits Imprecise type inferred with polymorphic type alias Jun 17, 2019
nicolasstucki added a commit to dotty-staging/dotty that referenced this issue Jan 9, 2020
OlivierBlanvillain added a commit that referenced this issue Jan 9, 2020
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

No branches or pull requests

4 participants