haxetink / tink_await

Haxe async/await
MIT License
58 stars 15 forks source link

with Haxe 4.3 Await.transform is called twice .. #48

Closed AdrianV closed 1 year ago

AdrianV commented 1 year ago

.. under some conditions, that I couldn't nail down until now.

I have a larger project with a lot of dependencies and I tried to compile it with Haxe 4.3. Currently I stuck at tink_await because in the case of this project Await.transform is called twice for each @await and @async function. With Haxe 4.2.5 this does not happen.

To minimize impact of the Haxe cache the code was compiled from command line without using the completion cache.

My first try was to compile with a dependency to this class:

@await
class TestAsync {
    inline public function new() {

    }

    @async
    public function foo(): Int {
        return 1;
    }

    @await
    static function __init__() {
        final test = new TestAsync();
                $type(test.foo);
        final x = @await test.foo();
    }
}

and compiled it with -D await_debug

this is the log I got for this class:

=======================
#pos(src/test/TestAsync.hx:10: lines 10-12)
foo
=======================
return tink.core.Promise.lift(tink.core.Future.irreversible(function(__return) try {
    return __return(tink.core.Outcome.Success(1));
} catch(e:Dynamic) __return(tink.core.Outcome.Failure(tink.core.Error.asError(e)))))
=======================
#pos(src/test/TestAsync.hx:15: lines 15-19)
__init__
=======================
{
    final test = new TestAsync();
    $type(test.foo);
    test.foo().handle(function(__t0) {
        var __t0_result;
        switch tink.await.OutcomeTools.getOutcome(__t0) {
            case Success(v):{
                __t0_result = v;
            };
            case Failure(e):{
                throw e;
                return;
            };
        };
        final x = __t0_result;
    });
}
=======================
#pos(src/test/TestAsync.hx:10: lines 10-12)
foo
=======================
return tink.core.Promise.lift(tink.core.Future.irreversible(function(__return) try return __return(tink.core.Outcome.Success(tink.core.Promise.lift(tink.core.Future.irreversible(function(__return) try {
    return __return(tink.core.Outcome.Success(1));
} catch(e:Dynamic) __return(tink.core.Outcome.Failure(tink.core.Error.asError(e))))))) catch(e:Dynamic) __return(tink.core.Outcome.Failure(tink.core.Error.asError(e)))))
=======================
#pos(src/test/TestAsync.hx:15: lines 15-19)
__init__
=======================
{
    final test = new TestAsync();
    $type(test.foo);
    test.foo().handle(function(__t0) {
        var __t0_result;
        switch tink.await.OutcomeTools.getOutcome(__t0) {
            case Success(v):{
                __t0_result = v;
            };
            case Failure(e):{
                throw e;
                return;
            };
        };
        final x = __t0_result;
    });
}

which shows the problem. TestAsync.foo is now typed as Future<Outcome<Future<Outcome<Int,Error>>,Error>> instead of Future<Outcome<Int,Error>>.

At the moment I am not able do bring a simple self contained example, since the problem goes away as soon as I simplify the code.

So I am not sure where the root of the problem lies:

AdrianV commented 1 year ago

closed with https://github.com/haxetink/tink_syntaxhub/commit/aae6e4536dd13551085b13cfce1f8cde9cb16498