Description
I've encountered a weird bug stemming from Dart's handling of generics/futures. Consider the following snippet:
Future<void> main() async {
Future<Object?> _nestedFuture() => Future.value('test');
Future<Object> _promoted() async {
return _nestedFuture();
}
Future<Object?> _notPromoted() async {
return _nestedFuture();
}
print('await _promoted() returns ${await _promoted()}');
print('await _notPromoted() returns ${await _notPromoted()}');
}
Here the _promoted()
method returns a Future wrapping the future from _nestedFuture()
, while the _notPromoted()
method returns the result of _nestedFuture()
directly. The issue lies in the fact that Future<Object?>
is not assignable to Future<Object>
, but is assignable to Object
, and hence the compiler wraps one future in another, and await _promoted()
returns the future from _nestedFuture()
.
It might not be against specification of the Dart language, but I would appreciate if such wrapping returned an analyzer warning about a potential misuse of Futures.
Dart SDK version: 2.16.2 (stable), reproducible on DartPad as well as Android/JIT (haven't checked other platforms).