diff: fix for bug with implied modes

Fergus Henderson fjh at hydra.cs.mu.oz.au
Tue Sep 16 07:10:45 AEST 1997


Estimated hours: 10

Fix a bug in the handling of implied modes.

compiler/modes.m:
	Change the representation of extra_goals from just a pair
	of lists of goals (goals to insert before & after the main
	goal, respectively) so that it includes an instmap, which
	is the instmap after the main goal.  This change is required
	because without it it was incorrectly computing the instmap
	delta for the main goal, if the after-goals list was non-empty.
	Also, delete the before-goals list, because it is not used
	and because getting the instmap deltas right for before-goals
	would be tricky.

compiler/modecheck_unify.m:
compiler/unique_modes.m:
compiler/modecheck_call.m:
	Various changes to use the new representation of extra_goals.

tests/hard_coded/Mmake:
tests/hard_coded/impossible_unify.m:
tests/hard_coded/impossible_unify.exp:
	Regression test for the above-mentioned bug.

cvs diff -N compiler/modecheck_call.m compiler/modecheck_unify.m compiler/modes.m compiler/unique_modes.m tests/hard_coded/Mmake tests/hard_coded/impossible_unify.exp tests/hard_coded/impossible_unify.m
Index: compiler/modecheck_call.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/modecheck_call.m,v
retrieving revision 1.15
diff -u -r1.15 modecheck_call.m
--- modecheck_call.m	1997/09/01 14:03:54	1.15
+++ modecheck_call.m	1997/09/15 18:36:32
@@ -25,13 +25,13 @@
 :- import_module term.
 
 :- pred modecheck_call_pred(pred_id, list(var), proc_id, list(var),
-				pair(list(hlds_goal)), mode_info, mode_info).
+				extra_goals, mode_info, mode_info).
 :- mode modecheck_call_pred(in, in, out, out, out,
 				mode_info_di, mode_info_uo) is det.
 
 :- pred modecheck_higher_order_call(pred_or_func, var, list(var),
 				list(type), list(mode), determinism, list(var),
-				pair(list(hlds_goal)), mode_info, mode_info).
+				extra_goals, mode_info, mode_info).
 :- mode modecheck_higher_order_call(in, in, in, out, out, out, out, out,
 				mode_info_di, mode_info_uo) is det.
 
@@ -151,7 +151,7 @@
 		Modes = [],
 		Det = erroneous,
 		Args = Args0,
-		ExtraGoals = [] - []
+		ExtraGoals = no_extra_goals
 	).
 
 modecheck_call_pred(PredId, ArgVars0, TheProcId, ArgVars, ExtraGoals,
@@ -179,7 +179,7 @@
 			ModeInfo0, ModeInfo),
 		invalid_proc_id(TheProcId),
 		ArgVars = ArgVars0,
-		ExtraGoals = [] - []
+		ExtraGoals = no_extra_goals
 	;
 		ProcIds = [ProcId],
 		\+ list__member(request(infer_modes), Markers)
@@ -234,13 +234,13 @@
 	).
 
 :- pred modecheck_call_pred_2(list(proc_id), pred_id, proc_table, list(var),
-			set(var), proc_id, list(var), pair(list(hlds_goal)),
+			set(var), proc_id, list(var), extra_goals,
 			mode_info, mode_info).
 :- mode modecheck_call_pred_2(in, in, in, in, in, out, out, out,
 			mode_info_di, mode_info_uo) is det.
 
 modecheck_call_pred_2([], PredId, _Procs, ArgVars, WaitingVars,
-			TheProcId, ArgVars, [] - [], ModeInfo0, ModeInfo) :-
+		TheProcId, ArgVars, no_extra_goals, ModeInfo0, ModeInfo) :-
 	%
 	% There were no matching modes.
 	% If we're inferring modes for this called predicate, then
Index: compiler/modecheck_unify.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/modecheck_unify.m,v
retrieving revision 1.22
diff -u -r1.22 modecheck_unify.m
--- modecheck_unify.m	1997/08/22 13:55:40	1.22
+++ modecheck_unify.m	1997/09/15 20:45:38
@@ -31,12 +31,22 @@
 			mode_info_di, mode_info_uo) is det.
 
 	% Work out what kind of unification a var-var unification is.
+
+
 :- pred categorize_unify_var_var(mode, mode, is_live, is_live, var, var,
 			determinism, unify_context, map(var, type), mode_info,
 			hlds_goal_expr, mode_info).
 :- mode categorize_unify_var_var(in, in, in, in, in, in, in, in, in,
 			mode_info_di, out, mode_info_uo) is det.
 
+	% Given a unification goal, which must be something that can be
+	% returned from categorize_unify_var_var (i.e.  a unification
+	% of two vars, a unification of a var and a functor, or a
+	% conjunction thereof), return a list of all the variables in the
+	% goal.
+:- pred unify_vars(hlds_goal_expr, list(var)).
+:- mode unify_vars(in, out) is det.
+
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
 
@@ -45,7 +55,7 @@
 :- import_module hlds_module, hlds_goal, hlds_pred, hlds_data, hlds_out.
 :- import_module mode_debug, mode_util, mode_info, modes, mode_errors.
 :- import_module inst_match, inst_util, unify_proc, code_util, unique_modes.
-:- import_module typecheck, modecheck_call, (inst).
+:- import_module typecheck, modecheck_call, (inst), quantification.
 :- import_module bool, list, std_util, int, map, set, require, varset.
 :- import_module string, assoc_list.
 
@@ -514,7 +524,7 @@
 			% return any old garbage
 		Unification = Unification0,
 		ArgVars = ArgVars0,
-		ExtraGoals = [] - []
+		ExtraGoals = no_extra_goals
 	;
 		abstractly_unify_inst_functor(LiveX, InstOfX, ConsId,
 			InstArgs, LiveArgs, real_unify, ModuleInfo0,
@@ -580,7 +590,7 @@
 			% return any old garbage
 		Unification = Unification0,
 		ArgVars = ArgVars0,
-		ExtraGoals = [] - []
+		ExtraGoals = no_extra_goals
 	),
 
 	%
@@ -620,7 +630,7 @@
 		%
 		(
 			HowToCheckGoal = check_unique_modes,
-			ExtraGoals \= [] - []
+			ExtraGoals \= no_extra_goals
 		->
 			error("unique_modes.m: re-modecheck of unification encountered complicated sub-unifies")
 		;
@@ -639,7 +649,7 @@
 	% into separate unifications by introducing fresh variables here.
 
 :- pred split_complicated_subunifies(unification, list(var),
-			unification, list(var), pair(list(hlds_goal)),
+			unification, list(var), extra_goals,
 			mode_info, mode_info).
 :- mode split_complicated_subunifies(in, in, out, out, out,
 			mode_info_di, mode_info_uo) is det.
@@ -664,16 +674,16 @@
 	;
 		{ Unification = Unification0 },
 		{ ArgVars = ArgVars0 },
-		{ ExtraGoals = [] - [] }
+		{ ExtraGoals = no_extra_goals }
 	).
 
 :- pred split_complicated_subunifies_2(list(var), list(uni_mode),
-			list(var), list(uni_mode), pair(list(hlds_goal)),
+			list(var), list(uni_mode), extra_goals,
 			mode_info, mode_info).
 :- mode split_complicated_subunifies_2(in, in, out, out, out,
-		mode_info_di, mode_info_uo) is semidet.
+			mode_info_di, mode_info_uo) is semidet.
 
-split_complicated_subunifies_2([], [], [], [], [] - []) --> [].
+split_complicated_subunifies_2([], [], [], [], no_extra_goals) --> [].
 split_complicated_subunifies_2([Var0 | Vars0], [UniMode0 | UniModes0],
 			Vars, UniModes, ExtraGoals, ModeInfo0, ModeInfo) :-
 	mode_info_get_module_info(ModeInfo0, ModuleInfo),
@@ -686,23 +696,22 @@
 		mode_to_arg_mode(ModuleInfo, ModeX, VarType, top_in),
 		mode_to_arg_mode(ModuleInfo, ModeY, VarType, top_in)
 	->
-		split_complicated_subunifies_2(Vars0, UniModes0,
-				Vars1, UniModes1, ExtraGoals0,
-				ModeInfo0, ModeInfo1),
-		ExtraGoals0 = BeforeGoals - AfterGoals0,
-
 		% introduce a new variable `Var'
-		mode_info_get_varset(ModeInfo1, VarSet1),
-		mode_info_get_var_types(ModeInfo1, VarTypes1),
-		varset__new_var(VarSet1, Var, VarSet),
-		map__set(VarTypes1, Var, VarType, VarTypes),
-		mode_info_set_varset(VarSet, ModeInfo1, ModeInfo2),
-		mode_info_set_var_types(VarTypes, ModeInfo2, ModeInfo3),
+		mode_info_get_varset(ModeInfo0, VarSet0),
+		mode_info_get_var_types(ModeInfo0, VarTypes0),
+		varset__new_var(VarSet0, Var, VarSet),
+		map__set(VarTypes0, Var, VarType, VarTypes),
+		mode_info_set_varset(VarSet, ModeInfo0, ModeInfo1),
+		mode_info_set_var_types(VarTypes, ModeInfo1, ModeInfo2),
 
 		% change the main unification to use `Var' instead of Var0
 		UniMode = (InitialInstX - free -> InitialInstX - InitialInstX),
-		UniModes = [UniMode | UniModes1],
-		Vars = [Var | Vars1],
+
+		% Compute the instmap that results after the main unification.
+		% We just need to set the inst of `Var'.
+		mode_info_get_instmap(ModeInfo2, OrigInstMap),
+		instmap__set(OrigInstMap, Var, InitialInstX, InstMapAfterMain),
+		mode_info_set_instmap(InstMapAfterMain, ModeInfo2, ModeInfo3),
 
 		% create code to do a unification between `Var' and `Var0'
 		ModeVar0 = (InitialInstY -> FinalInstY),
@@ -728,32 +737,43 @@
 						UnifyContext),
 		categorize_unify_var_var(ModeVar0, ModeVar,
 			live, dead, Var0, Var, Det, UnifyContext,
-			VarTypes, ModeInfo4, AfterGoal, ModeInfo),
+			VarTypes, ModeInfo4, NewUnifyGoal, ModeInfo5),
+		unify_vars(NewUnifyGoal, NewUnifyGoalVars),
 
 		% compute the goal_info nonlocal vars & instmap delta
 		% for the newly created goal
-		set__list_to_set([Var0, Var], NonLocals),
+		% N.B. This may overestimate the set of non-locals,
+		% but that shouldn't cause any problems.
+		set__list_to_set(NewUnifyGoalVars, NonLocals),
 		( InitialInstY = FinalInstY ->
-			InstMapAL0 = []
+			InstMapDeltaAL0 = []
 		;
-			InstMapAL0 = [Var0 - FinalInstY]
+			InstMapDeltaAL0 = [Var0 - FinalInstY]
 		),
-		InstMapAL = [Var - FinalInstX | InstMapAL0],
-		instmap_delta_from_assoc_list(InstMapAL, InstMapDelta),
+		InstMapDeltaAL = [Var - FinalInstX | InstMapDeltaAL0],
+		instmap_delta_from_assoc_list(InstMapDeltaAL, InstMapDelta),
 		goal_info_init(GoalInfo0),
-		goal_info_set_nonlocals(GoalInfo0, NonLocals,
-			GoalInfo1),
+		goal_info_set_nonlocals(GoalInfo0, NonLocals, GoalInfo1),
 		goal_info_set_instmap_delta(GoalInfo1, InstMapDelta, GoalInfo),
 
-		% insert the unification between `Var' and `Var0' at
-		% the start of the AfterGoals
-		AfterGoals = [AfterGoal - GoalInfo | AfterGoals0],
-		ExtraGoals = BeforeGoals - AfterGoals
+		% insert the new unification at
+		% the start of the extra goals
+		ExtraGoals0 = extra_goals(InstMapAfterMain,
+					[NewUnifyGoal - GoalInfo]),
+
+		% recursive call to handle the remaining variables...
+		split_complicated_subunifies_2(Vars0, UniModes0,
+				Vars1, UniModes1, ExtraGoals1,
+				ModeInfo5, ModeInfo),
+		Vars = [Var | Vars1],
+		UniModes = [UniMode | UniModes1],
+		append_extra_goals(ExtraGoals0, ExtraGoals1, ExtraGoals)
 	;
-		Vars = [Var0 | Vars1],
-		UniModes = [UniMode0 | UniModes1],
 		split_complicated_subunifies_2(Vars0, UniModes0,
-			Vars1, UniModes1, ExtraGoals, ModeInfo0, ModeInfo)
+				Vars1, UniModes1, ExtraGoals,
+				ModeInfo0, ModeInfo),
+		Vars = [Var0 | Vars1],
+		UniModes = [UniMode0 | UniModes1]
 	).
 
 %-----------------------------------------------------------------------------%
@@ -1083,6 +1103,36 @@
 	varset__new_var(VarSet0, Var, VarSet1),
 	map__det_insert(VarTypes0, Var, Type, VarTypes1),
 	make_fresh_vars(Types, VarSet1, VarTypes1, Vars, VarSet, VarTypes).
+
+%-----------------------------------------------------------------------------%
+
+	% Given a unification goal, which must be something that can be
+	% returned from categorize_unify_var_var (i.e. a unification
+	% of two vars, a unification of a var and a functor,
+	% an empty disjunction (fail), or a conjunction thereof),
+	% return a list of all the variables in the goal.
+unify_vars(Unify, UnifyVars) :-
+	( Unify = unify(LHS, RHS, _, _, _), RHS = var(RHS_Var) ->
+		UnifyVars = [LHS, RHS_Var]
+	; Unify = unify(LHS, RHS, _, _, _), RHS = functor(_, RHS_ArgVars) ->
+		UnifyVars = [LHS | RHS_ArgVars]
+	; Unify = conj(List) ->
+		unify_conj_vars(List, UnifyVars)
+	; Unify = disj([], _StoreMap) ->
+		UnifyVars = []
+	;
+		error("modecheck_unify: unify_vars")
+	).
+
+:- pred unify_conj_vars(list(hlds_goal), list(var)).
+:- mode unify_conj_vars(in, out) is det.
+
+unify_conj_vars([], []).
+unify_conj_vars([Goal | Goals], Vars) :-
+	quantification__goal_vars(Goal, Vars1Set),
+	set__to_sorted_list(Vars1Set, Vars1),
+	unify_conj_vars(Goals, Vars2),
+	list__append(Vars1, Vars2, Vars).
 
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
Index: compiler/modes.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/modes.m,v
retrieving revision 1.204
diff -u -r1.204 modes.m
--- modes.m	1997/09/01 14:04:09	1.204
+++ modes.m	1997/09/15 20:47:36
@@ -208,7 +208,7 @@
 :- mode modecheck_set_var_inst(in, in, mode_info_di, mode_info_uo) is det.
 
 :- pred modecheck_set_var_inst_list(list(var), list(inst), list(inst),
-					list(var), pair(list(hlds_goal)),
+					list(var), extra_goals,
 					mode_info, mode_info).
 :- mode modecheck_set_var_inst_list(in, in, in, out, out,
 					mode_info_di, mode_info_uo) is det.
@@ -239,10 +239,25 @@
 			mode_info, mode_info).
 :- mode modecheck_goal_expr(in, in, out, mode_info_di, mode_info_uo) is det.
 
+
+:- type extra_goals
+	--->	no_extra_goals
+	;	extra_goals(
+			instmap,		% instmap at end of main goal
+			list(hlds_goal)		% goals to append after
+						% the main goal
+		).
+
+	% append_extra_goals inserts adds some goals to the
+	% list of goals to insert before/after the main goal.
+	%
+:- pred append_extra_goals(extra_goals, extra_goals, extra_goals).
+:- mode append_extra_goals(in, in, out) is det.
+
 	% handle_extra_goals combines MainGoal and ExtraGoals into a single
 	% hlds_goal_expr.
 	%
-:- pred handle_extra_goals(hlds_goal_expr, pair(list(hlds_goal)),
+:- pred handle_extra_goals(hlds_goal_expr, extra_goals,
 		hlds_goal_info, list(var), list(var),
 		instmap, mode_info, hlds_goal_expr).
 :- mode handle_extra_goals(in, in, in, in, in, in, mode_info_ui, out)
@@ -826,12 +841,36 @@
 	set__delete_list(NonLocals0, LambdaVars, NonLocals),
 	set__to_sorted_list(NonLocals, Vars).
 
+append_extra_goals(no_extra_goals, ExtraGoals, ExtraGoals).
+append_extra_goals(extra_goals(InstMap, AfterGoals),
+		no_extra_goals, extra_goals(InstMap, AfterGoals)).
+append_extra_goals(extra_goals(InstMap0, AfterGoals0),
+			extra_goals(_InstMap1, AfterGoals1),
+			extra_goals(InstMap, AfterGoals)) :-
+	InstMap = InstMap0,
+	list__append(AfterGoals0, AfterGoals1, AfterGoals).
+
 handle_extra_goals(MainGoal, ExtraGoals, GoalInfo0, Args0, Args,
-		InstMap0, ModeInfo, Goal) :-
+		InstMapAtStart, _ModeInfo, Goal) :-
 	% did we introduced any extra variables (and code)?
-	( ExtraGoals = [] - [] ->
+	(
+		ExtraGoals = no_extra_goals,
 		Goal = MainGoal	% no
 	;
+		ExtraGoals = extra_goals(InstMapAfterMain, AfterGoals0),
+
+		%
+		% We need to be careful to update the delta-instmaps
+		% correctly, using the appropriate instmaps:
+		%
+		%		% InstMapAtStart is here
+		%	 main goal,
+		%		% InstMapAfterMain is here
+		%	 AfterGoals
+		%		% _InstMapAtEnd (= the instmap from _ModeInfo)
+		%		% is here, but as it happens we don't need it
+		%
+
 		% recompute the new set of non-local variables for the main goal
 		goal_info_get_nonlocals(GoalInfo0, NonLocals0),
 		set__list_to_set(Args0, OldArgVars),
@@ -842,18 +881,15 @@
 		goal_info_set_nonlocals(GoalInfo0, NonLocals, GoalInfo1),
 
 		% compute the instmap delta for the main goal
-		mode_info_get_instmap(ModeInfo, InstMap),
-		compute_instmap_delta(InstMap0, InstMap, NonLocals,
-			DeltaInstMap),
+		compute_instmap_delta(InstMapAtStart, InstMapAfterMain,
+			NonLocals, DeltaInstMap),
 		goal_info_set_instmap_delta(GoalInfo1, DeltaInstMap, GoalInfo),
 
 		% combine the main goal and the extra goals into a conjunction
 		Goal0 = MainGoal - GoalInfo,
-		ExtraGoals = BeforeGoals0 - AfterGoals0,
 		goal_info_get_context(GoalInfo0, Context),
-		handle_extra_goals_contexts(BeforeGoals0, Context, BeforeGoals),
 		handle_extra_goals_contexts(AfterGoals0, Context, AfterGoals),
-		list__append(BeforeGoals, [Goal0 | AfterGoals], GoalList),
+		GoalList = [Goal0 | AfterGoals],
 		Goal = conj(GoalList)
 	).
 
@@ -1127,7 +1163,7 @@
 modecheck_set_var_inst_list(Vars0, InitialInsts, FinalInsts, Vars, Goals) -->
 	(
 		modecheck_set_var_inst_list_2(Vars0, InitialInsts, FinalInsts,
-			Vars1, Goals1)
+			no_extra_goals, Vars1, Goals1)
 	->
 		{ Vars = Vars1, Goals = Goals1 }
 	;
@@ -1135,30 +1171,27 @@
 	).
 
 :- pred modecheck_set_var_inst_list_2(list(var), list(inst), list(inst),
-					list(var), pair(list(hlds_goal)),
+					extra_goals, list(var), extra_goals,
 					mode_info, mode_info).
-:- mode modecheck_set_var_inst_list_2(in, in, in, out, out,
+:- mode modecheck_set_var_inst_list_2(in, in, in, in, out, out,
 					mode_info_di, mode_info_uo) is semidet.
 
-modecheck_set_var_inst_list_2([], [], [], [], [] - []) --> [].
+modecheck_set_var_inst_list_2([], [], [], ExtraGoals, [], ExtraGoals) --> [].
 modecheck_set_var_inst_list_2([Var0 | Vars0], [InitialInst | InitialInsts],
-			[FinalInst | FinalInsts], [Var | Vars], Goals) -->
+			[FinalInst | FinalInsts], ExtraGoals0,
+			[Var | Vars], ExtraGoals) -->
 	modecheck_set_var_inst(Var0, InitialInst, FinalInst,
-				Var, BeforeGoals0 - AfterGoals0),
+				Var, ExtraGoals0, ExtraGoals1),
 	modecheck_set_var_inst_list_2(Vars0, InitialInsts, FinalInsts,
-				Vars, BeforeGoals1 - AfterGoals1),
-	{ list__append(BeforeGoals0, BeforeGoals1, BeforeGoals) },
-	{ list__append(AfterGoals0, AfterGoals1, AfterGoals) },
-	{ Goals = BeforeGoals - AfterGoals }.
-
-% XXX this might need to be revisited to handle unique modes
+				ExtraGoals1, Vars, ExtraGoals).
 
-:- pred modecheck_set_var_inst(var, inst, inst, var, pair(list(hlds_goal)),
+:- pred modecheck_set_var_inst(var, inst, inst, var, extra_goals, extra_goals,
 				mode_info, mode_info).
-:- mode modecheck_set_var_inst(in, in, in, out, out,
+:- mode modecheck_set_var_inst(in, in, in, out, in, out,
 				mode_info_di, mode_info_uo) is det.
 
-modecheck_set_var_inst(Var0, InitialInst, FinalInst, Var, Goals,
+modecheck_set_var_inst(Var0, InitialInst, FinalInst, Var,
+			ExtraGoals0, ExtraGoals,
 			ModeInfo0, ModeInfo) :-
 	mode_info_get_instmap(ModeInfo0, InstMap0),
 	( instmap__is_reachable(InstMap0) ->
@@ -1180,12 +1213,12 @@
 		mode_info_set_module_info(ModeInfo0, ModuleInfo, ModeInfo1),
 		handle_implied_mode(Var0,
 			VarInst0, VarInst, InitialInst, FinalInst, Det,
-		 	Var, Goals, ModeInfo1, ModeInfo2),
+		 	Var, ExtraGoals0, ExtraGoals, ModeInfo1, ModeInfo2),
 		modecheck_set_var_inst(Var0, FinalInst, ModeInfo2, ModeInfo3),
 		modecheck_set_var_inst(Var, FinalInst, ModeInfo3, ModeInfo)
 	;
 		Var = Var0,
-		Goals = [] - [],
+		ExtraGoals = ExtraGoals0,
 		ModeInfo = ModeInfo0
 	).
 
@@ -1194,8 +1227,6 @@
 	% The former is used for predicate calls, where we may need
 	% to introduce unifications to handle calls to implied modes.
 
-% XXX this might need to be revisited to handle unique modes
-
 modecheck_set_var_inst(Var0, FinalInst, ModeInfo0, ModeInfo) :-
 	mode_info_get_instmap(ModeInfo0, InstMap0),
 	( instmap__is_reachable(InstMap0) ->
@@ -1269,13 +1300,13 @@
 % introduce a fresh variable.
 
 :- pred handle_implied_mode(var, inst, inst, inst, inst, determinism,
-				var, pair(list(hlds_goal)),
+				var, extra_goals, extra_goals,
 				mode_info, mode_info).
-:- mode handle_implied_mode(in, in, in, in, in, in, out, out,
+:- mode handle_implied_mode(in, in, in, in, in, in, out, in, out,
 				mode_info_di, mode_info_uo) is det.
 
 handle_implied_mode(Var0, VarInst0, VarInst, InitialInst, FinalInst, Det,
-		Var, Goals, ModeInfo0, ModeInfo) :-
+		Var, ExtraGoals0, ExtraGoals, ModeInfo0, ModeInfo) :-
 	mode_info_get_module_info(ModeInfo0, ModuleInfo0),
 	(
 		% If the initial inst of the variable matches_final
@@ -1285,7 +1316,7 @@
 		inst_matches_final(VarInst0, InitialInst, ModuleInfo0)
 	->
 		Var = Var0,
-		Goals = [] - [],
+		ExtraGoals = ExtraGoals0,
 		ModeInfo = ModeInfo0
 	;
 		% This is the implied mode case.
@@ -1296,7 +1327,7 @@
 		( inst_is_bound(ModuleInfo0, InitialInst) ->
 			% This is the case we can't handle
 			Var = Var0,
-			Goals = [] - [],
+			ExtraGoals = ExtraGoals0,
 			set__singleton_set(WaitingVars, Var0),
 			mode_info_error(WaitingVars,
 				mode_error_implied_mode(Var0, VarInst0,
@@ -1316,34 +1347,52 @@
 			mode_info_set_varset(VarSet, ModeInfo0, ModeInfo1),
 			mode_info_set_var_types(VarTypes, ModeInfo1, ModeInfo2),
 
+			% Calculate the instmap after the main goal.
+			% We just need to set the inst of the newly
+			% introduced variable Var to the procedure
+			% argument's final inst.
+			mode_info_get_instmap(ModeInfo2, OrigInstMap),
+			instmap__set(OrigInstMap, Var, FinalInst,
+				InstMapAfterMain),
+			mode_info_set_instmap(InstMapAfterMain,
+				ModeInfo2, ModeInfo3),
+
 			% Construct the code to do the unification
 			ModeVar0 = (VarInst0 -> VarInst),
 			ModeVar = (FinalInst -> VarInst),
-			mode_info_get_mode_context(ModeInfo2, ModeContext),
-			mode_context_to_unify_context(ModeContext, ModeInfo2,
+			mode_info_get_mode_context(ModeInfo3, ModeContext),
+			mode_context_to_unify_context(ModeContext, ModeInfo3,
 				UnifyContext),
+
 			categorize_unify_var_var(ModeVar0, ModeVar,
 				live, dead, Var0, Var, Det, UnifyContext,
-				VarTypes, ModeInfo2,
-				AfterGoal, ModeInfo),
+				VarTypes, ModeInfo3, NewUnifyGoal, ModeInfo),
+			unify_vars(NewUnifyGoal, NewUnifyGoalVars),
 
 			% compute the goal_info nonlocal vars & instmap delta
-			set__list_to_set([Var0, Var], NonLocals),
+			% N.B.  This may overestimate the set of nonlocal vars,
+			% but that should not cause any problems.
+			set__list_to_set(NewUnifyGoalVars, NonLocals),
 			( VarInst = VarInst0 ->
 				InstMapDeltaAL0 = []
 			;
 				InstMapDeltaAL0 = [Var0 - VarInst]
 			),
-			
 			InstMapDeltaAL = [Var - VarInst | InstMapDeltaAL0],
+			instmap_delta_from_assoc_list(InstMapDeltaAL,
+				InstMapDelta),
 			goal_info_init(GoalInfo0),
 			goal_info_set_nonlocals(GoalInfo0, NonLocals,
 				GoalInfo1),
-			instmap_delta_from_assoc_list(InstMapDeltaAL,
-				InstMapDelta),
 			goal_info_set_instmap_delta(GoalInfo1, InstMapDelta,
 				GoalInfo),
-			Goals = [] - [AfterGoal - GoalInfo]
+
+			% append the goals together in the appropriate order:
+			% ExtraGoals0, then NewUnify
+			NewUnifyExtraGoal = extra_goals(InstMapAfterMain,
+						[NewUnifyGoal - GoalInfo]),
+			append_extra_goals(ExtraGoals0, NewUnifyExtraGoal,
+				ExtraGoals)
 		)
 	).
 
Index: compiler/unique_modes.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/unique_modes.m,v
retrieving revision 1.39
diff -u -r1.39 unique_modes.m
--- unique_modes.m	1997/09/01 14:05:35	1.39
+++ unique_modes.m	1997/09/15 18:36:32
@@ -20,6 +20,10 @@
 % called predicate (e.g. if a predicate is overloaded with both
 % `ui' and `in' modes)?
 
+% Variables can become nondet live in several places:
+% in negations, in the conditions of if-then-elses,
+% and in disjunctions, and at nondet calls.
+
 % XXX we currently make the conservative assumption that
 % any non-local variable in a disjunction or nondet call
 % is nondet-live - and stays nondet-live.
@@ -572,7 +576,7 @@
 	mode_list_get_final_insts(ProcArgModes, ModuleInfo, FinalInsts),
 	modecheck_set_var_inst_list(ArgVars, InitialInsts, FinalInsts,
 		NewArgVars, ExtraGoals, ModeInfo1, ModeInfo2),
-	( NewArgVars = ArgVars, ExtraGoals = [] - [] ->
+	( NewArgVars = ArgVars, ExtraGoals = no_extra_goals ->
 		true
 	;	
 		% this shouldn't happen, since modes.m should do
Index: tests/hard_coded/Mmake
===================================================================
RCS file: /home/staff/zs/imp/tests/hard_coded/Mmake,v
retrieving revision 1.56
diff -u -r1.56 Mmake
--- Mmake	1997/08/23 20:34:48	1.56
+++ Mmake	1997/09/15 20:57:30
@@ -39,6 +39,7 @@
 	ho_order \
 	ho_solns \
 	ho_univ_to_type \
+	impossible_unify \
 	name_mangling \
 	no_fully_strict \
 	no_inline \
Index: tests/hard_coded/impossible_unify.exp
===================================================================
RCS file: impossible_unify.exp
diff -N impossible_unify.exp
--- /dev/null	Tue Jan  1 15:00:00 1980
+++ impossible_unify.exp	Tue Sep 16 06:56:15 1997
@@ -0,0 +1 @@
+ok
Index: tests/hard_coded/impossible_unify.m
===================================================================
RCS file: impossible_unify.m
diff -N impossible_unify.m
--- /dev/null	Tue Jan  1 15:00:00 1980
+++ impossible_unify.m	Tue Sep 16 06:55:55 1997
@@ -0,0 +1,23 @@
+:- module impossible_unify.
+:- interface.
+
+:- import_module io.
+
+:- pred main(io__state::di, io__state::uo) is det.
+
+:- implementation.
+:- import_module bool.
+
+main -->
+	\+ { bar(42) },
+	print("ok"), nl.
+
+:- pred bar(int::in) is failure.
+
+:- pred foo(int, bool).
+:- mode foo(in, out(bound(no))) is det.
+
+foo(_, no).
+
+bar(X) :-
+	foo(X, yes).

-- 
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