Skip to content

Instantly share code, notes, and snippets.

@tpolecat
Created April 4, 2013 04:39
Show Gist options
  • Save tpolecat/5307872 to your computer and use it in GitHub Desktop.
Save tpolecat/5307872 to your computer and use it in GitHub Desktop.
trait Foo[A]
implicit val c: Foo[Int] = ???
implicit val d: Foo[String] = ???
def bar[A: Foo]: A = ???
bar: Int // compiles only if Foo is covariant in A ... why?
@luciferous
Copy link

Output of -Xprint:typer below. Note the comment which shows the differences between covariant and invariant versions:

package <empty> {
  object Main extends scala.AnyRef {
    def <init>(): Main.type = {
      Main.super.<init>();
      ()
    };
    def main(argv: Array[String]): Unit = {
      val args: Array[String] = argv;
      {
        final class $anon extends scala.AnyRef {
          def <init>(): anonymous class $anon = {
            $anon.super.<init>();
            ()
          };
          abstract trait Foo[A >: Nothing <: Any] extends scala.AnyRef;
          private[this] val c: this.Foo[Int] = scala.this.Predef.???;
          implicit <stable> <accessor> private def c: this.Foo[Int] = $anon.this.c;
          private[this] val d: this.Foo[String] = scala.this.Predef.???;
          implicit <stable> <accessor> private def d: this.Foo[String] = $anon.this.d;
          private def bar[A >: Nothing <: Any](implicit evidence$1: this.Foo[A]): A = scala.this.Predef.???;
          // Invariant
          ($anon.this.bar[Nothing](): Int)
          // Covariant
          // ($anon.this.bar[Int]($anon.this.c): Int)

        };
        {
          new $anon();
          ()
        }
      }
    }
  }
}

@luciferous
Copy link

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