[m-dev.] diff: more existential types bug fixes

Fergus Henderson fjh at cs.mu.OZ.AU
Wed Jun 16 01:52:48 AEST 1999


I've been labelling these with "diff:" rather than "for review:",
since I have been committing them (on a branch) as I go. 
But I've doubtless made some mistakes along the way, so
any review comments would certainly still be appreciated ;-)

With these changes, it bootstraps and passes all the tests.
So I hope to be able to merge this back onto the main branch fairly
soon.  But I expect this change to cause problems, so I will do a
bit more testing at different optimization levels and perhaps on
different architectures before I commit it on the main branch.

--------------------

Estimated hours taken: 7

Fix some more bugs that caused test case failures on the existential_types_2
branch.

----------

compiler/modes.m:
compiler/clause_to_proc.m:
	Don't copy the clauses to the proc_info for typeclass methods.
	Their proc_infos are generated already mode-correct, but their
	clauses_info is not valid, so copying the clauses to the proc_info
	would give incorrect results.
	(This bug caused failures on any test case with both mode inference
	and type classes, e.g. tests/hard_coded/typeclasses/inference_test)

----------

compiler/mercury_compile.m:
	If we get any type errors, then stop after purity checking,
	rather than going on and running polymorphism and mode checking.
	This is necessary because polymorphism currently gets lots of
	internal errors if you try to run it on type-incorrect code.
	(This bug caused failures on lots of cases in tests/invalid.)

tests/invalid/errors2.err_exp2:
tests/invalid/prog_io_erroneous.err_exp2:
tests/invalid/type_inf_loop.err_exp2:
tests/invalid/types.err_exp2:
	Add alternative expected outputs for these test cases --
	the difference from the .err_exp files is that these ones
	only include the type errors, not the mode errors.

----------

compiler/modecheck_unify.m:
compiler/mode_errors.m:
	Check for polymorphically-typed unifications in modes other
	than (in, in).
	(This bug caused tests/invalid/polymorphic_unification to fail.)

tests/invalid/polymorphic_unification.err_exp:
	Update the expected output for this test case --
	we now issue a mode error, rather than giving a
	"Software Error: sorry, not implemented" message.

tests/invalid/Mmakefile:
	Delete some special-case code for polymorphic_unification.m,
	since it is no longer needed.

----------

compiler/simplify.m:
	Disable the warning about det goals with no outputs,
	since it produces too many spurious warnings.

tests/warnings/simple_code.exp:
	Update the expected warnings for this test case:
	unfortunately we no longer warn about three of the
	dubious goals in this test case.

----------

compiler/table_gen.m:
	Fix a bug in my previous change: it was inserting type_infos
	even for some non-polymorphic calls, e.g. to table_lookup_insert_int.
	(This caused tests/tabling/fib.m to fail.)

----------

tests/debugger/queens.exp:
	Update the expected output for this test case --
	some of the variable numbers had changed,
	due to polymorphism being run before mode checking.

Workspace: /home/mercury0/fjh/mercury-other
Index: compiler/clause_to_proc.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/clause_to_proc.m,v
retrieving revision 1.24.2.1
diff -u -r1.24.2.1 clause_to_proc.m
--- clause_to_proc.m	1999/06/10 16:10:09	1.24.2.1
+++ clause_to_proc.m	1999/06/15 10:46:01
@@ -107,8 +107,17 @@
 copy_module_clauses_to_procs_2([], Preds, Preds).
 copy_module_clauses_to_procs_2([PredId | PredIds], Preds0, Preds) :-
 	map__lookup(Preds0, PredId, PredInfo0),
-	copy_clauses_to_procs(PredInfo0, PredInfo),
-	map__det_update(Preds0, PredId, PredInfo, Preds1),
+	(
+		% don't process typeclass methods, because their proc_infos
+		% are generated already mode-correct
+		pred_info_get_markers(PredInfo0, PredMarkers),
+		check_marker(PredMarkers, class_method)
+	->
+		Preds1 = Preds0
+	;
+		copy_clauses_to_procs(PredInfo0, PredInfo),
+		map__det_update(Preds0, PredId, PredInfo, Preds1)
+	),
 	copy_module_clauses_to_procs_2(PredIds, Preds1, Preds).
 
 
Index: compiler/mercury_compile.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/mercury_compile.m,v
retrieving revision 1.128.2.2
diff -u -r1.128.2.2 mercury_compile.m
--- mercury_compile.m	1999/06/12 00:50:33	1.128.2.2
+++ mercury_compile.m	1999/06/15 10:07:37
@@ -713,7 +713,17 @@
 		    { HLDS = HLDS4 },
 		    { bool__or(FoundTypeError, FoundTypeclassError,
 		    	FoundError) }
-	        ;
+	        ; { FoundTypeError = yes } ->
+		    %
+		    % XXX it would be nice if we could go on and mode-check
+		    % the predicates which didn't have type errors, but
+		    % we need to run polymorphism before running mode
+		    % analysis, and currently polymorphism may get internal
+		    % errors if any of the predicates are not type-correct.
+		    %
+		    { HLDS = HLDS4 },
+		    { FoundError = yes }
+		;
 		    % only write out the `.opt' file if there are no type errors
 		    % or undefined modes
 		    ( { FoundTypeError = no, FoundUndefModeError = no } ->
Index: compiler/mode_errors.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/mode_errors.m,v
retrieving revision 1.62.2.1
diff -u -r1.62.2.1 mode_errors.m
--- mode_errors.m	1999/06/13 08:57:17	1.62.2.1
+++ mode_errors.m	1999/06/15 09:40:35
@@ -50,6 +50,9 @@
 			% the predicate variable in a higher-order predicate
 			% or function call didn't have a higher-order
 			% predicate or function inst of the appropriate arity
+	;	mode_error_poly_unify(prog_var, inst)
+			% A variable in a polymorphic unification with unknown
+			% type has inst other than `ground' or `any'.
 	;	mode_error_var_is_live(prog_var)
 			% call to a predicate which will clobber its argument,
 			% but the argument is still live
@@ -189,6 +192,8 @@
 		Arity), ModeInfo) -->
 	report_mode_error_higher_order_pred_var(ModeInfo, PredOrFunc, Var,
 		Inst, Arity).
+report_mode_error(mode_error_poly_unify(Var, Inst), ModeInfo) -->
+	report_mode_error_poly_unify(ModeInfo, Var, Inst).
 report_mode_error(mode_error_var_is_live(Var), ModeInfo) -->
 	report_mode_error_var_is_live(ModeInfo, Var).
 report_mode_error(mode_error_var_has_inst(Var, InstA, InstB), ModeInfo) -->
@@ -540,6 +545,37 @@
 		io__write_int(Arity1)
 	),
 	io__write_string(").\n").
+
+:- pred report_mode_error_poly_unify(mode_info, prog_var, inst,
+					io__state, io__state).
+:- mode report_mode_error_poly_unify(mode_info_ui, in, in, di, uo) is det.
+
+report_mode_error_poly_unify(ModeInfo, Var, VarInst) -->
+	{ mode_info_get_context(ModeInfo, Context) },
+	{ mode_info_get_varset(ModeInfo, VarSet) },
+	{ mode_info_get_instvarset(ModeInfo, InstVarSet) },
+	mode_info_write_context(ModeInfo),
+	prog_out__write_context(Context),
+	io__write_string("  in polymorphically-typed unification:\n"),
+	prog_out__write_context(Context),
+	io__write_string("  mode error: variable `"),
+	mercury_output_var(Var, VarSet, no),
+	io__write_string("' has instantiatedness `"),
+	output_inst(VarInst, InstVarSet),
+	io__write_string("',\n"),
+	prog_out__write_context(Context),
+	io__write_string(
+		"  expected instantiatedness was `ground' or `any'.\n"),
+	globals__io_lookup_bool_option(verbose_errors, VerboseErrors),
+	( { VerboseErrors = yes } ->
+		io__write_string(
+"\tWhen unifying two variables whose type will not be known until
+\truntime, the variables must both be ground (or have inst `any').
+\tUnifications of polymorphically-typed variables with partially
+\tinstantiated modes are not allowed.\n")
+	;
+		[]
+	).
 
 :- pred report_mode_error_var_is_live(mode_info, prog_var,
 		io__state, io__state).
Index: compiler/modecheck_unify.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/modecheck_unify.m,v
retrieving revision 1.37.2.2
diff -u -r1.37.2.2 modecheck_unify.m
--- modecheck_unify.m	1999/06/12 00:50:35	1.37.2.2
+++ modecheck_unify.m	1999/06/15 09:43:48
@@ -778,9 +778,9 @@
 	% Build up the unification
 	%
 	mode_info_get_module_info(ModeInfo0, ModuleInfo0),
-	mode_get_insts(ModuleInfo0, ModeOfX, IX, FX),
-	mode_get_insts(ModuleInfo0, ModeOfY, IY, FY),
-	UniMode = ((IX - IY) -> (FX - FY)),
+	mode_get_insts(ModuleInfo0, ModeOfX, InitialInstX, FinalInstX),
+	mode_get_insts(ModuleInfo0, ModeOfY, InitialInstY, FinalInstY),
+	UniMode = ((InitialInstX - InitialInstY) -> (FinalInstX - FinalInstY)),
 	determinism_components(Det, CanFail, _),
 	( Unification0 = complicated_unify(_, _, UnifyTypeInfoVars0) ->
 		UnifyTypeInfoVars = UnifyTypeInfoVars0
@@ -807,15 +807,41 @@
 			InitialArgNum, ModeInfo1, ModeInfo2)
 	),
 
-	%
-	% check that we're not trying to do a higher-order unification
-	%
+	mode_info_get_module_info(ModeInfo2, ModuleInfo2),
+
 	(
 		mode_info_get_errors(ModeInfo2, Errors),
 		Errors \= []
 	->
 		ModeInfo = ModeInfo2
 	;
+		%
+		% Check that we're not trying to do a polymorphic unification
+		% in a mode other than (in, in).
+		% [Actually we also allow `any' insts, since the (in, in)
+		% mode of unification for types which have `any' insts must
+		% also be able to handle (in(any), in(any)) unifications.]
+		%
+		Type = term__variable(_),
+		\+ inst_is_ground_or_any(ModuleInfo2, InitialInstX)
+	->
+		set__singleton_set(WaitingVars, X),
+		mode_info_error(WaitingVars,
+			mode_error_poly_unify(X, InitialInstX),
+			ModeInfo2, ModeInfo)
+	;
+		Type = term__variable(_),
+		\+ inst_is_ground_or_any(ModuleInfo2, InitialInstY)
+	->
+		set__singleton_set(WaitingVars, Y),
+		mode_info_error(WaitingVars,
+			mode_error_poly_unify(Y, InitialInstY),
+			ModeInfo2, ModeInfo)
+	;
+
+		%
+		% check that we're not trying to do a higher-order unification
+		%
 		type_is_higher_order(Type, PredOrFunc, _)
 	->
 		% We do not want to report this as an error
@@ -827,7 +853,7 @@
 		% error message would be spurious if the 
 		% instmap is unreachable.
 		mode_info_get_predid(ModeInfo2, PredId),
-		module_info_pred_info(ModuleInfo0, PredId,
+		module_info_pred_info(ModuleInfo2, PredId,
 				PredInfo),
 		mode_info_get_instmap(ModeInfo2, InstMap0),
 		( 
@@ -853,7 +879,7 @@
 	->
 		mode_info_get_context(ModeInfo2, Context),
 		unify_proc__request_unify(TypeId - UniMode,
-			Det, Context, ModuleInfo0, ModuleInfo),
+			Det, Context, ModuleInfo2, ModuleInfo),
 		mode_info_set_module_info(ModeInfo2, ModuleInfo,
 			ModeInfo)
 	;
Index: compiler/modes.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/modes.m,v
retrieving revision 1.230.2.3
diff -u -r1.230.2.3 modes.m
--- modes.m	1999/06/13 08:57:19	1.230.2.3
+++ modes.m	1999/06/15 15:42:44
@@ -466,14 +466,25 @@
 :- mode copy_pred_body(in, in, in, out) is det.
 copy_pred_body(OldPredTable, PredId, PredTable0, PredTable) :-
 	map__lookup(PredTable0, PredId, PredInfo0),
-	pred_info_procedures(PredInfo0, ProcTable0),
-	map__lookup(OldPredTable, PredId, OldPredInfo),
-	pred_info_procedures(OldPredInfo, OldProcTable),
-	map__keys(OldProcTable, OldProcIds),
-	list__foldl(copy_proc_body(OldProcTable), OldProcIds,
-		ProcTable0, ProcTable),
-	pred_info_set_procedures(PredInfo0, ProcTable, PredInfo),
-	map__set(PredTable0, PredId, PredInfo, PredTable).
+	(
+		% don't copy type class methods, because their
+		% proc_infos are generated already mode-correct,
+		% and because copying from the clauses_info doesn't
+		% work for them.
+		pred_info_get_markers(PredInfo0, Markers),
+		check_marker(Markers, class_method)
+	->
+		PredTable = PredTable0
+	;
+		pred_info_procedures(PredInfo0, ProcTable0),
+		map__lookup(OldPredTable, PredId, OldPredInfo),
+		pred_info_procedures(OldPredInfo, OldProcTable),
+		map__keys(OldProcTable, OldProcIds),
+		list__foldl(copy_proc_body(OldProcTable), OldProcIds,
+			ProcTable0, ProcTable),
+		pred_info_set_procedures(PredInfo0, ProcTable, PredInfo),
+		map__set(PredTable0, PredId, PredInfo, PredTable)
+	).
 
 % copy_proc_body(OldProcTable, ProcId, ProcTable0, ProcTable):
 %	copy the body of the specified ProcId from OldProcTable
@@ -510,7 +521,9 @@
 			)
 		;
 			%
-			% don't modecheck class methods
+			% don't modecheck class methods, because they
+			% are generated already mode-correct and with
+			% correct instmap deltas.
 			%
 			{ pred_info_get_markers(PredInfo0, PredMarkers) },
 			{ check_marker(PredMarkers, class_method) }
Index: compiler/simplify.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/simplify.m,v
retrieving revision 1.66.2.3
diff -u -r1.66.2.3 simplify.m
--- simplify.m	1999/06/13 08:57:22	1.66.2.3
+++ simplify.m	1999/06/15 12:30:08
@@ -366,7 +366,14 @@
 		; code_aux__goal_cannot_loop(ModuleInfo, Goal0)
 		)
 	->
-		% warn about this, if the goal wasn't `true'
+/******************
+The following warning is disabled, because it often results in spurious
+warnings.  Sometimes predicate calls are used just to constrain the types,
+to avoid type ambiguities or unbound type variables, and in such cases,
+it is perfectly legitimate for a call to be det and to have no outputs.
+There's no simple way of telling those cases from cases for which we
+really ought to warn.
+		% warn about this, if the goal wasn't `true', wasn't `!',
 		% and wasn't a deconstruction unification.
 		% We don't warn about deconstruction unifications
 		% with no outputs that always succeed, because that
@@ -377,11 +384,11 @@
 		% We also don't warn about conjunctions or existential
 		% quantifications, because it seems that warnings in those
 		% cases are usually spurious.
-		% XXX perhaps it would be best to just disable this entirely.
-		goal_info_get_context(GoalInfo0, Context),
 		(
 			simplify_do_warn(Info0),
 			% Goal0 \= conj([]) - _,
+			\+ (Goal0 = call(_, _, _, _, _, SymName) - _,
+			    unqualify_name(SymName, "!")),
 			Goal0 \= conj(_) - _,
 			Goal0 \= some(_, _) - _,
 			\+ (Goal0 = unify(_, _, _, Unification, _) - _,
@@ -392,6 +399,8 @@
 		;
 			Info1 = Info0
 		),
+******************/
+		Info0 = Info1,
 		
 		% If the goal had any non-locals we should requantify. 
 		goal_info_get_nonlocals(GoalInfo0, NonLocals0),
@@ -402,6 +411,7 @@
 		),
 		pd_cost__goal(Goal0, CostDelta),
 		simplify_info_incr_cost_delta(Info2, CostDelta, Info3),
+		goal_info_get_context(GoalInfo0, Context),
 		true_goal(Context, Goal1)
 	;
 		Goal1 = Goal0,
Index: compiler/table_gen.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/table_gen.m,v
retrieving revision 1.7.2.1
diff -u -r1.7.2.1 table_gen.m
--- table_gen.m	1999/06/13 08:57:23	1.7.2.1
+++ table_gen.m	1999/06/15 11:37:31
@@ -789,6 +789,9 @@
 			error("gen_lookup: unexpected type")
 		)
 	;
+		generate_new_table_var("TableNodeVar", VarTypes0,
+			VarTypes1, VarSet0, VarSet1, NextTableVar),
+		InstMapAL = [NextTableVar - ground(unique, no)],
 		(
 			( TypeCat = pred_type
 			; TypeCat = polymorphic_type
@@ -799,27 +802,29 @@
 				LookupPredName = "table_lookup_insert_user"
 			;
 				LookupPredName = "table_lookup_insert_poly"
-			)
+			),
+			make_type_info_var(Type, TypeInfoVar, ExtraGoals,
+				VarTypes1, VarTypes, VarSet1, VarSet,
+				TableInfo0, TableInfo),
+
+			generate_call(LookupPredName,
+				[TypeInfoVar, TableVar, ArgVar, NextTableVar],
+				det, impure, InstMapAL, Module, CallGoal),
+
+			list__append(ExtraGoals, [CallGoal], ConjList),
+			CallGoal = _ - GoalInfo,
+			conj_list_to_goal(ConjList, GoalInfo, Goal)
 		;
 			builtin_type_to_string(TypeCat, CatString),
 			string__append("table_lookup_insert_", CatString,
-				LookupPredName)
-		),
-		generate_new_table_var("TableNodeVar", VarTypes0, VarTypes1,
-			VarSet0, VarSet1, NextTableVar),
-
-		make_type_info_var(Type, TypeInfoVar, ExtraGoals,
-			VarTypes1, VarTypes, VarSet1, VarSet,
-			TableInfo0, TableInfo),
-
-		InstMapAL = [NextTableVar - ground(unique, no)],
-		generate_call(LookupPredName,
-			[TypeInfoVar, TableVar, ArgVar, NextTableVar],
-			det, impure, InstMapAL, Module, CallGoal),
-
-		list__append(ExtraGoals, [CallGoal], ConjList),
-		CallGoal = _ - GoalInfo,
-		conj_list_to_goal(ConjList, GoalInfo, Goal)
+				LookupPredName),
+			generate_call(LookupPredName,
+				[TableVar, ArgVar, NextTableVar],
+				det, impure, InstMapAL, Module, Goal),
+			VarTypes = VarTypes1,
+			VarSet = VarSet1,
+			TableInfo = TableInfo0
+		)
 	).
 
 %-----------------------------------------------------------------------------%
Index: tests/debugger/queens.exp
===================================================================
RCS file: /home/mercury1/repository/tests/debugger/queens.exp,v
retrieving revision 1.11
diff -u -r1.11 queens.exp
--- queens.exp	1999/05/27 01:01:28	1.11
+++ queens.exp	1999/06/15 10:22:28
@@ -31,8 +31,8 @@
        8:      5  4 DISJ pred queens:qdelete/3-0 (nondet) c2;d1;
 mdb> print *
        HeadVar__2             	[1, 2, 3, 4, 5]
-       V_10                   	[2, 3, 4, 5]
-       V_11                   	1
+       V_11                   	[2, 3, 4, 5]
+       V_12                   	1
 mdb> level 1
    1       5       4    3 pred queens:qperm/2-0 (nondet) 
 Ancestor level set to 1.
@@ -69,8 +69,8 @@
       13:      7  5 DISJ pred queens:qdelete/3-0 (nondet) c2;d1;
 mdb> print *
        HeadVar__2             	[2, 3, 4, 5]
-       V_10                   	[3, 4, 5]
-       V_11                   	2
+       V_11                   	[3, 4, 5]
+       V_12                   	2
 mdb> 
       14:      7  5 EXIT pred queens:qdelete/3-0 (nondet) 
 mdb> print *
Index: tests/invalid/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/tests/invalid/Mmakefile,v
retrieving revision 1.40
diff -u -r1.40 Mmakefile
--- Mmakefile	1999/05/18 03:09:18	1.40
+++ Mmakefile	1999/06/15 11:14:53
@@ -94,13 +94,6 @@
 	if $(MC) $(ALL_MCFLAGS) --errorcheck-only $* > $*.err 2>&1; \
 	then false; else true; fi
 
-# We need a hard-coded rule for polymorphic_unification because we need to
-# do more than error check it: the error case we are checking for only
-# gets caught during polymorphism.
-polymorphic_unification.err: polymorphic_unification.m
-	if $(MC) $(ALL_MCFLAGS) polymorphic_unification > polymorphic_unification.err 2>&1; \
-	then false; else true; fi
-
 # Some tests have more than one possible valid output, so
 # we allow the test to pass if it matches *either* the .err_exp
 # or the .err_exp2 file. 
cvs diff: tests/invalid/errors2.err_exp2 is a new entry, no comparison available
Index: tests/invalid/polymorphic_unification.err_exp
===================================================================
RCS file: /home/mercury1/repository/tests/invalid/polymorphic_unification.err_exp,v
retrieving revision 1.2
diff -u -r1.2 polymorphic_unification.err_exp
--- polymorphic_unification.err_exp	1998/12/15 01:36:17	1.2
+++ polymorphic_unification.err_exp	1999/06/15 09:48:30
@@ -1,2 +1,6 @@
-Software error: polymorphic_unification.m:019: Sorry, not implemented: polymorphic unification in mode other than (in, in)
-Stack dump not available in this grade.
+polymorphic_unification.m:019: In clause for `p(in, ((list:list_skel) -> dead))':
+polymorphic_unification.m:019:   in argument 2 of clause head:
+polymorphic_unification.m:019:   in polymorphically-typed unification:
+polymorphic_unification.m:019:   mode error: variable `HeadVar__2' has instantiatedness `(list:list_skel)',
+polymorphic_unification.m:019:   expected instantiatedness was `ground' or `any'.
+For more information, try recompiling with `-E'.
cvs diff: tests/invalid/prog_io_erroneous.err_exp2 is a new entry, no comparison available
cvs diff: tests/invalid/type_inf_loop.err_exp2 is a new entry, no comparison available
cvs diff: tests/invalid/types.err_exp2 is a new entry, no comparison available
Index: tests/warnings/simple_code.exp
===================================================================
RCS file: /home/mercury1/repository/tests/warnings/simple_code.exp,v
retrieving revision 1.7.2.1
diff -u -r1.7.2.1 simple_code.exp
--- simple_code.exp	1999/06/13 05:38:04	1.7.2.1
+++ simple_code.exp	1999/06/15 12:37:48
@@ -6,8 +6,5 @@
 simple_code.m:025: Warning: the condition of this if-then-else cannot succeed.
 simple_code.m:030: Warning: the condition of this if-then-else cannot succeed.
 simple_code.m:033: Warning: the negated goal cannot succeed.
-simple_code.m:018: Warning: det goal has no outputs.
-simple_code.m:023: Warning: det goal has no outputs.
-simple_code.m:038: Warning: det goal has no outputs.
 simple_code.m:039: Warning: call to obsolete predicate `simple_code:obsolete/0'.
 simple_code.m:099: Warning: recursive call will lead to infinite recursion.

-- 
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.
--------------------------------------------------------------------------
mercury-developers mailing list
Post messages to:       mercury-developers at cs.mu.oz.au
Administrative Queries: owner-mercury-developers at cs.mu.oz.au
Subscriptions:          mercury-developers-request at cs.mu.oz.au
--------------------------------------------------------------------------



More information about the developers mailing list