Is this a bug on the language?

I have a app in production using the latest stable version of Flutter:

Flutter (Channel stable, v1.12.13+hotfix.8, on Microsoft Windows [versão 10.0.18362.657],
   locale pt-BR)`

This is definetly killing me for hours and I have no idea what is going on. But iin short terms:

  • I am passing a variable as parameter to a function and inside that function, it has a total different value (and type!)

This is the code :

I pass a variable localId to the function finishOrCancelRecover. In the moment I call that function, my variable is an integer of value 13983. But inside the function it becames an double of value -19.9848765. WTF?

This is the declaration of the localId variable (as you can see, it is immutable!):
image

return lastKnownLocation
                            .timeout(5.seconds)
                            .catchError((it) => null)
                            .then((location) async =>
                                DenoxRequests.finishOrCancelRecover(
                                    localId, //THIS VARIABLE HERE HAS A VALUE OF 13983
                                    false,
                                    location != null
                                        ? UserLocation(
                                            latitude: location.latitude,
                                            longitude: location.longitude,
                                            deviceId: await deviceId,
                                          )
                                        : null))
  • lastKnownLocation is a call for:
Future<Position> get lastKnownLocation async =>
    Geolocator().getLastKnownPosition(desiredAccuracy: LocationAccuracy.high);

I’ve set the debugger and I got this to proove that there is something wrong:

image

image

The result of printing the localId.runtimeType confirms that this is a double now:
image

As you can see on the photo above, the int variable localId has a double value and the value of 19.9848765 is exactly the latitude returned by the Geolocator package. How can it be possible?

Is this a bug on the language or I am crazy here?

Author: Fantashit

1 thought on “Is this a bug on the language?

  1. Thanks for the reproduction @shinayser! Things go wrong at the async transformation level – we don’t correctly allocate async temporaries.

    Pure Dart reduction:

    foo(int x) async {
      return bar(x - 1, x != null ? [x + 1, x + 2, await null] : null);
    }
    
    bar(int a, List b) {
      if (a != (b[0] - 2)) {
        throw 'failure: a=$a, b=$b';
      }
    }
    
    void main() async {
      await foo(0);
    }
    $  out/ReleaseX64/dart test.dart
    Unhandled exception:
    failure: a=1, b=[1, 2, null]
    #0      bar (file:///usr/local/google/home/vegorov/src/dart/sdk/test.dart:7:5)
    #1      foo (file:///usr/local/google/home/vegorov/src/dart/sdk/test.dart:2:10)
    <asynchronous suspension>
    #2      main (file:///usr/local/google/home/vegorov/src/dart/sdk/test.dart:12:9)
    #3      _startIsolate.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:301:19)
    #4      _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:168:12)
    

    Looking at Kernel reveals that we did not properly assign async temporary.

     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
           try {
             #L1:
             {
               :async_temporary_1 = x.{core::num::-}(1);  // Should be :async_temporary_2 I think.
               if(!x.{core::num::==}(null)) {
                 :async_temporary_1 = x.{core::num::+}(1);
                 :async_temporary_0 = x.{core::num::+}(2);
                 [yield] let dynamic #t1 = asy::_awaitHelper(null, :async_op_then, :async_op_error, :async_op) in null;
                 :async_temporary_0 = <dynamic>[:async_temporary_1, :async_temporary_0, _in::unsafeCast<core::Null?>(:result)];
               }
               else {
                 :async_temporary_0 = null;
               }
               :return_value = test::bar(:async_temporary_1, :async_temporary_0);
               break #L1;
             }
             asy::_completeOnAsyncReturn(:async_completer, :return_value);
             return;
           }
           on dynamic catch(dynamic :exception, dynamic :stack_trace) {
             :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
           }
    

    @cskau-g Clement could you take a look at this issue? It’s in the async transformation.

Comments are closed.