dart-lang / sdk

The Dart SDK, including the VM, JS and Wasm compilers, analysis, core libraries, and more.
https://dart.dev
BSD 3-Clause "New" or "Revised" License
10.25k stars 1.58k forks source link

Returning implicit nulls is not very helpful. #54830

Open modulovalue opened 9 months ago

modulovalue commented 9 months ago

Consider:

void main() {
  // y is `List<Null>`.
  final y = [0, 1, 2].map((final e) {
    //
  });
}

y evaluates to [null, null, null] because the function literal returns a null implicitly.

This doesn't seem very useful to me and It would be great if a warning could help with detecting such implicitly returned nulls.

I would have expected something along the lines of:

body_might_complete_normally_nullable:

// This function has a nullable return type of 'String?', but ends without returning a value.
String? foo() {}

One possible solution?

Notice that y is inferred to List<Null>. Perhaps a warning about inferred Nulls could be used as a proxy for detecting such "unexpected implicit nulls"?

void main() {
  // y was inferred to `List<Null>` ... this could be an error ... 
  final y = [0, 1, 2].map((final e) {
    //
  });
}
lrhn commented 9 months ago

This is probably a case where we should have an implicitly inferred dynamic . The expression has no context type from final y, the convert function has no return.

We can infer one of two things then, a callback return type of void and y of type Iterable<void>, or dynamic and Iterable<dynamic>. Both allow a convert function without a return statement.

I'd have guessed we choose dynamic.

If we choose Null, I think we should reconsider allowing Null return type functions to be allowed an implicit return or even return; statements. Null is the type of a value, only void should be allowed to omit a value (and dynamic, because it includes everything, including void).