Files
mercury/compiler/term_constr_errors.m
Zoltan Somogyi 0fa51cc45c Use color in typecheck_error_undef.m ...
... and change the coloring done in many other modules.

compiler/typecheck_error_undef.m:
    Add color to the diagnostics generated by this module.

    In a few cases, improve the wording of the diagnostic.

    Make the name of a function and of a function symbol more descriptive.

    Convert some predicates from using many clauses to using
    an explicit disjunction.

    Delete a function that was sort-of a specialize version of a
    utility function in error_spec.m.

compiler/hlds_error_util.m:
    Change the functions that return descriptions of predicates and procedures,
    mostly for use in diagnostics, to allow the parts of those descriptions
    specific to an individual predicate or procedure to be colored *without*
    coloring the generic parts (such as the word "predicate" or "function").

    Add simpler versions of the affected functions for use cases that
    do not need any coloring.

compiler/accumulator.m:
compiler/add_clause.m:
compiler/add_pragma.m:
compiler/check_pragma_format_call.m:
compiler/check_typeclass.m:
compiler/dead_proc_elim.m:
compiler/det_analysis.m:
compiler/det_report.m:
compiler/direct_arg_in_out.m:
compiler/fact_table.m:
compiler/float_regs.m:
compiler/format_call.m:
compiler/hlds_out_module.m:
compiler/hlds_statistics.m:
compiler/inst_mode_type_prop.m:
compiler/make_hlds_error.m:
compiler/mode_errors.m:
compiler/modes.m:
compiler/oisu_check.m:
compiler/old_type_constraints.m:
compiler/ordering_mode_constraints.m:
compiler/parse_module.m:
compiler/post_typecheck.m:
compiler/prop_mode_constraints.m:
compiler/purity.m:
compiler/simplify_goal_call.m:
compiler/stratify.m:
compiler/style_checks.m:
compiler/table_gen.m:
compiler/tabling_analysis.m:
compiler/term_constr_errors.m:
compiler/term_errors.m:
compiler/termination.m:
compiler/trailing_analysis.m:
compiler/typecheck.m:
compiler/typecheck_clauses.m:
compiler/typecheck_error_overload.m:
compiler/typecheck_error_util.m:
compiler/typecheck_errors.m:
compiler/typecheck_msgs.m:
    Conform to the changes in hlds_error_util.m.

    In many cases, improve the affected diagnostics, and maybe other nearby
    diagnostics, in other ways as well.

compiler/hlds_data.m:
    Fix comments.

tests/invalid/bad_exported_mode.err_exp:
tests/invalid/bad_fact_table_data.err_exp:
tests/invalid/bad_fact_table_data.err_exp2:
tests/invalid/bad_fact_table_decls.err_exp:
tests/invalid/bad_format_call.err_exp:
tests/invalid/bad_pred_arity.err_exp:
tests/invalid/bad_sv_unify_msg.err_exp:
tests/invalid/bug10.err_exp:
tests/invalid/bug113.err_exp:
tests/invalid/bug150.err_exp:
tests/invalid/bug184.err_exp:
tests/invalid/bug197.err_exp:
tests/invalid/bug214.err_exp:
tests/invalid/bug238.err_exp:
tests/invalid/bug257.err_exp:
tests/invalid/bug476.err_exp:
tests/invalid/bug496.err_exp:
tests/invalid/builtin_proc.err_exp:
tests/invalid/coerce_syntax.err_exp:
tests/invalid/coerce_void.err_exp:
tests/invalid/constructor_warning.err_exp:
tests/invalid/det_atomic_goal_msgs.err_exp:
tests/invalid/det_errors.err_exp:
tests/invalid/det_errors_and_io.err_exp:
tests/invalid/det_errors_cc.err_exp:
tests/invalid/erroneous_throw_promise.err_exp:
tests/invalid/exist_foreign_error.err_exp:
tests/invalid/exported_mode.err_exp:
tests/invalid/exported_unify.err_exp:
tests/invalid/field_syntax_error.err_exp:
tests/invalid/foreign_purity_mismatch.err_exp:
tests/invalid/foreign_purity_mismatch.err_exp2:
tests/invalid/foreign_purity_mismatch.err_exp3:
tests/invalid/foreign_type_2.err_exp:
tests/invalid/freefree.err_exp:
tests/invalid/getopt_io_old.err_exp:
tests/invalid/getopt_old_se.err_exp:
tests/invalid/gh72_errors.err_exp:
tests/invalid/hawkins_mm_fail_reset.err_exp:
tests/invalid/ho_unique_error.err_exp:
tests/invalid/impure_method_impl.err_exp:
tests/invalid/invalid_event.err_exp:
tests/invalid/invalid_new.err_exp:
tests/invalid/io_in_ite_cond.err_exp:
tests/invalid/loopcheck.err_exp:
tests/invalid/magicbox.err_exp:
tests/invalid/make_opt_error.err_exp:
tests/invalid/method_impl.err_exp:
tests/invalid/missing_det_decls.err_exp:
tests/invalid/mode_decl_in_wrong_section.err_exp:
tests/invalid/mostly_uniq1.err_exp:
tests/invalid/mostly_uniq2.err_exp:
tests/invalid/multimode_missing_impure.err_exp:
tests/invalid/multimode_syntax.err_exp:
tests/invalid/multiply_star.err_exp:
tests/invalid/no_method.err_exp:
tests/invalid/not_a_switch.err_exp:
tests/invalid/one_member.err_exp:
tests/invalid/pragma_c_code_dup_var.err_exp:
tests/invalid/pragma_c_code_no_det.err_exp:
tests/invalid/pragma_c_code_no_det.err_exp2:
tests/invalid/pragma_c_code_no_det.err_exp3:
tests/invalid/pragma_qual_error.err_exp:
tests/invalid/qual_basic_test2.err_exp:
tests/invalid/qualified_cons_id2.err_exp:
tests/invalid/quant_constraint_1.err_exp:
tests/invalid/quant_constraint_2.err_exp:
tests/invalid/record_syntax_errors.err_exp:
tests/invalid/ref_to_implicit_comma.err_exp:
tests/invalid/ref_to_implicit_pred.err_exp:
tests/invalid/spurious_mode_error.err_exp:
tests/invalid/state_vars_test_3.err_exp:
tests/invalid/string_format_bad.err_exp:
tests/invalid/string_format_unknown.err_exp:
tests/invalid/test_promise_equivalent_clauses.err_exp:
tests/invalid/test_type_spec.err_exp:
tests/invalid/transitive_import_class.err_exp:
tests/invalid/try_detism.err_exp:
tests/invalid/type_error_use_module.err_exp:
tests/invalid/type_inf_loop.err_exp:
tests/invalid/typeclass_dup_method_mode.err_exp:
tests/invalid/typeclass_mode_2.err_exp:
tests/invalid/typeclass_mode_3.err_exp:
tests/invalid/typeclass_mode_4.err_exp:
tests/invalid/typeclass_test_8.err_exp:
tests/invalid/types2.err_exp:
tests/invalid/undeclared_mode.err_exp:
tests/invalid/undef_mode_and_no_clauses.err_exp:
tests/invalid/undef_symbol.err_exp:
tests/invalid/unsatisfiable_constraint.err_exp:
tests/invalid/user_field_access_decl_override_1.err_exp:
tests/invalid/wrong_arity_function.err_exp:
tests/invalid_make_int/bad_end_module.int_err_exp:
tests/invalid_make_int/missing_initial_section.int_err_exp:
tests/invalid_nodepend/after_end_module.err_exp:
tests/invalid_nodepend/bad_fact_table.err_exp:
tests/invalid_nodepend/bigtest.err_exp:
tests/invalid_nodepend/bug410.err_exp:
tests/invalid_nodepend/constrained_poly_insts.err_exp:
tests/invalid_nodepend/duplicate_modes.err_exp:
tests/invalid_nodepend/errors_1.err_exp:
tests/invalid_nodepend/errors_2.err_exp:
tests/invalid_nodepend/errors_3.err_exp:
tests/invalid_nodepend/external.err_exp:
tests/invalid_nodepend/funcs_as_preds.err_exp:
tests/invalid_nodepend/impl_def_literal_syntax.err_exp:
tests/invalid_nodepend/invalid_binary_literal.err_exp:
tests/invalid_nodepend/invalid_decimal_literal.err_exp:
tests/invalid_nodepend/invalid_float_literal.err_exp:
tests/invalid_nodepend/invalid_hex_literal.err_exp:
tests/invalid_nodepend/invalid_main.err_exp:
tests/invalid_nodepend/invalid_octal_literal.err_exp:
tests/invalid_nodepend/no_exports.err_exp:
tests/invalid_nodepend/null_char.err_exp:
tests/invalid_nodepend/occurs.err_exp:
tests/invalid_nodepend/pragma_export.err_exp:
tests/invalid_nodepend/prog_io_erroneous.err_exp:
tests/invalid_nodepend/reserved_type_name.err_exp:
tests/invalid_nodepend/test_with_type.err_exp:
tests/invalid_nodepend/typeclass_test_1.err_exp:
tests/invalid_nodepend/typeclass_test_2.err_exp:
tests/invalid_nodepend/types.err_exp:
tests/invalid_nodepend/unbound_type_vars.err_exp:
tests/invalid_nodepend/unterminated_octal_escape.err_exp:
tests/invalid_nodepend/vars_in_wrong_places.err_exp:
tests/invalid_purity/impure_func_t2.err_exp:
tests/invalid_purity/impure_func_t3.err_exp:
tests/invalid_purity/impure_func_t4.err_exp:
tests/invalid_purity/pragma_c_and_mercury.err_exp:
tests/invalid_purity/purity.err_exp:
tests/invalid_purity/purity_nonsense_1.err_exp:
tests/invalid_purity/purity_nonsense_2.err_exp:
tests/invalid_submodules/exported_unify3.err_exp:
tests/invalid_submodules/func_class.err_exp:
tests/invalid_submodules/undef_mod_qual.err_exp:
tests/recompilation/typeclass_method_pragma_r.err_exp.2:
tests/recompilation/with_type_re.err_exp.2:
tests/warnings/arg_order_rearrangment.err_exp:
tests/warnings/bug477.err_exp:
tests/warnings/det_infer_warning.err_exp:
tests/warnings/disabled_warning.err_exp:
tests/warnings/foreign_term_invalid.err_exp:
tests/warnings/format_call_multi.err_exp:
tests/warnings/format_call_warning.err_exp:
tests/warnings/infinite_recursion.err_exp:
tests/warnings/non_contiguous_decls.err_exp:
tests/warnings/non_stratification.err_exp:
tests/warnings/obsolete_proc_pragma.err_exp:
tests/warnings/pragma_term_conflict.err_exp:
tests/warnings/purity_warnings.err_exp:
tests/warnings/save.err_exp:
tests/warnings/simple_code.err_exp:
tests/warnings/singleton_test.err_exp:
tests/warnings/spurious_obsolete.err_exp:
tests/warnings/suspicious_recursion.err_exp:
tests/warnings/unneeded_mode_specific_clause.err_exp:
tests/warnings/unsigned_zero_cmp.err_exp:
tests/warnings/warn_dead_procs.err_exp:
tests/warnings/warn_dead_procs_trace.err_exp:
tests/warnings/warn_non_contiguous.err_exp:
tests/warnings/warn_non_contiguous_foreign.err_exp:
tests/warnings/warn_stubs.err_exp:
    Expect updated diagnostics.
2024-05-20 18:31:15 +10:00

320 lines
12 KiB
Mathematica

%-----------------------------------------------------------------------------%
% vim: ft=mercury ts=4 sw=4 et
%-----------------------------------------------------------------------------%
% Copyright (C) 2002, 2005-2007, 2010-2011 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: term_constr_errors.m.
% Main author: juliensf.
%
%-----------------------------------------------------------------------------%
:- module transform_hlds.term_constr_errors.
:- interface.
:- import_module hlds.
:- import_module hlds.hlds_module.
:- import_module hlds.hlds_pred.
:- import_module parse_tree.
:- import_module parse_tree.error_spec.
:- import_module parse_tree.prog_data.
:- import_module list.
%-----------------------------------------------------------------------------%
%
% Termination 2 Errors
%
% The termination errors are all in reference to possible non-termination.
% While it is possible for pass 1 to go amiss the worst that will happen
% (barring an abnormal abort) is that the size of the arguments will be
% unconstrained.
:- type term2_error_kind
---> imported_pred
% Termination could not be proved because it depends upon
% information from another module and that information is not
% available.
; can_loop_proc_called(pred_proc_id, pred_proc_id)
% Termination could not be proved because the procedure called
% another procedure that may not terminate.
; cond_not_satisfied
% Termination could not be proved because no set of decreasing
% argument could be found.
; horder_call
% Termination could not be proved because the procedure makes
% higher-order calls.
; does_not_term_pragma(pred_id)
% Termination could not be proved because the procedure was marked
% with a `does_not_terminate' pragma.
; foreign_proc_called(pred_proc_id).
% Termination depends upon the properties of a piece of foreign
% code that cannot be established as terminating.
:- type term2_error
---> term2_error(prog_context, term2_error_kind).
%-----------------------------------------------------------------------------%
:- pred maybe_report_term2_errors(module_info::in, scc::in,
list(term2_error)::in,
list(error_spec)::in, list(error_spec)::out) is det.
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
:- implementation.
:- import_module hlds.hlds_error_util.
:- import_module libs.
:- import_module libs.globals.
:- import_module libs.options.
:- import_module transform_hlds.term_util.
:- import_module bool.
:- import_module cord.
:- import_module int.
:- import_module maybe.
:- import_module require.
:- import_module set.
:- import_module string.
%-----------------------------------------------------------------------------%
maybe_report_term2_errors(ModuleInfo, SCC, Errors, !Specs) :-
decide_what_term2_errors_to_report(ModuleInfo, SCC, Errors,
MaybeErrorsToReport),
(
MaybeErrorsToReport = no
;
MaybeErrorsToReport = yes(ErrorsToReport),
report_term2_errors(ModuleInfo, SCC, ErrorsToReport, !Specs)
).
:- pred decide_what_term2_errors_to_report(module_info::in,
scc::in, list(term2_error)::in, maybe(list(term2_error))::out) is det.
decide_what_term2_errors_to_report(ModuleInfo, SCC, Errors,
MaybeErrorsToReport) :-
% NOTE The code of this predicate follows the same logic as the
% code of decide_what_term_errors_to_report in termination.m.
% Although there are differences in the data types they operate on
% and the options they consult, any changes here probably require
% corresponding changes there as well.
% The logic of this code is documented in comments in
% decide_what_term_errors_to_report.
module_info_get_globals(ModuleInfo, Globals),
globals.lookup_bool_option(Globals, termination2_check, NormalErrors),
globals.lookup_bool_option(Globals, termination2_check_verbose,
VerboseErrors),
( if
IsCheckTerm =
( pred(PPId::in) is semidet :-
module_info_pred_proc_info(ModuleInfo, PPId, PredInfo, _),
not pred_info_is_imported(PredInfo),
pred_info_get_markers(PredInfo, Markers),
check_marker(Markers, marker_check_termination)
),
set.filter(IsCheckTerm, SCC, CheckTermPPIds),
set.is_non_empty(CheckTermPPIds)
then
MaybeErrorsToReport = yes(Errors)
else if
IsNonImported =
( pred(PPId::in) is semidet :-
module_info_pred_proc_info(ModuleInfo, PPId, PredInfo, _),
not pred_info_is_imported(PredInfo)
),
set.filter(IsNonImported, SCC, NonImportedPPIds),
set.is_non_empty(NonImportedPPIds)
then
(
VerboseErrors = yes,
MaybeErrorsToReport = yes(Errors)
;
VerboseErrors = no,
(
NormalErrors = yes,
IsDirect =
( pred(Error::in) is semidet :-
Error = term2_error(_, ErrorKind),
term2_error_kind_is_direct(ErrorKind) = yes
),
list.filter(IsDirect, Errors, DirectErrors),
(
DirectErrors = [],
MaybeErrorsToReport = yes(Errors)
;
DirectErrors = [_ | _],
MaybeErrorsToReport = yes(DirectErrors)
)
;
NormalErrors = no,
MaybeErrorsToReport = no
)
)
else
MaybeErrorsToReport = no
).
%-----------------------------------------------------------------------------%
:- pred report_term2_errors(module_info::in, scc::in,
list(term2_error)::in, list(error_spec)::in, list(error_spec)::out) is det.
report_term2_errors(ModuleInfo, SCC, Errors, !Specs) :-
get_context_from_scc(ModuleInfo, SCC, Context),
( if set.is_singleton(SCC, PPId) then
Pieces0 = [words("Termination of")],
ProcName = describe_qual_proc_name(ModuleInfo, PPId),
Pieces1 = Pieces0 ++ ProcName,
Single = yes(PPId)
else
Pieces0 = [words("Termination of the"),
words("mutually recursive procedures")],
ProcNames = describe_several_proc_names(ModuleInfo, no,
should_module_qualify, set.to_sorted_list(SCC)),
Pieces1 = Pieces0 ++ ProcNames,
Single = no
),
(
Errors = [],
Pieces2 = [words("not proven, for unknown reason(s).")],
ReasonMsgsCord = cord.init
;
Errors = [Error],
Pieces2 = [words("not proven for the following reason:")],
describe_term2_error(ModuleInfo, Single, no, Error,
cord.init, ReasonMsgsCord)
;
Errors = [_, _ | _],
Pieces2 = [words("not proven for the following reasons:")],
describe_term2_errors(ModuleInfo, Single, 1, Errors,
cord.init, ReasonMsgsCord)
),
ReasonMsgs = cord.list(ReasonMsgsCord),
Msgs = [simple_msg(Context, [always(Pieces1 ++ Pieces2)]) | ReasonMsgs],
Spec = error_spec($pred, severity_warning, phase_termination_analysis,
Msgs),
!:Specs = [Spec | !.Specs].
:- pred describe_term2_errors(module_info::in, maybe(pred_proc_id)::in,
int::in, list(term2_error)::in,
cord(error_msg)::in, cord(error_msg)::out) is det.
describe_term2_errors(_, _, _, [], !ReasonMsgsCord).
describe_term2_errors(ModuleInfo, Single, ErrNum0, [Error | Errors],
!ReasonMsgsCord) :-
describe_term2_error(ModuleInfo, Single, yes(ErrNum0), Error,
!ReasonMsgsCord),
describe_term2_errors(ModuleInfo, Single, ErrNum0 + 1, Errors,
!ReasonMsgsCord).
:- pred describe_term2_error(module_info::in, maybe(pred_proc_id)::in,
maybe(int)::in, term2_error::in,
cord(error_msg)::in, cord(error_msg)::out) is det.
describe_term2_error(ModuleInfo, Single, MaybeErrorNum, Error,
!ReasonMsgsCord) :-
Error = term2_error(Context, ErrorKind),
term2_error_kind_description(ModuleInfo, Single, ErrorKind, Pieces0),
(
MaybeErrorNum = yes(N),
string.int_to_string(N, Nstr),
Preamble = "Reason " ++ Nstr ++ ":",
Pieces = [fixed(Preamble) | Pieces0]
;
MaybeErrorNum = no,
Pieces = Pieces0
),
ReasonMsg = error_msg(yes(Context), always_treat_as_first, 0,
[always(Pieces)]),
!:ReasonMsgsCord = cord.snoc(!.ReasonMsgsCord, ReasonMsg).
:- pred term2_error_kind_description(module_info::in, maybe(pred_proc_id)::in,
term2_error_kind::in, list(format_piece)::out) is det.
term2_error_kind_description(ModuleInfo, Single, Error, Pieces) :-
(
Error = cond_not_satisfied,
Pieces = [words("The termination condition"),
words("is not satisfiable."), nl]
;
Error = imported_pred,
Pieces = [words("It contains one or more"),
words("predicates and/or functions"),
words("imported from another module."), nl]
;
Error = can_loop_proc_called(CallerPPId, CalleePPId),
(
Single = yes(PPId),
expect(unify(PPId, CallerPPId), $pred, "caller outside this SCC"),
Piece1 = [words("It")]
;
Single = no,
ProcName = describe_qual_proc_name(ModuleInfo, CallerPPId),
Piece1 = ProcName
),
Piece2 = words("calls"),
CalleePiece = describe_qual_proc_name(ModuleInfo, CalleePPId),
Pieces3 = [words("which could not be proven to terminate."), nl],
Pieces = Piece1 ++ [Piece2] ++ CalleePiece ++ Pieces3
;
Error = horder_call,
Pieces = [words("It contains a higher-order call."), nl]
;
Error = does_not_term_pragma(PredId),
Pieces1 = [words("There is a"), pragma_decl("does_not_terminate"),
words("declaration for")],
(
Single = yes(PPId),
PPId = proc(SCCPredId, _),
expect(unify(PredId, SCCPredId), $pred,
"does not terminate pragma outside this SCC"),
Pieces2 = [words("it."), nl]
;
Single = no,
PredDesc = describe_qual_pred_name(ModuleInfo, PredId),
Pieces2 = PredDesc ++ [suffix("."), nl]
),
Pieces = Pieces1 ++ Pieces2
;
Error = foreign_proc_called(PPId),
Name = describe_qual_proc_name(ModuleInfo, PPId),
Pieces = [words("There is a call the foreign procedure")] ++
Name ++ [words("which is not known to terminate."), nl]
).
%-----------------------------------------------------------------------------%
:- func term2_error_kind_is_direct(term2_error_kind) = bool.
term2_error_kind_is_direct(ErrorKind) = IsDirect :-
(
( ErrorKind = cond_not_satisfied
; ErrorKind = foreign_proc_called(_)
),
IsDirect = yes
;
( ErrorKind = imported_pred
; ErrorKind = horder_call
; ErrorKind = does_not_term_pragma(_)
; ErrorKind = can_loop_proc_called(_, _)
),
IsDirect = no
).
%-----------------------------------------------------------------------------%
:- end_module transform_hlds.term_constr_errors.
%-----------------------------------------------------------------------------%