You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The analyzer and front end currently use the following rules to perform type inference for equality expressions (expressions of the form e1 op e2, where op is either == or !=):
First, e1 is type inferred in context _, producing m1 with static type T1.
Let K be static type of the single argument accepted by T1.operator==.
Then, e2 is type inferred in context _, producing m2 with static type T2.
Define m as follows:
If T2 <: K?, let m be m1 op m2.
Otherwise, if a coercion C exists that coerces type T2 to T2', and T2' <: K?, then let m be m1 op C(m2).
Otherwise, it is a compile-time error.
Then, the result of type inferring e1 op e2 is m, with static type bool.
It seems odd to me that the type K? is used for coercions but not to supply a context when type inferring e2. This matters if a user decides to declare an operator== with a covariant argument type. For example:
classComparableList<T> {
finalList<T> _values;
ComparableList(this._values);
booloperator==(covariantComparableList<T> other) {
if (_values.length != other._values.length) returnfalse;
for (var i =0; i < _values.length; i++) {
if (_values[i] != other._values[i]) returnfalse;
}
returntrue;
}
}
f(ComparableList<double> doubles) => doubles ==ComparableList([0]);
main() {}
This code is rejected by both the analyzer and front end, with the error message:
The argument type 'ComparableList<int>' can't be assigned to the parameter type 'ComparableList<double>?'.
However, if C.operator== is replaced with any other user definable operator, then the code is accepted:
classComparableList<T> {
finalList<T> _values;
ComparableList(this._values);
booloperator+(covariantComparableList<T> other) {
if (_values.length != other._values.length) returnfalse;
for (var i =0; i < _values.length; i++) {
if (_values[i] != other._values[i]) returnfalse;
}
returntrue;
}
}
f(ComparableList<double> doubles) => doubles +ComparableList([0]);
main() {}
This seems unnecessarily inconsistent. I think we should change the third bullet in the type inference rules to be:
Then, e2 is type inferred in context K?, producing m2 with static type T2.
This would make type inference for operator == more consistent with other operators.
The text was updated successfully, but these errors were encountered:
Agree.
We do allow overriding operator==, so we should also use the overridden type in the minuscule amount of cases where someone does that. (But… like why? And like don't!)
The other alternative is to remove coercion as well, but this is a statically decided behavior, so it's cost-free in most cases (because K? will be Object? in almost every case), and in the hypothetical case where we know that calling is going to throw if we don't coerce, we might as well do the consistent thing.
(We still can't change the return type to the declared return type, even if we can now have extension types as subtypes of bool. Unless Erik's proposal of allowing extension type return types for fx async functions can be extended to operator==.)
lrhn
added
the
feature
Proposed language feature that solves one or more problems
label
Mar 18, 2024
The analyzer and front end currently use the following rules to perform type inference for equality expressions (expressions of the form
e1 op e2
, whereop
is either==
or!=
):e1
is type inferred in context_
, producingm1
with static typeT1
.K
be static type of the single argument accepted byT1.operator==
.e2
is type inferred in context_
, producingm2
with static typeT2
.m
as follows:T2 <: K?
, letm
bem1 op m2
.C
exists that coerces typeT2
toT2'
, andT2' <: K?
, then letm
bem1 op C(m2)
.e1 op e2
ism
, with static typebool
.It seems odd to me that the type
K?
is used for coercions but not to supply a context when type inferringe2
. This matters if a user decides to declare anoperator==
with a covariant argument type. For example:This code is rejected by both the analyzer and front end, with the error message:
However, if
C.operator==
is replaced with any other user definable operator, then the code is accepted:This seems unnecessarily inconsistent. I think we should change the third bullet in the type inference rules to be:
e2
is type inferred in contextK?
, producingm2
with static typeT2
.This would make type inference for
operator ==
more consistent with other operators.The text was updated successfully, but these errors were encountered: