Skip to content

Incorrect given resolution with abstract type parameter and same type constructor #12051

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
heaven-born opened this issue Apr 11, 2021 · 4 comments

Comments

@heaven-born
Copy link

heaven-born commented Apr 11, 2021

Compiler version

3.0.0-RC2

Minimized code

    trait Test[T]

    given [K]: Test[List[String] & K] with {}

     summon[Test[List[String] & Int]] // compiles
     summon[Test[List[String] & List[Int]]] // doesn't 
     summon[Test[List[String] & Option[Int]]] // compiles again

Output

no implicit argument of type  Test[List[String] & List[Int]] ...

Expectation

Not sure how it works with HKT, but I expected all of them to compile.

@heaven-born heaven-born changed the title Incorrect given resolution with abstract type parameter and HKT Incorrect given resolution with abstract type parameter and same type constructor Apr 11, 2021
@odersky
Copy link
Contributor

odersky commented Apr 11, 2021

List[String] & List[Int] gets simplified to List[String & Int] and then it does not match the intersection anymore.

Generally, matching on intersection is a bad idea since they are not rigid enough.

@odersky odersky closed this as completed Apr 11, 2021
@heaven-born
Copy link
Author

it this simplification apply to invariant type parameters as well?
Because this doesn't work either:

    trait Has0[T]
    trait Test[T]

    given [K]: Test[Has0[String] & K] with {}

    summon[Test[Has0[String] & Has0[Int]]]

@odersky

@odersky
Copy link
Contributor

odersky commented Apr 12, 2021

A good way to find out more about these things is to pass the given that you think should match to the summon.
Then you see:

-- [E007] Type Mismatch Error: ../new/test.scala:6:57 --------------------------
6 |    val x = summon[Test[Has0[String] & Has0[Int]]](using g[)
  |                                                         ^
  |                                  Found:    g[Nothing]
  |                                  Required: Test[Has0[String] & Has0[Int]]

longer explanation available when compiling with `-explain`

The compiler inferred g to have type parameter Nothing. If we pass the expected type, it works:

summon[Test[Has0[String] & Has0[Int]]](using g[Hash0[Int]])  // ok

So yes, in the presence of intersection types you will not get very good type inference.

@heaven-born
Copy link
Author

heaven-born commented Apr 12, 2021

is it possible to fix it in the compiler? I see a lot of ways how this kind of type inference can be used in ZIO for type-level programming. ZIO has its "HAS pattern" and it would be useful to have implicit resolution works this way for replacing one Has to another Has on compile time.
@odersky

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

No branches or pull requests

2 participants