This appears to either be a bug or a misunderstood feature of Dart 2.12+. In either case, it might be worth opening an issue on the Dart Github page.
If I run the following code in 2.12.0:
void main() {
final nums = [1, 2.0, 3.5];
final ints = [1, 2, 3];
final doubles = [1.1, 2.2, 3.3];
sums(nums);
sums(ints);
sums(doubles);
}
void sums<T extends num>(List<T> list) {
T res = list[0];
for (var i = 1; i < list.length; i++) {
res = res + list[i];
}
print(res);
}
I get the error you mentioned:
main.dart:14:9: Error: A value of type 'num' can't be assigned to a variable of type 'T'.
res = res + list[i];
^
If, however, I run the same code in Dart 2.10.5, the program compiles and runs without a problem and I get the following printout:
6.5
6
6.6
My best guess is that there is an issue with type inference where the type parameter of the List is concerned. Instead of taking the actual type parameter passed to sums, it seems instead to be taking the type restraint num as its inferred type. As a result, the type system sees that you are adding a num to a T extends num and then assigning it to the latter. (To explain, imagine T is int. A num plus an int would result in a num. Trying to then assign that to an int results in a type error since, for all the type system knows, the num might actually be a double.)
At any rate, the error goes away once you do what the error suggests and cast the elements of list to T:
void sums<T extends num>(List<T> list) {
T res = list[0] as T;
for (var i = 1; i < list.length; i++) {
res = res + list[i] as T;
}
print(res);
}
// Prints:
//
// 6.5
// 6
// 6.6
Interestingly, though, using an addition-assignment instead will cause the same error regardless of the cast:
void sums<T extends num>(List<T> list) {
T res = list[0];
for (var i = 1; i < list.length; i++) {
res += list[i] as T;
}
print(res);
}
// Prints:
//
// main.dart:14:9: Error: A value of type 'num' can't be assigned to a variable of type 'T'.
// res += list[i];
// ^
EDIT: I've filed an issue for this topic on the Dart SDK Github page.
EDIT 2: Turns out this is not a bug but the result of an intended change to Dart as part of 2.12. See Irn's answer for details.