NNBD SDK broke existing code – inference of `orElse` argument to Iterable.singleWhere

Here is a repro:

void main() {
  findKey(x, 'bar');
}

const x = {'foo': 'bar'};

void findKey(Map<String, dynamic> m, dynamic search) {
  print(m.entries
      .singleWhere((entry) => entry.value == search, orElse: () => null)
      ?.key);
}

This prints foo on all published SDKs, and the current SDK when it’s not built with --nnbd. When I build the SDK with --nnbd and run this code I instead get:

Unhandled exception:
type '() => MapEntry<String, dynamic>' is not a subtype of type '(() => MapEntry<String, String>)?' of 'orElse'
#0      Iterable.singleWhere (dart:core/iterable.dart)
#1      findKey (file:///usr/local/google/home/nbosch/projects/dart_repro/foo.dart:9:8)
#2      main (file:///usr/local/google/home/nbosch/projects/dart_repro/foo.dart:2:3)
#3      _startIsolate.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:300:19)
#4      _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:167:12)

So when the runtime is Map<String, String>, but statically we have Map<String, dynamic> the orElse argument gets the wrong time.

This does not require enabling the experiment or turning on strong mode.

Author: Fantashit

1 thought on “NNBD SDK broke existing code – inference of `orElse` argument to Iterable.singleWhere

Comments are closed.