diff: warning for unbound type variables

Fergus Henderson fjh at cs.mu.oz.au
Tue Apr 29 20:53:02 AEST 1997


Make the typechecker warn about unbound type variables.
(We might eventually upgrade this warning into an error.)

compiler/typecheck.m:
	Put back the old code to check for unbound type variables,
	as a warning rather than an error, after fixing some code
	rot and improving the message it prints out.

tests/warnings/singleton_test.m:
tests/warnings/singleton_test.exp:
tests/warnings/pragma_source_file.m:
tests/warnings/pragma_source_file.exp:
	Eliminate a few cases where deliberately incorrect code
	written to trigger singleton variable warnings also
	triggered the above-mentioned unresolved polymorphism
	warning.  I left one case in, to test the new warning.

Index: typecheck.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/typecheck.m,v
retrieving revision 1.199
diff -u -r1.199 typecheck.m
--- typecheck.m	1997/04/22 03:13:04	1.199
+++ typecheck.m	1997/04/26 11:14:41
@@ -169,7 +169,7 @@
 :- import_module mercury_to_mercury, mode_util, options, getopt, globals.
 :- import_module passes_aux, clause_to_proc.
 
-:- import_module int, list, map, string, require, std_util, tree234.
+:- import_module int, list, map, set, string, require, std_util, tree234.
 :- import_module varset, term, term_io.
 
 %-----------------------------------------------------------------------------%
@@ -482,7 +482,8 @@
 	% then we issue an error message here.
 
 	%
-	% If stuff-to-check = whole_pred, report an error for any ambiguity.
+	% If stuff-to-check = whole_pred, report an error for any ambiguity,
+	% and also check for unbound type variables.
 	% But if stuff-to-check = clause_only(HeadVars), then only report
 	% errors for type ambiguities that don't involve the head vars,
 	% because we may be able to resolve a type ambiguity for a head var
@@ -501,8 +502,17 @@
 
 typecheck_check_for_ambiguity(StuffToCheck, TypeCheckInfo0, TypeCheckInfo) :-
 	typecheck_info_get_type_assign_set(TypeCheckInfo0, TypeAssignSet),
-	( TypeAssignSet = [_TypeAssign] ->
-		TypeCheckInfo = TypeCheckInfo0
+	( TypeAssignSet = [TypeAssign] ->
+		typecheck_info_get_found_error(TypeCheckInfo0, FoundError),
+		(
+			StuffToCheck = whole_pred,
+			FoundError = no
+		->
+			check_type_bindings(TypeAssign,
+				TypeCheckInfo0, TypeCheckInfo)
+		;
+			TypeCheckInfo = TypeCheckInfo0
+		)
 	; TypeAssignSet = [TypeAssign1, TypeAssign2 | _] ->
 		%
 		% we only report an ambiguity error if
@@ -561,10 +571,6 @@
 		TypeCheckInfo = TypeCheckInfo0
 	).
 
-/************************ BEGIN JUNK
-This section is commented out, since the error which it attempts
-to detect is in fact not an error at all!
-
 	% Check that the all of the types which have been inferred
 	% for the variables in the clause do not contain any unbound type
 	% variables other than the HeadTypeParams.
@@ -575,91 +581,104 @@
 check_type_bindings(TypeAssign, TypeCheckInfo0, TypeCheckInfo) :-
 	typecheck_info_get_head_type_params(TypeCheckInfo0, HeadTypeParams),
 	type_assign_get_type_bindings(TypeAssign, TypeBindings),
-	type_assign_get_var_types(TypeAssign, VarTypes),
-	map__values(VarTypes, Types),
+	type_assign_get_var_types(TypeAssign, VarTypesMap),
+	map__to_assoc_list(VarTypesMap, VarTypesList),
 	set__init(Set0),
-	check_type_bindings_2(Types, TypeBindings, HeadTypeParams, Set0, Set),
-	set__to_sorted_list(Set, ErrorVars),
-	( ErrorVars = [] ->
+	check_type_bindings_2(VarTypesList, TypeBindings, HeadTypeParams,
+		[], Errs, Set0, _Set),
+	% ... we could at this point bind all the type variables in `Set'
+	% to `void' ...
+	( Errs = [] ->
 		TypeCheckInfo = TypeCheckInfo0
 	;
 		type_assign_get_typevarset(TypeAssign, TVarSet),
-		report_unresolved_type_error(ErrorVars, TVarSet, TypeCheckInfo0,
-			TypeCheckInfo)
+		report_unresolved_type_error(Errs, TVarSet, TypeCheckInfo0,
+				TypeCheckInfo)
 	).
 
-:- pred check_type_bindings_2(list(term), tsubst, headtypes, set(var),
-				set(var)).
-:- mode check_type_bindings_2(in, in, in, in, out) is det.
-
-check_type_bindings_2([], _, _, Set, Set).
-check_type_bindings_2([Type0 | Types], TypeBindings, HeadTypeParams, Set0,
-			Set) :-
+:- pred check_type_bindings_2(assoc_list(var, (type)), tsubst, headtypes,
+			assoc_list(var, (type)), assoc_list(var, (type)),
+			set(tvar), set(tvar)).
+:- mode check_type_bindings_2(in, in, in, in, out, in, out) is det.
+
+check_type_bindings_2([], _, _, Errs, Errs, Set, Set).
+check_type_bindings_2([Var - Type0 | VarTypes], TypeBindings, HeadTypeParams,
+			Errs0, Errs, Set0, Set) :-
 	term__apply_rec_substitution(Type0, TypeBindings, Type),
 	term__vars(Type, TVars),
 	set__list_to_set(TVars, TVarsSet0),
-	set__remove_list(TVarsSet0, HeadTypeParams, TVarsSet1),
-	set__union(Set0, TVarsSet1, Set1),
-	check_type_bindings_2(Types, TypeBindings, HeadTypeParams, Set1, Set).
+	set__delete_list(TVarsSet0, HeadTypeParams, TVarsSet1),
+	( \+ set__empty(TVarsSet1) ->
+		Errs1 = [Var - Type | Errs0],
+		set__union(Set0, TVarsSet1, Set1)
+	;
+		Errs1 = Errs0,
+		Set0 = Set1
+	),
+	check_type_bindings_2(VarTypes, TypeBindings, HeadTypeParams,
+		Errs1, Errs, Set1, Set).
 
 	% report an error: uninstantiated type parameter
 
-:- pred report_unresolved_type_error(list(var), tvarset, typecheck_info, 
-				typecheck_info).
+:- pred report_unresolved_type_error(assoc_list(var, (type)), tvarset,
+				typecheck_info, typecheck_info).
 :- mode report_unresolved_type_error(in, in, typecheck_info_di, 
 				typecheck_info_uo) is det.
 
-report_unresolved_type_error(TVars, TVarSet, TypeCheckInfo0, TypeCheckInfo) :-
+report_unresolved_type_error(Errs, TVarSet, TypeCheckInfo0, TypeCheckInfo) :-
 	typecheck_info_get_io_state(TypeCheckInfo0, IOState0),
-	report_unresolved_type_error_2(TypeCheckInfo0, TVars, TVarSet,
+	report_unresolved_type_error_2(TypeCheckInfo0, Errs, TVarSet,
 		IOState0, IOState),
-	typecheck_info_set_io_state(TypeCheckInfo0, IOState, TypeCheckInfo1),
-	typecheck_info_set_found_error(TypeCheckInfo1, yes, TypeCheckInfo).
+	typecheck_info_set_io_state(TypeCheckInfo0, IOState, TypeCheckInfo).
+	% Currently it is just a warning, not an error.
+	% typecheck_info_set_found_error(TypeCheckInfo1, yes, TypeCheckInfo).
 
-:- pred report_unresolved_type_error_2(typecheck_info, list(var), tvarset,
-					io__state, io__state).
+:- pred report_unresolved_type_error_2(typecheck_info, assoc_list(var, (type)),
+					tvarset, io__state, io__state).
 :- mode report_unresolved_type_error_2(typecheck_info_no_io, in, in, di, uo) 
 					is det.
 
-report_unresolved_type_error_2(TypeCheckInfo, TVars, TVarSet) -->
+report_unresolved_type_error_2(TypeCheckInfo, Errs, TVarSet) -->
 	write_typecheck_info_context(TypeCheckInfo),
+	{ typecheck_info_get_varset(TypeCheckInfo, VarSet) },
 	{ typecheck_info_get_context(TypeCheckInfo, Context) },
-	io__write_string("  type error: unresolved polymorphism.\n"),
+	io__write_string("  warning: unresolved polymorphism.\n"),
 	prog_out__write_context(Context),
-	io__write_string("  Unbound type vars were: "),
-	write_type_var_list(TVars, TVarSet),
-	io__write_string(".\n"),
-	globals__io_lookup_option(verbose_errors, bool(VerboseErrors)),
+	( { Errs = [_] } ->
+		io__write_string("  The variable with an unbound type was:\n")
+	;
+		io__write_string("  The variables with unbound types were:\n")
+	),
+	write_type_var_list(Errs, Context, VarSet, TVarSet),
+	prog_out__write_context(Context),
+	io__write_string("  The unbound type variable(s) will be implicitly\n"),
+	prog_out__write_context(Context),
+	io__write_string("  bound to the builtin type `void'.\n"),
+	globals__io_lookup_bool_option(verbose_errors, VerboseErrors),
 	( { VerboseErrors = yes } ->
 		io__write_string("\tThe body of the clause contains a call to a polymorphic predicate,\n"),
 		io__write_string("\tbut I can't determine which version should be called,\n"),
 		io__write_string("\tbecause the type variables listed above didn't get bound.\n"),
 			% XXX improve error message
-		io__write_string("\t(I ought to tell you which call caused the error, but I'm afraid\n"),
+		io__write_string("\t(I ought to tell you which call caused the problem, but I'm afraid\n"),
 		io__write_string("\tyou'll have to work it out yourself.  My apologies.)\n")
 	;
 		[]
 	).
 
-:- pred write_type_var_list(list(var), varset, io__state, io__state).
-:- mode write_type_var_list(in, in, di, uo) is det.
+:- pred write_type_var_list(assoc_list(var, (type)), term__context,
+			varset, tvarset, io__state, io__state).
+:- mode write_type_var_list(in, in, in, in, di, uo) is det.
 
-write_type_var_list([], _) -->
-	io__write_string("<none>").
-write_type_var_list([V|Vs], VarSet) -->
-	mercury_output_var(V, VarSet),
-	write_type_var_list_2(Vs, VarSet).
-
-:- pred write_type_var_list_2(list(var), varset, io__state, io__state).
-:- mode write_type_var_list_2(in, in, di, uo) is det.
-
-write_type_var_list_2([], _) --> [].
-write_type_var_list_2([V|Vs], VarSet) -->
-	io__write_string(", "),
-	mercury_output_var(V, VarSet),
-	write_type_var_list_2(Vs, VarSet).
-
-END JUNK ***************************/
+write_type_var_list([], _, _, _) --> [].
+write_type_var_list([Var - Type | Rest], Context, VarSet, TVarSet) -->
+	prog_out__write_context(Context),
+	io__write_string("      "),
+	mercury_output_var(Var, VarSet, no),
+	io__write_string(" :: "),
+	mercury_output_term(Type, TVarSet, no),
+	io__write_string("\n"),
+	write_type_var_list(Rest, Context, VarSet, TVarSet).
 
 %-----------------------------------------------------------------------------%
 

cvs diff: Diffing .
Index: pragma_source_file.exp
===================================================================
RCS file: /home/staff/zs/imp/tests/warnings/pragma_source_file.exp,v
retrieving revision 1.3
diff -u -r1.3 pragma_source_file.exp
--- pragma_source_file.exp	1997/04/21 07:09:19	1.3
+++ pragma_source_file.exp	1997/04/27 14:50:06
@@ -1,4 +1,4 @@
 foo.m:002: In clause for predicate `pragma_source_file:my_append/3':
-foo.m:002:   warning: variables `L1, L2' occur only once in this scope.
+foo.m:002:   warning: variable `L2' occurs only once in this scope.
 foo.m:011: In clause for predicate `pragma_source_file:my_append/3':
-foo.m:011:   warning: variables `X, Y' occur only once in this scope.
+foo.m:011:   warning: variable `X' occurs only once in this scope.
Index: pragma_source_file.m
===================================================================
RCS file: /home/staff/zs/imp/tests/warnings/pragma_source_file.m,v
retrieving revision 1.2
diff -u -r1.2 pragma_source_file.m
--- pragma_source_file.m	1997/02/23 06:12:22	1.2
+++ pragma_source_file.m	1997/04/27 14:49:28
@@ -12,8 +12,8 @@
 #1
 my_append([], L, L) :-
 #2
-	L1 = L2.
+	L = L2.
 #10
 my_append([H | T], L, [H | NT]) :-
-	X = Y,
+	X = L,
 	my_append(T, L, NT).
Index: singleton_test.exp
===================================================================
RCS file: /home/staff/zs/imp/tests/warnings/singleton_test.exp,v
retrieving revision 1.3
diff -u -r1.3 singleton_test.exp
--- singleton_test.exp	1997/04/21 07:09:20	1.3
+++ singleton_test.exp	1997/04/27 14:50:17
@@ -1,5 +1,5 @@
 singleton_test.m:022: In clause for predicate `singleton_test:my_append/3':
-singleton_test.m:022:   warning: variables `L1, L2' occur only once in this scope.
+singleton_test.m:022:   warning: variable `L2' occurs only once in this scope.
 singleton_test.m:026: In clause for function `singleton_test:my_append_func/2':
 singleton_test.m:026:   warning: variables `L1, L2' occur only once in this scope.
 singleton_test.m:027: In clause for function `singleton_test:my_append_func/2':
@@ -10,3 +10,10 @@
 singleton_test.m:033:   warning: variable `X' does not occur in the C code.
 singleton_test.m:039: In `:- pragma c_code' for predicate `singleton_test:c_hello_world/3':
 singleton_test.m:039:   warning: variable `Msg' does not occur in the C code.
+singleton_test.m:027: In clause for function `singleton_test:my_append_func/2':
+singleton_test.m:027:   warning: unresolved polymorphism.
+singleton_test.m:027:   The variables with unbound types were:
+singleton_test.m:027:       L2 :: V_2
+singleton_test.m:027:       L1 :: V_2
+singleton_test.m:027:   The unbound type variable(s) will be implicitly
+singleton_test.m:027:   bound to the builtin type `void'.
Index: singleton_test.m
===================================================================
RCS file: /home/staff/zs/imp/tests/warnings/singleton_test.m,v
retrieving revision 1.3
diff -u -r1.3 singleton_test.m
--- singleton_test.m	1997/04/21 07:09:21	1.3
+++ singleton_test.m	1997/04/27 14:47:42
@@ -19,7 +19,7 @@
 :- implementation.
 
 my_append([], L, L) :-
-	L1 = L2.
+	L = L2.
 my_append([H | T], L, [H | NT]) :-
 	my_append(T, L, NT).
 
-- 
Fergus Henderson <fjh at cs.mu.oz.au>   |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>   |  of excellence is a lethal habit"
PGP: finger fjh at 128.250.37.3         |     -- the last words of T. S. Garp.



More information about the developers mailing list