dart-lang / sdk

The Dart SDK, including the VM, dart2js, core libraries, and more.
https://dart.dev
BSD 3-Clause "New" or "Revised" License
9.98k stars 1.54k forks source link

[analyzer] return statements lead to a nullable type being inferred in generators. #51772

Open modulovalue opened 1 year ago

modulovalue commented 1 year ago

Consider the following:

void main() {
  final Iterable<String> foo = () sync* {
    yield "value";
    return;
  }();
  print(foo.toList());
}

I think that the return statement does not contribute to the output of the generator and that it shouldn't have any effect on the type of foo.

However, this fails analysis with:

A value of type 'Iterable<String?>' can't be assigned to a variable of type 'Iterable<String>'.

but compilation succeeds with the output:

[value]

Reproducible on DartPad

master channel
Use Flutter version 3.9.0-1.0.pre.166 and Dart version 3.0.0-322.0.dev
+ Dart experiments: --enable-experiment=records,patterns
srawlins commented 1 year ago

Great catch! It's interesting that this is legal but 🤷 in that case we should not let it influence the inferred types.

bwilkerson commented 1 year ago

@stereotype441

samlythemanly commented 3 months ago

To add some context, this occurs regardless of where the return statement is placed.

I believe this is a more representative use case than returning at the very end, which yields (pun intended) the same errantly inferred nullable type:

final conditionEmitter = () async* {
  if (hasConditionA) {
    yield true;
    return; 
  }

  if (hasConditionB) {
    yield false;
    return;
  }

  yield* _innerConditionEmitter;
};