[m-rev.] diff: fix ill-typed comparison abort

Simon Taylor stayl at cs.mu.OZ.AU
Thu Aug 21 02:05:13 AEST 2003


Estimated hours taken: 5
Branches: main

Fix a bug reported by Fergus, which caused an abort when a
user-defined unification or comparison predicate was ill-typed.

compiler/intermod.m:
	Don't attempt to module qualify the unification
	and comparison routines for type declarations that
	won't be used on the current back-end -- they won't
	have been typechecked. They will be ignored when read
	back in, but we put them in the `.opt' file because
	it is sometimes useful to test compiling a module
	against a workspace using a grade different to that
	used to build the workspace.

compiler/type_util.m:
	Choose the correct unification/comparison predicates for
	the current back-end where there are both Mercury and
	foreign definitions for a type.

compiler/make_hlds.m:
compiler/foreign.m:
	Move have_foreign_type_for_backend to foreign.m, for
	use by intermod.m. 

doc/reference_manual.texi:
	Clarify the documentation about user-defined unification and
	comparison predicates for foreign types.

tests/invalid/Mmakefile:
tests/invalid/illtyped_compare.{m,err_exp}:
	Add a test case.
	
tests/invalid/make_opt_error.{m,err_exp}:
	This change caused the error in this test case to not
	be reported any more (it occurred in code not used
	on the back-end being compiled for). Fix the test 
	so an error is reported.

Index: compiler/foreign.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/foreign.m,v
retrieving revision 1.29
diff -u -u -r1.29 foreign.m
--- compiler/foreign.m	25 Jul 2003 02:27:19 -0000	1.29
+++ compiler/foreign.m	20 Aug 2003 07:13:20 -0000
@@ -77,6 +77,11 @@
 	% exported_type representation of that type.
 :- func foreign__non_foreign_type((type)) = exported_type.
 
+	% Does the foreign_type_body contain a definition usable
+	% when compiling to the given target.
+:- pred have_foreign_type_for_backend(compilation_target::in,
+		foreign_type_body::in, bool::out) is det.
+
 	% Given an arbitary mercury type, get the exported_type representation
 	% of that type on the current backend.
 :- func foreign__to_exported_type(module_info, (type)) = exported_type.
@@ -655,6 +660,15 @@
 	).
 
 %-----------------------------------------------------------------------------%
+
+have_foreign_type_for_backend(c, ForeignTypeBody,
+		( ForeignTypeBody ^ c = yes(_) -> yes ; no )).
+have_foreign_type_for_backend(il, ForeignTypeBody,
+		( ForeignTypeBody ^ il = yes(_) -> yes ; no )).
+have_foreign_type_for_backend(java, ForeignTypeBody, 
+		( ForeignTypeBody ^ java = yes(_) -> yes ; no )).
+have_foreign_type_for_backend(asm, ForeignTypeBody, Result) :-
+	have_foreign_type_for_backend(c, ForeignTypeBody, Result).
 
 :- type exported_type
 	--->	foreign(sym_name)	% A type defined by a
Index: compiler/intermod.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/intermod.m,v
retrieving revision 1.144
diff -u -u -r1.144 intermod.m
--- compiler/intermod.m	25 Jul 2003 02:27:20 -0000	1.144
+++ compiler/intermod.m	20 Aug 2003 07:20:22 -0000
@@ -1036,19 +1036,34 @@
 		TypeBody0 = du_type(Ctors, Tags, Enum, MaybeUserEqComp0,
 			ReservedTag, IsSolverType, MaybeForeign0)
 	    ->
-		intermod__resolve_unify_compare_overloading(ModuleInfo,
-			TypeCtor, MaybeUserEqComp0, MaybeUserEqComp,
-			Info1, Info2),
+		module_info_globals(ModuleInfo, Globals),
+		globals__get_target(Globals, Target),
+
+		%
+		% Note that we don't resolve overloading for the definitions
+		% which won't be used on this back-end, because their
+		% unification and comparison predicates have not been
+		% typechecked. They are only written to the `.opt' it
+		% can be handy when building against a workspace for
+		% the other definitions to be present (e.g. when testing
+		% compiling a module to IL when the workspace was compiled
+		% to C).
+		%
 		(
-			MaybeForeign0 = yes(Foreign0),
+			MaybeForeign0 = yes(ForeignTypeBody0),
+			have_foreign_type_for_backend(Target,
+				ForeignTypeBody0, yes)
+		->
 			intermod__resolve_foreign_type_body_overloading(
-				ModuleInfo, TypeCtor, Foreign0, Foreign,
-				Info2, Info3),
-			MaybeForeign = yes(Foreign)
+				ModuleInfo, TypeCtor, ForeignTypeBody0,
+				ForeignTypeBody, Info1, Info3),
+			MaybeForeign = yes(ForeignTypeBody),
+			MaybeUserEqComp = MaybeUserEqComp0	
 		;
-			MaybeForeign0 = no,
-			MaybeForeign = no,
-			Info3 = Info2
+			intermod__resolve_unify_compare_overloading(ModuleInfo,
+				TypeCtor, MaybeUserEqComp0, MaybeUserEqComp,
+				Info1, Info3),
+			MaybeForeign = MaybeForeign0
 		),
 		TypeBody = du_type(Ctors, Tags, Enum, MaybeUserEqComp,
 				ReservedTag, IsSolverType, MaybeForeign),
@@ -1078,13 +1093,38 @@
 
 intermod__resolve_foreign_type_body_overloading(ModuleInfo,
 		TypeCtor, foreign_type_body(MaybeIL0, MaybeC0, MaybeJava0),
-		foreign_type_body(MaybeIL, MaybeC, MaybeJava), Info0, Info) :-
-	intermod__resolve_foreign_type_body_overloading_2(ModuleInfo, TypeCtor,
-		MaybeC0, MaybeC, Info0, Info1),
-	intermod__resolve_foreign_type_body_overloading_2(ModuleInfo, TypeCtor,
-		MaybeIL0, MaybeIL, Info1, Info2),
-	intermod__resolve_foreign_type_body_overloading_2(ModuleInfo, TypeCtor,
-		MaybeJava0, MaybeJava, Info2, Info).
+		foreign_type_body(MaybeIL, MaybeC, MaybeJava)) -->
+	{ module_info_globals(ModuleInfo, Globals) },
+	{ globals__get_target(Globals, Target) },
+
+	%
+	% Note that we don't resolve overloading for the foreign
+	% definitions which won't be used on this back-end, because
+	% their unification and comparison predicates have not been
+	% typechecked.
+	% They are only written to the `.opt' it can be handy when
+	% building against a workspace for the other definitions to
+	% be present (e.g. when testing compiling a module to IL when
+	% the workspace was compiled to C).
+	%
+	( { Target = c ; Target = asm } ->
+		intermod__resolve_foreign_type_body_overloading_2(ModuleInfo,
+			TypeCtor, MaybeC0, MaybeC)
+	;
+		{ MaybeC = MaybeC0 }
+	),
+	( { Target = il } ->
+		intermod__resolve_foreign_type_body_overloading_2(ModuleInfo,
+			TypeCtor, MaybeIL0, MaybeIL)
+	;
+		{ MaybeIL = MaybeIL0 }
+	),
+	( { Target = java } ->
+		intermod__resolve_foreign_type_body_overloading_2(ModuleInfo,
+			TypeCtor, MaybeJava0, MaybeJava)
+	;
+		{ MaybeJava = MaybeJava0 }
+	).
 
 :- pred intermod__resolve_foreign_type_body_overloading_2(module_info::in,
 		type_ctor::in, foreign_type_lang_body(T)::in,
Index: compiler/make_hlds.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/make_hlds.m,v
retrieving revision 1.444
diff -u -u -r1.444 make_hlds.m
--- compiler/make_hlds.m	25 Jul 2003 02:27:20 -0000	1.444
+++ compiler/make_hlds.m	20 Aug 2003 07:07:39 -0000
@@ -2588,18 +2588,6 @@
 		{ Module = Module0 }
 	).
 
-:- pred have_foreign_type_for_backend(compilation_target::in,
-		foreign_type_body::in, bool::out) is det.
-
-have_foreign_type_for_backend(c, ForeignTypeBody,
-		( ForeignTypeBody ^ c = yes(_) -> yes ; no )).
-have_foreign_type_for_backend(il, ForeignTypeBody,
-		( ForeignTypeBody ^ il = yes(_) -> yes ; no )).
-have_foreign_type_for_backend(java, ForeignTypeBody, 
-		( ForeignTypeBody ^ java = yes(_) -> yes ; no )).
-have_foreign_type_for_backend(asm, ForeignTypeBody, Result) :-
-	have_foreign_type_for_backend(c, ForeignTypeBody, Result).
-
 	% Do the options imply that we will generate code for a specific
 	% back-end?
 :- pred generating_code(bool::out, io::di, io::uo) is det.
Index: compiler/type_util.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/type_util.m,v
retrieving revision 1.123
diff -u -u -r1.123 type_util.m
--- compiler/type_util.m	25 Jul 2003 02:27:26 -0000	1.123
+++ compiler/type_util.m	20 Aug 2003 13:58:52 -0000
@@ -738,13 +738,24 @@
 		UserEqComp).
 
 type_body_has_user_defined_equality_pred(ModuleInfo, TypeBody, UserEqComp) :-
-	(
-		TypeBody ^ du_type_usereq = yes(UserEqComp)
-	;
-		TypeBody = foreign_type(ForeignTypeBody, _),
-		UserEqComp = foreign_type_body_has_user_defined_equality_pred(
-				ModuleInfo, ForeignTypeBody)
-	).
+    module_info_globals(ModuleInfo, Globals),
+    globals__get_target(Globals, Target),
+    (
+	TypeBody = du_type(_, _, _, _, _, _, _),
+        (
+	    TypeBody ^ du_type_is_foreign_type = yes(ForeignTypeBody),
+            have_foreign_type_for_backend(Target, ForeignTypeBody, yes)
+	->
+            UserEqComp = foreign_type_body_has_user_defined_equality_pred(
+                                ModuleInfo, ForeignTypeBody)
+        ;
+            TypeBody ^ du_type_usereq = yes(UserEqComp)
+        )
+    ;
+        TypeBody = foreign_type(ForeignTypeBody, _),
+        UserEqComp = foreign_type_body_has_user_defined_equality_pred(
+                        ModuleInfo, ForeignTypeBody)
+    ).
 
 type_util__is_solver_type(ModuleInfo, Type) :-
 	module_info_types(ModuleInfo, TypeTable),
Index: doc/reference_manual.texi
===================================================================
RCS file: /home/mercury1/repository/mercury/doc/reference_manual.texi,v
retrieving revision 1.278
diff -u -u -r1.278 reference_manual.texi
--- doc/reference_manual.texi	1 Aug 2003 04:29:24 -0000	1.278
+++ doc/reference_manual.texi	20 Aug 2003 04:24:01 -0000
@@ -5672,7 +5672,7 @@
 are @samp{foreign_type} declarations for the type. 
 
 As with discriminated union types, programmers can specify the unification
-and comparison predicates to use for values of the type using the following
+and/or comparison predicates to use for values of the type using the following
 syntax (@pxref{User-defined equality and comparison}):
 
 @example
Index: tests/invalid/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/tests/invalid/Mmakefile,v
retrieving revision 1.140
diff -u -u -r1.140 Mmakefile
--- tests/invalid/Mmakefile	3 Aug 2003 13:33:23 -0000	1.140
+++ tests/invalid/Mmakefile	20 Aug 2003 03:40:43 -0000
@@ -74,6 +74,7 @@
 	ho_default_func_3 \
 	ho_type_mode_bug \
 	ho_unique_error \
+	illtyped_compare \
 	impure_method_impl \
 	inline_conflict \
 	inst_list_dup \
@@ -251,6 +252,14 @@
 # This test case tests that we set the error status correctly
 # when building the `.opt' files.
 make_opt_error.err: make_opt_error.m
+	if $(MC) $(ALL_GRADEFLAGS) $(ALL_MCFLAGS) \
+			--make-optimization-interface $* > $*.err 2>&1; \
+	then false; \
+	else true; \
+	fi
+
+# This test case tests that we don't abort when building the `.opt' files.
+illtyped_compare.err: illtyped_compare.m
 	if $(MC) $(ALL_GRADEFLAGS) $(ALL_MCFLAGS) \
 			--make-optimization-interface $* > $*.err 2>&1; \
 	then false; \
Index: tests/invalid/illtyped_compare.err_exp
===================================================================
RCS file: tests/invalid/illtyped_compare.err_exp
diff -N tests/invalid/illtyped_compare.err_exp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/invalid/illtyped_compare.err_exp	20 Aug 2003 03:41:05 -0000
@@ -0,0 +1,17 @@
+illtyped_compare.m:015: In clause for unification predicate for type illtyped_compare.bar_rep:
+illtyped_compare.m:015:   in argument 2 of call to predicate `illtyped_compare.compare_bar/3':
+illtyped_compare.m:015:   type error: variable `HeadVar__1' has type `(illtyped_compare.bar_rep)',
+illtyped_compare.m:015:   expected type was `(illtyped_compare.bar)'.
+illtyped_compare.m:015: In clause for unification predicate for type illtyped_compare.bar_rep:
+illtyped_compare.m:015:   in argument 3 of call to predicate `illtyped_compare.compare_bar/3':
+illtyped_compare.m:015:   type error: variable `HeadVar__2' has type `(illtyped_compare.bar_rep)',
+illtyped_compare.m:015:   expected type was `(illtyped_compare.bar)'.
+illtyped_compare.m:015: In clause for comparison predicate for type illtyped_compare.bar_rep:
+illtyped_compare.m:015:   in argument 2 of call to predicate `illtyped_compare.compare_bar/3':
+illtyped_compare.m:015:   type error: variable `HeadVar__2' has type `(illtyped_compare.bar_rep)',
+illtyped_compare.m:015:   expected type was `(illtyped_compare.bar)'.
+illtyped_compare.m:015: In clause for comparison predicate for type illtyped_compare.bar_rep:
+illtyped_compare.m:015:   in argument 3 of call to predicate `illtyped_compare.compare_bar/3':
+illtyped_compare.m:015:   type error: variable `HeadVar__3' has type `(illtyped_compare.bar_rep)',
+illtyped_compare.m:015:   expected type was `(illtyped_compare.bar)'.
+For more information, try recompiling with `-E'.
Index: tests/invalid/illtyped_compare.m
===================================================================
RCS file: tests/invalid/illtyped_compare.m
diff -N tests/invalid/illtyped_compare.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/invalid/illtyped_compare.m	20 Aug 2003 04:28:20 -0000
@@ -0,0 +1,25 @@
+:- module illtyped_compare.
+
+:- interface.
+
+:- type bar.
+
+:- implementation.
+:- type bar ---> bar(bar_rep).
+
+% This comparison predicate is ill-typed.
+:- type bar_rep ---> bar_rep(int)
+		where comparison is compare_bar_rep.
+:- pragma foreign_type("C", bar_rep, "long") 
+		where comparison is compare_bar.
+:- pragma foreign_type("IL", bar_rep, "valuetype [mscorlib]System.Double")
+		where comparison is compare_bar.
+
+:- pred compare_bar(comparison_result::uo, bar::in, bar::in) is det.
+
+compare_bar((=), _, _).
+
+:- pred compare_bar_rep(comparison_result::uo,
+		bar_rep::in, bar_rep::in) is det.
+
+compare_bar_rep((=), _, _).
Index: tests/invalid/make_opt_error.err_exp
===================================================================
RCS file: /home/mercury1/repository/tests/invalid/make_opt_error.err_exp,v
retrieving revision 1.1
diff -u -u -r1.1 make_opt_error.err_exp
--- tests/invalid/make_opt_error.err_exp	17 Feb 2003 06:02:23 -0000	1.1
+++ tests/invalid/make_opt_error.err_exp	19 Aug 2003 15:56:42 -0000
@@ -1,5 +1,5 @@
-make_opt_error.m:101: Error: clause for automatically generated field access
-make_opt_error.m:101:   function `make_opt_error.x/1'.
-make_opt_error.m:102: Error: clause for automatically generated field access
-make_opt_error.m:102:   function `make_opt_error.y/1'.
+make_opt_error.m:014: Error: clause for automatically generated field access
+make_opt_error.m:014:   function `make_opt_error.x/1'.
+make_opt_error.m:015: Error: clause for automatically generated field access
+make_opt_error.m:015:   function `make_opt_error.y/1'.
 For more information, try recompiling with `-E'.
Index: tests/invalid/make_opt_error.m
===================================================================
RCS file: /home/mercury1/repository/tests/invalid/make_opt_error.m,v
retrieving revision 1.1
diff -u -u -r1.1 make_opt_error.m
--- tests/invalid/make_opt_error.m	17 Feb 2003 06:02:23 -0000	1.1
+++ tests/invalid/make_opt_error.m	19 Aug 2003 15:56:36 -0000
@@ -2,104 +2,14 @@
 
 :- interface.
 
-:- import_module io.
-
-:- pred main(io__state::di, io__state::uo) is det.
-
-:- implementation.
-
 :- type coord.
 
-:- func new(int, int) = coord.
-:- pragma export(new(in, in) = out, "exported_new").
-
 :- func x(coord) = int.
 :- func y(coord) = int.
 
-main -->
-	{ C = new(4, 5) },
-	io__write_string("X:"),
-	io__write_int(x(C)),
-	io__nl,
-	io__write_string("Y:"),
-	io__write_int(y(C)),
-	io__nl.
-
-%----------------------------------------------------------------------------%
-%----------------------------------------------------------------------------%
-%----------------------------------------------------------------------------%
-
-% IL implementation
-:- pragma foreign_type(il, coord,
-	"class [foreign_type__csharp_code]coord").
-
-:- pragma foreign_decl("C#", "
-public class coord {
-	public int x;
-	public int y;
-}
-").
-
-:- pragma foreign_proc("C#", new(X::in, Y::in) = (C::out),
-	[will_not_call_mercury, promise_pure],
-"
-	C = new coord();
-	C.x = X;
-	C.y = Y;
-").
-
-:- pragma foreign_proc("C#", x(C::in) = (X::out),
-	[will_not_call_mercury, promise_pure],
-"
-	X = C.x;
-").
-
-:- pragma foreign_proc("C#", y(C::in) = (Y::out),
-	[will_not_call_mercury, promise_pure],
-"
-	Y = C.y;
-").
-
-%----------------------------------------------------------------------------%
-%----------------------------------------------------------------------------%
-
-% C implementation
-:- pragma foreign_type(c, coord, "coord *").
-
-:- pragma foreign_decl(c, "
-typedef struct {
-	int x, y;
-} coord;
-").
-
-:- pragma foreign_proc(c, new(X::in, Y::in) = (C::out),
-	[will_not_call_mercury, promise_pure],
-"
-	C = MR_GC_NEW(coord);
-	C->x = X;
-	C->y = Y;
-").
-
-:- pragma foreign_proc(c, x(C::in) = (X::out),
-	[will_not_call_mercury, promise_pure],
-"
-	X = C->x;
-").
-
-:- pragma foreign_proc(c, y(C::in) = (Y::out),
-	[will_not_call_mercury, promise_pure],
-"
-	Y = C->y;
-").
-
-%----------------------------------------------------------------------------%
+:- implementation.
 
-% Mercury implementation
 :- type coord ---> coord(x :: int, y :: int).
 
-new(X, Y) = coord(X, Y).
 x(C) = C ^ x.
 y(C) = C ^ y.
-
-%----------------------------------------------------------------------------%
-%----------------------------------------------------------------------------%
--------------------------------------------------------------------------
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