Skip to content

Uncurry is picky about its erasure decision (when it shouldn't) #9443

Closed as duplicate of#9475
@scabug

Description

@scabug

Following up on #6443 and #9442, is seems the uncurry erasure is quite picky:

$ cat test2.scala 
trait Ctx {
  trait Tree
}
trait Lst[+A] {
  def zip[A1 >: A, B](that: Lst[B]): Nothing
}
object Test {
  def foo1(c: Ctx)(l: Lst[c.Tree]) = l zip l
  def foo2[T](c: Ctx)(l: Lst[c.Tree])(t: T) = l zip l
}

$ scalac test2.scala -Xprint:uncurry
[[syntax trees at end of                   uncurry]] // test2.scala
package <empty> {
  abstract trait Ctx extends Object {
    def /*Ctx*/$init$(): Unit = {
      ()
    };
    abstract trait Tree extends Object
  };
  abstract trait Lst[+A] extends Object {
    def zip[A1 >: A, B](that: Lst[B]): Nothing
  };
  object Test extends Object {
    def <init>(): Test.type = {
      Test.super.<init>();
      ()
    };
    def foo1(c: Ctx, l: Lst[Ctx#Tree]): Nothing = {
      <synthetic> val l$1: Lst[c.Tree] = l.asInstanceOf[Lst[c.Tree]]();
      l$1.zip[c.Tree, c.Tree](l$1)
    };
    def foo2[T](c: Ctx, l: Lst[c.Tree], t: T): Nothing = l.zip[c.Tree, c.Tree](l)
  }
}

So, depending on whether you have a type parameter, it decides to erase or not:

    def foo1(c: Ctx, l: Lst[Ctx#Tree]): Nothing = {
      <synthetic> val l$1: Lst[c.Tree] = l.asInstanceOf[Lst[c.Tree]]();
      l$1.zip[c.Tree, c.Tree](l$1)
    };
    def foo2[T](c: Ctx, l: Lst[c.Tree], t: T): Nothing = l.zip[c.Tree, c.Tree](l)

I think the problem lies in the isDependentMethodType method in class Type, but I may be wrong:

$ scala
Welcome to Scala 2.11.8-20150821-135328-f8a6d21a49 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_80).
Type in expressions for evaluation. Or try :help.

scala> trait Ctx {
     |   trait Tree
     | }
defined trait Ctx

scala> trait Lst[+A] {
     |   def zip[A1 >: A, B](that: Lst[B]): Nothing
     | }
defined trait Lst

scala> object Test {
     |   def foo1(c: Ctx)(l: Lst[c.Tree]) = l zip l
     |   def foo2[T](c: Ctx)(l: Lst[c.Tree])(t: T) = l zip l
     | }
defined object Test

scala> import scala.reflect.runtime.universe._
import scala.reflect.runtime.universe._

scala> typeTag[Test.type].tpe.member(TermName("foo1")).info.asInstanceOf[scala.reflect.internal.Types#Type].isDependentMethodType
res0: Boolean = true

scala> typeTag[Test.type].tpe.member(TermName("foo2")).info.asInstanceOf[scala.reflect.internal.Types#Type].isDependentMethodType
res1: Boolean = false

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions