Open jclark opened 3 years ago
In this case we know that if a value belongs to type Employee|Marks
, then it either belongs to Employee
or it belongs to Marks
.
This is not something that we know in general. In terms of sets if R is the union of E and M, and S is a subset of R, then it possible for S to be a subset of neither E nor M.
In this case we know it, because we know that
oneof
in gRPC)Our normal type narrowing algorithm works by creating an "immutable partition" of a type into uniform types. It's an immutable partition in that if a current shape of a value v is in one subset of the partition, v cannot be mutated so that it's shape is in another subset of the partition.
So the question then is whether we can in a general away perform a similar "immutable partition" of a subtype of a mutable uniform basic type. If we can, then this is applicable to if/else, as well as match
.
For this to be really useful, this should handle the case where we have a readonly field that is being used like a nominal type tag.
// Note that records are now open.
type Employee record {
readonly "Employee" tag = "Employee";
string name;
int id;
};
type Marks record {
readonly "Marks" tag = "Marks";
int math;
int physics;
int chemistry;
};
function func(Employee|Marks rec) {
match rec {
{ tag: "Marks" } => { }
_ => {
Employee e = rec; // should be OK
}
}
}
For the applicable type, I think there are also some cases where we can use a narrowed type, even in non-readonly cases.
For example, can't the applicable type at the start of the second clause of the following match statement be
Marks
?Originally posted by @MaryamZi in https://github.com/ballerina-platform/ballerina-spec/issues/827#issuecomment-828204811