for review: better messages for some type errors

Zoltan Somogyi zs at cs.mu.oz.au
Mon Oct 13 16:58:44 AEST 1997


Estimated hours taken: 4

compiler/typecheck.m:
	Emit better error messages when the type of a function symbol is known
	and some of the arguments have the wrong type.

tests/invalid/type_mismatch.{m,err_exp}:
	A new test case to exercise the new error messages.

tests/invalid/Mmakefile:
	Enable the new test case.

Zoltan.

Index: compiler/typecheck.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/typecheck.m,v
retrieving revision 1.215
diff -u -r1.215 typecheck.m
--- typecheck.m	1997/09/29 06:12:40	1.215
+++ typecheck.m	1997/10/13 08:30:43
@@ -3112,15 +3112,95 @@
 
 	% XXX we should print type pairs (one type from each side)
 	% only for the arguments in which the two types differ.
-	prog_out__write_context(Context),
-	io__write_string("  "),
-	write_functor_name(Functor, Arity),
-	write_type_of_functor(Functor, Arity, Context, ConsDefnList),
+	(
+		{ ConsDefnList = [SingleDefn] },
+		{ SingleDefn = cons_type_info(ConsTVarSet, _ResultType,
+			ConsArgTypes) },
+		{ assoc_list__from_corresponding_lists(Args, ConsArgTypes,
+			ArgExpTypes) },
+		{ find_mismatched_args(ArgExpTypes, TypeAssignSet, ConsTVarSet,
+			1, Mismatches) },
+		{ Mismatches = [_ | _] }
+	->
+		prog_out__write_context(Context),
+		io__write_string("  The types of the relevant arguments are\n"),
+		report_mismatched_args(Mismatches, VarSet, Context)
+	;
+		prog_out__write_context(Context),
+		io__write_string("  "),
+		write_functor_name(Functor, Arity),
+		write_type_of_functor(Functor, Arity, Context, ConsDefnList),
+
+		write_types_of_vars(Args, VarSet, Context, TypeCheckInfo, 
+			TypeAssignSet),
+
+		write_type_assign_set_msg(TypeAssignSet, VarSet)
+	).
+
+:- type mismatch_info
+	--->	mismatch(
+			int,		% argument number, starting from 1
+			var,		% variable in that position
+			type,		% actual type of that variable
+			tvarset,	% the type vars in the actual type
+			type,		% expected type of that variable
+			tvarset		% the type vars in the expected type
+		).
 
-	write_types_of_vars(Args, VarSet, Context, TypeCheckInfo, 
-		TypeAssignSet),
+:- pred find_mismatched_args(assoc_list(var, type), type_assign_set, tvarset,
+	int, list(mismatch_info)).
+:- mode find_mismatched_args(in, in, in, in, out) is semidet.
 
-	write_type_assign_set_msg(TypeAssignSet, VarSet).
+find_mismatched_args([], _, _, _, []).
+find_mismatched_args([Arg - ExpType | ArgExpTypes], TypeAssignSet, ExpTVarSet,
+		ArgNum0, Mismatched) :-
+	ArgNum1 is ArgNum0 + 1,
+	find_mismatched_args(ArgExpTypes, TypeAssignSet, ExpTVarSet,
+		ArgNum1, Mismatched1),
+	get_type_stuff(TypeAssignSet, Arg, TypeStuffList),
+	TypeStuffList = [type_stuff(ArgType, ArgVarSet, ArgBinding)],
+	term__apply_rec_substitution(ArgType, ArgBinding, FullArgType),
+	(
+		(
+			FullArgType = ExpType
+		;
+			FullArgType = term__functor(term__atom("<any>"), [], _)
+		)
+	->
+		Mismatched = Mismatched1
+	;
+		Mismatched = [mismatch(ArgNum0, Arg, FullArgType, ArgVarSet,
+			ExpType, ExpTVarSet) | Mismatched1]
+	).
+
+:- pred report_mismatched_args(list(mismatch_info), varset, term__context,
+	io__state, io__state).
+:- mode report_mismatched_args(in, in, in, di, uo) is det.
+
+report_mismatched_args([], _, _) --> [].
+report_mismatched_args([Mismatch | Mismatches], VarSet, Context) -->
+	{ Mismatch = mismatch(ArgNum, Var, ActType, ActTVarSet,
+		ExpType, ExpTVarSet) },
+	prog_out__write_context(Context),
+	io__write_string("  argument "),
+	io__write_int(ArgNum),
+	( { varset__search_name(VarSet, Var, _) } ->
+		io__write_string(" ("),
+		mercury_output_var(Var, VarSet, no),
+		io__write_string(")")
+	;
+		[]
+	),
+	io__write_string(": actual `"),
+	mercury_output_term(ActType, ActTVarSet, no),
+	io__write_string("', expected `"),
+	mercury_output_term(ExpType, ExpTVarSet, no),
+	( { Mismatches = [] } ->
+		io__write_string("'.\n")
+	;
+		io__write_string("';\n"),
+		report_mismatched_args(Mismatches, VarSet, Context)
+	).
 
 :- pred write_types_of_vars(list(var), varset, term__context, typecheck_info,
 				type_assign_set, io__state, io__state).
Index: tests/invalid/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/tests/invalid/Mmakefile,v
retrieving revision 1.1
diff -u -r1.1 Mmakefile
--- Mmakefile	1997/09/29 18:04:49	1.1
+++ Mmakefile	1997/10/13 07:31:52
@@ -32,6 +32,7 @@
 	pragma_c_code_and_clauses2.m \
 	qual_basic_test2.m \
 	type_loop.m \
+	type_mismatch.m \
 	unbound_inst_var.m \
 	undef_lambda_mode.m \
 	undef_mode.m \

New File: tests/invalid/type_mismatch.err_exp
===================================================================
type_mismatch.m:019: In clause for predicate `type_mismatch:p1/2':
type_mismatch.m:019:   in unification of variable `Tuple'
type_mismatch.m:019:   and term `f1(V_5, Field, V_6)':
type_mismatch.m:019:   type error in argument(s) of functor `f1/3'.
type_mismatch.m:019:   The types of the relevant arguments are
type_mismatch.m:019:   argument 2 (Field): actual `float', expected `int'.
type_mismatch.m:022: In clause for predicate `type_mismatch:p2/2':
type_mismatch.m:022:   in unification of variable `Tuple'
type_mismatch.m:022:   and term `f2(V_5, Field, V_6)':
type_mismatch.m:022:   type error in argument(s) of functor `f2/3'.
type_mismatch.m:022:   The types of the relevant arguments are
type_mismatch.m:022:   argument 2 (Field): actual `float', expected `int'.
type_mismatch.m:025: In clause for predicate `type_mismatch:p3/2':
type_mismatch.m:025:   in unification of variable `Tuple'
type_mismatch.m:025:   and term `f3(V_5, Field, V_6)':
type_mismatch.m:025:   type error in argument(s) of functor `f3/3'.
type_mismatch.m:025:   The types of the relevant arguments are
type_mismatch.m:025:   argument 2 (Field): actual `F3c', expected `T3b'.
type_mismatch.m:032: In clause for predicate `type_mismatch:p4a/2':
type_mismatch.m:032:   in unification of variable `Tuple'
type_mismatch.m:032:   and term `f4(Field, V_5, V_6)':
type_mismatch.m:032:   type error in argument(s) of functor `f4/3'.
type_mismatch.m:032:   The types of the relevant arguments are
type_mismatch.m:032:   argument 1 (Field): actual `float', expected `T4'.
type_mismatch.m:035: In clause for predicate `type_mismatch:p4b/3':
type_mismatch.m:035:   in unification of variable `Tuple'
type_mismatch.m:035:   and term `f4(Field1, Field2, V_7)':
type_mismatch.m:035:   type error in argument(s) of functor `f4/3'.
type_mismatch.m:035:   The types of the relevant arguments are
type_mismatch.m:035:   argument 1 (Field1): actual `float', expected `T4';
type_mismatch.m:035:   argument 2 (Field2): actual `float', expected `int'.
For more information, try recompiling with `-E'.

New File: tests/invalid/type_mismatch.m
===================================================================
:- module type_mismatch.

:- interface.

:- type t1		--->	f1(int, int, int).
:- type t2(T2)		--->	f2(T2, int, int).
:- type t3(T3a, T3b)	--->	f3(T3a, T3b, int).
:- type t4(T4)		--->	f4(T4, int, int).

:- pred p1(t1::in, float::out) is semidet.
:- pred p2(t2(F2)::in, float::out) is semidet.
:- pred p3(t3(F3a, F3b)::in, F3c::out) is semidet.
:- pred p4a(t4(F4)::in, float::out) is semidet.
:- pred p4b(t4(F4)::in, float::out, float::out) is semidet.

:- implementation.

p1(Tuple, Field) :-
	Tuple = f1(_, Field, 5).

p2(Tuple, Field) :-
	Tuple = f2(_, Field, 5).

p3(Tuple, Field) :-
	Tuple = f3(_, Field, 5).

% The error message for p4a could be improved. At the moment we only get
% an error for argument 1, since the transformation to superhomogeneous form
% replaces the second occurrence of Field inside f4 with another variable.

p4a(Tuple, Field) :-
	Tuple = f4(Field, Field, 5).

p4b(Tuple, Field1, Field2) :-
	Tuple = f4(Field1, Field2, 5).




More information about the developers mailing list