[m-rev.] for review: fix infinite loop for `:- inst x == x.'

Fergus Henderson fjh at cs.mu.OZ.AU
Fri Nov 22 23:23:49 AEDT 2002


On 21-Nov-2002, Mark Brown <dougl at cs.mu.OZ.AU> wrote:
> 
> An alternative solution to this problem may be to do a pass over all the
> inst equivalence declarations to check for circularities, before mode
> analysis even starts.  One way that this may be better is that errors
> such as
> 
> 	:- inst f == f.
> 
> would be detected even if the inst is never used.
...
> It seems to me that the only way this can loop is if, when expanding a
> particular user defined inst f/N, the same inst constructor f/N is reached
> at the top level of the expanded inst.  Perhaps I've overlooked something,
> but it should be sufficient for the Expansions argument to have type
> set(sym_name_and_arity), and only be checked/updated when the inst is of
> the form defined_inst(user_inst(_, _)).  This approach would also solve the
> XXX in the log message.

These are all excellent suggestions.

However, rather than doing a separate pass, I've done the check as part
of make_hlds.m, when we add inst or mode definitions to the HLDS.
This required only a very minor change to the existing infrastructure
in make_hlds.m (threading an extra boolean return value through pass 1).

----------

Estimated hours taken: 18
Branches: main, release

Fix a bug where the compiler was going into an infinite loop for
insts and modes that are infinitely recursive at the top level,
e.g. `:- inst foo == foo.' or `:- mode foo == foo'.

compiler/make_hlds.m:
	Check for circular insts and modes, and report an error if any occur.

	Also, pass back a boolean from pass 1 indicating whether or not
	any cyclic insts and modes.  Rename the "UndefModes" argument
	for parse_tree_to_hlds as "InvalidModes", and set it to yes
	if there were any circular insts or modes, to ensure that
	mercury_compile.m will not run mode analysis.  This is needed
	to avoid infinite loops in mode analysis when processing
	circular 

compiler/notes/compiler_design.html:
	Mention that make_hlds.m checks for circular insts and modes.
	Also mention that it expands state variable syntax.

compiler/mercury_compile.m:
	Add a comment about circular insts and modes to the list of
	reasons why we might need to stop before running mode analysis.

tests/invalid/circ_inst2.m:
	Fix a misleading comment.

tests/invalid/Mmakefile:
tests/invalid/circ_inst.err_exp:
tests/invalid/circ_inst2.err_exp:
tests/invalid/circ_inst3.err_exp:
tests/invalid/circ_inst4.err_exp:
tests/invalid/circ_mode.err_exp:
tests/invalid/circ_mode2.err_exp:
tests/invalid/circ_mode3.err_exp:
tests/invalid/circ_mode4.err_exp:
	Enable these test cases, and add expected output files for them.

tests/invalid/Mmakefile:
tests/invalid/circ_type3.m:
tests/invalid/circ_type3.err_exp:
	Add another test for circular equivalence types.

Workspace: /home/mars/fjh/ws1/mercury
Index: compiler/make_hlds.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/make_hlds.m,v
retrieving revision 1.426
diff -u -d -r1.426 make_hlds.m
--- compiler/make_hlds.m	10 Nov 2002 15:57:52 -0000	1.426
+++ compiler/make_hlds.m	22 Nov 2002 11:28:57 -0000
@@ -30,12 +30,12 @@
 :- import_module bool, list, io, std_util.
 
 % parse_tree_to_hlds(ParseTree, MQInfo, EqvMap, HLDS, QualInfo,
-%		UndefTypes, UndefModes):
+%		InvalidTypes, InvalidModes):
 %	Given MQInfo (returned by module_qual.m) and EqvMap (returned by
 %	equiv_type.m), converts ParseTree to HLDS.
 %	Any errors found are recorded in the HLDS num_errors field.
-%	Returns UndefTypes = yes if undefined types found.
-%	Returns UndefModes = yes if undefined modes found.
+%	Returns InvalidTypes = yes if undefined types found.
+%	Returns InvalidModes = yes if undefined or cyclic insts or modes found.
 %	QualInfo is an abstract type that is then passed back to
 %	produce_instance_method_clauses (see below).	
 :- pred parse_tree_to_hlds(compilation_unit, mq_info, eqv_map, module_info,
@@ -121,12 +121,13 @@
 :- import_module bag, term, varset, getopt, assoc_list, term_io.
 
 parse_tree_to_hlds(module(Name, Items), MQInfo0, EqvMap, Module, QualInfo,
-		UndefTypes, UndefModes) -->
+		InvalidTypes, InvalidModes) -->
 	globals__io_get_globals(Globals),
 	{ mq_info_get_partial_qualifier_info(MQInfo0, PQInfo) },
 	{ module_info_init(Name, Items, Globals, PQInfo, no, Module0) },
 	add_item_list_decls_pass_1(Items,
-		item_status(local, may_be_unqualified), Module0, Module1),
+		item_status(local, may_be_unqualified), Module0, Module1,
+		no, InvalidModes0),
 	globals__io_lookup_bool_option(statistics, Statistics),
 	maybe_report_stats(Statistics),
 	add_item_list_decls_pass_2(Items,
@@ -145,8 +146,9 @@
 	add_item_list_clauses(Items, local, Module4, Module5,
 				QualInfo0, QualInfo),
 	{ qual_info_get_mq_info(QualInfo, MQInfo) },
-	{ mq_info_get_type_error_flag(MQInfo, UndefTypes) },
-	{ mq_info_get_mode_error_flag(MQInfo, UndefModes) },
+	{ mq_info_get_type_error_flag(MQInfo, InvalidTypes) },
+	{ mq_info_get_mode_error_flag(MQInfo, InvalidModes1) },
+	{ InvalidModes = bool__or(InvalidModes0, InvalidModes1) },
 	{ mq_info_get_num_errors(MQInfo, MQ_NumErrors) },
 	{ module_info_num_errors(Module4, NumErrors0) },
 	{ NumErrors is NumErrors0 + MQ_NumErrors },
@@ -168,16 +170,22 @@
 	% Add the declarations one by one to the module,
 	% except for type definitions and pragmas.
 
+	% The `InvalidModes' bool records whether we detected
+	% any cyclic insts or modes.
+
 :- pred add_item_list_decls_pass_1(item_list, item_status,
-				module_info, module_info,
-				io__state, io__state).
-:- mode add_item_list_decls_pass_1(in, in, in, out, di, uo) is det.
+		module_info, module_info, bool, bool, io__state, io__state).
+:- mode add_item_list_decls_pass_1(in, in, in, out, in, out, di, uo) is det.
 
-add_item_list_decls_pass_1([], _, Module, Module) --> [].
-add_item_list_decls_pass_1([Item - Context | Items], Status0, Module0, Module)
-		-->
-	add_item_decl_pass_1(Item, Context, Status0, Module0, Status1, Module1),
-	add_item_list_decls_pass_1(Items, Status1, Module1, Module).
+add_item_list_decls_pass_1([], _, Module, Module, InvalidModes, InvalidModes)
+	--> [].
+add_item_list_decls_pass_1([Item - Context | Items], Status0, Module0, Module,
+		InvalidModes0, InvalidModes) -->
+	add_item_decl_pass_1(Item, Context, Status0, Module0,
+		Status1, Module1, InvalidModes1),
+	{ InvalidModes2 = bool__or(InvalidModes0, InvalidModes1) },
+	add_item_list_decls_pass_1(Items, Status1, Module1, Module,
+		InvalidModes2, InvalidModes).
 
 	% pass 2:
 	% Add the type definitions and pragmas one by one to the module,
@@ -227,33 +235,36 @@
 
 %-----------------------------------------------------------------------------%
 
-	% dispatch on the different types of items
+	% The bool records whether any cyclic insts or modes were
+	% detected.
 
-:- pred add_item_decl_pass_1(item, prog_context, item_status,
-		module_info, item_status, module_info, io__state, io__state).
-:- mode add_item_decl_pass_1(in, in, in, in, out, out, di, uo) is det.
+:- pred add_item_decl_pass_1(item, prog_context, item_status, module_info,
+		item_status, module_info, bool, io__state, io__state).
+:- mode add_item_decl_pass_1(in, in, in, in, out, out, out, di, uo) is det.
+
+	% Dispatch on the different types of items.
 
 	% skip clauses
-add_item_decl_pass_1(clause(_, _, _, _, _), _, Status, Module, Status, Module)
-		--> [].
+add_item_decl_pass_1(clause(_, _, _, _, _), _, Status, Module,
+		Status, Module, no) --> [].
 
 add_item_decl_pass_1(type_defn(_, _, _, _, _), _, Status, Module,
-		Status, Module) --> [].
+		Status, Module, no) --> [].
 
 add_item_decl_pass_1(inst_defn(VarSet, Name, Params, InstDefn, Cond), Context,
-		Status, Module0, Status, Module) -->
+		Status, Module0, Status, Module, InvalidMode) -->
 	module_add_inst_defn(Module0, VarSet, Name, Params,
-		InstDefn, Cond, Context, Status, Module).
+		InstDefn, Cond, Context, Status, Module, InvalidMode).
 
 add_item_decl_pass_1(mode_defn(VarSet, Name, Params, ModeDefn, Cond), Context,
-		Status, Module0, Status, Module) -->
+		Status, Module0, Status, Module, InvalidMode) -->
 	module_add_mode_defn(Module0, VarSet, Name, Params, ModeDefn,
-		Cond, Context, Status, Module).
+		Cond, Context, Status, Module, InvalidMode).
 
 add_item_decl_pass_1(pred_or_func(TypeVarSet, InstVarSet, ExistQVars,
 		PredOrFunc, PredName, TypesAndModes, _WithType, _WithInst,
 		MaybeDet, Cond, Purity, ClassContext),
-		Context, Status, Module0, Status, Module) -->
+		Context, Status, Module0, Status, Module, no) -->
 	{ init_markers(Markers) },
 	module_add_pred_or_func(Module0, TypeVarSet, InstVarSet, ExistQVars,
 		PredOrFunc, PredName, TypesAndModes, MaybeDet, Cond,
@@ -262,7 +273,7 @@
 add_item_decl_pass_1(
 		pred_or_func_mode(VarSet, MaybePredOrFunc, PredName,
 			Modes, _WithInst, MaybeDet, Cond),
-		Context, Status, Module0, Status, Module) -->
+		Context, Status, Module0, Status, Module, no) -->
 	( { MaybePredOrFunc = yes(PredOrFunc) } ->
 		{ Status = item_status(ImportStatus, _) },
 		{ IsClassMethod = no },
@@ -276,13 +287,13 @@
 		"add_item_decl_pass_1: no pred_or_func on mode declaration") }
 	).
 
-add_item_decl_pass_1(pragma(_), _, Status, Module, Status, Module) --> [].
+add_item_decl_pass_1(pragma(_), _, Status, Module, Status, Module, no) --> [].
 
-add_item_decl_pass_1(promise(_, _, _, _), _, Status, Module, Status, Module)
-	--> [].
+add_item_decl_pass_1(promise(_, _, _, _), _, Status, Module, Status, Module,
+		no) --> [].
 
 add_item_decl_pass_1(module_defn(_VarSet, ModuleDefn), Context,
-		Status0, Module0, Status, Module) -->
+		Status0, Module0, Status, Module, no) -->
 	( { module_defn_update_import_status(ModuleDefn, Status1) } ->
 		{ Status = Status1 },
 		{ Module = Module0 }
@@ -349,17 +360,17 @@
 		report_warning("Warning: declaration not yet implemented.\n")
 	).
 
-add_item_decl_pass_1(nothing(_), _, Status, Module, Status, Module) --> [].
+add_item_decl_pass_1(nothing(_), _, Status, Module, Status, Module, no) --> [].
 
 add_item_decl_pass_1(typeclass(Constraints, Name, Vars, Interface, VarSet), 
-		Context, Status, Module0, Status, Module) -->
+		Context, Status, Module0, Status, Module, no) -->
 	module_add_class_defn(Module0, Constraints, Name, Vars, Interface,
 		VarSet, Context, Status, Module).
 
 	% We add instance declarations on the second pass so that we don't add
 	% an instance declaration before its class declaration.
 add_item_decl_pass_1(instance(_, _, _, _, _,_), _, Status, Module, Status,
-	Module) --> [].
+	Module, no) --> [].
 
 %-----------------------------------------------------------------------------%
 
@@ -1803,18 +1814,28 @@
 
 :- pred module_add_inst_defn(module_info, inst_varset, sym_name, list(inst_var),
 		inst_defn, condition, prog_context, item_status, 
-		module_info, io__state, io__state).
+		module_info, bool, io__state, io__state).
 :- mode module_add_inst_defn(in, in, in, in, in, in, in, in,
-		out, di, uo) is det.
+		out, out, di, uo) is det.
 
 module_add_inst_defn(Module0, VarSet, Name, Args, InstDefn, Cond,
-		Context, item_status(Status, _NeedQual), Module) -->
+		Context, item_status(Status, _NeedQual),
+		Module, InvalidMode) -->
+	%
+	% add the definition of this inst to the HLDS inst table
+	%
 	{ module_info_insts(Module0, InstTable0) },
 	{ inst_table_get_user_insts(InstTable0, Insts0) },
 	insts_add(Insts0, VarSet, Name, Args, InstDefn, Cond,
 		Context, Status, Insts),
 	{ inst_table_set_user_insts(InstTable0, Insts, InstTable) },
-	{ module_info_set_insts(Module0, InstTable, Module) }.
+	{ module_info_set_insts(Module0, InstTable, Module) },
+	%
+	% check if the inst is infinitely recursive (at the top level)
+	%
+	{ Arity = list__length(Args) },
+	{ InstId = Name - Arity },
+	check_for_cyclic_inst(Insts, InstId, InstId, [], Context, InvalidMode).
 
 :- pred insts_add(user_inst_table, inst_varset, sym_name, list(inst_var),
 		inst_defn, condition, prog_context, import_status,
@@ -1848,44 +1869,146 @@
 			Context, OrigContext, _)
 	).
 
+	%
+	% check if the inst is infinitely recursive (at the top level)
+	%
+:- pred check_for_cyclic_inst(user_inst_table, inst_id, inst_id, list(inst_id),
+		prog_context, bool, io__state, io__state).
+:- mode check_for_cyclic_inst(in, in, in, in, in, out, di, uo) is det.
+
+check_for_cyclic_inst(UserInstTable, OrigInstId, InstId0, Expansions0,
+		Context, InvalidMode) -->
+	( { list__member(InstId0, Expansions0) } ->
+		report_circular_equiv_error("inst", OrigInstId, InstId0,
+			Expansions0, Context),
+		{ InvalidMode = yes }
+	;
+		{ user_inst_table_get_inst_defns(UserInstTable, InstDefns) },
+		(
+			{ map__search(InstDefns, InstId0, InstDefn) },
+			{ InstDefn = hlds_inst_defn(_, _, Body, _, _, _) },
+			{ Body = eqv_inst(EqvInst) },
+			{ EqvInst = defined_inst(user_inst(Name, Args)) }
+		->
+			{ Arity = list__length(Args) },
+			{ InstId = Name - Arity },
+			{ Expansions = [InstId0 | Expansions0] },
+			check_for_cyclic_inst(UserInstTable, OrigInstId,
+				InstId, Expansions, Context, InvalidMode)
+		;
+			{ InvalidMode = no }
+		)
+	).
+
 %-----------------------------------------------------------------------------%
 
 :- pred module_add_mode_defn(module_info, inst_varset, sym_name,
 		list(inst_var), mode_defn, condition, prog_context,
-		item_status, module_info, io__state, io__state).
+		item_status, module_info, bool, io__state, io__state).
 :- mode module_add_mode_defn(in, in, in, in, in, in, in,
-		in, out, di, uo) is det.
+		in, out, out, di, uo) is det.
 
 module_add_mode_defn(Module0, VarSet, Name, Params, ModeDefn, Cond,
-		Context, item_status(Status, _NeedQual), Module) -->
+		Context, item_status(Status, _NeedQual),
+		Module, InvalidMode) -->
 	{ module_info_modes(Module0, Modes0) },
 	modes_add(Modes0, VarSet, Name, Params, ModeDefn,
-		Cond, Context, Status, Modes),
+		Cond, Context, Status, Modes, InvalidMode),
 	{ module_info_set_modes(Module0, Modes, Module) }.
 
 :- pred modes_add(mode_table, inst_varset, sym_name, list(inst_var),
 		mode_defn, condition, prog_context, import_status,
-		mode_table, io__state, io__state).
-:- mode modes_add(in, in, in, in, in, in, in, in, out, di, uo) is det.
+		mode_table, bool, io__state, io__state).
+:- mode modes_add(in, in, in, in, in, in, in, in, out, out, di, uo) is det.
 
 modes_add(Modes0, VarSet, Name, Args, eqv_mode(Body),
-			Cond, Context, Status, Modes) -->
+			Cond, Context, Status, Modes, InvalidMode) -->
 	{ list__length(Args, Arity) },
+	{ ModeId = Name - Arity },
 	(
 		{ I = hlds_mode_defn(VarSet, Args, eqv_mode(Body), Cond,
 			Context, Status) },
-		{ mode_table_insert(Modes0, Name - Arity, I, Modes1) }
+		{ mode_table_insert(Modes0, ModeId, I, Modes1) }
 	->
 		{ Modes = Modes1 }
 	;
 		{ Modes = Modes0 },
 		{ mode_table_get_mode_defns(Modes, ModeDefns) },
-		{ map__lookup(ModeDefns, Name - Arity, OrigI) },
+		{ map__lookup(ModeDefns, ModeId, OrigI) },
 		{ OrigI = hlds_mode_defn(_, _, _, _, OrigContext, _) },
 		% XXX we should record each error using
 		% 	module_info_incr_errors
 		multiple_def_error(Status, Name, Arity, "mode",
 			Context, OrigContext, _)
+	),
+	check_for_cyclic_mode(Modes, ModeId, ModeId, [], Context,
+		InvalidMode).
+
+	%
+	% check if the mode is infinitely recursive at the top level
+	%
+:- pred check_for_cyclic_mode(mode_table, mode_id, mode_id, list(mode_id),
+		prog_context, bool, io__state, io__state).
+:- mode check_for_cyclic_mode(in, in, in, in, in, out, di, uo) is det.
+
+check_for_cyclic_mode(ModeTable, OrigModeId, ModeId0, Expansions0, Context,
+		InvalidMode) -->
+	( { list__member(ModeId0, Expansions0) } ->
+		report_circular_equiv_error("mode", OrigModeId, ModeId0,
+			Expansions0, Context),
+		{ InvalidMode = yes }
+	;
+		{ mode_table_get_mode_defns(ModeTable, ModeDefns) },
+		(
+			{ map__search(ModeDefns, ModeId0, ModeDefn) },
+			{ ModeDefn = hlds_mode_defn(_, _, Body, _, _, _) },
+			{ Body = eqv_mode(EqvMode) },
+			{ EqvMode = user_defined_mode(Name, Args) }
+		->
+			{ Arity = list__length(Args) },
+			{ ModeId = Name - Arity },
+			{ Expansions = [ModeId0 | Expansions0] },
+			check_for_cyclic_mode(ModeTable, OrigModeId, ModeId,
+				Expansions, Context, InvalidMode)
+		;
+			{ InvalidMode = no }
+		)
+	).
+
+:- type id == pair(sym_name, arity).
+:- pred report_circular_equiv_error(string::in, id::in, id::in, list(id)::in,
+		prog_context::in, io__state::di, io__state::uo) is det.
+
+report_circular_equiv_error(Kind, OrigId, Id, Expansions, Context) -->
+	( { Id = OrigId } ->
+		%
+		% Report an error message of the form
+		%	Error: circular equivalence <kind> foo/0.
+		% or
+		%	Error: circular equivalence <kind>s foo/0 and bar/1.
+		% or
+		%	Error: circular equivalence <kind>s foo/0, bar/1,
+		%	and baz/2.
+		% where <kind> is either "inst" or "mode".
+		%
+		{ Kinds = (if Expansions = [_] then Kind else Kind ++ "s") },
+		{ Pieces0 = list__map(
+			(func(SymName - Arity) =
+			    error_util__describe_sym_name_and_arity(
+			    	SymName / Arity)),
+			Expansions) },
+		{ error_util__list_to_pieces(Pieces0, Pieces1) },
+		{ Pieces = append_punctuation(
+			[words("Error: circular equivalence"),
+				fixed(Kinds) | Pieces1], '.') },
+		error_util__write_error_pieces(Context, 0, Pieces),
+		io__set_exit_status(1)
+	;
+		% We have an inst `OrigId' which is not itself circular,
+		% but which is defined in terms of `Id' which is circular.
+		% Don't bother reporting it now -- it have already been
+		% reported when we processed the definition of Id.
+		[]
 	).
 
 %-----------------------------------------------------------------------------%
Index: compiler/mercury_compile.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/mercury_compile.m,v
retrieving revision 1.267
diff -u -d -r1.267 mercury_compile.m
--- compiler/mercury_compile.m	31 Oct 2002 05:47:51 -0000	1.267
+++ compiler/mercury_compile.m	22 Nov 2002 11:00:38 -0000
@@ -1553,6 +1553,7 @@
 	    % error, since propagate_types_into_proc_modes
 	    % (in post_typecheck.m -- called by purity.m)
 	    % and mode analysis would get internal errors.
+	    % Also mode analysis can loop if there are cyclic insts/modes.
 	    %
 	    % We can't continue if the type inference iteration
 	    % limit was exceeeded because the code to resolve
Index: compiler/notes/compiler_design.html
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/notes/compiler_design.html,v
retrieving revision 1.79
diff -u -d -r1.79 compiler_design.html
--- compiler/notes/compiler_design.html	31 Oct 2002 05:47:59 -0000	1.79
+++ compiler/notes/compiler_design.html	22 Nov 2002 12:17:33 -0000
@@ -276,9 +276,9 @@
 
 <li> conversion to superhomogeneous form and into HLDS <br>
 
-	make_hlds.m transforms the code into superhomogeneous form,
+	make_hlds.m transforms the clauses into superhomogeneous form,
 	and at the same time converts the parse tree into the HLDS.
-	It expands away universal quantification
+	It expands away state variable syntax, universal quantification
 	(using `all [Vs] G' ===> `not (some [Vs] (not G))')
 	and implication (using `A => B' ===> `not(A, not B)').
 	It converts `pragma import', `pragma c_code' and `pragma fact_table'
@@ -291,6 +291,9 @@
 	make_hlds.m also calls make_tags.m which chooses the data
 	representation for each discriminated union type by
 	assigning tags to each functor.
+	make_hlds.m also performs a number of semantic checks,
+	such as checking for circular insts and modes
+	and warning about singleton variables.
 </ul>
 
 <p>
Index: tests/invalid/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/tests/invalid/Mmakefile,v
retrieving revision 1.130
diff -u -d -r1.130 Mmakefile
--- tests/invalid/Mmakefile	22 Nov 2002 09:00:51 -0000	1.130
+++ tests/invalid/Mmakefile	22 Nov 2002 11:39:28 -0000
@@ -34,8 +34,17 @@
 	bind_var_errors \
 	builtin_int \
 	builtin_proc \
+	circ_inst \
+	circ_inst2 \
+	circ_inst3 \
+	circ_inst4 \
+	circ_mode \
+	circ_mode2 \
+	circ_mode3 \
+	circ_mode4 \
 	circ_type \
 	circ_type2 \
+	circ_type3 \
 	constrained_poly_insts \
 	constructor_warning \
 	det_errors \
@@ -161,10 +170,6 @@
 #			the type class name should be in quotes)
 #	typeclass_mode_{2,3,4} (compiler calls error/1)
 #	cyclic_typeclass (compiler goes into an infinite loop)
-#	circ_inst{,2} (error is not detected)
-#	circ_inst{3,4} (compiler goes into an infinite loop)
-#	circ_mode{,2} (error is not detected)
-#	circ_mode{3,4} (compiler goes into an infinite loop)
 #	ho_default_func_4 (due to a bug in the mode-checker ---
 #			see XXX comment in inst_match:inst_matches_final_3)
 #	inst_matches_final_bug (due to same bug as ho_default_func_4)
Index: tests/invalid/circ_inst.err_exp
===================================================================
RCS file: tests/invalid/circ_inst.err_exp
diff -N tests/invalid/circ_inst.err_exp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/invalid/circ_inst.err_exp	22 Nov 2002 11:42:51 -0000
@@ -0,0 +1,4 @@
+circ_inst.m:006: Error: circular equivalence inst `circ_inst:circ/0'.
+circ_inst.m:010: Error: circular equivalence insts `circ_inst:circ1/0' and
+circ_inst.m:010:   `circ_inst:circ2/0'.
+For more information, try recompiling with `-E'.
Index: tests/invalid/circ_inst2.err_exp
===================================================================
RCS file: tests/invalid/circ_inst2.err_exp
diff -N tests/invalid/circ_inst2.err_exp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/invalid/circ_inst2.err_exp	22 Nov 2002 11:44:07 -0000
@@ -0,0 +1,6 @@
+circ_inst2.m:010: Error: circular equivalence inst `circ_inst2:circ1/1'.
+circ_inst2.m:011: Error: circular equivalence inst `circ_inst2:circ2/1'.
+circ_inst2.m:013: Error: circular equivalence inst `circ_inst2:circ4/1'.
+circ_inst2.m:016: Error: circular equivalence insts `circ_inst2:left/1' and
+circ_inst2.m:016:   `circ_inst2:right/1'.
+For more information, try recompiling with `-E'.
Index: tests/invalid/circ_inst2.m
===================================================================
RCS file: /home/mercury1/repository/tests/invalid/circ_inst2.m,v
retrieving revision 1.2
diff -u -d -r1.2 circ_inst2.m
--- tests/invalid/circ_inst2.m	22 Nov 2002 09:00:52 -0000	1.2
+++ tests/invalid/circ_inst2.m	22 Nov 2002 11:43:32 -0000
@@ -10,7 +10,7 @@
 :- inst circ1(I) == circ1(I).			% error -- cyclic
 :- inst circ2(I) == circ2(circ2(I)).		% error -- cyclic
 :- inst circ3(I) == list_skel(circ3(I)).	% OK
-:- inst circ4(I) == circ4(list_skel(I)).	% OK
+:- inst circ4(I) == circ4(list_skel(I)).	% error -- cyclic
 
 :- inst left(I) == right(I).			% error -- cyclic
 :- inst right(I) == left(I).			% error -- cyclic
Index: tests/invalid/circ_inst3.err_exp
===================================================================
RCS file: tests/invalid/circ_inst3.err_exp
diff -N tests/invalid/circ_inst3.err_exp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/invalid/circ_inst3.err_exp	22 Nov 2002 10:47:08 -0000
@@ -0,0 +1,3 @@
+circ_inst3.m:009: Error: circular equivalence inst `circ_inst3:circ/0'.
+circ_inst3.m:013: Error: circular equivalence insts `circ_inst3:circ1/0' and
+circ_inst3.m:013:   `circ_inst3:circ2/0'.
Index: tests/invalid/circ_inst4.err_exp
===================================================================
RCS file: tests/invalid/circ_inst4.err_exp
diff -N tests/invalid/circ_inst4.err_exp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/invalid/circ_inst4.err_exp	22 Nov 2002 11:44:58 -0000
@@ -0,0 +1,6 @@
+circ_inst4.m:010: Error: circular equivalence inst `circ_inst4:circ1/1'.
+circ_inst4.m:011: Error: circular equivalence inst `circ_inst4:circ2/1'.
+circ_inst4.m:013: Error: circular equivalence inst `circ_inst4:circ4/1'.
+circ_inst4.m:016: Error: circular equivalence insts `circ_inst4:left/1' and
+circ_inst4.m:016:   `circ_inst4:right/1'.
+For more information, try recompiling with `-E'.
Index: tests/invalid/circ_mode.err_exp
===================================================================
RCS file: tests/invalid/circ_mode.err_exp
diff -N tests/invalid/circ_mode.err_exp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/invalid/circ_mode.err_exp	22 Nov 2002 11:45:06 -0000
@@ -0,0 +1,4 @@
+circ_mode.m:006: Error: circular equivalence mode `circ_mode:circ/0'.
+circ_mode.m:010: Error: circular equivalence modes `circ_mode:circ1/0' and
+circ_mode.m:010:   `circ_mode:circ2/0'.
+For more information, try recompiling with `-E'.
Index: tests/invalid/circ_mode2.err_exp
===================================================================
RCS file: tests/invalid/circ_mode2.err_exp
diff -N tests/invalid/circ_mode2.err_exp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/invalid/circ_mode2.err_exp	22 Nov 2002 11:45:15 -0000
@@ -0,0 +1,5 @@
+circ_mode2.m:010: Error: circular equivalence mode `circ_mode2:circ1/1'.
+circ_mode2.m:011: Error: circular equivalence mode `circ_mode2:circ2/1'.
+circ_mode2.m:014: Error: circular equivalence modes `circ_mode2:left/1' and
+circ_mode2.m:014:   `circ_mode2:right/1'.
+For more information, try recompiling with `-E'.
Index: tests/invalid/circ_mode3.err_exp
===================================================================
RCS file: tests/invalid/circ_mode3.err_exp
diff -N tests/invalid/circ_mode3.err_exp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/invalid/circ_mode3.err_exp	22 Nov 2002 11:45:29 -0000
@@ -0,0 +1,4 @@
+circ_mode3.m:009: Error: circular equivalence mode `circ_mode3:circ/0'.
+circ_mode3.m:013: Error: circular equivalence modes `circ_mode3:circ1/0' and
+circ_mode3.m:013:   `circ_mode3:circ2/0'.
+For more information, try recompiling with `-E'.
Index: tests/invalid/circ_mode4.err_exp
===================================================================
RCS file: tests/invalid/circ_mode4.err_exp
diff -N tests/invalid/circ_mode4.err_exp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/invalid/circ_mode4.err_exp	22 Nov 2002 11:45:44 -0000
@@ -0,0 +1,5 @@
+circ_mode4.m:010: Error: circular equivalence mode `circ_mode4:circ1/1'.
+circ_mode4.m:011: Error: circular equivalence mode `circ_mode4:circ2/1'.
+circ_mode4.m:014: Error: circular equivalence modes `circ_mode4:left/1' and
+circ_mode4.m:014:   `circ_mode4:right/1'.
+For more information, try recompiling with `-E'.
Index: tests/invalid/circ_type3.err_exp
===================================================================
RCS file: tests/invalid/circ_type3.err_exp
diff -N tests/invalid/circ_type3.err_exp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/invalid/circ_type3.err_exp	22 Nov 2002 10:37:29 -0000
@@ -0,0 +1,4 @@
+circ_type3.m:008: Error: circular equivalence type `circ_type3:circ/0'.
+circ_type3.m:010: Error: circular equivalence type `circ_type3:circ1/0'.
+circ_type3.m:012: Error: circular equivalence type `circ_type3:circ2/0'.
+For more information, try recompiling with `-E'.
Index: tests/invalid/circ_type3.m
===================================================================
RCS file: tests/invalid/circ_type3.m
diff -N tests/invalid/circ_type3.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/invalid/circ_type3.m	22 Nov 2002 11:43:32 -0000
@@ -0,0 +1,18 @@
+% Test for circular equivalence types.
+% This is the same as circ_type.m, except that we also have 
+% a predicate that uses the types.
+:- module circ_type3.
+
+:- interface.
+
+:- type circ == circ.
+
+:- type circ1 == circ2.
+
+:- type circ2 == circ1.
+
+:- pred p(circ, circ1, circ2).
+:- mode p(in, in, out) is det.
+
+:- implementation.
+p(_, X, X).
-- 
Fergus Henderson <fjh at cs.mu.oz.au>  |  "I have always known that the pursuit
The University of Melbourne         |  of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh>  |     -- the last words of T. S. Garp.
--------------------------------------------------------------------------
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