Files
mercury/compiler/instance_method_clauses.m
Zoltan Somogyi 4f57c70ff7 Tweak and announce the unneeded statevar options.
compiler/pre_typecheck.m:
    Add a heuristic: do NOT generate a warning about unused final statevars
    if all of a predicate's clauses are facts. In such cases, the warnings
    are more noise than helpful.

compiler/add_clause.m:
    Record for each clause whether it is a fact.

compiler/hlds_clauses.m:
    Add a slot for this new fact_or_not flag.

compiler/add_foreign_proc.m:
compiler/add_pragma_type_spec.m:
compiler/add_pred.m:
compiler/hlds_out_pred.m:
compiler/instance_method_clauses.m:
compiler/intermod.m:
compiler/typecheck.m:
compiler/typecheck_clauses.m:
compiler/unify_proc.m:
compiler/var_origins.m:
    Conform to the changes above.

compiler/options.m:
    Turn the options on by default. Their documentation already assumes this.

NEWS.md:
    Announce the new options warning about unneeded state variables.

tests/invalid/Mercury.options:
tests/invalid_purity/Mercury.options:
tests/invalid_nodepend/Mercury.options:
    Turn the new warn options off for test cases that

    - would otherwise get them, but
    - for which this is irrelevant to what they want to test for.

tests/invalid/state_vars_test_5.err_exp:
tests/invalid/try_io_else.err_exp:
tests/warnings/unify_x_f_x.err_exp:
    For these other cases, expect the new warnings.
2025-05-20 03:05:10 +10:00

174 lines
7.4 KiB
Mathematica

%-----------------------------------------------------------------------------%
% vim: ft=mercury ts=4 sw=4 et
%-----------------------------------------------------------------------------%
% Copyright (C) 2022-2023, 2025 The Mercury team.
% This file may only be copied under the terms of the GNU General
% Public License - see the file COPYING in the Mercury distribution.
%-----------------------------------------------------------------------------%
%
% This module produces definitions for the predicates that implement
% instance methods.
%
%-----------------------------------------------------------------------------%
:- module hlds.make_hlds.instance_method_clauses.
:- interface.
:- import_module hlds.hlds_clauses.
:- import_module hlds.hlds_markers.
:- import_module hlds.hlds_module.
:- import_module hlds.make_hlds.qual_info.
:- import_module hlds.status.
:- import_module mdbcomp.
:- import_module mdbcomp.prim_data.
:- import_module parse_tree.
:- import_module parse_tree.error_spec.
:- import_module parse_tree.prog_data.
:- import_module list.
:- import_module term.
% Given the instance_proc_def for a predicate or function from an instance
% declaration, produce the clauses_info for that instance_proc_def.
%
:- pred produce_instance_method_clauses(instance_proc_def::in,
pred_or_func::in, list(mer_type)::in, pred_markers::in, term.context::in,
instance_status::in, clauses_info::out, tvarset::in, tvarset::out,
module_info::in, module_info::out, qual_info::in, qual_info::out,
list(error_spec)::in, list(error_spec)::out) is det.
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
:- implementation.
:- import_module hlds.hlds_args.
:- import_module hlds.hlds_goal.
:- import_module hlds.hlds_pred.
:- import_module hlds.hlds_rtti.
:- import_module hlds.instmap.
:- import_module hlds.make_hlds.add_clause.
:- import_module hlds.make_hlds.state_var.
:- import_module mdbcomp.sym_name.
:- import_module parse_tree.maybe_error.
:- import_module parse_tree.prog_item.
:- import_module parse_tree.prog_util.
:- import_module parse_tree.set_of_var.
:- import_module parse_tree.var_table.
:- import_module parse_tree.vartypes.
:- import_module cord.
:- import_module map.
:- import_module require.
:- import_module set.
:- import_module varset.
%-----------------------------------------------------------------------------%
produce_instance_method_clauses(InstanceProcDefn, PredOrFunc, ArgTypes,
Markers, Context, InstanceStatus, ClausesInfo,
!TVarSet, !ModuleInfo, !QualInfo, !Specs) :-
PredFormArity = arg_list_arity(ArgTypes),
(
% Handle the `pred(<MethodName>/<Arity>) is <ImplName>' syntax.
InstanceProcDefn = instance_proc_def_name(InstancePredName),
% Add the body of the introduced pred.
% First the goal info, ...
PredFormArity = pred_form_arity(PredFormArityInt),
varset.init(VarSet0),
make_n_fresh_vars("HeadVar__", PredFormArityInt, HeadVars,
VarSet0, VarSet),
set_of_var.list_to_set(HeadVars, NonLocals),
( if marker_is_present(Markers, marker_is_impure) then
Purity = purity_impure
else if marker_is_present(Markers, marker_is_semipure) then
Purity = purity_semipure
else
Purity = purity_pure
),
instmap_delta_init_unreachable(DummyInstMapDelta),
DummyDetism = detism_erroneous,
goal_info_init(NonLocals, DummyInstMapDelta, DummyDetism, Purity,
Context, GoalInfo),
% ... and then the goal itself.
construct_and_record_pred_or_func_call(invalid_pred_id, PredOrFunc,
InstancePredName, HeadVars, GoalInfo, IntroducedGoal, !QualInfo),
IntroducedClause = clause(all_modes, IntroducedGoal, impl_lang_mercury,
Context, [], init_unused_statevar_arg_map, clause_is_not_a_fact),
vartypes_from_corresponding_lists(HeadVars, ArgTypes,
ExplicitVarTypes),
init_var_table(VarTable),
rtti_varmaps_init(RttiVarMaps),
map.init(TVarNameMap),
HeadVarVec = proc_arg_vector_init(PredOrFunc, HeadVars),
set_clause_list([IntroducedClause], ClausesRep),
ClausesInfo = clauses_info(VarSet, ExplicitVarTypes,
VarTable, RttiVarMaps, TVarNameMap, HeadVarVec, ClausesRep,
init_clause_item_numbers_comp_gen,
no_foreign_lang_clauses, no_clause_syntax_errors)
;
% Handle the arbitrary clauses syntax.
InstanceProcDefn = instance_proc_def_clauses(InstanceClausesCord),
InstanceClauses = cord.list(InstanceClausesCord),
% XXX CIT_TYPES: should be cit_types(ArgTypes)
clauses_info_init(PredOrFunc, cit_no_types(PredFormArity),
init_clause_item_numbers_comp_gen, ClausesInfo0),
list.foldl5(
produce_instance_method_clause(PredOrFunc, Context,
InstanceStatus),
InstanceClauses, !TVarSet, !ModuleInfo, !QualInfo,
ClausesInfo0, ClausesInfo, !Specs)
).
:- pred produce_instance_method_clause(pred_or_func::in,
prog_context::in, instance_status::in, item_clause_info::in,
tvarset::in, tvarset::out, module_info::in, module_info::out,
qual_info::in, qual_info::out, clauses_info::in, clauses_info::out,
list(error_spec)::in, list(error_spec)::out) is det.
produce_instance_method_clause(PredOrFunc, Context, InstanceStatus,
InstanceClause, TVarSet0, TVarSet, !ModuleInfo, !QualInfo,
!ClausesInfo, !Specs) :-
InstanceClause = item_clause_info(ClausePredOrFunc, PredSymName,
HeadTerms0, ClauseVarSet, MaybeBodyGoal, _ClauseContext, _SeqNum),
% XXX Can this ever fail? If yes, we should generate an error message
% instead of aborting.
expect(unify(PredOrFunc, ClausePredOrFunc), $pred, "PredOrFunc mismatch"),
( if
illegal_state_var_func_result(PredOrFunc, HeadTerms0, StateVar,
StateVarContext)
then
TVarSet = TVarSet0,
ResultSpec = report_illegal_func_svar_result_raw(StateVarContext,
ClauseVarSet, StateVar),
!:Specs = [ResultSpec | get_any_errors_warnings2(MaybeBodyGoal)] ++
!.Specs
else
(
MaybeBodyGoal = error2(BodyGoalSpecs),
TVarSet = TVarSet0,
!:Specs = BodyGoalSpecs ++ !.Specs
;
MaybeBodyGoal = ok2(BodyGoal, BodyGoalWarningSpecs),
!:Specs = BodyGoalWarningSpecs ++ !.Specs,
expand_bang_state_pairs_in_terms(HeadTerms0, HeadTerms),
% AllProcIds is only used when the predicate has foreign procs,
% which the instance method pred should not have, so this
% dummy value should be ok.
AllProcIds = [],
% XXX STATUS
InstanceStatus = instance_status(OldImportStatus),
PredStatus = pred_status(OldImportStatus),
add_clause_to_clauses_info(all_modes, AllProcIds, PredStatus,
clause_not_for_promise, PredOrFunc, PredSymName, HeadTerms,
Context, item_no_seq_num, BodyGoal, ClauseVarSet,
TVarSet0, TVarSet, !ClausesInfo, !ModuleInfo,
!QualInfo, !Specs)
)
).
%-----------------------------------------------------------------------------%
:- end_module hlds.make_hlds.instance_method_clauses.
%-----------------------------------------------------------------------------%