Files
mercury/compiler/check_field_access_functions.m
Zoltan Somogyi c5b0481b97 Simplify the construction of cons_infos.
typecheck_unify_var_functor.m used to have separate code paths
- to handle the functors of builtin types, and
- to handle the functors of all other types.

However, the second path invoked code in typecheck_cons_infos.m that
*also* handled builtin types.

compiler/typecheck_unify_var_functor.m:
    Simplify this arrangement by deleting the code that chose between
    the two paths, and handling functors of builtin types together with
    all the other functors in (what used to be) the second path.

compiler/typecheck_cons_infos.m:
    Return a distinct result for cons_ids of all builtin types
    (including some that typecheck_unify_var_functor.m did not handle
    via the first code path.)

    Document the meanings of the possible results.

compiler/hlds_cons.m:
    Change the ctor_field_table type to encode the invariant
    that we don't map sym_names to the empty list of field definitions.

compiler/hlds_pred.m:
    The predicates that test whether a sym_name/arity pair or pred_info
    refer to a field access function must search the ctor_field_table
    to answer the question. Make them return the info they get from that
    search, to save their callers from having to do it again.

    Give a predicate a more meaningful name.

compiler/typecheck_info.m:
    Record extra info if we are typechecking in a field access function,
    since it may be needed, and storing it costs next to nothing.

compiler/add_clause.m:
compiler/add_type.m:
compiler/check_field_access_functions.m:
compiler/field_access.m:
compiler/intermod_decide.m:
compiler/pre_typecheck.m:
compiler/recompilation.check.m:
compiler/recompilation.usage.m:
compiler/resolve_unify_functor.m:
compiler/typecheck_error_undef.m:
    Conform to the changes above.
2025-10-23 23:18:11 +11:00

146 lines
6.0 KiB
Mathematica

%---------------------------------------------------------------------------%
% vim: ft=mercury ts=4 sw=4 et
%---------------------------------------------------------------------------%
% Copyright (C) 1993-2012 The University of Melbourne.
% Copyright (C) 2014-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.
%---------------------------------------------------------------------------%
%
% File: check_field_access_functions.m.
%
% Check that the declarations for field extraction and update functions
% are sensible, and generate error messages for the ones that aren't.
% We can do this only after we have processed every predicate declaration,
% as well as everything that affects either the type table or the
% constructor table.
%
%---------------------------------------------------------------------------%
:- module hlds.make_hlds.check_field_access_functions.
:- interface.
:- import_module hlds.hlds_module.
:- import_module hlds.make_hlds.make_hlds_types.
:- import_module hlds.status.
:- import_module mdbcomp.
:- import_module mdbcomp.sym_name.
:- import_module parse_tree.
:- import_module parse_tree.error_spec.
:- import_module parse_tree.prog_data.
:- import_module parse_tree.prog_item.
:- import_module list.
:- pred check_preds_if_field_access_function(module_info::in,
sec_list(item_pred_decl_info)::in,
list(error_spec)::in, list(error_spec)::out) is det.
:- pred maybe_check_field_access_function(module_info::in,
sym_name::in, user_arity::in, pred_status::in, prog_context::in,
list(error_spec)::in, list(error_spec)::out) is det.
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
:- implementation.
:- import_module hlds.hlds_cons.
:- import_module hlds.hlds_pred.
:- import_module mdbcomp.prim_data.
:- import_module parse_tree.prog_util.
:- import_module maybe.
:- import_module one_or_more.
:- import_module term_context.
:- import_module varset.
%---------------------------------------------------------------------------%
check_preds_if_field_access_function(_ModuleInfo, [], !Specs).
check_preds_if_field_access_function(ModuleInfo, [SecList | SecLists],
!Specs) :-
SecList = sec_sub_list(SectionInfo, ItemPredSecls),
SectionInfo = sec_info(ItemMercuryStatus, _NeedQual),
item_mercury_status_to_pred_status(ItemMercuryStatus, PredStatus),
list.foldl(check_pred_if_field_access_function(ModuleInfo, PredStatus),
ItemPredSecls, !Specs),
check_preds_if_field_access_function(ModuleInfo, SecLists, !Specs).
:- pred check_pred_if_field_access_function(module_info::in, pred_status::in,
item_pred_decl_info::in,
list(error_spec)::in, list(error_spec)::out) is det.
check_pred_if_field_access_function(ModuleInfo, PredStatus, ItemPredDecl,
!Specs) :-
ItemPredDecl = item_pred_decl_info(SymName, PredOrFunc, TypesAndMaybeModes,
_, _, _, _, _, _, _, _, _, Context, _SeqNum),
(
PredOrFunc = pf_predicate
;
PredOrFunc = pf_function,
PredFormArity = types_and_maybe_modes_arity(TypesAndMaybeModes),
user_arity_pred_form_arity(pf_function, UserArity, PredFormArity),
maybe_check_field_access_function(ModuleInfo, SymName, UserArity,
PredStatus, Context, !Specs)
).
maybe_check_field_access_function(ModuleInfo, FuncSymName, UserArity,
FuncStatus, Context, !Specs) :-
UserArity = user_arity(UserArityInt),
( if
% XXX ARITY Make this take UserArity, not UserArityInt.
is_field_access_function_name(ModuleInfo, FuncSymName, UserArityInt,
AccessType, FieldName, OoMFieldDefns)
then
check_field_access_function(Context, FuncSymName, UserArity,
FuncStatus, AccessType, FieldName, OoMFieldDefns, !Specs)
else
true
).
:- pred check_field_access_function(prog_context::in,
sym_name::in, user_arity::in, pred_status::in,
field_access_type::in, sym_name::in, one_or_more(hlds_ctor_field_defn)::in,
list(error_spec)::in, list(error_spec)::out) is det.
check_field_access_function(Context, FuncSymName, UserArity,
FuncStatus, _AccessType, _FieldName, OoMFieldDefns, !Specs) :-
% Check that a function applied to an exported type is also exported.
( if
% Abstract types have status `abstract_exported', so errors won't be
% reported for local field access functions for them.
% XXX This check is effectively disabled if the module contains
% two or more definitions of the field name that this access function
% is for.
OoMFieldDefns = one_or_more(FieldDefn, []),
FieldDefn = hlds_ctor_field_defn(_, DefnStatus, _, _, _),
DefnStatus = type_status(status_exported),
FuncStatus \= pred_status(status_exported)
then
user_arity_pred_form_arity(pf_function, UserArity, PredFormArity),
PFSymNameArity =
pf_sym_name_arity(pf_function, FuncSymName, PredFormArity),
report_field_status_mismatch(Context, PFSymNameArity, !Specs)
else
true
).
:- pred report_field_status_mismatch(prog_context::in, pf_sym_name_arity::in,
list(error_spec)::in, list(error_spec)::out) is det.
report_field_status_mismatch(Context, PFSymNameArity, !Specs) :-
Pieces = [words("In declaration of"),
unqual_pf_sym_name_pred_form_arity(PFSymNameArity), suffix(":"), nl,
words("error:")] ++
color_as_subject(
[words("a field access function for an exported field")]) ++
color_as_incorrect([words("must also be exported.")]) ++ [nl],
% XXX Should we add "to ensure consistency"?
Spec = spec($pred, severity_error, phase_pt2h, Context, Pieces),
!:Specs = [Spec | !.Specs].
%---------------------------------------------------------------------------%
:- end_module hlds.make_hlds.check_field_access_functions.
%---------------------------------------------------------------------------%