Mercury-Language/mercury

'unification cannot succeed' warning is very easily dropped

jrfondren opened this issue · 1 comments

This properly warns:

:- module recur.
:- interface.
:- import_module io.
:- pred main(io::di, io::uo) is det.
:- implementation.
:- import_module list.

main(!IO) :-
    io.command_line_arguments(Args, !IO),
    ( if Args = [_ | Args] then
        io.set_exit_status(1, !IO)
    else
        true
    ).

With output:

Making Mercury/int3s/recur.int3
Making Mercury/ints/recur.int
Making Mercury/cs/recur.c
recur.m:010: In clause for `main(di, uo)':
recur.m:010:   warning: unification of `Args' and list.'[|]' cannot succeed,
recur.m:010:   because `Args' cannot be equal to a term containing itself.
recur.m:010: Warning: the condition of this if-then-else cannot succeed.
Making Mercury/os/recur.o
Making recur

This (the same code with a second pre-| binding) does not:

:- module recur.
:- interface.
:- import_module io.
:- pred main(io::di, io::uo) is det.
:- implementation.
:- import_module list.

main(!IO) :-
    io.command_line_arguments(Args, !IO),
    ( if Args = [_, _ | Args] then
        io.set_exit_status(1, !IO)
    else
        true
    ).

This came up in troubleshooting some unusual command line handling (for an app that can't just use getopt):

    else if Args = [NStr, Command | Args] then
        ( if to_int(NStr, N) then
            Res = ok(options(!.Opt^p_input, !.Opt^p_brief, N, Command, Args))
        else
            Res = error(count(NStr))
        )

The compiler can now generate warnings for code like this in many more situations.
The change that does this is in the latest ROTD.