The future 4.03 release of OCaml has added a new warning, 57
, to prevent ambiguous guarded pattern. Namely, the issue is that on an or-pattern with a when
clause, if the first part of the or-pat matches, but the when
evaluates to false
, the complete pattern will be discarded, although another variant of the or-pat could have succeed. For instance, on the following code, ko
will be bound to 1
, which can be surprising:
type t = A of string | B of string
let bad x y =
match x,y with
| A s, _ | _, A s when s = "foo" -> 0
| _, _ -> 1
let ok = bad (A "foo") (A "bar")
let ko = bad (A "bar") (A "foo")
In 4.03, OCaml will complain with Warning 57: Ambiguous guarded pattern, variable s may match different or-pattern arguments
, suggesting you to check whether you really intended this behavior or not.
However, the warning is also active on the second line of the pattern matching in the following definition:
let f x y =
match x,y with
| A _, A _ -> 0
| A s, _ | _, A s when s = "foo" -> 1
| _ -> 2
Here, I'd argue that the ambiguity cannot arise, since A _, A _
is matched by the first line, hence at most one of the components of the or-pattern can match if the program gets to this point. Is this reasoning correct?
If the answer is yes, I would like to know in addition whether it is possible to silence this warning on this specific branch. Indeed, I can do match [@warning "-57"] x,y with
, but this will silence the warning if someone introduces another ambiguous pattern there sometime later. I've tried to put the attribute at the pattern level (| A s, _ | _, A s [@warning "-57"] when s = "foo"
), but this has no effect.
NB: I know that in this specific case I could just replace the catch-all with | A s, B _ | B _, A s when s = "foo"
to make the ambiguity disappear, but consider that this is only a reduced example.
The warning is for people unaware that when
guards are not part of the pattern and imagine that A s, _ | _, A s when s = ""
is the same as A s, _ | (_, A s when s = "")
which is syntactically invalid.
It seems like a good idea to keep the warning, although it would be nice if explicit parentheses prevented it, e.g. (A s, _ | _, A s) when s = ""
.
You're suggesting that the compiler should be smarter than the average reader and suppress warnings based on non-obvious rules. In other words your reasoning is correct but it's too much overhead for the programmer who is used to rely on warnings.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With