[m-rev.] for review: check that abstract type declarations have definitions

Julien Fischer juliensf at cs.mu.OZ.AU
Fri Apr 22 10:46:39 AEST 2005


Estimated hours taken: 10
Branches: main, release

Check that abstract type declarations do actually have a
corresponding definition somewhere in the module.  Emit
an error message if an abstract type declarations does not
have a corresponding definition.

compiler/post_typecheck.m:
	Check that abstract type declarations have a corresponding
	definition somewhere in the module.  Emit an error message
	if they do not.

compiler/gcc.m:
	Comment an abstract type declaration that does not have
	a corresponding definition.

compiler/typecheck.m:
	Module qualify the names of predicates in the error message
	about predicates have no clauses.

tests/invalid/Mmakefile:
tests/invalid/type_with_no_defn.m:
tests/invalid/type_with_no_defn.err_exp:
	Add a test case for the above.

tests/invalid/*:
	Update test cases and expected error outputs as
	necessary.

Julien.

Workspace:/home/swordfish/juliensf/ws75
Index: compiler/gcc.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/gcc.m,v
retrieving revision 1.32
diff -u -r1.32 gcc.m
--- compiler/gcc.m	24 Mar 2005 02:00:25 -0000	1.32
+++ compiler/gcc.m	21 Apr 2005 08:18:14 -0000
@@ -184,7 +184,10 @@
 %

 % A GCC `tree' representing a declaration.
-:- type gcc__decl.
+% XXX This doesn't have a definition and appears to be unused anyway.
+% - juliensf
+%
+%:- type gcc__decl.

 %
 % Stuff for variable declarations
Index: compiler/post_typecheck.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/post_typecheck.m,v
retrieving revision 1.72
diff -u -r1.72 post_typecheck.m
--- compiler/post_typecheck.m	1 Apr 2005 14:28:59 -0000	1.72
+++ compiler/post_typecheck.m	21 Apr 2005 08:20:26 -0000
@@ -21,6 +21,8 @@
 %	- it reports errors for unsatisfied type class constraints
 %	- it reports an error if there are indistinguishable modes for
 %	  a predicate of function.
+%	- it checks that declarations for abstract types also have a
+%	  corresponding definition somewhere in the module.
 %
 % These actions cannot be done until after type inference is complete,
 % so they need to be a separate "post-typecheck pass".  For efficiency
@@ -118,6 +120,7 @@
 	hlds_goal::out) is det.

 %-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%

 :- implementation.

@@ -147,7 +150,6 @@
 :- import_module require.
 :- import_module set.
 :- import_module string.
-:- import_module term.
 :- import_module varset.

 %-----------------------------------------------------------------------------%
@@ -155,7 +157,10 @@
 post_typecheck__finish_preds(PredIds, ReportTypeErrors, NumErrors,
 		FoundTypeError, !ModuleInfo, !IO) :-
 	post_typecheck__finish_preds(PredIds, ReportTypeErrors,
-		!ModuleInfo, 0, NumErrors, no, FoundTypeError, !IO).
+		!ModuleInfo, 0, NumErrors0, no, FoundTypeError0, !IO),
+	check_for_missing_definitions(!.ModuleInfo,
+		NumErrors0, NumErrors, FoundTypeError0, FoundTypeError,
+		!IO).

 :- pred post_typecheck__finish_preds(list(pred_id)::in, bool::in,
 	module_info::in, module_info::out, int::in, int::out,
@@ -1651,4 +1656,80 @@
 	map__det_insert(!.VarTypes, Var, Type, !:VarTypes).

 %-----------------------------------------------------------------------------%
+%
+% Check that every abstract type in a module has at least one definition
+% in either the interface or implementation of the module.  A type may
+% have several definitions, e.g. some foreign definitions and a default
+% Mercury definition.
+%
+
+:- pred check_for_missing_definitions(module_info::in,
+	int::in, int::out, bool::in, bool::out, io::di, io::uo) is det.
+
+check_for_missing_definitions(ModuleInfo, !NumErrors, !FoundTypeError,
+		!IO) :-
+	module_info_types(ModuleInfo, TypeTable),
+	map.foldl3(check_for_missing_definitions_2, TypeTable,
+		 !NumErrors, !FoundTypeError, !IO).
+
+:- pred check_for_missing_definitions_2(type_ctor::in, hlds_type_defn::in,
+	int::in, int::out, bool::in, bool::out, io::di, io::uo) is det.
+
+check_for_missing_definitions_2(TypeCtor, TypeDefn, !NumErrors,
+		!FoundTypeError, !IO) :-
+	(
+		get_type_defn_status(TypeDefn, ImportStatus),
+		status_defined_in_this_module(ImportStatus, LocalDefn),
+		LocalDefn = yes,
+		get_type_defn_body(TypeDefn, TypeBody),
+		TypeBody = abstract_type(_)
+	->
+		% We expect builtin types character, float, int and
+		% string to have abstract declarations with no
+		% definitions.  The following types from the type_desc
+		% module also only have abstract declarations:
+		%
+		% 	- type_desc/0
+		% 	- pseudo_type_desc/0
+		% 	- type_ctor_desc/0
+		%
+		% We do not emit an error for these types.  In addition,
+		% we also don't bother checking for corresponding
+		% definitions in any of the builtin modules in the
+		% standard library.
+		%
+		TypeCtor = SymName - Arity,
+		BuiltinTypeCtors = builtin_type_ctors_with_no_hlds_type_defn,
+		(
+			sym_name_get_module_name(SymName, ModuleName),
+			not any_mercury_builtin_module(ModuleName),
+			%
+			% Several of the type defined in type_desc do not
+			% have Mercury definitions.
+			%
+			not ModuleName = unqualified("type_desc"),
+			not list.member(TypeCtor, BuiltinTypeCtors)
+		->
+			ErrorPieces = [
+				words("Error: abstract"),
+				words("declaration for type"),
+				sym_name_and_arity(SymName / Arity),
+				words("has no corresponding"),
+				words("definition.")
+			],
+			get_type_defn_context(TypeDefn, TypeContext),
+			write_error_pieces(TypeContext, 0,
+				ErrorPieces, !IO),
+			io.set_exit_status(1, !IO),
+			!:FoundTypeError = yes,
+			!:NumErrors = !.NumErrors + 1
+		;
+			true
+		)
+	;
+		true
+	).
+
+%-----------------------------------------------------------------------------%
+:- end_module post_typecheck.
 %-----------------------------------------------------------------------------%
Index: compiler/typecheck.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/typecheck.m,v
retrieving revision 1.370
diff -u -r1.370 typecheck.m
--- compiler/typecheck.m	20 Apr 2005 12:57:17 -0000	1.370
+++ compiler/typecheck.m	22 Apr 2005 00:24:38 -0000
@@ -5157,7 +5157,7 @@
 report_no_clauses(MessageKind, PredId, PredInfo, ModuleInfo, !IO) :-
 	pred_info_context(PredInfo, Context),
 	PredPieces = describe_one_pred_name(ModuleInfo,
-		should_not_module_qualify, PredId),
+		should_module_qualify, PredId),
 	ErrorMsg = [words(MessageKind ++ ": no clauses for ") | PredPieces] ++
 		[suffix(".")],
 	error_util__write_error_pieces(Context, 0, ErrorMsg, !IO).
Index: tests/invalid/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/tests/invalid/Mmakefile,v
retrieving revision 1.165
diff -u -r1.165 Mmakefile
--- tests/invalid/Mmakefile	20 Apr 2005 12:57:44 -0000	1.165
+++ tests/invalid/Mmakefile	20 Apr 2005 23:26:53 -0000
@@ -169,6 +169,7 @@
 	type_mismatch \
 	types	\
 	type_vars \
+	type_with_no_defn \
 	unbound_type_vars \
 	undeclared_mode \
 	undef_inst \
Index: tests/invalid/import_in_parent.err_exp
===================================================================
RCS file: /home/mercury1/repository/tests/invalid/import_in_parent.err_exp,v
retrieving revision 1.2
diff -u -r1.2 import_in_parent.err_exp
--- tests/invalid/import_in_parent.err_exp	17 Jan 2003 05:57:08 -0000	1.2
+++ tests/invalid/import_in_parent.err_exp	21 Apr 2005 06:43:58 -0000
@@ -1,3 +1,3 @@
-import_in_parent.m:019: In clause for predicate `import_in_parent.sub.foo/1':
-import_in_parent.m:019:   error: undefined predicate `bool.foo/1'.
+import_in_parent.m:021: In clause for predicate `import_in_parent.sub.foo/1':
+import_in_parent.m:021:   error: undefined predicate `bool.foo/1'.
 For more information, try recompiling with `-E'.
Index: tests/invalid/import_in_parent.m
===================================================================
RCS file: /home/mercury1/repository/tests/invalid/import_in_parent.m,v
retrieving revision 1.1
diff -u -r1.1 import_in_parent.m
--- tests/invalid/import_in_parent.m	24 Oct 2002 04:36:57 -0000	1.1
+++ tests/invalid/import_in_parent.m	21 Apr 2005 06:43:13 -0000
@@ -8,6 +8,8 @@

 :- implementation.

+	:- type foo ---> foo.
+
 	:- module import_in_parent__sub.

 	:- interface.
Index: tests/invalid/modes_erroneous.err_exp
===================================================================
RCS file: /home/mercury1/repository/tests/invalid/modes_erroneous.err_exp,v
retrieving revision 1.5
diff -u -r1.5 modes_erroneous.err_exp
--- tests/invalid/modes_erroneous.err_exp	23 Aug 2004 09:53:13 -0000	1.5
+++ tests/invalid/modes_erroneous.err_exp	21 Apr 2005 06:42:35 -0000
@@ -1,7 +1,5 @@
-modes_erroneous.m:001: Warning: interface for module `modes_erroneous' does not
-modes_erroneous.m:001:   export anything.
-modes_erroneous.m:009: In clause for `p((ground >> ground), (free >> ground))':
-modes_erroneous.m:009:   in argument 1 of call to predicate `modes_erroneous.p/2':
-modes_erroneous.m:009:   mode error: variable `V_5' has instantiatedness `free',
-modes_erroneous.m:009:   expected instantiatedness was `ground'.
+modes_erroneous.m:015: In clause for `p((ground >> ground), (free >> ground))':
+modes_erroneous.m:015:   in argument 1 of call to predicate `modes_erroneous.p/2':
+modes_erroneous.m:015:   mode error: variable `V_5' has instantiatedness `free',
+modes_erroneous.m:015:   expected instantiatedness was `ground'.
 For more information, try recompiling with `-E'.
Index: tests/invalid/modes_erroneous.m
===================================================================
RCS file: /home/mercury1/repository/tests/invalid/modes_erroneous.m,v
retrieving revision 1.2
diff -u -r1.2 modes_erroneous.m
--- tests/invalid/modes_erroneous.m	25 Aug 2004 08:21:29 -0000	1.2
+++ tests/invalid/modes_erroneous.m	21 Apr 2005 06:42:06 -0000
@@ -1,10 +1,17 @@
 :- module modes_erroneous.

+:- interface.
+
 :- type foo.

+:- implementation.
+
+:- type foo ---> foo.
+
 :- pred p(foo, foo).
 :- mode p(ground >> ground, free >> ground).

 p(_, X) :-
 	p(_, X).
 p(_, _).
+
Index: tests/invalid/type_spec.m
===================================================================
RCS file: /home/mercury1/repository/tests/invalid/type_spec.m,v
retrieving revision 1.2
diff -u -r1.2 type_spec.m
--- tests/invalid/type_spec.m	3 Oct 1999 04:17:29 -0000	1.2
+++ tests/invalid/type_spec.m	21 Apr 2005 06:32:59 -0000
@@ -26,3 +26,8 @@
 :- pragma type_spec(type_spec2/1, U = list(U)).

 :- pragma type_spec(type_spec2/1, (U = int, U = list(int))).
+
+:- implementation.
+
+:- type the_type(T, U) ---> type_type(T, U).
+
Index: tests/invalid/type_with_no_defn.err_exp
===================================================================
RCS file: tests/invalid/type_with_no_defn.err_exp
diff -N tests/invalid/type_with_no_defn.err_exp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/invalid/type_with_no_defn.err_exp	21 Apr 2005 07:01:03 -0000
@@ -0,0 +1,7 @@
+type_with_no_defn.m:005: Error: abstract declaration for type
+type_with_no_defn.m:005:   `type_with_no_defn.alpha'/0 has no corresponding
+type_with_no_defn.m:005:   definition.
+type_with_no_defn.m:013: Error: abstract declaration for type
+type_with_no_defn.m:013:   `type_with_no_defn.baz'/0 has no corresponding
+type_with_no_defn.m:013:   definition.
+For more information, try recompiling with `-E'.
Index: tests/invalid/type_with_no_defn.m
===================================================================
RCS file: tests/invalid/type_with_no_defn.m
diff -N tests/invalid/type_with_no_defn.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/invalid/type_with_no_defn.m	21 Apr 2005 07:00:34 -0000
@@ -0,0 +1,19 @@
+:- module type_with_no_defn.
+
+:- interface.
+
+:- type alpha.
+
+:- type beta == int.
+
+:- type gamma.
+
+:- implementation.
+
+:- type baz.	% This is redundant but we allow it.
+
+:- type beta.
+
+:- type gamma == float.
+
+:- type delta == string.
Index: tests/invalid/typeclass_missing_det.m
===================================================================
RCS file: /home/mercury1/repository/tests/invalid/typeclass_missing_det.m,v
retrieving revision 1.1
diff -u -r1.1 typeclass_missing_det.m
--- tests/invalid/typeclass_missing_det.m	29 Apr 2001 07:54:37 -0000	1.1
+++ tests/invalid/typeclass_missing_det.m	21 Apr 2005 06:44:39 -0000
@@ -9,3 +9,5 @@
 :- typeclass c(T) where [
 	pred p(T::in)		% error -- missing det declaration for p/1
 ].
+
+:- type dummy ---> dummy.
Index: tests/invalid/typeclass_missing_det_2.m
===================================================================
RCS file: /home/mercury1/repository/tests/invalid/typeclass_missing_det_2.m,v
retrieving revision 1.1
diff -u -r1.1 typeclass_missing_det_2.m
--- tests/invalid/typeclass_missing_det_2.m	29 Apr 2001 07:54:37 -0000	1.1
+++ tests/invalid/typeclass_missing_det_2.m	21 Apr 2005 06:47:17 -0000
@@ -10,3 +10,5 @@
 	pred p(T),
 	mode p(in)		% error -- missing det declaration for p/1
 ].
+
+:- type dummy ---> dummy.
Index: tests/invalid/types.err_exp
===================================================================
RCS file: /home/mercury1/repository/tests/invalid/types.err_exp,v
retrieving revision 1.10
diff -u -r1.10 types.err_exp
--- tests/invalid/types.err_exp	17 Jan 2003 05:57:10 -0000	1.10
+++ tests/invalid/types.err_exp	22 Apr 2005 00:31:02 -0000
@@ -1,4 +1,4 @@
-types.m:  1: Warning: interface for module `types' does not export anything.
+types.m:001: Warning: interface for module `types' does not export anything.
 types.m:003: Error: constructor `types.a/0' for type `types.t/0' multiply defined.
 types.m:003: Error: constructor `types.f/1' for type `types.t/0' multiply defined.
 types.m:017: Error: clause for predicate `types.r/0'
@@ -25,6 +25,6 @@
 types.m:018:   error: undefined predicate `s/0'.
 types.m:020: In clause for predicate `types.a/1':
 types.m:020:   error: undefined predicate `b/1'.
-types.m:042: Error: no mode declaration for predicate `types.baz/1'.
-types.m:052: Error: no mode declaration for predicate `types.baz2/1'.
+types.m:048: Error: abstract declaration for type `types.t'/2 has no
+types.m:048:   corresponding definition.
 For more information, try recompiling with `-E'.
Index: tests/invalid/uu_type.err_exp
===================================================================
RCS file: /home/mercury1/repository/tests/invalid/uu_type.err_exp,v
retrieving revision 1.3
diff -u -r1.3 uu_type.err_exp
--- tests/invalid/uu_type.err_exp	26 Feb 2002 02:46:05 -0000	1.3
+++ tests/invalid/uu_type.err_exp	21 Apr 2005 06:34:45 -0000
@@ -1,2 +1,4 @@
 uu_type.m:022: Error: type parameters must be variables: hiddenrenamedtype = hiddentype.
+uu_type.m:012: Error: abstract declaration for type
+uu_type.m:012:   `uu_type.hiddenrenamedtype'/0 has no corresponding definition.
 For more information, try recompiling with `-E'.


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