[m-rev.] diff: fix bug reported by Peter Ross

Mark Brown mark at csse.unimelb.edu.au
Thu Jan 11 15:54:22 AEDT 2007


Estimated hours taken: 1.5
Branches: main

Fix a bug reported by Peter Ross.

compiler/check_typeclass.m:
	Only check concrete instance definitions for mutual consistency.
	Abstract definitions will always appear to be inconsistent with
	the concrete ones.

tests/valid/Mmakefile:
tests/valid/logged_stream.m:
	New test case.

Index: compiler/check_typeclass.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/check_typeclass.m,v
retrieving revision 1.109
diff -u -r1.109 check_typeclass.m
--- compiler/check_typeclass.m	1 Dec 2006 15:03:50 -0000	1.109
+++ compiler/check_typeclass.m	10 Jan 2007 16:16:12 -0000
@@ -63,7 +63,12 @@
 % dependencies.  This doesn't necessarily catch all cases of inconsistent
 % instances, however, since in general that cannot be done until link time.
 % We try to catch as many cases as possible here, though, since we can give
-% better error messages.
+% better error messages.  Note that we only check concrete instance definitions
+% for mutual consistency, since otherwise the abstract instance definitions
+% would conflict with their corresponding concrete definitions.  If in
+% future we allow stub instances, where the concrete definition is compiler
+% generated, we should add the concrete definitions before this pass to
+% ensure that they get checked.
 %
 % Last, in check_typeclass_constraints/4, we check typeclass constraints on
 % predicate and function declarations and on existentially typed data
@@ -1102,8 +1107,17 @@
     map.lookup(InstanceTable, ClassId, InstanceDefns),
     FunDeps = ClassDefn ^ class_fundeps,
     check_coverage(ClassId, InstanceDefns, FunDeps, !ModuleInfo, !Specs),
-    check_consistency(ClassId, ClassDefn, InstanceDefns, FunDeps,
+    % Concrete definitions will always overlap with abstract ones; we only
+    % need to check the former.
+    list.filter(is_concrete_instance_defn, InstanceDefns,
+        ConcreteInstanceDefns),
+    check_consistency(ClassId, ClassDefn, ConcreteInstanceDefns, FunDeps,
         !ModuleInfo, !Specs).
+
+:- pred is_concrete_instance_defn(hlds_instance_defn::in) is semidet.
+
+is_concrete_instance_defn(InstanceDefn) :-
+    InstanceDefn ^ instance_body = instance_body_concrete(_).
 
 :- pred check_coverage(class_id::in, list(hlds_instance_defn)::in,
     hlds_class_fundeps::in, module_info::in, module_info::out,
Index: tests/valid/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/tests/valid/Mmakefile,v
retrieving revision 1.184
diff -u -r1.184 Mmakefile
--- tests/valid/Mmakefile	19 Dec 2006 03:01:49 -0000	1.184
+++ tests/valid/Mmakefile	10 Jan 2007 16:16:12 -0000
@@ -32,6 +32,7 @@
 	fundeps_poly_instance \
 	instance_superclass \
 	instance_unconstrained_tvar \
+	logged_stream \
 	mpj2 \
 	mpj5 \
 	mpj6 \
Index: tests/valid/logged_stream.m
===================================================================
RCS file: tests/valid/logged_stream.m
diff -N tests/valid/logged_stream.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/valid/logged_stream.m	10 Jan 2007 16:16:12 -0000
@@ -0,0 +1,41 @@
+% $ mmc -e logged_stream.m
+% logged_stream.m:041: Inconsistent instance declaration for typeclass
+% logged_stream.m:041:   `stream.input'/3 with functional dependency
+% logged_stream.m:041:   `(Stream -> Error)'.
+% logged_stream.m:027: Here is the conflicting instance.
+:- module logged_stream.
+
+:- interface.
+
+:- import_module stream.
+:- import_module io.
+
+:- type logged_stream(S, L)
+    --->    logged_stream(
+                stream  :: S,
+                logged  :: L
+            ).
+
+:- type logged_error(E)
+    --->    error(E)
+    .
+
+:- instance stream(logged_stream(S, L), io) <= (stream(S, io), stream(L, io)).
+:- instance error(logged_error(E)) <= error(E).
+
+% Comment the following line out and this code compiles fine.
+:- instance input(logged_stream(S, L), io, logged_error(E)) <= (input(S, io, E), output(L, io)).
+
+:- implementation.
+
+:- instance stream(logged_stream(S, L), io) <= (stream(S, io), stream(L, io)) where [
+    (name(logged_stream(S, _), Name, !State) :-
+        name(S, Name, !State)
+    )
+].
+
+:- instance error(logged_error(E)) <= error(E) where [
+    error_message(error(E)) = error_message(E)
+].
+
+:- instance input(logged_stream(S, L), io, logged_error(E)) <= (input(S, io, E), output(L, io)) where [].
--------------------------------------------------------------------------
mercury-reviews mailing list
Post messages to:       mercury-reviews at csse.unimelb.edu.au
Administrative Queries: owner-mercury-reviews at csse.unimelb.edu.au
Subscriptions:          mercury-reviews-request at csse.unimelb.edu.au
--------------------------------------------------------------------------



More information about the reviews mailing list