dart-lang / language

Design of the Dart language
Other
2.68k stars 205 forks source link

Null-aware return doesn't promote variable #4156

Open feinstein opened 4 weeks ago

feinstein commented 4 weeks ago

Consider this code:

final lastTransaction = transactions.lastOrNull;
if (lastTransaction?.expirationDate == null) {
  return false;
}

final expirationDate = DateTime.tryParse(lastTransaction!.expirationDate!);

If I remove the !, I get an analyser error saying I can't use lastTransaction because it can be null. I believe the analyser should be able to conclude that lastTransaction can't be null, because it's a final local variable, and the ?. in the if check would ensure there's no valid code path for it to still be null.

lrhn commented 3 weeks ago

The compiler doesn't recognize that x?.y != null implies that x is not null. Only comparisons directly against it x can promote x.

There are existing issues suggesting such indirect implications, but they're not always as clear-cut as directed checks out the variable.

In this case x?.y != null can promote x to non-null, but x?.y == null does not imply that x is null.

mateusfccp commented 3 weeks ago

Similar to #1224.

Doesn't this work for you?

final expirationDate = transactions.lastOrNull?.expirationDate;
if (expirationDate == null) {
  return false;
}

final parsedExpirationDate = DateTime.tryParse(expirationDate);
feinstein commented 3 weeks ago

In this case x?.y != null can promote x to non- null, but x?.y == null does not imply that x is null.

@lrhn I agree that x?.y == null doesn't imply that x is null, but in this case the compiler could be able to have some more sofisticated logic to promote it, as if the if-check is not null, then x could not be null.

Do you want me to leave this as a request or close it?

@mateusfccp I made it work, thanks, my goal with this snippet was more to showcase my point.