Files
mercury/compiler/make_hlds_error.m
Zoltan Somogyi 3a1ed2efcb Replace simple_call_id with pf_sym_name_arity.
compiler/prog_data.m:
    Delete the simple_call_id data type, since it is isomorphic
    to the pf_sym_name_arity type, which more clearly specifies
    what is stored inside it.

compiler/prog_out.m:
    Rename (all three versions of) simple_call_id_to_string to
    pf_sym_name_orig_arity_to_string, both to conform to the change
    in the input data type, and to emphasize that the resulting string
    will contain the *original* arity of functions (which does not include
    the return value), which is one less than the arity in the
    pf_sym_name_arity structure (which, in accordance with the
    convention inside the compiler that the arity is the length
    of the argument list, *does* include the return value).

    Delete the provision inside simple_call_id_to_string, now
    pf_sym_name_orig_arity_to_string, for special handling of the names
    of the predicates we use to implement promises, because it seems that
    *none* of the call sites to any of the three versions of this function
    can actually pass to it the identity of such a predicate. These calls
    refer to a predicate or mode declaration item (which promise predicates
    do not have), to clause or foreign_proc items (which again, promise
    predicates cannot have) or calls to the predicate (promise predicates
    cannot be called).

    Delete the exported predicate simple_call_id_to_sym_name_arity.
    It was called from exactly one place, inside prog_out.m itself,
    and this diff inlines that call.

    Avoid unnecessary forwarding of work from prog_out.m to error_util.m.

    Delete (all three versions of) write_simple_call_id. The changes
    below replace all their (few) uses with calls to
    pf_sym_name_orig_arity_to_string.

compiler/error_util.m:
    Replace the simple_call() error piece with qual_pf_sym_name_orig_arity,
    and add a new version unqual_pf_sym_name_orig_arity. Their names
    explicitly say that they print the original arities of functions,
    also say whether they strip away any module qualification on the
    sym_name inside the pf_sym_name_arity. We prefer the unqual version
    in situations where the module qualifier is implicit, which usually means
    that it must be the same as the name of the module being compiled, because
    it reduces visual clutter for readers of error messages.

    Put {qual,unqual}_pf_sym_name_orig_arity next to their most closely
    related function symbols, {qual,unqual}_sym_name_arity, in the
    format_component type. (This yields a few inconsequential changes
    in the order of error_specs when sorted.)

compiler/add_class.m:
compiler/add_clause.m:
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/check_libgrades.m:
compiler/check_parse_tree_type_defns.m:
compiler/check_promise.m:
compiler/check_typeclass.m:
compiler/convert_parse_tree.m:
compiler/equiv_type.m:
compiler/goal_expr_to_goal.m:
compiler/hlds_data.m:
compiler/hlds_desc.m:
compiler/hlds_goal.m:
compiler/hlds_out_pred.m:
compiler/hlds_out_util.m:
compiler/hlds_pred.m:
compiler/inst_util.m:
compiler/llds_out_instr.m:
compiler/make.module_target.m:
compiler/make.program_target.m:
compiler/make_hlds_error.m:
compiler/make_hlds_warn.m:
compiler/mark_tail_calls.m:
compiler/ml_unify_gen_construct.m:
compiler/mlds_to_c_stmt.m:
compiler/mode_errors.m:
compiler/mode_info.m:
compiler/modecheck_util.m:
compiler/module_qual.collect_mq_info.m:
compiler/module_qual.qualify_items.m:
compiler/parse_item.m:
compiler/parse_module.m:
compiler/parse_type_repn.m:
compiler/polymorphism.m:
compiler/post_typecheck.m:
compiler/pre_quantification.m:
compiler/pred_table.m:
compiler/prog_item.m:
compiler/recompilation.version.m:
compiler/term_constr_build.m:
compiler/termination.m:
compiler/type_ctor_info.m:
compiler/typecheck.m:
compiler/typecheck_errors.m:
compiler/typecheck_info.m:
compiler/unify_gen_construct.m:
compiler/unused_imports.m:
    Conform to the changes above. Where I am pretty sure that in an error
    message, the module qualifier of a name must be the current module,
    use unqual_pf_sym_name_orig_arity instead of qual_pf_sym_name_orig_arity.

    Add some sanity checks where they seem appropriate.

    Replace sequences of io.write_strings with uses of io.format where this
    yields clearer code. (This is why there were no remaining calls to
    write_simple_call_id.)

    Shorten some too-long lines.

    In add_pred.m, make the order of some predicate definitions match
    the order of the calls to them.

tests/invalid/ambiguous_method.err_exp:
tests/invalid/ambiguous_method_2.err_exp:
tests/invalid/bad_pred_arity.err_exp:
tests/invalid/bad_sv_unify_msg.err_exp:
tests/invalid/bigtest.err_exp:
tests/invalid/bug113.err_exp:
tests/invalid/bug197.err_exp:
tests/invalid/bug278.err_exp:
tests/invalid/bug410.err_exp:
tests/invalid/bug476.err_exp:
tests/invalid/bug487.err_exp:
tests/invalid/complex_constraint_err.err_exp:
tests/invalid/constrained_poly_insts.err_exp:
tests/invalid/errors.err_exp:
tests/invalid/errors1.err_exp:
tests/invalid/errors2.err_exp:
tests/invalid/exported_mode.err_exp:
tests/invalid/field_syntax_error.err_exp:
tests/invalid/foreign_singleton.err_exp:
tests/invalid/funcs_as_preds.err_exp:
tests/invalid/imported_mode.err_exp:
tests/invalid/invalid_binary_literal.err_exp:
tests/invalid/invalid_float_literal.err_exp:
tests/invalid/invalid_hex_literal.err_exp:
tests/invalid/invalid_octal_literal.err_exp:
tests/invalid/make_opt_error.err_exp:
tests/invalid/missing_det_decls.err_exp:
tests/invalid/multimode_syntax.err_exp:
tests/invalid/null_char.err_exp:
tests/invalid/occurs.err_exp:
tests/invalid/record_syntax_errors.err_exp:
tests/invalid/ref_to_implicit_pred.err_exp:
tests/invalid/require_tailrec_1.err_exp:
tests/invalid/require_tailrec_1.err_exp2:
tests/invalid/require_tailrec_2.err_exp:
tests/invalid/require_tailrec_2.err_exp2:
tests/invalid/require_tailrec_3.err_exp:
tests/invalid/require_tailrec_3.err_exp2:
tests/invalid/state_vars_test2.err_exp:
tests/invalid/state_vars_test3.err_exp:
tests/invalid/state_vars_test5.err_exp:
tests/invalid/type_inf_loop.err_exp:
tests/invalid/typeclass_constraint_extra_var.err_exp:
tests/invalid/typeclass_mode_2.err_exp:
tests/invalid/typeclass_test_12.err_exp:
tests/invalid/typeclass_test_2.err_exp:
tests/invalid/typeclass_test_9.err_exp:
tests/invalid/types.err_exp:
tests/invalid/types2.err_exp:
tests/invalid/unbound_type_vars.err_exp:
tests/invalid/with_type.err_exp:
tests/invalid_purity/purity_nonsense.err_exp:
tests/invalid_purity/purity_nonsense2.err_exp:
tests/warnings/double_underscore.exp:
tests/warnings/pragma_source_file.exp:
tests/warnings/singleton_test.exp:
tests/warnings/singleton_test.exp2:
tests/warnings/singleton_test.exp3:
tests/warnings/singleton_test.exp4:
tests/warnings/singleton_test_state_var.exp:
tests/warnings/warn_return.exp:
tests/warnings/warn_return.exp2:
tests/warnings/warn_return.exp3:
tests/warnings/warn_succ_ind.exp:
tests/warnings/warn_succ_ind.exp2:
tests/warnings/warn_succ_ind.exp3:
tests/warnings/warn_succ_ind.exp4:
    Update all these expected output files. Most changes are due to
    predicate and function names no longer being module qualified when
    the module qualification is obvious. A few changes are due to the
    change in the relative ordering of the function symbols of the
    format_component type.

    For singleton_test, warn_return and warn_succ_ind in warnings,
    the changes to the non-C .exp files were done by hand, so they
    may have the wrong white space.
2020-03-16 12:10:28 +11:00

271 lines
11 KiB
Mathematica

%-----------------------------------------------------------------------------%
% vim: ft=mercury ts=4 sw=4 et
%-----------------------------------------------------------------------------%
% Copyright (C) 1993-2006, 2008 The University of Melbourne.
% This file may only be copied under the terms of the GNU General
% Public License - see the file COPYING in the Mercury distribution.
%-----------------------------------------------------------------------------%
%
% File: make_hlds_error.m.
%
% Utility predicates for writing out warning and error messages when
% building the HLDS. Error messages specific to a given submodule of
% make_hlds.m are in that specific submodule; this module is for error messages
% that are either needed by more than one submodule of make_hlds.m, or are
% needed outside make_hlds.m.
%
%-----------------------------------------------------------------------------%
:- module hlds.make_hlds_error.
:- interface.
:- import_module hlds.hlds_module.
:- import_module hlds.status.
:- import_module mdbcomp.
:- import_module mdbcomp.prim_data.
:- import_module mdbcomp.sym_name.
:- import_module parse_tree.
:- import_module parse_tree.error_util.
:- import_module parse_tree.prog_data.
:- import_module list.
:- import_module maybe.
%-----------------------------------------------------------------------------%
:- pred report_multiple_def_error(sym_name::in, int::in, string::in,
prog_context::in, prog_context::in, list(format_component)::in,
list(error_spec)::in, list(error_spec)::out) is det.
:- pred report_undefined_pred_or_func_error(maybe(pred_or_func)::in,
sym_name::in, arity::in, list(arity)::in, prog_context::in,
list(format_component)::in,
list(error_spec)::in, list(error_spec)::out) is det.
% Similar to report_undeclared_mode_error, but gives less information.
% XXX perhaps we should get rid of this, and change the callers to
% instead call undeclared_mode_error.
%
:- pred report_undefined_mode_error(sym_name::in, int::in, prog_context::in,
list(format_component)::in,
list(error_spec)::in, list(error_spec)::out) is det.
:- pred maybe_report_undefined_pred_error(module_info::in,
sym_name::in, int::in, pred_or_func::in, pred_status::in,
maybe_class_method::in, prog_context::in, list(format_component)::in,
list(error_spec)::in, list(error_spec)::out) is det.
%----------------------------------------------------------------------------%
%----------------------------------------------------------------------------%
:- implementation.
:- import_module hlds.hlds_pred.
:- import_module hlds.pred_table.
:- import_module libs.
:- import_module libs.globals.
:- import_module libs.options.
:- import_module parse_tree.prog_out.
:- import_module parse_tree.prog_util.
:- import_module bool.
:- import_module set.
:- import_module string.
%-----------------------------------------------------------------------------%
report_multiple_def_error(Name, Arity, DefType, Context, OrigContext,
ExtraPieces, !Specs) :-
% The flattening of source item blocks by modules.m puts
% all items in a given section together. Since the original
% source code may have had the contents of the different sections
% intermingled, this may change the relative order of items.
% Put them back in the original order for this error message.
compare(CmpRes, OrigContext, Context),
(
( CmpRes = (<)
; CmpRes = (=)
),
FirstContext = OrigContext,
SecondContext = Context
;
CmpRes = (>),
FirstContext = Context,
SecondContext = OrigContext
),
SNA = qual_sym_name_arity(sym_name_arity(Name, Arity)),
SecondDeclPieces = [words("Error:"), fixed(DefType), SNA,
words("multiply defined."), nl],
FirstDeclPieces = [words("Here is the previous definition of"),
fixed(DefType), SNA, suffix("."), nl],
SecondDeclMsg = simplest_msg(SecondContext, SecondDeclPieces),
FirstDeclMsg = error_msg(yes(FirstContext), treat_as_first, 0,
[always(FirstDeclPieces)]),
(
ExtraPieces = [],
ExtraMsgs = []
;
ExtraPieces = [_ | _],
ExtraMsgs = [simplest_msg(SecondContext, ExtraPieces)]
),
Spec = error_spec($pred, severity_error, phase_parse_tree_to_hlds,
[SecondDeclMsg, FirstDeclMsg | ExtraMsgs]),
!:Specs = [Spec | !.Specs].
report_undefined_pred_or_func_error(MaybePorF, Name, Arity, OtherArities,
Context, DescPieces, !Specs) :-
(
MaybePorF = no,
PredOrFuncPieces = [decl("pred"), words("or"), decl("func")]
;
MaybePorF = yes(pf_predicate),
PredOrFuncPieces = [decl("pred")]
;
MaybePorF = yes(pf_function),
PredOrFuncPieces = [decl("func")]
),
MainPieces = [words("Error:") | DescPieces] ++ [words("for"),
unqual_sym_name_arity(sym_name_arity(Name, Arity)),
words("without corresponding")] ++ PredOrFuncPieces ++
[words("declaration."), nl],
(
OtherArities = [],
OtherArityPieces = []
;
OtherArities = [_ | _],
list.map(string.int_to_string, OtherArities, OtherArityStrs),
OtherArityPieces = [unqual_sym_name(Name), words("does exist with"),
words(choose_number(OtherArityStrs, "arity", "arities"))] ++
list_to_pieces(OtherArityStrs) ++
[suffix("."), nl]
),
Spec = simplest_spec($pred, severity_error, phase_parse_tree_to_hlds,
Context, MainPieces ++ OtherArityPieces),
!:Specs = [Spec | !.Specs].
report_undefined_mode_error(Name, Arity, Context, DescPieces, !Specs) :-
Pieces = [words("Error:") | DescPieces] ++ [words("for"),
qual_sym_name_arity(sym_name_arity(Name, Arity)),
words("specifies non-existent mode.")],
Spec = simplest_spec($pred, severity_error, phase_parse_tree_to_hlds,
Context, Pieces),
!:Specs = [Spec | !.Specs].
%----------------------------------------------------------------------------%
maybe_report_undefined_pred_error(ModuleInfo, Name, Arity, PredOrFunc, Status,
IsClassMethod, Context, DescPieces, !Specs) :-
% Our caller (or one of its ancestors) will add an implicit declaration
% for every undeclared predicate or function that has a reference to it
% either in a clause or in some other declaration (e.g. a tabling pragma).
% It will also mark the predicate as one whose type should be inferred.
% We allow programmers to define predicates without declaring them first
% if the user has specified the `--infer-types' option, unless
% circumstances force us to require a predicate declaration anyway.
%
% The two relevant circumstances are:
%
% - predicates exported from their defining module, which must be declared
% to allow the compiler to put that declaration into the module's
% interface file without running the typechecker, and
%
% - predicates which implement type class methods.
% XXX Document the reason for the requirement here.
DefinedInThisModule = pred_status_defined_in_this_module(Status),
IsExported = pred_status_is_exported(Status),
module_info_get_globals(ModuleInfo, Globals),
globals.lookup_bool_option(Globals, infer_types, InferTypes),
( if
DefinedInThisModule = yes,
IsExported = no,
IsClassMethod = is_not_a_class_method,
InferTypes = yes
then
true
else
PFSymNameArity = pf_sym_name_arity(PredOrFunc, Name, Arity),
PredOrFuncStr = pred_or_func_to_str(PredOrFunc),
MainPieces = [invis_order_default_start(1),
words("Error:") | DescPieces] ++ [words("for"),
unqual_pf_sym_name_orig_arity(PFSymNameArity), nl,
words("without corresponding"),
decl(PredOrFuncStr), words("declaration."), nl],
MainMsg = simplest_msg(Context, MainPieces),
module_info_get_predicate_table(ModuleInfo, PredicateTable),
predicate_table_lookup_pf_sym(PredicateTable,
is_fully_qualified, PredOrFunc, Name, AllArityPredIds),
gather_porf_arities(ModuleInfo, AllArityPredIds, PredOrFunc,
PorFArities),
set.delete(Arity, PorFArities, OtherArities),
% The sorting is to make the error message easier to read.
% There should not be any duplicates among OtherArities, but better
% safe than sorry ...
set.to_sorted_list(OtherArities, OtherAritiesList),
FullPredOrFuncStr = pred_or_func_to_full_str(PredOrFunc),
(
OtherAritiesList = [],
Spec = error_spec($pred, severity_error, phase_parse_tree_to_hlds,
[MainMsg])
;
(
OtherAritiesList = [OtherArity],
OtherAritiesPieces = [words("However, a"),
words(FullPredOrFuncStr), words("of that name"),
words("does exist with arity"), int_fixed(OtherArity),
suffix("."), nl]
;
OtherAritiesList = [_, _ | _],
OtherAritiesPieces = [words("However,"),
words(FullPredOrFuncStr), suffix("s"),
words("of that name do exist with arities") |
component_list_to_pieces("and",
list.map(wrap_int_fixed, OtherAritiesList))] ++
[suffix("."), nl]
),
OtherAritiesMsg = simplest_msg(Context, OtherAritiesPieces),
Spec = error_spec($pred, severity_error, phase_parse_tree_to_hlds,
[MainMsg, OtherAritiesMsg])
),
!:Specs = [Spec | !.Specs]
).
% Given a list of pred ids, find out which of them represent
% procedures which have the right pred_or_func field (WantedPorF),
% and return their original arities.
%
:- pred gather_porf_arities(module_info::in, list(pred_id)::in,
pred_or_func::in, set(int)::out) is det.
gather_porf_arities(_ModuleInfo, [], _WantedPorF, set.init).
gather_porf_arities(ModuleInfo, [PredId | PredIds], WantedPorF,
!:PorFArities) :-
gather_porf_arities(ModuleInfo, PredIds, WantedPorF, !:PorFArities),
module_info_pred_info(ModuleInfo, PredId, PredInfo),
PorF = pred_info_is_pred_or_func(PredInfo),
( if PorF = WantedPorF then
pred_info_get_markers(PredInfo, Markers),
( if check_marker(Markers, marker_no_pred_decl) then
% This pred has no declaration, so including its arity in the list
% would be misleading.
true
else
pred_info_get_orig_arity(PredInfo, OrigArity),
adjust_func_arity(PorF, OrigArity, Arity),
set.insert(Arity, !PorFArities)
)
else
true
).
:- func wrap_int_fixed(int) = format_component.
wrap_int_fixed(N) = int_fixed(N).
%----------------------------------------------------------------------------%
:- end_module hlds.make_hlds_error.
%----------------------------------------------------------------------------%