[m-rev.] for review: nicer error messages
Peter Wang
novalazy at gmail.com
Wed Apr 15 12:10:35 AEST 2009
Branches: main
Make type errors where there are multiple inferred types more readable.
compiler/typecheck_errors.m:
Don't list expected types multiple times, once for each inferred
type. List expected types before inferred types.
Indent lists of ambiguous types surrounded by braces.
tests/invalid/Mmakefile:
tests/invalid/type_error_ambiguous.err_exp:
tests/invalid/type_error_ambiguous.m:
Add test case.
diff --git a/compiler/typecheck_errors.m b/compiler/typecheck_errors.m
index 1c6e558..6f2fa9e 100644
--- a/compiler/typecheck_errors.m
+++ b/compiler/typecheck_errors.m
@@ -875,9 +875,10 @@ report_error_var(Info, Var, Type, TypeAssignSet0) = Spec :-
argument_name_to_pieces(VarSet, Var) ++
[words("does not match its expected type;"), nl] ++
argument_name_to_pieces(VarSet, Var) ++
- [words("has overloaded actual/expected types {"), nl] ++
+ [words("has overloaded actual/expected types {")] ++
+ [nl_indent_delta(1)] ++
actual_expected_types_list_to_pieces(ActualExpectedList) ++
- [nl, fixed("}."), nl]
+ [nl_indent_delta(-1), fixed("}."), nl]
),
VerbosePieces = type_assign_set_msg_to_pieces(TypeAssignSet0, VarSet),
@@ -927,11 +928,12 @@ report_error_var_either_type(Info, Var, TypeA,
TypeB, TypeAssignSet0) = Spec :-
argument_name_to_pieces(VarSet, Var) ++
[words("does not match its expected type;"), nl] ++
argument_name_to_pieces(VarSet, Var) ++
- [words("has overloaded actual/expected types {"), nl] ++
+ [words("has overloaded actual/expected types {")] ++
+ [nl_indent_delta(1)] ++
actual_expected_types_list_to_pieces(ActualExpectedListA) ++
- [nl, fixed("} or {."), nl] ++
+ [nl_indent_delta(-1), fixed("} or {"), nl_indent_delta(1)] ++
actual_expected_types_list_to_pieces(ActualExpectedListB) ++
- [nl, fixed("}."), nl]
+ [nl_indent_delta(-1), fixed("}."), nl]
),
VerbosePieces = type_assign_set_msg_to_pieces(TypeAssignSet0, VarSet),
@@ -973,9 +975,10 @@ report_error_arg_var(Info, Var,
ArgTypeAssignSet0) = Spec :-
argument_name_to_pieces(VarSet, Var) ++
[words("does not match its expected type;"), nl] ++
argument_name_to_pieces(VarSet, Var) ++
- [words("has overloaded actual/expected types {"), nl] ++
+ [words("has overloaded actual/expected types {")] ++
+ [nl_indent_delta(1)] ++
actual_expected_types_list_to_pieces(ActualExpectedList) ++
- [nl, fixed("}."), nl]
+ [nl_indent_delta(-1), fixed("}."), nl]
),
VerbosePieces = args_type_assign_set_msg_to_pieces(ArgTypeAssignSet0,
@@ -1442,9 +1445,8 @@ type_of_functor_to_pieces(Functor, Arity,
ConsDefnList) = Pieces :-
;
ConsTypeListPieces =
cons_type_list_to_pieces(ConsDefnList, Functor, Arity),
- Pieces = [words("has overloaded type"), nl_indent_delta(1)] ++
- [fixed("{")] ++ ConsTypeListPieces ++
- [nl_indent_delta(-1), fixed("}")]
+ Pieces = [words("has overloaded type {"), nl_indent_delta(1)] ++
+ ConsTypeListPieces ++ [nl_indent_delta(-1), fixed("}")]
).
% Return a description of the given data constructor's argument types.
@@ -1600,17 +1602,29 @@
arg_type_stuff_to_actual_expected(ArgTypeStuff) = ActualExpected :-
:- func actual_expected_types_list_to_pieces(list(actual_expected_types))
= list(format_component).
-actual_expected_types_list_to_pieces(ActualExpectedList) =
- component_list_to_line_pieces(
- list.map(actual_expected_types_to_pieces, ActualExpectedList), []).
+actual_expected_types_list_to_pieces(ActualExpectedList) = Pieces :-
+ ExpectedPieces = list.foldl(expected_types_to_pieces, ActualExpectedList,
+ []),
+ ActualPieces = list.map(actual_types_to_pieces, ActualExpectedList),
+ Pieces = component_list_to_line_pieces(ExpectedPieces ++ ActualPieces, []).
-:- func actual_expected_types_to_pieces(actual_expected_types)
- = list(format_component).
+:- func expected_types_to_pieces(actual_expected_types,
+ list(list(format_component))) = list(list(format_component)).
+
+expected_types_to_pieces(ActualExpected, Pieces0) = Pieces :-
+ ActualExpected = actual_expected_types(_ActualPieces, ExpectedPieces),
+ TaggedPieces = [words("(expected)") | ExpectedPieces],
+ ( list.member(TaggedPieces, Pieces0) ->
+ Pieces = Pieces0
+ ;
+ Pieces = Pieces0 ++ [TaggedPieces]
+ ).
+
+:- func actual_types_to_pieces(actual_expected_types) = list(format_component).
-actual_expected_types_to_pieces(ActualExpected) = Pieces :-
- ActualExpected = actual_expected_types(ActualPieces, ExpectedPieces),
- Pieces = [words("(inferred)")] ++ ActualPieces ++ [suffix(","), nl] ++
- [words("(expected)")] ++ ExpectedPieces.
+actual_types_to_pieces(ActualExpected) = Pieces :-
+ ActualExpected = actual_expected_types(ActualPieces, _ExpectedPieces),
+ Pieces = [words("(inferred)") | ActualPieces].
:- func bound_type_to_pieces(mer_type, tvarset, tsubst, head_type_params)
= list(format_component).
diff --git a/tests/invalid/Mmakefile b/tests/invalid/Mmakefile
index a7ac648..15f2291 100644
--- a/tests/invalid/Mmakefile
+++ b/tests/invalid/Mmakefile
@@ -192,6 +192,7 @@ SINGLEMODULE= \
tricky_assert1 \
try_bad_params \
try_io_else \
+ type_error_ambiguous \
type_inf_loop \
type_loop \
type_mismatch \
diff --git a/tests/invalid/type_error_ambiguous.err_exp
b/tests/invalid/type_error_ambiguous.err_exp
new file mode 100644
index 0000000..c1ed263
--- /dev/null
+++ b/tests/invalid/type_error_ambiguous.err_exp
@@ -0,0 +1,14 @@
+type_error_ambiguous.m:035: In clause for predicate `main'/2:
+type_error_ambiguous.m:035: in argument 1 of call to predicate
+type_error_ambiguous.m:035: `io.write_int'/3:
+type_error_ambiguous.m:035: type error: type of variable `X' does not match
+type_error_ambiguous.m:035: its expected type;
+type_error_ambiguous.m:035: variable `X' has overloaded actual/expected types
+type_error_ambiguous.m:035: {
+type_error_ambiguous.m:035: (expected) int,
+type_error_ambiguous.m:035: (inferred) (type_error_ambiguous.t1),
+type_error_ambiguous.m:035: (inferred) (type_error_ambiguous.t2),
+type_error_ambiguous.m:035: (inferred) character,
+type_error_ambiguous.m:035: (inferred) pred(int, string)
+type_error_ambiguous.m:035: }.
+For more information, recompile with `-E'.
diff --git a/tests/invalid/type_error_ambiguous.m
b/tests/invalid/type_error_ambiguous.m
new file mode 100644
index 0000000..9c7222e
--- /dev/null
+++ b/tests/invalid/type_error_ambiguous.m
@@ -0,0 +1,39 @@
+% Type error where inferred type is ambiguous. The error message used to
+% contain the same expected type multiple times.
+
+:- module type_error_ambiguous.
+:- interface.
+
+:- import_module io.
+
+:- pred main(io::di, io::uo) is det.
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+
+:- implementation.
+
+:- import_module int.
+:- import_module list.
+
+%-----------------------------------------------------------------------------%
+
+:- type t1
+ ---> f
+ ; g.
+
+:- type t2
+ ---> f
+ ; g.
+
+:- pred f(int::out, string::out) is det.
+
+f(1, "s").
+
+main(!IO) :-
+ X = f,
+ io.write_int(X, !IO),
+ io.nl(!IO).
+
+%-----------------------------------------------------------------------------%
+% vim: ft=mercury ts=8 sts=4 sw=4 et
--------------------------------------------------------------------------
mercury-reviews mailing list
Post messages to: mercury-reviews at csse.unimelb.edu.au
Administrative Queries: owner-mercury-reviews at csse.unimelb.edu.au
Subscriptions: mercury-reviews-request at csse.unimelb.edu.au
--------------------------------------------------------------------------
More information about the reviews
mailing list