dart-lang / language

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

Inconsistent inference in analyzer and CFE #2130

Open leafpetersen opened 2 years ago

leafpetersen commented 2 years ago

The following code is inferred inconsistently between the CFE and the analyzer:

void main(){
  String? variable;
  var f = Future.value(variable);
  Future<String> x = f;
}

The analyzer emits no error, suggesting that inference is inferring String for the type argument to Future.value, whereas the CFE emits the following error:

leafp-macbookpro2:sdk leafp$ ~/src/dart-repo/sdk/xcodebuild/ReleaseARM64/dart ~/tmp/example.dart
../../../tmp/example.dart:5:22: Error: A value of type 'Future<String?>' can't be assigned to a variable of type 'Future<String>' because 'String?' is nullable and 'String' isn't.
 - 'Future' is from 'dart:async'.
  Future<String> x = f;

I believe the analyzer behavior here is in general more useful, I'm not sure off hand which is consistent with the spec. cc @stereotype441 @eernstg @johnniwinther @scheglov

scheglov commented 2 years ago

We apply following rules when gathering constraints here in the analyzer:

String? vs FutureOr<T>?

  • If Q is Q0? the match holds under constraint set C:
    • If P is P0? and P0 is a subtype match for Q0 under constraint set C.

String vs FutureOr<T>

  • If Q is FutureOr<Q0> the match holds under constraint set C:
    • Or if P is a subtype match for Q0 under constraint set C.

String vs T.

johnniwinther commented 2 years ago

cc @chloestefantsova

lrhn commented 2 years ago

This does suck extra because the parameter to Future.value is optional and nullable, and it's not part of the type system that you must only pass null when the type argument is nullable.

(We should fix that!)