sdk icon indicating copy to clipboard operation
sdk copied to clipboard

Cast instead of null assertion when migrating to Null Safety

Open michalt opened this issue 4 years ago • 6 comments

Steps to reproduce

Small repro:

Future<String> foo() async {
  return null;
}

Future<int> bar() async {
  var str = await foo();
  return str.length;
}

What did you expect to happen?

I would've expected:

Future<String?>  foo() async {
  return null;
}

Future<int> bar() async {
  var str = await foo();
  return str!.length;
}

Or alternatively:

[...] // foo() as above

Future<int> bar() async {
  var str = (await foo())!;
  return str.length;
}

What actually happened?

Future<String?>  foo() async {
  return null;
}

Future<int >  bar() async {
  var str = await (foo() as FutureOr<String>);
  return str.length;
}

Dart SDK version: 2.12.340383196-edge+google3-v2

michalt avatar Nov 03 '20 14:11 michalt

cc @stereotype441

mit-mit avatar Nov 03 '20 14:11 mit-mit

Note that this should probably be fixed because the cast inserted is actually unsound, not just ugly. It will cause problems when enabling sound null safety, repro example:

void main() async {
  var y = await (foo('hello') as Future<String>);
}

Future<T?> foo<T extends Object>(T arg) async => arg;

This fails with Uncaught Error: TypeError: Instance of '_Future<String?>': type '_Future<String?>' is not a subtype of type 'Future<String>' in sound mode

jakemac53 avatar Jun 17 '22 17:06 jakemac53

I'm seeing some bogus uses of as FutureOr<String> in g3 likely caused by this issue. @stereotype441 what is the minimum we can do to prevent the tool from generating these casts? I'd be ok if the migration tool just failed to try to handle this case at all leaving this as a case for users to manually resolve.

jacob314 avatar Aug 04 '22 21:08 jacob314

Followed up with @stereotype441 offline and we agree that just preventing the tool from generating the as FutureOr<String> is the most realistic solution. This will cause a few analysis errors that users will need to manually have to fix but that is better than having the tool generate casts that will fail at runtime.

jacob314 avatar Aug 04 '22 21:08 jacob314

Fwiw, this does occur with other generic types other than String as well. These are generally responses from some API from what I have seen, and often have the word Response in the name of the type. I don't know what percentage of cases that would catch, or if you would consider dropping all casts to FutureOr<any type here>.

Fwiw, I can't think of a single valid cast to any type of FutureOr that has been generated by the tool.

jakemac53 avatar Aug 04 '22 23:08 jakemac53

Actually, I would wager that the significant majority of casts to anything with a specific generic type are invalid. I have seen similarly invalid casts to types like Iterable<String> etc that will fail at runtime.

jakemac53 avatar Aug 04 '22 23:08 jakemac53