Skip to content

Unable to infer type in presence of type constructors, generics, implicits parameters, and path-dependent types #8802

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
julienrf opened this issue Apr 26, 2020 · 1 comment

Comments

@julienrf
Copy link
Contributor

julienrf commented Apr 26, 2020

(Sorry for the very vague name… I couldn’t figure out what is really specific to this issue)

Minimized code

trait Foo[A, B] {
  type Out
}

object Test {

  type Bar[A]

  def unit: Bar[Unit] = ???
  def product[A, B](fst: Bar[A], snd: Bar[B])(implicit foo: Foo[A, B]): Bar[foo.Out] = ???

  implicit def foo[A]: Foo[A, Unit] { type Out = A } = ???

  def check[A](bar: Bar[A])(a: A): Unit = {}

  check(product(unit, unit))(()) // error
}

Output

-- [E007] Type Mismatch Error: try/i8802.scala:16:8 ----------------------------
16 |  check(product(unit, unit))(()) // error
   |        ^^^^^^^^^^^^^^^^^^^
   |        Found:    Test.Bar[Unit]
   |        Required: Test.Bar[(Foo[Unit, Unit] & Singleton)#Out]
-- [E007] Type Mismatch Error: try/i8802.scala:16:29 ---------------------------
16 |  check(product(unit, unit))(()) // error
   |                             ^^
   |                             Found:    Unit
   |                             Required: (Foo[Unit, Unit] & Singleton)#Out
2 errors found

It seems that the compiler doesn’t completely compute the type resulting from calling product(unit, unit). It shows Foo[Unit, Unit]#Out instead of taking into account the fact that the actual implicit parameter foo had fixed the type Out to Unit.

Expectation

The same code compiles with Scala 2. Is it possible to make it compile with Scala 3 as well?

Workarounds

  • Add explicit type instantiations:
- check(product(unit, unit))(()) // error
+ check[Unit](product(unit, unit))(())
  • Change the signature of product to use an additional type parameter instead of using a path-dependent type:
- def product[A, B](fst: Bar[A], snd: Bar[B])(implicit foo: Foo[A, B]): Bar[foo.Out]
+ def product[A, B, O](fst: Bar[A], snd: Bar[B])(implicit foo: Foo[A, B] { type Out = O }): Bar[O]
@smarter
Copy link
Member

smarter commented Apr 26, 2020

This & Singleton thing comes from the way we handle depend result types:
https://github.com/lampepfl/dotty/blob/f2e5fd08036b2ecbcbc536d49517c8d66ecfa7a5/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala#L532-L547 If I tweak replacement to always return WildcardType instead of creating new typevars, typechecking succeeds for this testcase, because we don't end up polluting the bounds of the type variable of check.

odersky added a commit that referenced this issue Apr 28, 2020
Fix #8802: Use wildcards for result type approximation of implicits
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