Files
mercury/tests/hard_coded/sv_nested_closures.m
Zoltan Somogyi f70b5d6de7 Implement options to warn about unused state vars.
The new --warn-unneeded-initial-statevar option asks the compiler
to warn about code such as

    pred_a(!.X, ...) :-
        ... code that uses !.X, but does not update it ...

In this case, the preferred fix is to just replace all occurrences
of !.X with X.

The new --warn-unneeded-final-statevar option asks the compiler
to warn about code such as

    pred_a(!X, ...) :-
        ... code that maybe uses !.X, but does not update it ...

In this case, the preferred fix also involves replacing all occurrences
of !.X with X, but it also involves either deleting the argument
containing !:X (the best option), or, if there is some reason why
the predicate's signature must stay unchanged, to replace !:X with X as well.
And if the clause body does not actually refer to either !.X or !:X, then
*both* arguments represented by !X should be deleted.

The first option is a style warning; the second option, due to the
signature change it may call for, is a non-style warning.

Both options have a version whose name adds a "-lambda" suffix, and which
does the same warnings for the heads of lambda expressions, not clauses.

Note that several of the modules below, including some that help to implement
the warnings, also contain code changes that result from *acting* on
the new warnings, e.g. by deleting unneeded statevar arguments.
Other, similar changes will also come after this diff is committed.

compiler/options.m:
doc/user_guide.texi:
    Document the new options.

compiler/state_var.m:
    Gather the information needed to decide what code merits the new warnings.
    Do so in three stages:

    - when processing the head of a clause or of a lambda expression,
    - when processing the body goal of that clause or lambda expression,
    - when finishing up the processing of the clause or lambda expression.

    Add a predicate to generate the warnings for lambda expressions.

    Do not generate the warnings for clauses. This is because whether or not
    we want to warn about state vars in some clauses depends on the properties
    of *other* clauses of the same predicate, and state_var.m has access
    to only one clause at a time. Instead,

    - return the info needed by the warning-generating code in pre_typecheck.m
      (one of the first passes we execute after adding all clauses
      to the HLDS), and

    - we export some functionality for use by that code.

    Switch to a convention for naming the program variables corresponding
    to the middle (non-initial, non-final) versions of state variables
    whose output is affected by changes in the code of the clause body goal
    only if they involve that specific state variable.

    Give some predicates more descriptive names.

compiler/make_hlds.m:
    Make state_var.m and its new functionality visible from outside
    the make_hlds package.

compiler/add_clause.m:
    Record the information gathered by state_var.m in each clause.

compiler/hlds_clauses.m:
    Add a slot to each clause for this information.

    Give some predicates more descriptive names.

compiler/headvar_names.m:
    Use the contents of the new slots to detect whether any clauses
    have unused state vars, and if so, return the chosen consensus names
    of the head vars to the code of pre_typecheck.m, which uses this info
    as part of the implementation of the new warnings.

compiler/pre_typecheck.m:
    Implement the new warnings.

compiler/mercury_compile_front_end.m:
    Record the warnings that pre_typecheck.m can now return.

compiler/error_spec.m:
compiler/write_error_spec.m:
    Add unsigned versions of the format pieces involving ints, for use
    by the new code in pre_typecheck.m, and implement them.

compiler/hlds_out_util.m:
compiler/maybe_util.m:
    Move two related types from hlds_out_util.m to maybe_util.m,
    in order to allow pre_typecheck.m to use one of them.

compiler/hlds_args.m:
    Add a new utility function for use by the new code above.

compiler/foreign.m:
    Act on the new warnings by deleting the long-unused predicates
    being warned about.

compiler/post_typecheck.m:
    Speed up this traversal. (I originally thought to implement
    the new warnings in this pass.)

compiler/add_foreign_proc.m:
compiler/add_pragma.m:
compiler/add_pragma_tabling.m:
compiler/add_pragma_type_spec.m:
compiler/add_pred.m:
compiler/add_type.m:
compiler/build_mode_constraints.m:
compiler/call_gen.m:
compiler/check_typeclass.m:
compiler/clause_to_proc.m:
compiler/code_loc_dep.m:
compiler/delay_info.m:
compiler/delay_partial_inst.m:
compiler/dense_switch.m:
compiler/det_check_goal.m:
compiler/det_infer_goal.m:
compiler/disj_gen.m:
compiler/du_type_layout.m:
compiler/format_call.m:
compiler/goal_expr_to_goal.m:
compiler/hlds_dependency_graph.m:
compiler/hlds_out_pred.m:
compiler/hlds_pred.m:
compiler/hlds_rtti.m:
compiler/inst_merge.m:
compiler/instance_method_clauses.m:
compiler/intermod.m:
compiler/interval.m:
compiler/ite_gen.m:
compiler/lookup_switch.m:
compiler/make_hlds_passes.m:
compiler/mark_tail_calls.m:
compiler/mercury_compile_llds_back_end.m:
compiler/mode_errors.m:
compiler/parse_string_format.m:
compiler/passes_aux.m:
compiler/polymorphism.m:
compiler/polymorphism_info.m:
compiler/polymorphism_type_info.m:
compiler/pragma_c_gen.m:
compiler/prop_mode_constraints.m:
compiler/purity.m:
compiler/quantification.m:
compiler/simplify_goal_call.m:
compiler/simplify_goal_conj.m:
compiler/string_switch.m:
compiler/superhomogeneous.m:
compiler/switch_gen.m:
compiler/tag_switch.m:
compiler/type_constraints.m:
compiler/typecheck.m:
compiler/typecheck_clauses.m:
compiler/typecheck_coerce.m:
compiler/typecheck_error_unify.m:
compiler/unify_gen_deconstruct.m:
compiler/unify_proc.m:
compiler/var_origins.m:
    Conform to the changes above, and/or act on the new warnings.

browser/diff.m:
library/bit_buffer.m:
library/getopt.m:
library/getopt_io.m:
library/io.error_util.m:
library/io.file.m:
library/mercury_term_lexer.m:
library/parsing_utils.m:
library/pretty_printer.m:
library/robdd.m:
library/rtti_implementation.m:
library/string.builder.m:
library/string.parse_runtime.m:
mdbcomp/feedback.m:
    Act on the new warnings.

tests/hard_coded/sv_nested_closures.m:
    Change this test's code to avoid the new warnings, since
    (if --halt-at-warn is ever enabled) the warnings would interfere
    with its job .

tests/invalid/bug197.err_exp:
tests/invalid/bug487.err_exp:
tests/invalid/nullary_ho_func_error.err_exp:
tests/invalid/try_detism.err_exp:
tests/warnings/singleton_test_state_var.err_exp:
    Expect variable names for the middle versions of state vars
    using the new naming scheme.
2025-05-18 06:43:24 +10:00

53 lines
1.5 KiB
Mathematica

%---------------------------------------------------------------------------%
% vim: ts=4 sw=4 et ft=mercury
%---------------------------------------------------------------------------%
:- module sv_nested_closures.
:- interface.
:- import_module io.
:- pred main(io::di, io::uo) is det.
:- implementation.
:- import_module int.
:- import_module list.
:- import_module string.
main(!IO) :-
some [!X] (
!:X = 10,
Foo =
( pred(I::in, !.IO::di, !:IO::uo) is det :-
Bar =
( pred(J::in, !.IO::di, !:IO::uo) is det :-
Result = J + I + !.X,
io.write_int(Result, !IO),
io.nl(!IO)
),
Bar(4, !IO)
),
Foo(3, !IO)
),
baz(-200, X, !IO),
io.write_int(X, !IO),
io.nl(!IO).
:- pred baz(int::in, int::out, io::di, io::uo) is det.
baz(!Y, !IO) :-
% The occurrences of " + 0" prevent warnings about !Y and !Z being unused.
io.format("(baz) !.Y = %d\n", [i(!.Y)], !IO),
BazFoo =
( pred(!.Y::in, !:Y::out, !.IO::di, !:IO::uo) is det :-
!:Y = !.Y + 0,
io.format("(BazFoo) !.Y = %d\n", [i(!.Y)], !IO),
BazBar =
( pred(!.Z::in, !:Z::out, !.IO::di, !:IO::uo) is det :-
!:Z = !.Z + 0,
io.format("(BazBar) !.Y = %d\n", [i(!.Y)], !IO)
),
BazBar(400, _, !IO)
),
BazFoo(700, _, !IO).