Description
The current type inference specification for patterns use the same mathed value type for both branches of an and-pattern.
That effectively means that the and-pattern cannot promote the matched value from the first clause to the second, and use the promoted type in the second clause.
Examples where that might be valuable could be:
num? x = ...;
if (x case != null & > 0) ...
// or
if (x case int() & > 0) ...
The former can be written as (>0)?
, because we have an inline null-check, the latter cannot as easily.
Users will likely expect promotion for patterns like this.
Maybe it's as easy as saying:
* **Logical-and**, `e1 & e2`: Type check `e1` using `M` as the matched value type, let `R1` be the required type of `e1`. Then type check `e2` using **GLB**(`M`,`R1`) as the matched value type, and let `R2` be the required type of `e2`. The required type of `e1 & e2` is **GLB**(`M`, `R1`, `R2`).
(Don't know if the or
pattern needs work too, but case == null | <= 0
on an int?
might be useful as well. Can't be expressed as simply as the above, so we might want to use our entire type promotion machinery, and treat the matched value as a variable. Which it is, since we cache the value it's even final
.)
The workaround, which I never want to see happen:
extension Value<T> on T {
T get value => this;
}
...
if (x case int(value: > 0)) ...
Removing any incentive for that workaround is motivation enough to do something!