[m-rev.] for review: fix bug with any insts in inst_merge

David Overton dmo at cs.mu.OZ.AU
Tue Sep 11 11:35:20 AEST 2001


Hi,

This is for Fergus to review when he gets a chance.

Estimated hours taken: 8
Branches: main

Fix a bug in inst_merge when merging a ground inst with a bound inst
containing 'any' insts.  Previously,

	inst_merge(ground, bound(f(..., any, ...)))

would return a result of 'any' which is not as accurate as we would
like (e.g. this problem occurs often in Mercury code generated by the
HAL compiler).  To improve this, we pass the type of the variable
being merged to inst_merge and when this situation arises we expand
'ground' to 'bound(<functors of type>)' and use this inst in the
merge.

An alternative to passing the types through inst_merge would be to
reinstate the use of 'typed_inst' and 'typed_ground' which are created
by (currently commented out) code in 'propagate_types_into_insts'.
However, this has previously been found to cause performance problems
since it greatly expands the size of all insts and instmaps in the
program.  The approach used here is the same as that adopted for
inst_matches_{initial,final} some time ago, where it does not appear
to have a noticeable performance impact on typical programs.

compiler/inst_util.m:
	Pass types through inst_merge and implement the changes to
	inst_merge(ground, bound(...)) described above.

compiler/inst_match.m:
compiler/instmap.m:
compiler/mode_util.m:
compiler/simplify.m:
	Pass types to calls to inst_merge.

compiler/inst_match.m:
compiler/type_util.m:
	Move 'maybe_get_cons_id_arg_types' and
	'maybe_get_higher_order_arg_types' from inst_match.m to
	type_util.m and export them.

compiler/mode_util.m:
	Export 'constructors_to_bound_insts'.

tests/valid/Mmakefile:
tests/valid/merge_ground_any.m :
	Add a regression test.

tests/invalid/Mmakefile:
tests/invalid/merge_ground_any.err_exp:
tests/invalid/merge_ground_any.m:
	Add a test to make sure the ground inst is expanded out to the
	full set of functors for the type.
Index: compiler/inst_match.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/inst_match.m,v
retrieving revision 1.46
diff -u -r1.46 inst_match.m
--- compiler/inst_match.m	13 Oct 2000 13:55:28 -0000	1.46
+++ compiler/inst_match.m	11 Sep 2001 00:25:08 -0000
@@ -344,7 +344,7 @@
 	bound_inst_list_is_ground(ListA, Info^module_info),
 	bound_inst_list_matches_uniq(ListA, UniqB, Info^module_info).
 inst_matches_initial_3(bound(UniqA, ListA),
-		ground(UniqB, constrained_inst_var(InstVarB)), _,
+		ground(UniqB, constrained_inst_var(InstVarB)), MaybeType,
 		Info0, Info) :-
 	unique_matches_initial(UniqA, UniqB),
 	ModuleInfo0 = Info0^module_info,
@@ -358,7 +358,8 @@
 	Live = dead,
 	abstractly_unify_inst(Live, bound(UniqA, ListA), ground(UniqB, none),
 		fake_unify, ModuleInfo0, Inst, _Det, ModuleInfo1),
-	update_inst_var_sub(InstVarB, Inst, ModuleInfo1, ModuleInfo, Sub0, Sub),
+	update_inst_var_sub(InstVarB, Inst, MaybeType, ModuleInfo1, ModuleInfo,
+		Sub0, Sub),
 	Info = (Info0^module_info := ModuleInfo)
 		^sub := Sub.
 inst_matches_initial_3(bound(Uniq, List), abstract_inst(_,_), _, Info, Info) :-
@@ -506,18 +507,19 @@
 	% Update the inst_var_sub that is computed by inst_matches_initial.
 	% The inst_var_sub records what inst should be substituted for each
 	% inst_var that occurs in the called procedure's argument modes.
-:- pred update_inst_var_sub(inst_var, inst, module_info, module_info,
-		maybe(inst_var_sub), maybe(inst_var_sub)).
-:- mode update_inst_var_sub(in, in, in, out, in, out) is semidet.
+:- pred update_inst_var_sub(inst_var, inst, maybe(type), module_info,
+		module_info, maybe(inst_var_sub), maybe(inst_var_sub)).
+:- mode update_inst_var_sub(in, in, in, in, out, in, out) is semidet.
 
-update_inst_var_sub(_, _, ModuleInfo, ModuleInfo, no, no).
-update_inst_var_sub(InstVar, InstA, ModuleInfo0, ModuleInfo,
+update_inst_var_sub(_, _, _, ModuleInfo, ModuleInfo, no, no).
+update_inst_var_sub(InstVar, InstA, MaybeType, ModuleInfo0, ModuleInfo,
 		yes(Sub0), yes(Sub)) :-
 	( map__search(Sub0, InstVar, InstB) ->
 		% If InstVar already has an inst associated with it,
 		% merge the old inst and the new inst.  Fail if this merge
 		% is not possible.
-		inst_merge(InstA, InstB, ModuleInfo0, Inst, ModuleInfo),
+		inst_merge(InstA, InstB, MaybeType, ModuleInfo0, Inst,
+			ModuleInfo),
 		map__det_update(Sub0, InstVar, Inst, Sub)
 	;
 		ModuleInfo = ModuleInfo0,
@@ -534,15 +536,15 @@
 
 ground_inst_info_matches_initial(_, none, _, _) --> [].
 ground_inst_info_matches_initial(higher_order(PredInstA),
-		higher_order(PredInstB), _, Type) -->
-	pred_inst_matches_initial(PredInstA, PredInstB, Type).
+		higher_order(PredInstB), _, MaybeType) -->
+	pred_inst_matches_initial(PredInstA, PredInstB, MaybeType).
 ground_inst_info_matches_initial(GroundInstInfoA,
-		constrained_inst_var(InstVarB), UniqB, _) -->
+		constrained_inst_var(InstVarB), UniqB, MaybeType) -->
 	{ Inst = ground(UniqB, GroundInstInfoA) },
 	ModuleInfo0 =^ module_info,
 	Sub0 =^ sub,
-	{ update_inst_var_sub(InstVarB, Inst, ModuleInfo0, ModuleInfo,
-		Sub0, Sub) },
+	{ update_inst_var_sub(InstVarB, Inst, MaybeType, ModuleInfo0,
+		ModuleInfo, Sub0, Sub) },
 	^module_info := ModuleInfo,
 	^sub := Sub.
 
@@ -719,56 +721,6 @@
 inst_list_matches_initial([X|Xs], [Y|Ys], [Type | Types]) -->
 	inst_matches_initial_2(X, Y, Type),
 	inst_list_matches_initial(Xs, Ys, Types).
-
-	% If possible, get the argument types for the cons_id.
-	% We need to pass in the arity rather than using the arity
-	% from the cons_id because the arity in the cons_id will not
-	% include any extra type_info arguments for existentially
-	% quantified types.
-:- pred maybe_get_cons_id_arg_types(module_info, maybe(type), cons_id,
-		arity, list(maybe(type))).
-:- mode maybe_get_cons_id_arg_types(in, in, in, in, out) is det.
-
-maybe_get_cons_id_arg_types(ModuleInfo, MaybeType, ConsId0, Arity, MaybeTypes)
-		:-
-	( ConsId0 = cons(SymName, _) ->
-		( SymName = qualified(_, Name) ->
-			% get_cons_id_non_existential_arg_types
-			% expects an unqualified cons_id.
-			ConsId = cons(unqualified(Name), Arity)
-		;
-			ConsId = ConsId0
-		),
-		(
-			MaybeType = yes(Type),
-
-			% XXX get_cons_id_non_existential_arg_types will fail
-			% for ConsIds with existentially typed arguments.
-			get_cons_id_non_existential_arg_types(ModuleInfo, Type,
-				ConsId, Types),
-			list__length(Types, Arity)
-		->
-			list__map(pred(T::in, yes(T)::out) is det, Types,
-				MaybeTypes)
-		;
-			list__duplicate(Arity, no, MaybeTypes)
-		)
-	;
-		MaybeTypes = []
-	).
-
-:- pred maybe_get_higher_order_arg_types(maybe(type), arity, list(maybe(type))).
-:- mode maybe_get_higher_order_arg_types(in, in, out) is det.
-
-maybe_get_higher_order_arg_types(MaybeType, Arity, MaybeTypes) :-
-	(
-		MaybeType = yes(Type),
-		type_is_higher_order(Type, _, _, Types)
-	->
-		list__map(pred(T::in, yes(T)::out) is det, Types, MaybeTypes)
-	;
-		list__duplicate(Arity, no, MaybeTypes)
-	).
 
 %-----------------------------------------------------------------------------%
 
Index: compiler/inst_util.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/inst_util.m,v
retrieving revision 1.16
diff -u -r1.16 inst_util.m
--- compiler/inst_util.m	30 Mar 2001 06:04:22 -0000	1.16
+++ compiler/inst_util.m	11 Sep 2001 00:25:08 -0000
@@ -42,7 +42,7 @@
 :- interface.
 
 :- import_module hlds_module, hlds_data, prog_data, (inst).
-:- import_module list.
+:- import_module list, std_util.
 
 :- pred abstractly_unify_inst(is_live, inst, inst, unify_is_real, module_info,
 				inst, determinism, module_info).
@@ -86,8 +86,8 @@
 
 %-----------------------------------------------------------------------------%
 
-:- pred inst_merge(inst, inst, module_info, inst, module_info).
-:- mode inst_merge(in, in, in, out, out) is semidet.
+:- pred inst_merge(inst, inst, maybe(type), module_info, inst, module_info).
+:- mode inst_merge(in, in, in, in, out, out) is semidet.
 
 	% inst_merge(InstA, InstB, InstC):
 	%       Combine the insts found in different arms of a
@@ -101,7 +101,7 @@
 %-----------------------------------------------------------------------------%
 
 :- implementation.
-:- import_module hlds_data, inst_match, mode_util, det_analysis.
+:- import_module hlds_data, inst_match, mode_util, det_analysis, type_util.
 :- import_module bool, std_util, require, map, list, set, int.
 
 	% Abstractly unify two insts.
@@ -1264,7 +1264,7 @@
 	%       InstB specify a binding (free or bound), it must be
 	%       the same in both.
 
-inst_merge(InstA, InstB, ModuleInfo0, Inst, ModuleInfo) :-
+inst_merge(InstA, InstB, MaybeType, ModuleInfo0, Inst, ModuleInfo) :-
 		% check whether this pair of insts is already in
 		% the merge_insts table
 	module_info_insts(ModuleInfo0, InstTable0),
@@ -1287,7 +1287,9 @@
 		module_info_set_insts(ModuleInfo0, InstTable1, ModuleInfo1),
 
 			% merge the insts
-		inst_merge_2(InstA, InstB, ModuleInfo1, Inst0, ModuleInfo2),
+		inst_merge_2(InstA, InstB, MaybeType, ModuleInfo1, Inst0,
+			ModuleInfo2),
+			
 
 			% now update the value associated with ThisInstPair
 		module_info_insts(ModuleInfo2, InstTable2),
@@ -1305,10 +1307,10 @@
 		Inst = Inst0
 	).
 
-:- pred inst_merge_2(inst, inst, module_info, inst, module_info).
-:- mode inst_merge_2(in, in, in, out, out) is semidet.
+:- pred inst_merge_2(inst, inst, maybe(type), module_info, inst, module_info).
+:- mode inst_merge_2(in, in, in, in, out, out) is semidet.
 
-inst_merge_2(InstA, InstB, ModuleInfo0, Inst, ModuleInfo) :-
+inst_merge_2(InstA, InstB, MaybeType, ModuleInfo0, Inst, ModuleInfo) :-
 /*********
 		% would this test improve efficiency??
 	( InstA = InstB ->
@@ -1322,11 +1324,12 @@
 		Inst = InstA2,
 		ModuleInfo = ModuleInfo0
 	;
-		inst_merge_3(InstA2, InstB2, ModuleInfo0, Inst, ModuleInfo)
+		inst_merge_3(InstA2, InstB2, MaybeType, ModuleInfo0, Inst,
+			ModuleInfo)
 	).
 
-:- pred inst_merge_3(inst, inst, module_info, inst, module_info).
-:- mode inst_merge_3(in, in, in, out, out) is semidet.
+:- pred inst_merge_3(inst, inst, maybe(type), module_info, inst, module_info).
+:- mode inst_merge_3(in, in, in, in, out, out) is semidet.
 
 % We do not yet allow merging of `free' and `any',
 % except in the case where the any is `mostly_clobbered_any'
@@ -1340,12 +1343,12 @@
 % too weak -- it might not be able to detect bugs as well
 % as it can currently.
 
-inst_merge_3(any(UniqA), any(UniqB), M, any(Uniq), M) :-
+inst_merge_3(any(UniqA), any(UniqB), _, M, any(Uniq), M) :-
 	merge_uniq(UniqA, UniqB, Uniq).
-inst_merge_3(any(Uniq), free, M, any(Uniq), M) :-
+inst_merge_3(any(Uniq), free, _, M, any(Uniq), M) :-
 	% we do not yet allow merge of any with free, except for clobbered anys
 	( Uniq = clobbered ; Uniq = mostly_clobbered ).
-inst_merge_3(any(UniqA), bound(UniqB, ListB), ModInfo, any(Uniq), ModInfo) :-
+inst_merge_3(any(UniqA), bound(UniqB, ListB), _, ModInfo, any(Uniq), ModInfo) :-
 	merge_uniq_bound(UniqA, UniqB, ListB, ModInfo, Uniq),
 	% we do not yet allow merge of any with free, except for clobbered anys
 	( ( Uniq = clobbered ; Uniq = mostly_clobbered ) ->
@@ -1353,16 +1356,16 @@
 	;
 		bound_inst_list_is_ground_or_any(ListB, ModInfo)
 	).
-inst_merge_3(any(UniqA), ground(UniqB, _), M, any(Uniq), M) :-
+inst_merge_3(any(UniqA), ground(UniqB, _), _, M, any(Uniq), M) :-
 	merge_uniq(UniqA, UniqB, Uniq).
-inst_merge_3(any(UniqA), abstract_inst(_, _), M, any(Uniq), M) :-
+inst_merge_3(any(UniqA), abstract_inst(_, _), _, M, any(Uniq), M) :-
 	merge_uniq(UniqA, shared, Uniq),
 	% we do not yet allow merge of any with free, except for clobbered anys
 	( Uniq = clobbered ; Uniq = mostly_clobbered ).
-inst_merge_3(free, any(Uniq), M, any(Uniq), M) :-
+inst_merge_3(free, any(Uniq), _, M, any(Uniq), M) :-
 	% we do not yet allow merge of any with free, except for clobbered anys
 	( Uniq = clobbered ; Uniq = mostly_clobbered ).
-inst_merge_3(bound(UniqA, ListA), any(UniqB), ModInfo, any(Uniq), ModInfo) :-
+inst_merge_3(bound(UniqA, ListA), any(UniqB), _, ModInfo, any(Uniq), ModInfo) :-
 	merge_uniq_bound(UniqB, UniqA, ListA, ModInfo, Uniq),
 	% we do not yet allow merge of any with free, except for clobbered anys
 	( ( Uniq = clobbered ; Uniq = mostly_clobbered ) ->
@@ -1370,37 +1373,28 @@
 	;
 		bound_inst_list_is_ground_or_any(ListA, ModInfo)
 	).
-inst_merge_3(ground(UniqA, _), any(UniqB), M, any(Uniq), M) :-
+inst_merge_3(ground(UniqA, _), any(UniqB), _, M, any(Uniq), M) :-
 	merge_uniq(UniqA, UniqB, Uniq).
-inst_merge_3(abstract_inst(_, _), any(UniqB), M, any(Uniq), M) :-
+inst_merge_3(abstract_inst(_, _), any(UniqB), _, M, any(Uniq), M) :-
 	merge_uniq(shared, UniqB, Uniq),
 	% we do not yet allow merge of any with free, except for clobbered anys
 	( Uniq = clobbered ; Uniq = mostly_clobbered ).
-inst_merge_3(free, free, M, free, M).
-inst_merge_3(bound(UniqA, ListA), bound(UniqB, ListB), ModuleInfo0,
+inst_merge_3(free, free, _, M, free, M).
+inst_merge_3(bound(UniqA, ListA), bound(UniqB, ListB), MaybeType, ModuleInfo0,
 		bound(Uniq, List), ModuleInfo) :-
 	merge_uniq(UniqA, UniqB, Uniq),
-	bound_inst_list_merge(ListA, ListB, ModuleInfo0, List, ModuleInfo).
-inst_merge_3(bound(UniqA, ListA), ground(UniqB, _), ModuleInfo,
+	bound_inst_list_merge(ListA, ListB, MaybeType, ModuleInfo0, List,
+		ModuleInfo).
+inst_merge_3(bound(UniqA, ListA), ground(UniqB, _), MaybeType, ModuleInfo0,
 		Result, ModuleInfo) :-
-	merge_uniq_bound(UniqB, UniqA, ListA, ModuleInfo, Uniq),
-	( bound_inst_list_is_ground(ListA, ModuleInfo) ->
-		Result = ground(Uniq, none)
-	;
-		bound_inst_list_is_ground_or_any(ListA, ModuleInfo),
-		Result = any(Uniq)
-	).
-inst_merge_3(ground(UniqA, _), bound(UniqB, ListB), ModuleInfo,
+	inst_merge_bound_ground(UniqA, ListA, UniqB, MaybeType,
+		ModuleInfo0, Result, ModuleInfo).
+inst_merge_3(ground(UniqA, _), bound(UniqB, ListB), MaybeType, ModuleInfo0,
 		Result, ModuleInfo) :-
-	merge_uniq_bound(UniqA, UniqB, ListB, ModuleInfo, Uniq),
-	( bound_inst_list_is_ground(ListB, ModuleInfo) ->
-		Result = ground(Uniq, none)
-	;
-		bound_inst_list_is_ground_or_any(ListB, ModuleInfo),
-		Result = any(Uniq)
-	).
+	inst_merge_bound_ground(UniqB, ListB, UniqA, MaybeType,
+		ModuleInfo0, Result, ModuleInfo).
 inst_merge_3(ground(UniqA, GroundInstInfoA), ground(UniqB, GroundInstInfoB),
-		ModuleInfo, ground(Uniq, GroundInstInfo), ModuleInfo) :-
+		_, ModuleInfo, ground(Uniq, GroundInstInfo), ModuleInfo) :-
 	(
 		GroundInstInfoA = higher_order(PredA),
 		GroundInstInfoB = higher_order(PredB)
@@ -1425,9 +1419,12 @@
 	),
 	merge_uniq(UniqA, UniqB, Uniq).
 inst_merge_3(abstract_inst(Name, ArgsA), abstract_inst(Name, ArgsB),
-		ModuleInfo0, abstract_inst(Name, Args), ModuleInfo) :-
-	inst_list_merge(ArgsA, ArgsB, ModuleInfo0, Args, ModuleInfo).
-inst_merge_3(not_reached, Inst, M, Inst, M).
+		_, ModuleInfo0, abstract_inst(Name, Args), ModuleInfo) :-
+	MaybeTypes = list__duplicate(list__length(ArgsA), no),
+		% We don't know the arguments types of an abstract inst.
+	inst_list_merge(ArgsA, ArgsB, MaybeTypes, ModuleInfo0, Args,
+		ModuleInfo).
+inst_merge_3(not_reached, Inst, _, M, Inst, M).
 
 :- pred merge_uniq(uniqueness, uniqueness, uniqueness).
 :- mode merge_uniq(in, in, out) is det.
@@ -1515,15 +1512,51 @@
 
 %-----------------------------------------------------------------------------%
 
-:- pred inst_list_merge(list(inst), list(inst), module_info, list(inst),
-			module_info).
-:- mode inst_list_merge(in, in, in, out, out) is semidet.
-
-inst_list_merge([], [], ModuleInfo, [], ModuleInfo).
-inst_list_merge([ArgA | ArgsA], [ArgB | ArgsB], ModuleInfo0,
-		[Arg | Args], ModuleInfo) :-
-	inst_merge(ArgA, ArgB, ModuleInfo0, Arg, ModuleInfo1),
-	inst_list_merge(ArgsA, ArgsB, ModuleInfo1, Args, ModuleInfo).
+:- pred inst_merge_bound_ground(uniqueness, list(bound_inst),
+		uniqueness, maybe(type), module_info, inst, module_info).
+:- mode inst_merge_bound_ground(in, in, in, in, in, out, out) is semidet.
+
+inst_merge_bound_ground(UniqA, ListA, UniqB, MaybeType, ModuleInfo0,
+		Result, ModuleInfo) :-
+	( bound_inst_list_is_ground(ListA, ModuleInfo0) ->
+		merge_uniq_bound(UniqB, UniqA, ListA, ModuleInfo0, Uniq),
+		Result = ground(Uniq, none),
+		ModuleInfo = ModuleInfo0
+	;
+		bound_inst_list_is_ground_or_any(ListA, ModuleInfo0),
+		% If we know the type, we can give a more accurate result than
+		% just "any".
+		(
+			MaybeType = yes(Type),
+			type_constructors(Type, ModuleInfo0, Constructors),
+			constructors_to_bound_insts(Constructors, UniqB,
+				ModuleInfo0, ListB0),
+			list__sort_and_remove_dups(ListB0, ListB),
+			inst_merge_3(bound(UniqA, ListA),
+				bound(UniqB, ListB), MaybeType,
+				ModuleInfo0, Result, ModuleInfo)
+		;
+			MaybeType = no,
+			merge_uniq_bound(UniqB, UniqA, ListA, ModuleInfo0,
+				Uniq),
+			Result = any(Uniq),
+			ModuleInfo = ModuleInfo0
+		)
+	).
+	
+
+%-----------------------------------------------------------------------------%
+
+:- pred inst_list_merge(list(inst), list(inst), list(maybe(type)), module_info,
+		list(inst), module_info).
+:- mode inst_list_merge(in, in, in, in, out, out) is semidet.
+
+inst_list_merge([], [], _, ModuleInfo, [], ModuleInfo).
+inst_list_merge([ArgA | ArgsA], [ArgB | ArgsB], [MaybeType | MaybeTypes],
+		ModuleInfo0, [Arg | Args], ModuleInfo) :-
+	inst_merge(ArgA, ArgB, MaybeType, ModuleInfo0, Arg, ModuleInfo1),
+	inst_list_merge(ArgsA, ArgsB, MaybeTypes, ModuleInfo1, Args,
+		ModuleInfo).
 
 	% bound_inst_list_merge(Xs, Ys, ModuleInfo0, Zs, ModuleInfo):
 	% The two input lists Xs and Ys must already be sorted.
@@ -1532,10 +1565,10 @@
 	% of the functors of the input lists Xs and Ys.
 
 :- pred bound_inst_list_merge(list(bound_inst), list(bound_inst),
-				module_info, list(bound_inst), module_info).
-:- mode bound_inst_list_merge(in, in, in, out, out) is semidet.
+		maybe(type), module_info, list(bound_inst), module_info).
+:- mode bound_inst_list_merge(in, in, in, in, out, out) is semidet.
 
-bound_inst_list_merge(Xs, Ys, ModuleInfo0, Zs, ModuleInfo) :-
+bound_inst_list_merge(Xs, Ys, MaybeType, ModuleInfo0, Zs, ModuleInfo) :-
 	( Xs = [] ->
 		Zs = Ys,
 		ModuleInfo = ModuleInfo0
@@ -1548,19 +1581,21 @@
 		X = functor(ConsIdX, ArgsX),
 		Y = functor(ConsIdY, ArgsY),
 		( ConsIdX = ConsIdY ->
-			inst_list_merge(ArgsX, ArgsY, ModuleInfo0,
+			maybe_get_cons_id_arg_types(ModuleInfo0, MaybeType,
+				ConsIdX, list__length(ArgsX), MaybeTypes),
+			inst_list_merge(ArgsX, ArgsY, MaybeTypes, ModuleInfo0,
 					Args, ModuleInfo1),
 			Z = functor(ConsIdX, Args),
 			Zs = [Z | Zs1],
-			bound_inst_list_merge(Xs1, Ys1, ModuleInfo1,
+			bound_inst_list_merge(Xs1, Ys1, MaybeType, ModuleInfo1,
 				Zs1, ModuleInfo)
 		; compare(<, ConsIdX, ConsIdY) ->
 			Zs = [X | Zs1],
-			bound_inst_list_merge(Xs1, Ys, ModuleInfo0,
+			bound_inst_list_merge(Xs1, Ys, MaybeType, ModuleInfo0,
 						Zs1, ModuleInfo)
 		;
 			Zs = [Y | Zs1],
-			bound_inst_list_merge(Xs, Ys1, ModuleInfo0,
+			bound_inst_list_merge(Xs, Ys1, MaybeType, ModuleInfo0,
 						Zs1, ModuleInfo)
 		)
 	).
Index: compiler/instmap.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/instmap.m,v
retrieving revision 1.27
diff -u -r1.27 instmap.m
--- compiler/instmap.m	13 Oct 2000 13:55:30 -0000	1.27
+++ compiler/instmap.m	11 Sep 2001 00:25:08 -0000
@@ -257,18 +257,18 @@
 	%	InstMapDeltaA, InstMapDeltaB, ModuleInfo0, ModuleInfo)
 	% Merge the instmap_deltas of different branches of an if-then-else,
 	% disj or switch.
-:- pred merge_instmap_delta(instmap, set(prog_var), instmap_delta,
+:- pred merge_instmap_delta(instmap, set(prog_var), vartypes, instmap_delta,
 		instmap_delta, instmap_delta, module_info, module_info).
-:- mode merge_instmap_delta(in, in, in, in, out, in, out) is det.
+:- mode merge_instmap_delta(in, in, in, in, in, out, in, out) is det.
 
 	% merge_instmap_deltas(Vars, InstMapDeltas,
 	%	MergedInstMapDelta, ModuleInfo0, ModuleInfo)
 	% takes a list of instmap deltas from the branches of an if-then-else,
 	% switch, or disj and merges them. This is used in situations
 	% where the bindings are known to be compatible.
-:- pred merge_instmap_deltas(instmap, set(prog_var), list(instmap_delta),
-		instmap_delta, module_info, module_info).
-:- mode merge_instmap_deltas(in, in, in, out, in, out) is det.
+:- pred merge_instmap_deltas(instmap, set(prog_var), vartypes,
+		list(instmap_delta), instmap_delta, module_info, module_info).
+:- mode merge_instmap_deltas(in, in, in, in, out, in, out) is det.
 
 	% unify_instmap_delta(InitialInstMap, NonLocals,
 	%	InstMapDeltaA, InstMapDeltaB, ModuleInfo0, ModuleInfo)
@@ -612,8 +612,10 @@
 		ModeInfo2 = ModeInfo0
 	; InstMap0 = reachable(InstMapping0) ->
 		set__to_sorted_list(NonLocals, NonLocalsList),
-		instmap__merge_2(NonLocalsList, InstMapList, ModuleInfo0,
-			InstMapping0, ModuleInfo, InstMapping, ErrorList),
+		mode_info_get_var_types(ModeInfo0, VarTypes),
+		instmap__merge_2(NonLocalsList, InstMapList, VarTypes,	
+			ModuleInfo0, InstMapping0, ModuleInfo, InstMapping,
+			ErrorList),
 		mode_info_set_module_info(ModeInfo0, ModuleInfo, ModeInfo1),
 		( ErrorList = [FirstError | _] ->
 			FirstError = Var - _,
@@ -651,18 +653,18 @@
 	%       there are two instmaps in `InstMaps' for which the inst
 	%       the variable is incompatible.
 
-:- pred instmap__merge_2(list(prog_var), list(instmap), module_info,
+:- pred instmap__merge_2(list(prog_var), list(instmap), vartypes, module_info,
 		map(prog_var, inst), module_info, map(prog_var, inst),
 		merge_errors).
-:- mode instmap__merge_2(in, in, in, in, out, out, out) is det.
+:- mode instmap__merge_2(in, in, in, in, in, out, out, out) is det.
 
-instmap__merge_2([], _, ModuleInfo, InstMap, ModuleInfo, InstMap, []).
-instmap__merge_2([Var|Vars], InstMapList, ModuleInfo0, InstMap0,
+instmap__merge_2([], _, _, ModuleInfo, InstMap, ModuleInfo, InstMap, []).
+instmap__merge_2([Var|Vars], InstMapList, VarTypes, ModuleInfo0, InstMap0,
 			ModuleInfo, InstMap, ErrorList) :-
-	instmap__merge_2(Vars, InstMapList, ModuleInfo0, InstMap0,
+	instmap__merge_2(Vars, InstMapList, VarTypes, ModuleInfo0, InstMap0,
 			ModuleInfo1, InstMap1, ErrorList1),
-	instmap__merge_var(InstMapList, Var, ModuleInfo1,
-			Insts, Inst, ModuleInfo, Error),
+	instmap__merge_var(InstMapList, Var, VarTypes ^ det_elem(Var),
+		ModuleInfo1, Insts, Inst, ModuleInfo, Error),
 	( Error = yes ->
 		ErrorList = [Var - Insts | ErrorList1],
 		map__set(InstMap1, Var, not_reached, InstMap)
@@ -677,18 +679,21 @@
 	%       there are two instmaps for which the inst of `Var'
 	%       is incompatible.
 
-:- pred instmap__merge_var(list(instmap), prog_var, module_info,
+:- pred instmap__merge_var(list(instmap), prog_var, (type), module_info,
 				list(inst), inst, module_info, bool).
-:- mode instmap__merge_var(in, in, in, out, out, out, out) is det.
+:- mode instmap__merge_var(in, in, in, in, out, out, out, out) is det.
 
-instmap__merge_var([], _, ModuleInfo, [], not_reached, ModuleInfo, no).
-instmap__merge_var([InstMap | InstMaps], Var, ModuleInfo0,
+instmap__merge_var([], _, _, ModuleInfo, [], not_reached, ModuleInfo, no).
+instmap__merge_var([InstMap | InstMaps], Var, Type, ModuleInfo0,
 		InstList, Inst, ModuleInfo, Error) :-
-	instmap__merge_var(InstMaps, Var, ModuleInfo0,
+	instmap__merge_var(InstMaps, Var, Type, ModuleInfo0,
 		InstList0, Inst0, ModuleInfo1, Error0),
 	instmap__lookup_var(InstMap, Var, VarInst),
 	InstList = [VarInst | InstList0],
-	( inst_merge(Inst0, VarInst, ModuleInfo1, Inst1, ModuleInfo2) ->
+	(
+		inst_merge(Inst0, VarInst, yes(Type), ModuleInfo1, Inst1,
+			ModuleInfo2)
+	->
 		Inst = Inst1,
 		ModuleInfo = ModuleInfo2,
 		Error = Error0
@@ -700,28 +705,28 @@
 
 %-----------------------------------------------------------------------------%
 
-merge_instmap_deltas(InstMap, NonLocals, InstMapDeltaList, MergedDelta,
-		ModuleInfo0, ModuleInfo) :-
+merge_instmap_deltas(InstMap, NonLocals, VarTypes, InstMapDeltaList,
+		MergedDelta, ModuleInfo0, ModuleInfo) :-
 	(
 		InstMapDeltaList = [],
 		error("merge_instmap_deltas: empty instmap_delta list.")
 	;
 		InstMapDeltaList = [Delta | Deltas],
-		merge_instmap_deltas(InstMap, NonLocals, Delta, Deltas,
-			MergedDelta, ModuleInfo0, ModuleInfo)
+		merge_instmap_deltas(InstMap, NonLocals, VarTypes, Delta,
+			Deltas, MergedDelta, ModuleInfo0, ModuleInfo)
 	).
 
-:- pred merge_instmap_deltas(instmap, set(prog_var), instmap_delta,
+:- pred merge_instmap_deltas(instmap, set(prog_var), vartypes, instmap_delta,
 		list(instmap_delta), instmap_delta, module_info, module_info).
-:- mode merge_instmap_deltas(in, in, in, in, out, in, out) is det.
+:- mode merge_instmap_deltas(in, in, in, in, in, out, in, out) is det.
 
-merge_instmap_deltas(_InstMap, _NonLocals, MergedDelta, [], MergedDelta,
-		ModuleInfo, ModuleInfo).
-merge_instmap_deltas(InstMap, NonLocals, MergedDelta0, [Delta|Deltas],
+merge_instmap_deltas(_InstMap, _NonLocals, _VarTypes, MergedDelta, [],
+		MergedDelta, ModuleInfo, ModuleInfo).
+merge_instmap_deltas(InstMap, NonLocals, VarTypes, MergedDelta0, [Delta|Deltas],
 		MergedDelta, ModuleInfo0, ModuleInfo) :-
-	merge_instmap_delta(InstMap, NonLocals, MergedDelta0, Delta,
+	merge_instmap_delta(InstMap, NonLocals, VarTypes, MergedDelta0, Delta,
 		MergedDelta1, ModuleInfo0, ModuleInfo1),
-	merge_instmap_deltas(InstMap, NonLocals, MergedDelta1, Deltas,
+	merge_instmap_deltas(InstMap, NonLocals, VarTypes, MergedDelta1, Deltas,
 		MergedDelta, ModuleInfo1, ModuleInfo).
 
 %-----------------------------------------------------------------------------%
@@ -912,19 +917,19 @@
 
 	% Given two instmap deltas, merge them to produce a new instmap_delta.
 
-merge_instmap_delta(_, _, unreachable, InstMapDelta, InstMapDelta) --> [].
-merge_instmap_delta(_, _, reachable(InstMapping), unreachable,
+merge_instmap_delta(_, _, _, unreachable, InstMapDelta, InstMapDelta) --> [].
+merge_instmap_delta(_, _, _, reachable(InstMapping), unreachable,
 				reachable(InstMapping)) --> [].
-merge_instmap_delta(InstMap, NonLocals, reachable(InstMappingA),
+merge_instmap_delta(InstMap, NonLocals, VarTypes, reachable(InstMappingA),
 		reachable(InstMappingB), reachable(InstMapping)) -->
-	merge_instmapping_delta(InstMap, NonLocals, InstMappingA,
+	merge_instmapping_delta(InstMap, NonLocals, VarTypes, InstMappingA,
 		InstMappingB, InstMapping).
 
-:- pred merge_instmapping_delta(instmap, set(prog_var), instmapping,
+:- pred merge_instmapping_delta(instmap, set(prog_var), vartypes, instmapping,
 		instmapping, instmapping, module_info, module_info).
-:- mode merge_instmapping_delta(in, in, in, in, out, in, out) is det.
+:- mode merge_instmapping_delta(in, in, in, in, in, out, in, out) is det.
 
-merge_instmapping_delta(InstMap, NonLocals, InstMappingA,
+merge_instmapping_delta(InstMap, NonLocals, VarTypes, InstMappingA,
 		InstMappingB, InstMapping) -->
 	{ map__keys(InstMappingA, VarsInA) },
 	{ map__keys(InstMappingB, VarsInB) },
@@ -933,18 +938,19 @@
 	{ set__intersect(SetofVars0, NonLocals, SetofVars) },
 	{ map__init(InstMapping0) },
 	{ set__to_sorted_list(SetofVars, ListofVars) },
-	merge_instmapping_delta_2(ListofVars, InstMap, InstMappingA,
+	merge_instmapping_delta_2(ListofVars, InstMap, VarTypes, InstMappingA,
 		InstMappingB, InstMapping0, InstMapping).
 
-:- pred merge_instmapping_delta_2(list(prog_var), instmap, instmapping,
-		instmapping, instmapping, instmapping,
+:- pred merge_instmapping_delta_2(list(prog_var), instmap, vartypes,
+		instmapping, instmapping, instmapping, instmapping,
 		module_info, module_info).
-:- mode merge_instmapping_delta_2(in, in, in, in, in, out, in, out) is det.
+:- mode merge_instmapping_delta_2(in, in, in, in, in, in, out, in, out) is det.
 
-merge_instmapping_delta_2([], _, _, _, InstMapping, InstMapping,
+merge_instmapping_delta_2([], _, _, _, _, InstMapping, InstMapping,
 		ModInfo, ModInfo).
-merge_instmapping_delta_2([Var | Vars], InstMap, InstMappingA, InstMappingB,
-			InstMapping0, InstMapping, ModuleInfo0, ModuleInfo) :-
+merge_instmapping_delta_2([Var | Vars], InstMap, VarTypes, InstMappingA,
+		InstMappingB, InstMapping0, InstMapping,
+		ModuleInfo0, ModuleInfo) :-
 	( map__search(InstMappingA, Var, InstInA) ->
 		InstA = InstInA
 	;
@@ -955,7 +961,10 @@
 	;
 		instmap__lookup_var(InstMap, Var, InstB)
 	),
-	( inst_merge(InstA, InstB, ModuleInfo0, Inst, ModuleInfoPrime) ->
+	(
+		inst_merge(InstA, InstB, yes(VarTypes ^ det_elem(Var)),
+			ModuleInfo0, Inst, ModuleInfoPrime)
+	->
 		ModuleInfo1 = ModuleInfoPrime,
 		map__det_insert(InstMapping0, Var, Inst, InstMapping1)
 	;
@@ -965,8 +974,9 @@
 			[i(VarInt)], Msg),
 		error(Msg)
 	),
-	merge_instmapping_delta_2(Vars, InstMap, InstMappingA, InstMappingB,
-		InstMapping1, InstMapping, ModuleInfo1, ModuleInfo).
+	merge_instmapping_delta_2(Vars, InstMap, VarTypes, InstMappingA,
+		InstMappingB, InstMapping1, InstMapping,
+		ModuleInfo1, ModuleInfo).
 
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
Index: compiler/mode_util.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/mode_util.m,v
retrieving revision 1.136
diff -u -r1.136 mode_util.m
--- compiler/mode_util.m	7 Apr 2001 14:04:50 -0000	1.136
+++ compiler/mode_util.m	11 Sep 2001 00:25:08 -0000
@@ -136,6 +136,14 @@
 		list(inst), list(inst)).
 :- mode propagate_types_into_inst_list(in, in, in, in, out) is det.
 
+	% Convert a list of constructors to a list of bound_insts.
+	% Note that the list(bound_inst) is not sorted and may contain
+	% duplicates.
+:- pred constructors_to_bound_insts(list(constructor), uniqueness, module_info,
+				list(bound_inst)).
+:- mode constructors_to_bound_insts(in, in, in, out) is det.
+
+
 	% Given the mode of a predicate,
 	% work out which arguments are live (might be used again
 	% by the caller of that predicate) and which are dead.
@@ -816,10 +824,6 @@
 		PredArgModes0, PredArgModes),
 	PredInstInfo = pred_inst_info(function, PredArgModes, det).
 
-:- pred constructors_to_bound_insts(list(constructor), uniqueness, module_info,
-				list(bound_inst)).
-:- mode constructors_to_bound_insts(in, in, in, out) is det.
-
 constructors_to_bound_insts([], _, _, []).
 constructors_to_bound_insts([Ctor | Ctors], Uniq, ModuleInfo,
 		[BoundInst | BoundInsts]) :-
@@ -1346,7 +1350,7 @@
 		InstMapDelta4) },
 	{ goal_info_get_nonlocals(GoalInfo, NonLocals) },
 	update_module_info(merge_instmap_delta(InstMap0, NonLocals,
-		InstMapDelta3, InstMapDelta4), InstMapDelta).
+		VarTypes, InstMapDelta3, InstMapDelta4), InstMapDelta).
 
 recompute_instmap_delta_2(Atomic, some(Vars, CanRemove, Goal0), _,
 		some(Vars, CanRemove, Goal),
@@ -1441,7 +1445,7 @@
 	recompute_instmap_delta_disj(Atomic, Goals0, Goals,
 		VarTypes, InstMap, NonLocals, InstMapDelta1),
 	update_module_info(merge_instmap_delta(InstMap, NonLocals,
-		InstMapDelta0, InstMapDelta1), InstMapDelta).
+		VarTypes, InstMapDelta0, InstMapDelta1), InstMapDelta).
 
 :- pred recompute_instmap_delta_par_conj(bool::in, list(hlds_goal)::in,
 	list(hlds_goal)::out, vartypes::in, instmap::in, set(prog_var)::in,
@@ -1485,7 +1489,7 @@
 	recompute_instmap_delta_cases(Atomic, Var, Cases0, Cases,
 		VarTypes, InstMap0, NonLocals, InstMapDelta2),
 	update_module_info(merge_instmap_delta(InstMap0, NonLocals,
-		InstMapDelta1, InstMapDelta2), InstMapDelta).
+		VarTypes, InstMapDelta1, InstMapDelta2), InstMapDelta).
 
 %-----------------------------------------------------------------------------%
 
Index: compiler/simplify.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/simplify.m,v
retrieving revision 1.97
diff -u -r1.97 simplify.m
--- compiler/simplify.m	20 Aug 2001 16:01:44 -0000	1.97
+++ compiler/simplify.m	11 Sep 2001 00:25:09 -0000
@@ -558,7 +558,8 @@
 		Goal = disj(Disjuncts, SM),
 		simplify_info_get_module_info(Info1, ModuleInfo1),
 		goal_info_get_nonlocals(GoalInfo0, NonLocals),
-		merge_instmap_deltas(InstMap0, NonLocals, InstMaps,
+		simplify_info_get_var_types(Info1, VarTypes),
+		merge_instmap_deltas(InstMap0, NonLocals, VarTypes, InstMaps,
 			NewDelta, ModuleInfo1, ModuleInfo2),
 		simplify_info_set_module_info(Info1, ModuleInfo2, Info2),
 		goal_info_set_instmap_delta(GoalInfo0, NewDelta, GoalInfo)
@@ -631,8 +632,9 @@
 		    ->
 		    	Goal = switch(Var, SwitchCanFail, Cases, SM),
 			goal_info_get_nonlocals(GoalInfo0, NonLocals),
-			merge_instmap_deltas(InstMap0, NonLocals, InstMaps,
-				NewDelta, ModuleInfo1, ModuleInfo2),
+			simplify_info_get_var_types(Info1, VarTypes),
+			merge_instmap_deltas(InstMap0, NonLocals, VarTypes,
+				InstMaps, NewDelta, ModuleInfo1, ModuleInfo2),
 			simplify_info_set_module_info(Info1,
 				ModuleInfo2, Info4),
 			goal_info_set_instmap_delta(GoalInfo0,
@@ -680,7 +682,8 @@
 		Goal = switch(Var, SwitchCanFail, Cases, SM),
 		simplify_info_get_module_info(Info1, ModuleInfo1),
 		goal_info_get_nonlocals(GoalInfo0, NonLocals),
-		merge_instmap_deltas(InstMap0, NonLocals, InstMaps,
+		simplify_info_get_var_types(Info1, VarTypes),
+		merge_instmap_deltas(InstMap0, NonLocals, VarTypes, InstMaps,
 			NewDelta, ModuleInfo1, ModuleInfo2),
 		simplify_info_set_module_info(Info1, ModuleInfo2, Info5),
 		goal_info_set_instmap_delta(GoalInfo0, NewDelta, GoalInfo)
@@ -1054,7 +1057,8 @@
 		goal_info_get_instmap_delta(ElseInfo, ElseDelta),
                 goal_info_get_nonlocals(GoalInfo0, NonLocals),
 		simplify_info_get_module_info(Info6, ModuleInfo0),
-		merge_instmap_deltas(InstMap0, NonLocals,
+		simplify_info_get_var_types(Info6, VarTypes),
+		merge_instmap_deltas(InstMap0, NonLocals, VarTypes,
 			[CondThenDelta, ElseDelta], NewDelta,
 			ModuleInfo0, ModuleInfo1),
 		simplify_info_set_module_info(Info6, ModuleInfo1, Info7),
Index: compiler/type_util.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/type_util.m,v
retrieving revision 1.99
diff -u -r1.99 type_util.m
--- compiler/type_util.m	24 Aug 2001 08:37:48 -0000	1.99
+++ compiler/type_util.m	11 Sep 2001 00:25:09 -0000
@@ -438,6 +438,20 @@
 :- mode get_unconstrained_tvars(in, in, out) is det.
 
 %-----------------------------------------------------------------------------%
+
+	% If possible, get the argument types for the cons_id.
+	% We need to pass in the arity rather than using the arity
+	% from the cons_id because the arity in the cons_id will not
+	% include any extra type_info arguments for existentially
+	% quantified types.
+:- pred maybe_get_cons_id_arg_types(module_info, maybe(type), cons_id,
+		arity, list(maybe(type))).
+:- mode maybe_get_cons_id_arg_types(in, in, in, in, out) is det.
+
+:- pred maybe_get_higher_order_arg_types(maybe(type), arity, list(maybe(type))).
+:- mode maybe_get_higher_order_arg_types(in, in, out) is det.
+
+%-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
 
 :- implementation.
@@ -1636,5 +1650,45 @@
 	constraint_list_get_tvars(Constraints, ConstrainedTvars),
 	list__delete_elems(Tvars, ConstrainedTvars, Unconstrained0),
 	list__remove_dups(Unconstrained0, Unconstrained).
+
+%-----------------------------------------------------------------------------%
+
+maybe_get_cons_id_arg_types(ModuleInfo, MaybeType, ConsId0, Arity, MaybeTypes)
+		:-
+	( ConsId0 = cons(SymName, _) ->
+		( SymName = qualified(_, Name) ->
+			% get_cons_id_non_existential_arg_types
+			% expects an unqualified cons_id.
+			ConsId = cons(unqualified(Name), Arity)
+		;
+			ConsId = ConsId0
+		),
+		(
+			MaybeType = yes(Type),
+
+			% XXX get_cons_id_non_existential_arg_types will fail
+			% for ConsIds with existentially typed arguments.
+			get_cons_id_non_existential_arg_types(ModuleInfo, Type,
+				ConsId, Types),
+			list__length(Types, Arity)
+		->
+			list__map(pred(T::in, yes(T)::out) is det, Types,
+				MaybeTypes)
+		;
+			list__duplicate(Arity, no, MaybeTypes)
+		)
+	;
+		MaybeTypes = []
+	).
+
+maybe_get_higher_order_arg_types(MaybeType, Arity, MaybeTypes) :-
+	(
+		MaybeType = yes(Type),
+		type_is_higher_order(Type, _, _, Types)
+	->
+		list__map(pred(T::in, yes(T)::out) is det, Types, MaybeTypes)
+	;
+		list__duplicate(Arity, no, MaybeTypes)
+	).
 
 %-----------------------------------------------------------------------------%
Index: tests/invalid/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/tests/invalid/Mmakefile,v
retrieving revision 1.96
diff -u -r1.96 Mmakefile
--- tests/invalid/Mmakefile	2 Sep 2001 10:33:07 -0000	1.96
+++ tests/invalid/Mmakefile	11 Sep 2001 00:25:09 -0000
@@ -54,6 +54,7 @@
 	invalid_typeclass.m \
 	io_in_ite_cond.m \
 	lambda_syntax_error.m \
+	merge_ground_any.m \
 	method_impl.m \
 	missing_det_decls.m \
 	missing_interface_import.m \
Index: tests/invalid/merge_ground_any.err_exp
===================================================================
RCS file: tests/invalid/merge_ground_any.err_exp
diff -N tests/invalid/merge_ground_any.err_exp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/invalid/merge_ground_any.err_exp	11 Sep 2001 00:25:09 -0000
@@ -0,0 +1,5 @@
+merge_ground_any.m:013: In clause for `pass(in, in(merge_ground_any:hpair(ground, any)), out(merge_ground_any:hpair(ground, any)))':
+merge_ground_any.m:013:   mode error: argument 5 did not get sufficiently instantiated.
+merge_ground_any.m:013:   Final instantiatedness of `HeadVar__3' was `bound(merge_ground_any:'+'(ground, ground) ; merge_ground_any:'-'(ground, any))',
+merge_ground_any.m:013:   expected final instantiatedness was `merge_ground_any:hpair(ground, any)'.
+For more information, try recompiling with `-E'.
Index: tests/invalid/merge_ground_any.m
===================================================================
RCS file: tests/invalid/merge_ground_any.m
diff -N tests/invalid/merge_ground_any.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/invalid/merge_ground_any.m	11 Sep 2001 00:25:09 -0000
@@ -0,0 +1,13 @@
+:- module merge_ground_any.
+:- interface.
+
+:- type hpair(A,B)  ---> (A-B) ; (A+B).
+:- inst hpair(A,B)  = bound(A-B).
+
+:- pred pass(hpair(A,B),hpair(A,B),hpair(A,B)).
+:- mode pass(in,in(hpair(ground,any)),out(hpair(ground,any))) is multi.
+
+:- implementation.
+
+pass(X,_,X).
+pass(_,X,X).
Index: tests/valid/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/tests/valid/Mmakefile,v
retrieving revision 1.90
diff -u -r1.90 Mmakefile
--- tests/valid/Mmakefile	5 Sep 2001 09:10:11 -0000	1.90
+++ tests/valid/Mmakefile	11 Sep 2001 00:25:09 -0000
@@ -111,6 +111,7 @@
 	livevals_seq.m \
 	loop.m \
 	loop_in_disj.m \
+	merge_ground_any.m \
 	middle_rec_labels.m \
 	modes_bug.m \
 	mode_syntax.m \
Index: tests/valid/merge_ground_any.m
===================================================================
RCS file: tests/valid/merge_ground_any.m
diff -N tests/valid/merge_ground_any.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/valid/merge_ground_any.m	11 Sep 2001 00:25:09 -0000
@@ -0,0 +1,13 @@
+:- module merge_ground_any.
+:- interface.
+
+:- type hpair(A,B)  ---> (A-B).
+:- inst hpair(A,B)  = bound(A-B).
+
+:- pred pass(hpair(A,B),hpair(A,B),hpair(A,B)).
+:- mode pass(in,in(hpair(ground,any)),out(hpair(ground,any))) is multi.
+
+:- implementation.
+
+pass(X,_,X).
+pass(_,X,X).

-- 
David Overton      Department of Computer Science & Software Engineering
PhD Student        The University of Melbourne, Victoria 3010, Australia
+61 3 8344 9159    http://www.cs.mu.oz.au/~dmo
--------------------------------------------------------------------------
mercury-reviews mailing list
post:  mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------



More information about the reviews mailing list