Files
mercury/tests/warnings/gh85.m
Zoltan Somogyi 79e8804db9 Fix "this disjunct can't have solutions" warnings in multimode preds.
This fixes github issue #85.

A complication is that the compiler itself has code, in make.util.m,
in which a disjunct has no solutions in only one mode of a two mode
function, but in this case, the code works (though its programming style
is pretty bad), so to get this change to bootstrap, we also need
a way to disable the "this disjunct can't have solutions" warning
in a scope.

compiler/simplify_goal_disj.m:
    When we generate a "this disjunct can't succeed" warning,
    do not insist on all modes generating that warning.
    We used to insist on that because in a multi-mode predicate,
    such warnings can be inappropriate for other modes.
    Instead, achieve the same objective of minimizing programmer
    confusion by adding a codicil explicitly mentioninging
    this possibility.

    Make the generation of this warning conditional on a simplify task
    that can be disabled by "disable_warnings" scope.

compiler/prog_data.m:
    Add "no_solution_disjunct" as a warning kind that may be disabled.

compiler/parse_goal.m:
    Parse the new kind of warning.

compiler/prog_out.m:
    Output the new kind of warning.

    Improve some adjacent though unrelated code.

compiler/make.util.m:
    Add code disable this warning in the affected predicate.
    Comment out this code until installed compilers know how
    to parse it and understand it.

compiler/Mercury.options:
    Don't turn warnings into errors for make.util.m until then.

compiler/simplify_goal_scope.m:
compiler/simplify_info.m:
compiler/simplify_tasks.m:
    Provide the mechanism needed to make it possible to disable
    warnings about no solution disjuncts.

doc/reference_manual.texi:
    Document the new disable-able warning.

NEWS:
    Document both the changed behavior of the old warning
    and the new way to disable it.

tests/warnings/gh85.{m,exp}:
    A regression test for the bug, based on the code in the
    github issue. It also tests the way to disable the warning.

tests/warnings/Mmakefile:
    Enable the new test case.
2020-03-24 15:20:59 +11:00

80 lines
2.2 KiB
Mathematica

%---------------------------------------------------------------------------%
% vim: ft=mercury ts=4 sw=4 et
%---------------------------------------------------------------------------%
% Any copyright is dedicated to the Public Domain.
% http://creativecommons.org/publicdomain/zero/1.0/
%
% Released by Transnat Games for testing purposes.
%
% This is a regression test for github issue #85.
%
% The bug was that the presence of the second mode on test1 used to silence
% the "disjunct has no solutions" warning for the second disjunct.
:- module gh85.
:- interface.
:- type x
---> a
; b
; c.
:- type y
---> ok
; error(string).
:- pred test1(x, y).
:- mode test1(out, in) is det.
:- mode test1(in, out) is det.
:- pred test2(x, y).
:- mode test2(out, in) is det.
:- mode test2(in, out) is det.
%---------------------------------------------------------------------------%
:- implementation.
:- use_module exception.
% In the first mode, which is the <out,in> mode, the second disjunct here
% is not part of the switch on the second argument; it is just a disjunct
% that can have no solution. Since --warn-simple-code is on by default,
% the compiler should generate a warning about this fact.
%
% The bug was that although the compiler *did* generate this warning,
% the warning was marked report_only_if_in_all_modes. In the second mode,
% which is the <in,out> mode, the second clause turns into a switch arm
% in the switch on the first argument. In this mode, we don't generate
% the same message about a disjunct having no solutions, for two separate
% and distinct reasons: first, it is ok (and common) for a switch arm
% to have no solutions, and second, there is no disjunct left to complain
% about anyway (switch arms are *made* from disjuncts, but *are not*
% disjuncts anymore).
test1(X, Y) :-
(
X = a,
Y = ok
;
X = b,
exception.throw(exception.software_error("ERROR"))
;
X = c,
Y = error("c")
).
test2(X, Y) :-
disable_warning [no_solution_disjunct]
(
X = a,
Y = ok
;
X = b,
exception.throw(exception.software_error("ERROR"))
;
X = c,
Y = error("c")
).