The thing to recognize here is that the restriction against merging (and
fallthrough) is not about _cases_, but about _bindings_, because a
binding would have an impossible type. Right now, there's no way to
have one without the other, so its easy to conflate them. As you say,
once there's a way to say "there's no binding", it becomes possible to
merge otherwise incompatible patterns.
So yes, I agree once we revisit underscore (or other means of no-binding
patterns), we should refine this.
We use comma in between constants, we should be able to use comma in
between patterns.
This was always the intent. Recall that we discussed cases like:
case IntBox(int x), IntBag(int x):
and backed away not because they were unsound, but because they
presented confusing questions like "where is the declaration of x".
On 8/28/2021 5:42 PM, Remi Forax wrote:
I believe that the rule for merging type pattern is overly restrictive,
here is an example of a method that collects all the declared variables (the
language is a kind of functional JavaScript i'm using for teaching)
private static void visitVariable(Expr expr, JSObject env) {
switch (expr) {
case Block block -> {
for (Expr instr : block.instrs()) {
visitVariable(instr, env);
}
}
case Literal literal -> {
// do nothing
}
case FunCall funCall -> {
// do nothing
}
case LocalVarAssignment localVarAssignment -> {
if (localVarAssignment.declaration()) {
env.register(localVarAssignment.name(), env.length());
}
}
case LocalVarAccess localVarAccess -> {
// do nothing
}
case Fun fun -> {
// do nothing
}
case Return _return -> {
// do nothing
}
case If _if -> {
visitVariable(_if.trueBlock(), env);
visitVariable(_if.falseBlock(), env);
}
case New _new -> {
// do nothing
}
case FieldAccess fieldAccess -> {
// do nothing
}
case FieldAssignment fieldAssignment -> {
// do nothing
}
case MethodCall methodCall -> {
// do nothing
}
default -> throw new AssertionError("unknown case " + expr.getClass());
};
}
Here i can not group the cases that do nothing together because we have
explicitly disallow it,
so the code below does not compile
case Literal literal, FunCall funcall -> {
// do nothing
}
I think we should revisit that discussion and just not introduce the any bindings in that case so
the example above will compile but "literal" or "funcall" are not added as
local variable.
Once we will introduce '_', the "correct" way to write such code will be
case Literal _, FunCall _ -> {
// do nothing
}
regards,
Rémi