Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Manual: add extended description of warning 57 #468

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
47 changes: 47 additions & 0 deletions manual/manual/cmds/comp.etex
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,7 @@ that are currently defined are ignored. The warnings are as follows.
\begin{options}
\input{warnings-help.tex}
\end{options}
Some warnings are described in more detail in section~\ref{s:comp-warnings}.

The default setting is "-w +a-4-6-7-9-27-29-32..39-41..42-44-45".
It is displayed by "ocamlc -help".
Expand Down Expand Up @@ -733,3 +734,49 @@ command line, and possibly the "-custom" option.

\end{options}

\section{Warning reference} \label{s:comp-warnings}

This section describes and explains in detail some warnings:

\begin{options}
\item[Warning 57: ambiguous variables in or-patterns]
The semantics of or-patterns in OCaml is specified with
a left-to-right bias: a value \var{v} matches the pattern \var{p} "|" \var{q}
if it matches \var{p} or \var{q}, but if it matches both,
the environment captured by the match is the environment captured by
\var{p}, never the one captured by \var{q}.

While this property is generally intuitive, there is at least one specific
case where a different semantics might be expected.
Consider a pattern followed by a when-guard:
"|"~\var{p}~"when"~\var{g}~"->"~\var{e}, for example:
\begin{verbatim}
| ((Const x, _) | (_, Const x)) when is_neutral x -> branch
\end{verbatim}
The semantics is clear:
match the scrutinee against the pattern, if it matches, test the guard,
and if the guard passes, take the branch.
In particular, consider the input "(Const"~\var{a}", Const"~\var{b}")", where
\var{a} fails the test "is_neutral"~\var{a}, while \var{b} passes the test
"is_neutral"~\var{b}. With the left-to-right semantics, the clause above is
{\em not} taken by its input: matching "(Const"~\var{a}", Const"~\var{b}")"
against the or-pattern succeeds in the left branch, it returns the
environment \var{x}~"->"~\var{a}, and then the guard
"is_neutral"~\var{a} is tested and fails, the branch is not taken.

However, another semantics may be considered more natural here:
any pair that has one side passing the test will take the branch. With this
semantics the previous code fragment would be equivalent to
\begin{verbatim}
| (Const x, _) when is_neutral x -> branch
| (_, Const x) when is_neutral x -> branch
\end{verbatim}
This is {\em not} the semantics adopted by OCaml.

The warning 57 is dedicated to warning about these confusing cases where the
specified left-to-right semantics is not equivalent to a non-deterministic
semantics (any branch can be taken) relatively to a specific guard.
More precisely, it warns when guard uses ``ambiguous'' variables, that are bound
to different parts of the scrutinees by different sides of a or-pattern.

\end{options}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ then just above there should be *no* warning text.
# Characters 46-71:
| ((Val x, _) | (_, Val x)) when x < 0 -> ()
^^^^^^^^^^^^^^^^^^^^^^^^^
Warning 57: Ambiguous guarded pattern, variable x may match different or-pattern arguments
Warning 57: Ambiguous guarded pattern, variable x may match different or-pattern arguments (see manual section 8.5)
val ambiguous_typical_example : expr * expr -> unit = <fun>
# Note that an Assert_failure is expected just below.
# Exception: Assert_failure ("//toplevel//", 23, 6).
Expand All @@ -33,19 +33,19 @@ val ambiguous_typical_example : expr * expr -> unit = <fun>
# Characters 33-72:
| (`B (x, _, Some y) | `B (x, Some y, _)) when y -> ignore x
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Warning 57: Ambiguous guarded pattern, variable y may match different or-pattern arguments
Warning 57: Ambiguous guarded pattern, variable y may match different or-pattern arguments (see manual section 8.5)
val ambiguous__y : [> `B of 'a * bool option * bool option ] -> unit = <fun>
# * * * * * * * * val not_ambiguous__rhs_not_protected :
[> `B of 'a * bool option * bool option ] -> unit = <fun>
# Characters 35-74:
| (`B (x, _, Some y) | `B (x, Some y, _)) when x < y -> ()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Warning 57: Ambiguous guarded pattern, variable y may match different or-pattern arguments
Warning 57: Ambiguous guarded pattern, variable y may match different or-pattern arguments (see manual section 8.5)
val ambiguous__x_y : [> `B of 'a * 'a option * 'a option ] -> unit = <fun>
# Characters 37-76:
| (`B (x, z, Some y) | `B (x, Some y, z)) when x < y || Some x = z -> ()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Warning 57: Ambiguous guarded pattern, variables y,z may match different or-pattern arguments
Warning 57: Ambiguous guarded pattern, variables y,z may match different or-pattern arguments (see manual section 8.5)
val ambiguous__x_y_z : [> `B of 'a * 'a option * 'a option ] -> unit = <fun>
# val not_ambiguous__disjoint_in_depth :
[> `A of [> `B of bool | `C of bool ] ] -> unit = <fun>
Expand All @@ -54,7 +54,7 @@ val ambiguous__x_y_z : [> `B of 'a * 'a option * 'a option ] -> unit = <fun>
# Characters 40-76:
| `A (`B (Some x, _) | `B (_, Some x)) when x -> ()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Warning 57: Ambiguous guarded pattern, variable x may match different or-pattern arguments
Warning 57: Ambiguous guarded pattern, variable x may match different or-pattern arguments (see manual section 8.5)
val ambiguous__in_depth :
[> `A of [> `B of bool option * bool option ] ] -> unit = <fun>
# val not_ambiguous__several_orpats :
Expand All @@ -66,7 +66,7 @@ val ambiguous__in_depth :
# Characters 43-140:
....`A ((`B (Some x, _) | `B (_, Some x)),
(`C (Some y, Some _, _) | `C (Some y, _, Some _))).................
Warning 57: Ambiguous guarded pattern, variable x may match different or-pattern arguments
Warning 57: Ambiguous guarded pattern, variable x may match different or-pattern arguments (see manual section 8.5)
val ambiguous__first_orpat :
[> `A of
[> `B of 'a option * 'a option ] *
Expand All @@ -75,7 +75,7 @@ val ambiguous__first_orpat :
# Characters 44-141:
....`A ((`B (Some x, Some _, _) | `B (Some x, _, Some _)),
(`C (Some y, _) | `C (_, Some y))).................
Warning 57: Ambiguous guarded pattern, variable y may match different or-pattern arguments
Warning 57: Ambiguous guarded pattern, variable y may match different or-pattern arguments (see manual section 8.5)
val ambiguous__second_orpat :
[> `A of
[> `B of 'a option * 'b option * 'c option ] *
Expand All @@ -97,13 +97,13 @@ val ambiguous__second_orpat :
# Characters 40-73:
..X (Z x,Y (y,0))
| X (Z y,Y (x,_))
Warning 57: Ambiguous guarded pattern, variables x,y may match different or-pattern arguments
Warning 57: Ambiguous guarded pattern, variables x,y may match different or-pattern arguments (see manual section 8.5)
val ambiguous__amoi : amoi -> int = <fun>
# module type S = sig val b : bool end
# Characters 56-101:
....(module M:S),_,(1,_)
| _,(module M:S),(_,1)...................
Warning 57: Ambiguous guarded pattern, variable M may match different or-pattern arguments
Warning 57: Ambiguous guarded pattern, variable M may match different or-pattern arguments (see manual section 8.5)
val ambiguous__module_variable :
(module S) * (module S) * (int * int) -> bool -> int = <fun>
# val not_ambiguous__module_variable :
Expand All @@ -123,7 +123,7 @@ It will remain exhaustive when constructors are added to type t.
Characters 55-107:
| A (x as z,(0 as y))|A (0 as y as z,x)|B (x,(y as z)) when g x (y+z) -> 1
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Warning 57: Ambiguous guarded pattern, variables x,y may match different or-pattern arguments
Warning 57: Ambiguous guarded pattern, variables x,y may match different or-pattern arguments (see manual section 8.5)
val ambiguous_xy_but_not_ambiguous_z : (int -> int -> bool) -> t -> int =
<fun>
#
2 changes: 1 addition & 1 deletion utils/warnings.ml
Original file line number Diff line number Diff line change
Expand Up @@ -453,7 +453,7 @@ let message = function
"variables " ^ String.concat "," vars in
Printf.sprintf
"Ambiguous guarded pattern, %s may match different or-pattern \
arguments"
arguments (see manual section 8.5)"
msg
| No_cmx_file name ->
Printf.sprintf
Expand Down