[m-rev.] for review: mode checking changes for HAL

David Overton dmo at cs.mu.OZ.AU
Fri Aug 9 14:15:41 AEST 2002


Estimated hours taken: 8
Branches: main

Add two new options `--any-matches-ground' and `--ground-matches-bound'
which, when set, alter mode analysis so that `any' matches `ground' and
`ground' matches `bound', respectively.  These options are unsafe in
general, but are required for some Mercury code generated by HAL.  They
will always be safe to use in such cases since the HAL compiler will
only produce code where the assumptions are valid.

An example of when this is required is that for certain types, HAL knows
that `any' is equivalent to `ground', but the Mercury compiler does not
know this.  If the type is an instance of a type class where the methods
have arguments requiring inst `any', we would like it to be possible for
the user to supply an instance where the method argument is required to
be `ground', if we know that `any' and `ground' are equivalent for this
type.

The HAL mode checker also carries around more precise type information
than the Mercury mode checker so sometimes HAL is able to determine that
`ground' matches a particular `bound' inst for a certain type, but
Mercury is unable to prove this.

A third case is where an `any' inst appears in a negated context.
Mercury is unable to prove that the variable with inst `any' is not
instantiated in the negated context, but HAL can in some cases.

compiler/options.m:
	Add the new options.

compiler/inst_match.m:
	Add an argument to `inst_matches_{initial,final}' to specify
	whether the match is "real" or "fake".  If the match is real,
	lookup the options `--any-matches-ground' and
	`--ground-matches-bound' to determine how comparisons between
	`any' and `ground', and `ground' and `bound' should be treated.
	Also lookup and use these options in `inst_matches_binding'.

compiler/modes.m:
compiler/mode_util.m:
compiler/modecheck_call.m:
compiler/constraint.m:
compiler/inst_util.m:
compiler/instmap.m:
compiler/pd_info.m:
compiler/post_typecheck.m:
compiler/unique_modes.m:
	Pass the extra argument to `inst_matches_{initial,final}'.  The
	match test is "real" when mode-checking calls, the ends of
	procedure bodies, and when deciding which procedure best matches
	the argument modes of a call.  The match test is "fake" when we
	are comparing two procedures of the same predicate to determine
	whether they are distinguishable.  This is because in this case
	we still want `ground' to be distinguishable from `any' and
	`bound'.

doc/user_guide.texi:
	Document the new options.

Index: compiler/options.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/options.m,v
retrieving revision 1.382
diff -u -r1.382 options.m
--- compiler/options.m	8 Aug 2002 06:25:45 -0000	1.382
+++ compiler/options.m	9 Aug 2002 02:12:28 -0000
@@ -158,6 +158,8 @@
 		;	infer_all
 		;	type_inference_iteration_limit
 		;	mode_inference_iteration_limit
+		;	any_matches_ground
+		;	ground_matches_bound
 	% Compilation Model options
 		;	grade
 
@@ -727,7 +729,9 @@
 	infer_det		-	bool(yes),
 	infer_all		-	bool_special,
 	type_inference_iteration_limit	-	int(60),
-	mode_inference_iteration_limit	-	int(30)
+	mode_inference_iteration_limit	-	int(30),
+	any_matches_ground	-	bool(no),
+	ground_matches_bound	-	bool(no)
 ]).
 option_defaults_2(compilation_model_option, [
 	%
@@ -1298,6 +1302,8 @@
 					type_inference_iteration_limit).
 long_option("mode-inference-iteration-limit",
 					mode_inference_iteration_limit).
+long_option("any-matches-ground", any_matches_ground).
+long_option("ground-matches-bound", ground_matches_bound).
 
 % compilation model options
 long_option("grade",			grade).
Index: compiler/inst_match.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/inst_match.m,v
retrieving revision 1.50
diff -u -r1.50 inst_match.m
--- compiler/inst_match.m	20 Mar 2002 12:36:24 -0000	1.50
+++ compiler/inst_match.m	9 Aug 2002 02:12:28 -0000
@@ -60,7 +60,21 @@
 
 %-----------------------------------------------------------------------------%
 
-	% inst_matches_initial(InstA, InstB, Type, ModuleInfo):
+	% The type `match_is_real' is passed to inst_matches_{initial,final}
+	% to specify whether the match is a `real_match' or `fake_match'.  
+	% `real_match' should be used when checking that the inst of a variable
+	% matches the initial/final inst of a procedure argument at either a
+	% call site or at the end of the predicate body.
+	% `fake_match' should be used for any other purpose where two insts are
+	% compared.
+	% Currently, the only difference is that if `real_match' is used, the
+	% options `--any-matches-bound' and `--ground-matches-any' will be
+	% checked, otherwise they will be ignored.
+:- type match_is_real
+	--->	real_match
+	;	fake_match.
+
+	% inst_matches_initial(InstA, InstB, Type, MatchIsReal, ModuleInfo):
 	%	Succeed iff `InstA' specifies at least as much
 	%	information as `InstB', and in those parts where they
 	%	specify the same information, `InstA' is at least as
@@ -71,12 +85,14 @@
 	%	inst_matches_initial(bound(a), bound(a;b), _) should
 	%	succeed, but not vice versa.
 
-:- pred inst_matches_initial(inst, inst, type, module_info).
-:- mode inst_matches_initial(in, in, in, in) is semidet.
+:- pred inst_matches_initial(inst, inst, type, match_is_real, module_info).
+:- mode inst_matches_initial(in, in, in, in, in) is semidet.
 
 	% This version of inst_matches_initial builds up a substitution map
 	% (inst_var_sub).  For each inst_var which occurs in InstA there will be
 	% a substitution to the corresponding inst in InstB.
+	% This version of inst_matches_initial should always be a `real_match'
+	% so there is no `match_is_real' argument.
 
 :- pred inst_matches_initial(inst, inst, type, module_info, module_info,
 		inst_var_sub, inst_var_sub).
@@ -91,8 +107,8 @@
 	%	is the same and both insts specify a binding, the binding
 	%	must be identical.
 
-:- pred inst_matches_final(inst, inst, module_info).
-:- mode inst_matches_final(in, in, in) is semidet.
+:- pred inst_matches_final(inst, inst, match_is_real, module_info).
+:- mode inst_matches_final(in, in, in, in) is semidet.
 
 	% This version of inst_matches_final allows you to pass in the type of
 	% the variables being compared.  This allows it to be more precise (i.e.
@@ -100,8 +116,8 @@
 	%	inst_matches_final(ground(...), bound(...), ...).
 	% This version is to be preferred when the type is available.
 
-:- pred inst_matches_final(inst, inst, type, module_info).
-:- mode inst_matches_final(in, in, in, in) is semidet.
+:- pred inst_matches_final(inst, inst, type, match_is_real, module_info).
+:- mode inst_matches_final(in, in, in, in, in) is semidet.
 
 	%	The difference between inst_matches_initial and
 	%	inst_matches_final is that inst_matches_initial requires
@@ -288,14 +304,17 @@
 :- import_module hlds__hlds_data, check_hlds__mode_util.
 :- import_module parse_tree__prog_data, check_hlds__inst_util.
 :- import_module check_hlds__type_util.
+:- import_module libs__globals, libs__options.
 :- import_module list, set, map, term, std_util, require, bool.
 
-inst_matches_initial(InstA, InstB, Type, ModuleInfo) :-
-	inst_matches_initial_1(InstA, InstB, Type, ModuleInfo, _, no, _).
+inst_matches_initial(InstA, InstB, Type, MatchIsReal, ModuleInfo) :-
+	inst_matches_initial_1(InstA, InstB, Type, MatchIsReal, ModuleInfo,
+		_, no, _).
 
 inst_matches_initial(InstA, InstB, Type, ModuleInfo0, ModuleInfo, Sub0, Sub) :-
-	inst_matches_initial_1(InstA, InstB, Type, ModuleInfo0, ModuleInfo,
-		yes(Sub0), MaybeSub),
+	MatchIsReal = real_match,
+	inst_matches_initial_1(InstA, InstB, Type, MatchIsReal,
+		ModuleInfo0, ModuleInfo, yes(Sub0), MaybeSub),
 	(
 		MaybeSub = yes(Sub)
 	;
@@ -303,14 +322,18 @@
 		error("inst_matches_initial: missing inst_var_sub")
 	).
 
-:- pred inst_matches_initial_1(inst, inst, type, module_info, module_info,
-		maybe(inst_var_sub), maybe(inst_var_sub)).
-:- mode inst_matches_initial_1(in, in, in, in, out, in, out) is semidet.
-
-inst_matches_initial_1(InstA, InstB, Type, ModuleInfo0, ModuleInfo,
-		MaybeSub0, MaybeSub) :-
+:- pred inst_matches_initial_1(inst, inst, type, match_is_real,
+	module_info, module_info, maybe(inst_var_sub), maybe(inst_var_sub)).
+:- mode inst_matches_initial_1(in, in, in, in, in, out, in, out) is semidet.
+
+inst_matches_initial_1(InstA, InstB, Type, MatchIsReal,
+		ModuleInfo0, ModuleInfo, MaybeSub0, MaybeSub) :-
+	maybe_lookup_match_options(MatchIsReal, ModuleInfo0, AnyMatchesGround,
+		GroundMatchesBound),
 	Info0 = init_inst_match_info(ModuleInfo0) ^ maybe_sub := MaybeSub0,
-	inst_matches_initial_2(InstA, InstB, yes(Type), Info0, Info),
+	Info1 = Info0 ^ any_matches_ground := AnyMatchesGround,
+	Info2 = Info1 ^ ground_matches_bound := GroundMatchesBound,
+	inst_matches_initial_2(InstA, InstB, yes(Type), Info2, Info),
 	ModuleInfo = Info^module_info,
 	MaybeSub = Info ^ maybe_sub.
 
@@ -318,9 +341,11 @@
 
 :- type inst_match_info
 	--->	inst_match_info(
-			module_info	:: module_info,
-			expansions	:: expansions,
-			maybe_sub	:: maybe(inst_var_sub)
+			module_info	     :: module_info,
+			expansions	     :: expansions,
+			maybe_sub	     :: maybe(inst_var_sub),
+			any_matches_ground   :: bool,
+			ground_matches_bound :: bool
 		).
 
 :- func sub(inst_match_info) = inst_var_sub is semidet.
@@ -335,7 +360,8 @@
 
 :- func init_inst_match_info(module_info) = inst_match_info.
 
-init_inst_match_info(ModuleInfo) = inst_match_info(ModuleInfo, Exp, no) :-
+init_inst_match_info(ModuleInfo) =
+		inst_match_info(ModuleInfo, Exp, no, no, no) :-
 	set__init(Exp).
 
 :- pred inst_matches_initial_2(inst, inst, maybe(type), 
@@ -381,7 +407,8 @@
 	; InstA = constrained_inst_vars(_InstVarsA, InstA1) ->
 		inst_matches_initial_2(InstA1, InstB, Type, Info0, Info)
 	;
-		inst_matches_initial_4(InstA, InstB, Type, Info0, Info)
+		inst_matches_initial_4(maybe_any_to_ground(InstA, Info0),
+			InstB, Type, Info0, Info)
 	).
 
 :- pred inst_matches_initial_4(inst, inst, maybe(type), 
@@ -408,15 +435,18 @@
 inst_matches_initial_4(bound(UniqA, ListA), ground(UniqB, none), _,
 		Info, Info) :-
 	unique_matches_initial(UniqA, UniqB),
-	bound_inst_list_is_ground(ListA, Info^module_info),
+	bound_inst_list_is_ground_or_maybe_any(ListA, Info^module_info,
+		Info ^ any_matches_ground),
 	bound_inst_list_matches_uniq(ListA, UniqB, Info^module_info).
 inst_matches_initial_4(bound(Uniq, List), abstract_inst(_,_), _, Info, Info) :-
 	Uniq = unique,
-	bound_inst_list_is_ground(List, Info^module_info),
+	bound_inst_list_is_ground_or_maybe_any(List, Info^module_info,
+		Info ^ any_matches_ground),
 	bound_inst_list_is_unique(List, Info^module_info).
 inst_matches_initial_4(bound(Uniq, List), abstract_inst(_,_), _, Info, Info) :-
 	Uniq = mostly_unique,
-	bound_inst_list_is_ground(List, Info^module_info),
+	bound_inst_list_is_ground_or_maybe_any(List, Info^module_info,
+		Info ^ any_matches_ground),
 	bound_inst_list_is_mostly_unique(List, Info^module_info).
 inst_matches_initial_4(ground(UniqA, GroundInstInfoA), any(UniqB), _,
 		Info, Info) :-
@@ -426,12 +456,21 @@
 inst_matches_initial_4(ground(_Uniq, _PredInst), free, _, I, I).
 inst_matches_initial_4(ground(UniqA, _GII_A), bound(UniqB, ListB), MaybeType,
 		Info0, Info) :-
-	MaybeType = yes(Type),
-		% We can only check this case properly if the type is known.
 	unique_matches_initial(UniqA, UniqB),
-	bound_inst_list_is_complete_for_type(set__init, Info0^module_info,
-		ListB, Type),
-	ground_matches_initial_bound_inst_list(UniqA, ListB, yes(Type),
+
+	% We require that the `bound' inst contains all the functors
+	% for the type.
+	% We can only check this properly if the type is known.
+	% If option `--ground-matches-bound' is present then we assume that the
+	% inst contains all the functors for the type without checking it.
+	( 
+		Info0 ^ ground_matches_bound = yes
+	;
+		MaybeType = yes(Type),
+		bound_inst_list_is_complete_for_type(set__init,
+			Info0^module_info, ListB, Type)
+	),
+	ground_matches_initial_bound_inst_list(UniqA, ListB, MaybeType,
 		Info0, Info).
 inst_matches_initial_4(ground(UniqA, GroundInstInfoA),
 		ground(UniqB, GroundInstInfoB), Type, Info0, Info) :-
@@ -795,13 +834,23 @@
 
 %-----------------------------------------------------------------------------%
 
-inst_matches_final(InstA, InstB, ModuleInfo) :-
-	Info0 = init_inst_match_info(ModuleInfo),
-	inst_matches_final_2(InstA, InstB, no, Info0, _).
+inst_matches_final(InstA, InstB, MatchIsReal, ModuleInfo) :-
+	inst_matches_final_1(InstA, InstB, no, MatchIsReal, ModuleInfo).
+
+inst_matches_final(InstA, InstB, Type, MatchIsReal, ModuleInfo) :-
+	inst_matches_final_1(InstA, InstB, yes(Type), MatchIsReal, ModuleInfo).
+
+:- pred inst_matches_final_1(inst, inst, maybe(type), match_is_real,
+		module_info).
+:- mode inst_matches_final_1(in, in, in, in, in) is semidet.
 
-inst_matches_final(InstA, InstB, Type, ModuleInfo) :-
+inst_matches_final_1(InstA, InstB, MaybeType, MatchIsReal, ModuleInfo) :-
+	maybe_lookup_match_options(MatchIsReal, ModuleInfo, AnyMatchesGround,
+		GroundMatchesBound),
 	Info0 = init_inst_match_info(ModuleInfo),
-	inst_matches_final_2(InstA, InstB, yes(Type), Info0, _).
+	Info1 = Info0 ^ any_matches_ground := AnyMatchesGround,
+	Info2 = Info1 ^ ground_matches_bound := GroundMatchesBound,
+	inst_matches_final_2(InstA, InstB, MaybeType, Info2, _).
 
 :- pred inst_matches_final_2(inst, inst, maybe(type),
 		inst_match_info, inst_match_info).
@@ -817,8 +866,8 @@
 		inst_expand(Info0^module_info, InstA, InstA2),
 		inst_expand(Info0^module_info, InstB, InstB2),
 		set__insert(Info0^expansions, ThisExpansion, Expansions1),
-		inst_matches_final_3(InstA2, InstB2, MaybeType,
-			Info0^expansions := Expansions1, Info)
+		inst_matches_final_3(maybe_any_to_ground(InstA2, Info0), InstB2,
+			MaybeType, Info0^expansions := Expansions1, Info)
 	).
 
 :- pred inst_matches_final_3(inst, inst, maybe(type),
@@ -848,7 +897,8 @@
 inst_matches_final_3(bound(UniqA, ListA), ground(UniqB, none), _,
 		Info, Info) :-
 	unique_matches_final(UniqA, UniqB),
-	bound_inst_list_is_ground(ListA, Info^module_info),
+	bound_inst_list_is_ground_or_maybe_any(ListA, Info^module_info,
+		Info ^ any_matches_ground),
 	bound_inst_list_matches_uniq(ListA, UniqB, Info^module_info).
 inst_matches_final_3(ground(UniqA, GroundInstInfoA), any(UniqB), _,
 		Info, Info) :-
@@ -860,7 +910,8 @@
 	\+ ground_inst_info_is_nonstandard_func_mode(GroundInstInfoA,
 		Info^module_info),
 	unique_matches_final(UniqA, UniqB),
-	bound_inst_list_is_ground(ListB, Info^module_info),
+	bound_inst_list_is_ground_or_maybe_any(ListB, Info^module_info,
+		Info ^ any_matches_ground),
 	uniq_matches_bound_inst_list(UniqA, ListB, Info^module_info),
 	(
 		MaybeType = yes(Type),
@@ -868,6 +919,10 @@
 		bound_inst_list_is_complete_for_type(set__init,
 			Info^module_info, ListB, Type)
 	;
+		% If the option --ground-matches-bound was given we trust
+		% that this is mode correct.
+		Info ^ ground_matches_bound = yes
+	;
 		true
 		% XXX enabling the check for bound_inst_list_is_complete
 		% for type makes the mode checker too conservative in
@@ -957,7 +1012,14 @@
 	).
 
 inst_matches_binding(InstA, InstB, Type, ModuleInfo) :-
-	Info0 = init_inst_match_info(ModuleInfo),
+	module_info_globals(ModuleInfo, Globals),
+	globals__lookup_bool_option(Globals, any_matches_ground,
+		AnyMatchesGround),
+	globals__lookup_bool_option(Globals, ground_matches_bound,
+		GroundMatchesBound),
+	Info0 = (init_inst_match_info(ModuleInfo)
+		^ any_matches_ground := AnyMatchesGround)
+		^ ground_matches_bound := GroundMatchesBound,
 	inst_matches_binding_2(InstA, InstB, yes(Type), Info0, _).
 
 :- pred inst_matches_binding_2(inst, inst, maybe(type), inst_match_info,
@@ -974,7 +1036,8 @@
 		inst_expand_and_remove_constrained_inst_vars(Info0^module_info,
 			InstB, InstB2),
 		set__insert(Info0^expansions, ThisExpansion, Expansions1),
-		inst_matches_binding_3(InstA2, InstB2, MaybeType,
+		inst_matches_binding_3(maybe_any_to_ground(InstA2, Info0),
+			maybe_any_to_ground(InstB2, Info0), MaybeType,
 			Info0^expansions := Expansions1, Info)
 	).
 
@@ -982,23 +1045,32 @@
 		inst_match_info).
 :- mode inst_matches_binding_3(in, in, in, in, out) is semidet.
 
-% Note that `any' is *not* considered to match `any'.
+% Note that `any' is *not* considered to match `any' unless the option
+% `--any_matches-ground' was given.
+% WARNING allowing this in negations and the conditions of if-then-elses is
+% potentially unsound.
 inst_matches_binding_3(free, free, _, I, I).
 inst_matches_binding_3(bound(_UniqA, ListA), bound(_UniqB, ListB), MaybeType,
 		Info0, Info) :-
 	bound_inst_list_matches_binding(ListA, ListB, MaybeType, Info0, Info).
 inst_matches_binding_3(bound(_UniqA, ListA), ground(_UniqB, none), _,
 		Info, Info) :-
-	bound_inst_list_is_ground(ListA, Info^module_info).
+	bound_inst_list_is_ground_or_maybe_any(ListA, Info^module_info,
+		Info ^ any_matches_ground).
 inst_matches_binding_3(ground(_UniqA, _), bound(_UniqB, ListB), MaybeType,
 		Info, Info) :-
-	bound_inst_list_is_ground(ListB, Info^module_info),
+	bound_inst_list_is_ground_or_maybe_any(ListB, Info^module_info,
+		Info ^ any_matches_ground),
 	(
 		MaybeType = yes(Type),
 		% We can only do this check if the type is known.
 		bound_inst_list_is_complete_for_type(set__init,
 			Info^module_info, ListB, Type)
 	;
+		% If the option --ground-matches-bound was given we trust
+		% that this is mode correct.
+		Info ^ ground_matches_bound = yes
+	;
 		true
 		% XXX enabling the check for bound_inst_list_is_complete
 		% for type makes the mode checker too conservative in
@@ -1413,6 +1485,22 @@
 
 %-----------------------------------------------------------------------------%
 
+	% bound_inst_list_is_ground_or_maybe_any(BoundInsts, ModuleInfo,
+	% 	AnyMatchesGround)
+	% is equivalent to bound_inst_list_is_ground of AnyMatchesGround = no,
+	% and equivalent to bound_inst_list_is_ground_or_any if
+	% AnyMatchesGround = yes.
+:- pred bound_inst_list_is_ground_or_maybe_any(list(bound_inst),
+		module_info, bool).
+:- mode bound_inst_list_is_ground_or_maybe_any(in, in, in) is semidet.
+
+bound_inst_list_is_ground_or_maybe_any(BoundInsts, ModuleInfo, no) :-
+	bound_inst_list_is_ground(BoundInsts, ModuleInfo).
+bound_inst_list_is_ground_or_maybe_any(BoundInsts, ModuleInfo, yes) :-
+	bound_inst_list_is_ground_or_any(BoundInsts, ModuleInfo).
+
+%-----------------------------------------------------------------------------%
+
 :- pred bound_inst_list_is_ground_2(list(bound_inst), module_info,
 		set(inst), set(inst)).
 :- mode bound_inst_list_is_ground_2(in, in, in, out) is semidet.
@@ -1779,6 +1867,41 @@
 		list__member(Inst, Insts)
 	),
 	inst_contains_inst_var(Inst, InstVar).
+
+%-----------------------------------------------------------------------------%
+
+:- func maybe_any_to_ground((inst), inst_match_info) = (inst).
+
+maybe_any_to_ground(Inst, Info) =
+		(
+			Inst = any(UniqA),
+			Info ^ any_matches_ground = yes
+		->
+			% If option `--any-matches-ground' was given, treat
+			% `any' the same as `ground'.
+			ground(UniqA, none)
+		;
+			Inst
+		).
+
+%-----------------------------------------------------------------------------%
+:- pred maybe_lookup_match_options(match_is_real, module_info, bool, bool).
+:- mode maybe_lookup_match_options(in, in, out, out) is det.
+
+maybe_lookup_match_options(MatchIsReal, ModuleInfo, AnyMatchesGround,
+		GroundMatchesBound) :-
+	(
+		MatchIsReal = real_match,
+		module_info_globals(ModuleInfo, Globals),
+		globals__lookup_bool_option(Globals, any_matches_ground,
+			AnyMatchesGround),
+		globals__lookup_bool_option(Globals, ground_matches_bound,
+			GroundMatchesBound)
+	;
+		MatchIsReal = fake_match,
+		AnyMatchesGround = no,
+		GroundMatchesBound = no
+	).
 
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
Index: compiler/modes.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/modes.m,v
retrieving revision 1.261
diff -u -r1.261 modes.m
--- compiler/modes.m	26 Jul 2002 04:18:24 -0000	1.261
+++ compiler/modes.m	9 Aug 2002 02:12:28 -0000
@@ -908,7 +908,10 @@
 		=(ModeInfo),
 		{ mode_info_get_var_types(ModeInfo, VarTypes) },
 		{ map__lookup(VarTypes, Var, Type) },
-		( { inst_matches_final(VarInst, Inst, Type, ModuleInfo) } ->
+		(
+			{ inst_matches_final(VarInst, Inst, Type, real_match,
+				ModuleInfo) }
+		->
 			{ Changed1 = Changed0 }
 		;
 			{ Changed1 = yes },
@@ -920,11 +923,15 @@
 			;
 				% XXX this might need to be reconsidered now
 				% we have unique modes
-				( { inst_matches_initial(VarInst, Inst,
-					    Type, ModuleInfo) } ->
+				(
+					{ inst_matches_initial(VarInst, Inst,
+						Type, fake_match, ModuleInfo) }
+				->
 					{ Reason = too_instantiated }
-				; { inst_matches_initial(Inst, VarInst,
-					    Type, ModuleInfo) } ->
+				;
+					{ inst_matches_initial(Inst, VarInst,
+						Type, fake_match, ModuleInfo) }
+				->
 					{ Reason = not_instantiated_enough }
 				;
 					% I don't think this can happen. 
@@ -1849,7 +1856,8 @@
 				ModuleInfo, Subst0, Subst1)
 		;
 			NeedExactMatch = yes,
-			inst_matches_final(VarInst, Inst, Type, ModuleInfo0),
+			inst_matches_final(VarInst, Inst, Type, real_match,
+				ModuleInfo0),
 			ModuleInfo = ModuleInfo0,
 			Subst1 = Subst0
 			% WARNING:
@@ -1971,7 +1979,8 @@
 			% the only thing we can have done is lose uniqueness.
 			mode_info_get_var_types(ModeInfo1, VarTypes),
 			map__lookup(VarTypes, Var0, Type),
-			inst_matches_initial(Inst0, Inst, Type, ModuleInfo)
+			inst_matches_initial(Inst0, Inst, Type, fake_match,
+				ModuleInfo)
 		->
 			instmap__set(InstMap0, Var0, Inst, InstMap),
 			mode_info_set_instmap(InstMap, ModeInfo1, ModeInfo3)
@@ -2049,7 +2058,8 @@
 		% the initial inst specified in the pred's mode declaration,
 		% then it's not a call to an implied mode, it's an exact
 		% match with a genuine mode.
-		inst_matches_final(VarInst1, InitialInst, VarType, ModuleInfo0)
+		inst_matches_final(VarInst1, InitialInst, VarType,
+			real_match, ModuleInfo0)
 	->
 		Var = Var0,
 		ExtraGoals = ExtraGoals0,
Index: compiler/modecheck_call.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/modecheck_call.m,v
retrieving revision 1.40
diff -u -r1.40 modecheck_call.m
--- compiler/modecheck_call.m	20 Mar 2002 12:36:55 -0000	1.40
+++ compiler/modecheck_call.m	9 Aug 2002 02:12:28 -0000
@@ -875,17 +875,29 @@
 :- mode compare_inst(in, in, in, in, out, in) is det.
 
 compare_inst(InstA, InstB, MaybeArgInst, Type, Result, ModuleInfo) :-
+	% If we have an argument inst we need `MatchIsReal = real_match'.  This
+	% is because, if `--any-matches-ground' is set we still want to, e.g.,
+	% prefer `any' over `ground' if the argument inst is `any', but we
+	% should prefer `ground' if the argument inst is ground.
+	(
+		MaybeArgInst = yes(_),
+		MatchIsReal = real_match
+	;
+		MaybeArgInst = no,
+		MatchIsReal = fake_match
+	),
+
 	% inst_matches_initial(A,B) succeeds iff
 	%	A specifies at least as much information
 	%	and at least as much binding as B --
 	%	with the exception that `any' matches_initial `free'
 	% 	and perhaps vice versa.
-	( inst_matches_initial(InstA, InstB, Type, ModuleInfo) ->
+	( inst_matches_initial(InstA, InstB, Type, MatchIsReal, ModuleInfo) ->
 		A_mi_B = yes
 	;
 		A_mi_B = no
 	),
-	( inst_matches_initial(InstB, InstA, Type, ModuleInfo) ->
+	( inst_matches_initial(InstB, InstA, Type, MatchIsReal, ModuleInfo) ->
 		B_mi_A = yes
 	;
 		B_mi_A = no
@@ -907,9 +919,13 @@
 			Result0 = same
 		;
 			MaybeArgInst = yes(ArgInst),
+
+			% Here we need to use `fake_match' so that `any' and
+			% `ground' are differentiated, even when
+			% `--any-matches-ground' is set.
 			(
 				inst_matches_final(ArgInst, InstA, Type,
-					ModuleInfo)
+					fake_match, ModuleInfo)
 			->
 				Arg_mf_A = yes
 			;
@@ -917,7 +933,7 @@
 			),
 			(
 				inst_matches_final(ArgInst, InstB, Type,
-					ModuleInfo)
+					fake_match, ModuleInfo)
 			->
 				Arg_mf_B = yes
 			;
@@ -935,12 +951,18 @@
 			% or comparing with the arg inst doesn't help,
 			% then compare the two proc insts
 			%
-			( inst_matches_final(InstA, InstB, Type, ModuleInfo) ->
+			(
+				inst_matches_final(InstA, InstB, Type,
+					fake_match, ModuleInfo)
+			->
 				A_mf_B = yes
 			;
 				A_mf_B = no
 			),
-			( inst_matches_final(InstB, InstA, Type, ModuleInfo) ->
+			(
+				inst_matches_final(InstB, InstA, Type,
+					fake_match, ModuleInfo)
+			->
 				B_mf_A = yes
 			;
 				B_mf_A = no
Index: compiler/constraint.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/constraint.m,v
retrieving revision 1.49
diff -u -r1.49 constraint.m
--- compiler/constraint.m	28 Mar 2002 03:42:49 -0000	1.49
+++ compiler/constraint.m	9 Aug 2002 02:12:28 -0000
@@ -285,7 +285,8 @@
 			instmap__lookup_var(InstMap0, Var, InstBefore),
 			instmap_delta_search_var(InstMapDelta, Var, InstAfter),
 			\+ inst_matches_initial(InstAfter, InstBefore,
-				map__lookup(VarTypes, Var), ModuleInfo)
+				map__lookup(VarTypes, Var), fake_match,
+				ModuleInfo)
 		),
 	IncompatibleInstVars = set__list_to_set(
 			list__filter(InCompatible, InstMapVars)),
Index: compiler/inst_util.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/inst_util.m,v
retrieving revision 1.23
diff -u -r1.23 inst_util.m
--- compiler/inst_util.m	30 Jul 2002 04:29:42 -0000	1.23
+++ compiler/inst_util.m	9 Aug 2002 02:12:28 -0000
@@ -483,7 +483,8 @@
 		abstractly_unify_inst_functor(Live, InstA3, ConsId, ArgInsts,
 			ArgLives, Real, ModuleInfo0, Inst0, Det, ModuleInfo),
 		(
-			inst_matches_final(Inst0, InstA3, ModuleInfo)
+			inst_matches_final(Inst0, InstA3, fake_match,
+				ModuleInfo)
 		->
 			% We can keep the constrained_inst_vars.
 			Inst = constrained_inst_vars(InstVars, Inst0)
@@ -705,7 +706,8 @@
 	abstractly_unify_inst(IsLive, InstConstraint, InstB, UnifyIsReal,
 		ModuleInfo0, Inst0, Det, ModuleInfo),
 	( 
-		\+ inst_matches_final(Inst0, InstConstraint, ModuleInfo)
+		\+ inst_matches_final(Inst0, InstConstraint, fake_match,
+			ModuleInfo)
 	->
 		% The inst has become too instantiated so the
 		% constrained_inst_vars must be removed.
@@ -1132,7 +1134,7 @@
 		ModuleInfo) :-
 	make_shared_inst(Inst0, ModuleInfo0, Inst1, ModuleInfo),
 	(
-		\+ inst_matches_final(Inst1, Inst0, ModuleInfo)
+		\+ inst_matches_final(Inst1, Inst0, fake_match, ModuleInfo)
 	->
 		Inst = Inst1
 	;
@@ -1233,7 +1235,7 @@
 		ModuleInfo) :-
 	make_mostly_uniq_inst(Inst0, ModuleInfo0, Inst1, ModuleInfo),
 	(
-		\+ inst_matches_final(Inst1, Inst0, ModuleInfo)
+		\+ inst_matches_final(Inst1, Inst0, fake_match, ModuleInfo)
 	->
 		Inst = Inst1
 	;
Index: compiler/instmap.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/instmap.m,v
retrieving revision 1.29
diff -u -r1.29 instmap.m
--- compiler/instmap.m	20 Mar 2002 12:36:26 -0000	1.29
+++ compiler/instmap.m	9 Aug 2002 02:12:28 -0000
@@ -419,7 +419,8 @@
 	map__lookup(VarTypes, VarB, Type),
 
 	(
-		inst_matches_final(InitialInst, FinalInst, Type, ModuleInfo)
+		inst_matches_final(InitialInst, FinalInst, Type, fake_match,
+			ModuleInfo)
 	->
 		ChangedVars = ChangedVars0
 	;
Index: compiler/pd_info.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/pd_info.m,v
retrieving revision 1.9
diff -u -r1.9 pd_info.m
--- compiler/pd_info.m	20 Mar 2002 12:37:06 -0000	1.9
+++ compiler/pd_info.m	9 Aug 2002 02:12:28 -0000
@@ -662,14 +662,15 @@
 	map__lookup(VarRenaming, OldVar, NewVar),
 	instmap__lookup_var(NewInstMap, NewVar, NewVarInst),
 	map__lookup(VarTypes, NewVar, Type),
-	inst_matches_initial(NewVarInst, OldVarInst, Type, ModuleInfo),
+	inst_matches_initial(NewVarInst, OldVarInst, Type, fake_match,
+		ModuleInfo),
 	( ExactSoFar0 = exact ->
 		% Does inst_matches_initial(Inst1, Inst2, M) and
 		% inst_matches_initial(Inst2, Inst1, M) imply that Inst1
 		% and Inst2 are interchangable? 
 		(
 			inst_matches_initial(OldVarInst, NewVarInst, Type,
-				ModuleInfo)
+				fake_match, ModuleInfo)
 		->
 			ExactSoFar1 = exact
 		;
Index: compiler/post_typecheck.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/post_typecheck.m,v
retrieving revision 1.41
diff -u -r1.41 post_typecheck.m
--- compiler/post_typecheck.m	22 Jul 2002 06:29:45 -0000	1.41
+++ compiler/post_typecheck.m	9 Aug 2002 02:12:28 -0000
@@ -1105,7 +1111,7 @@
 		mode_get_insts(ModuleInfo, Mode, InitialInst, _),
 		% Mode analysis will check the final inst.
 		inst_matches_initial(InitialInst, InitialAditiStateInst,
-			Type, ModuleInfo)
+			Type, real_match, ModuleInfo)
 	;
 		check_aditi_state_modes_2(ModuleInfo, Types, Modes,
 			InitialAditiStateInst)
Index: compiler/unique_modes.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/unique_modes.m,v
retrieving revision 1.74
diff -u -r1.74 unique_modes.m
--- compiler/unique_modes.m	28 Mar 2002 03:43:46 -0000	1.74
+++ compiler/unique_modes.m	9 Aug 2002 02:12:28 -0000
@@ -205,7 +205,7 @@
 	(
 		instmap_delta_is_reachable(DeltaInstMap),
 		instmap_delta_search_var(DeltaInstMap, Var, Inst),
-		\+ inst_matches_final(Inst, Inst0, Type, ModuleInfo)
+		\+ inst_matches_final(Inst, Inst0, Type, fake_match, ModuleInfo)
 	->
 		ChangedVars = [Var | ChangedVars1],
 		select_changed_inst_vars(Vars, DeltaInstMap, ModeInfo,
Index: user_guide.texi
===================================================================
RCS file: /home/mercury1/repository/mercury/doc/user_guide.texi,v
retrieving revision 1.320
diff -u -r1.320 user_guide.texi
--- user_guide.texi	8 Aug 2002 06:25:48 -0000	1.320
+++ user_guide.texi	9 Aug 2002 04:05:53 -0000
@@ -4231,6 +4231,20 @@
 @cindex Inference of modes
 @cindex Mode inference
 Perform at most @var{n} passes of mode inference (default: 30).
+
+ at sp 1
+ at item --any-matches-ground
+Assume that @samp{any} matches @samp{ground} when mode checking calls and the
+ends of procedure bodies.
+Warning: this option is dangerous if used incorrectly (i.e.@: in situations
+where the assumption does not hold).
+
+ at sp 1
+ at item --ground-matches-bound
+Assume that @samp{ground} matches @samp{bound} when mode checking calls and the
+ends of procedure bodies.
+Warning: this option is dangerous if used incorrectly (i.e.@: in situations
+where the assumption does not hold).
 @end table
 
 @node Termination analysis options
-- 
David Overton                  Uni of Melbourne     +61 3 8344 9159
dmo at cs.mu.oz.au                Monash Uni (Clayton) +61 3 9905 5779
http://www.cs.mu.oz.au/~dmo    Mobile Phone         +61 4 0337 4393
--------------------------------------------------------------------------
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