Skip to content

Nil.type widens to Nil$ #4987

Closed
Closed
@nicolasstucki

Description

@nicolasstucki
object Foo {

  class Expr[T]

  abstract class Liftable[T] {
    def toExpr(x: T): Expr[T]
  }

  implicit class LiftExprOps[T](val x: T) extends AnyVal {
    def toExpr(implicit ev: Liftable[T]): Expr[T] = ev.toExpr(x)
  }

  implicit def NilIsLiftable: Liftable[Nil.type] = ???

  Nil.toExpr(NilIsLiftable)
  (Nil.toExpr: Expr[Nil.type])
  Nil.toExpr
}

fails with

-- Error: Foo.scala:49:12 ------------------------------------------------------
49 |  Nil.toExpr
   |            ^
   |no implicit argument of type Foo.Liftable[scala.collection.immutable.Nil] was found for parameter ev of method toExpr in class LiftExprOps

the last case inferes the type scala.collection.immutable.Nil$ instead of collection.immutable.Nil.type for the type parameter of the implicit class LiftExprOps.

This can be seen after typer

result of Foo.scala after frontend:
package <empty> {
  final lazy module val Foo: Foo$ = new Foo$()
  final module class Foo$() extends Object() { this: Foo.type => 
    class Expr[T >: Nothing <: Any]() extends Object() { 
       T
    }
    abstract class Liftable[T >: Nothing <: Any]() extends Object() { 
       T
      def toExpr(x: Liftable.this.T): Foo.Expr[Liftable.this.T]
    }
    final class LiftExprOps[T >: Nothing <: Any](x: T) extends AnyVal() { 
       T
      val x: T
      def toExpr(implicit ev: Foo.Liftable[LiftExprOps.this.T]): 
        Foo.Expr[LiftExprOps.this.T]
       = ev.toExpr(LiftExprOps.this.x)
    }
    final lazy module val LiftExprOps: Foo.LiftExprOps$ = new Foo.LiftExprOps$()
    final module class LiftExprOps$() extends Object() { 
      this: Foo.LiftExprOps.type =>
    }
    implicit def LiftExprOps[T >: Nothing <: Any](x: T): Foo.LiftExprOps[T] = 
      new Foo.LiftExprOps[T](x)
    implicit def NilIsLiftable: Foo.Liftable[Nil.type] = ???
    Foo.LiftExprOps[=> collection.immutable.Nil.type(Nil)](Nil).toExpr(
      Foo.NilIsLiftable
    )
    Foo.LiftExprOps[=> collection.immutable.Nil.type(Nil)](Nil).toExpr(
      Foo.NilIsLiftable
    ): Foo.Expr[Nil.type]
    Foo.LiftExprOps[scala.collection.immutable.Nil$](Nil).toExpr(
      /* missing */implicitly[<notype>]
    )
  }
}

This code does compile on Scala 2.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions