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

Inference of higher-kinded type parameters is not precise enough #732

Closed
smarter opened this issue Jul 22, 2015 · 2 comments
Closed

Inference of higher-kinded type parameters is not precise enough #732

smarter opened this issue Jul 22, 2015 · 2 comments

Comments

@smarter
Copy link
Member

smarter commented Jul 22, 2015

In the following code:

class Foo[A](x: A) { override def toString = "Foo(" + x + ")" }
class Bar[A](x: A) extends Foo[A](x) { override def toString = "Bar(" + x + ")" }

object Foo {
  implicit val f: Foo[Int] = new Foo(42)
}

object Bar {
  implicit val b: Bar[Int] = new Bar(42)
}

object Test {
  def printImplicit[CC[X] <: Foo[X]](x: CC[Int])(implicit ev: CC[Int]) = println(ev)

  def main(args: Array[String]) = {
    printImplicit(new Foo(1)) // print "Foo(42)"
    printImplicit[Bar](new Bar(1)) // print "Bar(42)"
    printImplicit(new Bar(1)) // dotty: print "Foo(42)" || scalac: print "Bar(42)"
  }
}

The third implicit in mainis not correctly inferred, because the type parameter is not precise enough:

result of try/hk.scala after frontend:
...
def main(args: Array[String]): Unit = {
  Test.printImplicit[([HK$0] =>  <: Foo[HK$0])](new Foo[Int](1))(Foo.f)
  Test.printImplicit[Bar](new Bar[Int](1))(Bar.b)
  Test.printImplicit[([HK$0] =>  <: Foo[HK$0])](new Bar[Int](1))(Foo.f)
}

scalac handles this correctly:

[syntax trees at end of                     typer]] // hk.scala
...
def main(args: Array[String]): Unit = {
  Test.this.printImplicit[Foo](new Foo[Int](1))(Foo.f);
  Test.this.printImplicit[Bar](new Bar[Int](1))(Bar.b);
  Test.this.printImplicit[Bar](new Bar[Int](1))(Bar.b)
}

Fixing this is necessary to replace #716 by a proper fix, see the work-in-progress at https://github.com/smarter/dotty/commits/fix/missing-implicits .

@odersky : Note that this also happens after applying #731 .

smarter added a commit to smarter/dotty that referenced this issue Jul 22, 2015
This does not work for i553-shuffle.scala because of scala#732
@smarter
Copy link
Member Author

smarter commented Jul 24, 2015

Somehow, the inference seems to only stop working if a higher-kinded type parameter is used in the second parameter list of a method (even if it's used in the first parameter list), unless it is also used in the return type of the method:

class Baz[A]

object Test {
  def one[CC[X]](ev: CC[Int]): Nothing = ???
  def two1[CC[X]](ev: CC[Int])(): Nothing = ???
  def two2a[CC[X]]()(ev: CC[Int]): Nothing = ???
  def two2b[CC[X]]()(ev: CC[Int]): CC[Int] = ???
  def two3a[CC[X]](ev: CC[Int])(ev2: CC[Int]): Nothing = ???
  def two3b[CC[X]](ev: CC[Int])(ev2: CC[Int]): CC[Int] = ???

  def test = {
    val baz: Baz[Int] = new Baz[Int]
    one(baz) // Correct: Infer "[hk$0] => Baz[hk$0]"
    two1(baz)() // Correct: Infer "[hk$0] => Baz[hk$0]"
    two2a()(baz) // Wrong: Infer "[hk$0] => "
    two2b()(baz) // Correct: Infer "[hk$0] => Baz[hk$0]"
    two3a(baz)(baz) // Wrong: Infer "[hk$0] => "
    two3b(baz)(baz) // Correct: Infer "[hk$0] => Baz[hk$0]"
  }

}
package <empty> {
  class Baz[A]() extends Object() { 
    type Baz$$A
    private[this] type A = Baz$$A
  }
  final lazy module val Test: Test$ = new Test$()
  final module class Test$() extends Object() { this: Test.type => 
    def one[CC <: [hk$0] => ](ev: CC[Int]): Nothing = ???
    def two1[CC <: [hk$0] => ](ev: CC[Int])(): Nothing = ???
    def two2a[CC <: [hk$0] => ]()(ev: CC[Int]): Nothing = ???
    def two2b[CC <: [hk$0] => ]()(ev: CC[Int]): CC[Int] = ???
    def two3a[CC <: [hk$0] => ](ev: CC[Int])(ev2: CC[Int]): Nothing = ???
    def two3b[CC <: [hk$0] => ](ev: CC[Int])(ev2: CC[Int]): CC[Int] = ???
    def test: Baz[Int] = {
      val baz: Baz[Int] = new Baz[Int][Int]()
      Test.one[([hk$0] => Baz[hk$0])[hk$0 = Int]](baz)
      Test.two1[([hk$0] => Baz[hk$0])[hk$0 = Int]](baz)()
      Test.two2a[([hk$0] => )]()(baz)
      Test.two2b[([hk$0] => Baz[hk$0])[hk$0 = Int]]()(baz)
      Test.two3a[([hk$0] => )](baz)(baz)
      Test.two3b[([hk$0] => Baz[hk$0])[hk$0 = Int]](baz)(baz)
    }
  }
}

@smarter
Copy link
Member Author

smarter commented Jul 24, 2015

This issue is not specific to higher-kinded types, I've opened #738 to track it and I'm closing this issue for now.

@smarter smarter closed this as completed Jul 24, 2015
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

1 participant