Closed
Description
For this code:
void main() {
int Function(int) f;
List<num> l;
var a = l.map(f);
int x = a;
}
the analyzer infers int
as the type argument to map
, and with an implicit downcast on the argument to map
(from int -> int
to num -> int
), as witnessed by this error message:
[error] A value of type 'Iterable<int>' can't be assigned to a variable of type 'int'. (../../../tmp/ddctest.dart, line 11, col 11)
The CFE infers dynamic
as the type argument to map
, with the result that the argument to map
is invalid (a cross cast from int -> int
to num -> dynamic
):
file:///Users/leafp/tmp/ddctest.dart:10:17: Error: A value of type '(dart.core::int) → dart.core::int' can't be assigned to a variable of type '(dart.core::num) → dynamic'.
Try changing the type of the left hand side, or casting the right hand side to '(dart.core::num) → dynamic'.
var a = l.map(f);
^
file:///Users/leafp/tmp/ddctest.dart:11:11: Error: A value of type 'dart.core::Iterable<dynamic>' can't be assigned to a variable of type 'dart.core::int'.
Try changing the type of the left hand side, or casting the right hand side to 'dart.core::int'.
int x = a;
^
I believe that the CFE behavior is correct for Dart 2. We intentionally push the context type down into sub-terms and insert casts to the context type (or to the greatest closure thereof), in order to avoid relying on least upper bound with the pathologies that result (e.g. giving no error message for String x = (b) ? 3 : []
).
cc @jmesserly @stereotype441 @vsmenon to check my thinking on this.