[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