sdk icon indicating copy to clipboard operation
sdk copied to clipboard

Late members declared with initializers are not initialized at optimization level 0 of dart2js

Open whesse opened this issue 2 years ago • 2 comments

A class with a late member, declared with an initializer, fails to get initialized when accessed if the program is compiled with dart2js optimization level 0.

The initialization is carried out correctly at higher optimization levels.

The command

dart compile js -O0  test.dart -o test.dart.js

creates a compiled program that fails on Chrome, with the exception:

Uncaught TypeError: this.get$lateMap(...).putIfAbsent$2 is not a function
    at Foo.mapLookup$1 (test.dart:15:20)

on the program

void main()
{
  final foo = Foo();
  final bar = foo.mapLookup('a');
}

class Foo {
  late var lateMap = <String, String>{};
  var map = <String, String>{};

  String mapLookup(String key) {
    final result = map.putIfAbsent(key, () => 'b'); // Succeeds
    final getIt = lateMap; // Not needed to reproduce failure
    // print(getIt); // Fails - toString and runtimeType are absent.
    return lateMap.putIfAbsent(key, () =>'c'); // Fails
    
  }
}

The error is present on the stable branch, and on current tip-of-tree 2.19.0-59.0.dev.

whesse avatar Aug 05 '22 10:08 whesse

Looking at the generated code, I find this:

    isSentinel(value) {
      return false;
    },

and that seems to make the logic around the late final variable go wrong: The variable lateFinalMap is considered initialized even though it isn't.

    get$lateFinalMap() {
      var t1, result,
        value = this.__Foo_lateFinalMap_FI;
      if (A.boolConversionCheck(A.isSentinel(value))) {
        t1 = type$.String;
        result = A.LinkedHashMap_LinkedHashMap$_empty(t1, t1);
        this.__Foo_lateFinalMap_FI !== $ && A.throwLateFieldADI("lateFinalMap");
        this.set$__Foo_lateFinalMap_FI(result);
        value = result;
      }
      return value;
    },

(Edit: I got the example from a different place, the variable was declared as late final lateFinalMap = <String, String>{}; in the example I compiled.)

eernstg avatar Aug 05 '22 11:08 eernstg

This is failing due to --disable-type-inference. See #48312 for a similar issue - I closed that one since some improvements we landed happened to fix it, but I can start digging into the root cause.

fishythefish avatar Aug 08 '22 21:08 fishythefish