Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return type depending on parameter type (e.g. Await.ready()) does not work as expected

Scala Await.ready() method is defined like this:

def ready[T](awaitable: Awaitable[T], atMost: Duration): awaitable.type = ...

That is, the return type is a path-dependent type of awaitable parameter. I thought that (and IntelliJ IDEA agreed with me) this means that if I pass Future to the function, it should return Future of the same type, and indeed, it does work in simple cases:

val f: Future[Int] = Future { 10 }
val ft: Future[Int] = Await.ready(f, ???)

This code compiles, that is, Await.ready() here really returns Future[Int]. However, the following does not work:

val f: Future[Int] = Future { 10 }
val ft: Future[Int] = Await.ready(f.map(identity), ???)

It fails with this error:

[error] /Users/netvl/dev/work/sandbox/src/main/scala/circuit/actors/Example.scala:53: type mismatch;
[error]  found   : awaitable.type (with underlying type scala.concurrent.Awaitable[Int])
[error]  required: scala.concurrent.Future[Int]
[error]       val ft: Future[Int] = Await.ready(f.map(identity), ???)
[error]                                        ^

Why does it happen? f.map(identity) returns Future[Int], so I thought that calling methods on the future which return another future should work too. The only thing to fix this (aside from rewriting) seems to be asInstanceOf[Future[Int]] call, type ascriptions do not work.

BTW, as a small side question, how variable.type syntax is properly called? I know it is related to path-dependent types, but I couldn't find its exact name or description and had a hard time googling for it.

I'm using Scala 2.10.4.

like image 718
Vladimir Matveev Avatar asked Nov 01 '22 20:11

Vladimir Matveev


1 Answers

The Scala version would be helpful here. With Scala 2.11.1 it works perfectly fine:

scala> val f: Future[Int] = Future(10)
f: scala.concurrent.Future[Int] = scala.concurrent.impl.Promise$DefaultPromise@68d0db31

scala> val ft: Future[Int] = Await.ready(f.map(identity), 1.second)
ft: scala.concurrent.Future[Int] = scala.concurrent.impl.Promise$DefaultPromise@68d0db31
like image 177
drexin Avatar answered Nov 15 '22 05:11

drexin