Skip to content

FutureSystem impl where futureSystem.Tryy != scala.util.Try fails to compile #57

Closed
@tdyas

Description

@tdyas

I have an implementation of FutureSystem nearly complete to connect scala-async with the Twitter util-core implementation of futures. It fails to compile with this error:

[error] /Users/tdyas/Code/twitter-util-async/src/test/scala/com/foursquare/common/async/TwitterFutureSystemTest.scala:16: class stateMachine$1 needs to be abstract, since method apply in trait Function1 of type (v1: scala.util.Try[Any])Unit is not defined
[error] (Note that T1 does not match com.twitter.util.Try[Any])
[error]     val f3 = async {

The issue seems to be the hard-coded reference to scala.util.Try in src/main/scala/scala/async/internal/AsyncTransform.scala:

val template = Template(List(typeOf[(scala.util.Try[Any] => Unit)], typeOf[() => Unit]).map(TypeTree(_)), emptyValDef, body)

Basically, the apply method is expecting com.twitter.util.Try but scala-async is hard-coding scala.util.Try.

The AST produced by the code is:

asyncImpl: tree=Expr[AsyncBase.this.futureSystem.Fut[Int]]({
  class stateMachine$1 extends scala.util.Try[Any] => Unit with () => Unit {
    <synthetic> <stable> private[this] var await$2$1: Int = 0;
    <synthetic> <stable> private[this] var await$1$1: Int = 0;
    <stable> private[this] var v1$1: Int = 0;
    def <init>(): stateMachine$1 = {
      stateMachine$1.super.<init>();
      ()
    };
    private[this] var state: Int = 0;
    private[this] val result: com.twitter.util.Promise[Int] = Promise.apply[Int]();
    private[this] val execContext: scala.concurrent.ExecutionContextExecutor = scala.concurrent.ExecutionContext.Implicits.global;
    def resume(): Unit = try {
      stateMachine$1.this.state match {
        case 0 => {
          ();
          <synthetic> val awaitable$1: com.twitter.util.Future[Int] @scala.reflect.internal.annotations.uncheckedBounds = f1;
          {
            awaitable$1.respond(((x: com.twitter.util.Try[Int]) => {
              this.apply(x);
              ()
            }));
            ()
          };
          ()
        }
        case 1 => {
          stateMachine$1.this.v1$1 = stateMachine$1.this.await$1$1;
          <synthetic> val awaitable$2: com.twitter.util.Future[Int] @scala.reflect.internal.annotations.uncheckedBounds = f2;
          {
            awaitable$2.respond(((x: com.twitter.util.Try[Int]) => {
              this.apply(x);
              ()
            }));
            ()
          };
          ()
        }
        case 2 => {
          stateMachine$1.this.result.update(Return.apply[Int]({
            val v2: Int = stateMachine$1.this.await$2$1;
            stateMachine$1.this.v1$1.+(v2)
          }));
          ()
        }
      }
    } catch {
      case (throwable @ _) if NonFatal.apply(throwable) => {
        stateMachine$1.this.result.update(Throw.apply[Int](throwable));
        ()
      }
    };
    def apply(tr: com.twitter.util.Try[Any]): Unit = stateMachine$1.this.state match {
      case 0 => {
        if (tr.isThrow)
          {
            stateMachine$1.this.result.update(tr.asInstanceOf[com.twitter.util.Try[Int]]);
            ()
          }
        else
          {
            stateMachine$1.this.await$1$1 = tr.get().asInstanceOf[Int];
            stateMachine$1.this.state = 1;
            stateMachine$1.this.resume()
          };
        ()
      }
      case 1 => {
        if (tr.isThrow)
          {
            stateMachine$1.this.result.update(tr.asInstanceOf[com.twitter.util.Try[Int]]);
            ()
          }
        else
          {
            stateMachine$1.this.await$2$1 = tr.get().asInstanceOf[Int];
            stateMachine$1.this.state = 2;
            stateMachine$1.this.resume()
          };
        ()
      }
    };
    def apply: Unit = resume();
    private[this] val extra: Unit = ()
  };
  val stateMachine$1 = new stateMachine$1();
  {
    val promise = Promise.apply[Unit]();
    stateMachine$1.execContext.execute({
      final class $anon extends Runnable {
        def <init>() = {
          super.<init>();
          ()
        };
        def run(): Unit = try {
          promise.setValue(stateMachine$1.apply())
        } catch {
          case (ex @ (_: `package`.Exception)) => promise.setException(ex)
        }
      };
      new $anon()
    });
    promise
  };
  stateMachine$1.result
})

I tried changing AsyncTransform.scala to refer to typeOf[futureSystem.Tryy[Any] => Unit] instead but then running the scala-async tests gave errors like this:

[error] /Users/tdyas/Code/scala-async/src/test/scala/scala/async/run/ifelse3/IfElse3.scala:24: type mismatch;
[error]  found   : stateMachine$1
[error]  required: scala.util.Try[Int] => ?
[error]   def m(y: Int): Future[Int] = async {
[error]                                      ^

Any ideas?

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