[m-rev.] diff: check for duplicated instance tvars

Mark Brown mark at csse.unimelb.edu.au
Thu Oct 19 17:28:39 AEST 2006


Estimated hours taken: 1.5
Branches: main

compiler/prog_io_typeclass.m:
	Enforce the requirement that type variables in instance declarations
	are distinct.

tests/invalid/Mmakefile:
tests/invalid/instance_dup_var.err_exp:
tests/invalid/instance_dup_var.m:
	Test case.

tests/hard_coded/typeclasses/Mmakefile:
	Disable the instance_unconstrained_tvar_dup test case, since we
	don't support the feature that it tests.

tests/invalid/range_restrict.err_exp:
tests/invalid/range_restrict.m:
tests/valid/mpj5.m:
	Comment out the parts of these test cases which use duplicated
	instance variables, and adjust the expected output where applicable.

Index: compiler/prog_io_typeclass.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/prog_io_typeclass.m,v
retrieving revision 1.55
diff -u -r1.55 prog_io_typeclass.m
--- compiler/prog_io_typeclass.m	13 Oct 2006 04:52:24 -0000	1.55
+++ compiler/prog_io_typeclass.m	19 Oct 2006 05:33:53 -0000
@@ -68,6 +68,7 @@
 :- import_module maybe.
 :- import_module pair.
 :- import_module set.
+:- import_module solutions.
 :- import_module string.
 :- import_module term.
 :- import_module varset.
@@ -604,18 +605,21 @@
         ModuleName, Result) :-
     (
         % Check that each type in the arguments of the instance decl
-        % is a functor with vars as args.
-        some [Type] (
-            list.member(Type, Types),
-            \+ type_is_functor_and_vars(Type)
-        )
+        % is a functor with vars as args...
+        all [Type] (
+            list.member(Type, Types)
+        =>
+            type_is_functor_and_vars(Type)
+        ),
+        % ...and that the vars are distinct across the entire arg list.
+        type_vars_are_distinct(Types)
     ->
+        Result = ok1(item_instance([], ClassName, Types,
+            instance_body_abstract, TVarSet, ModuleName))
+    ;
         Msg = "types in instance declarations must be functors " ++
             "with distinct variables as arguments",
         Result = error1([Msg - ErrorTerm])
-    ;
-        Result = ok1(item_instance([], ClassName, Types,
-            instance_body_abstract, TVarSet, ModuleName))
     ).
 
 :- pred type_is_functor_and_vars(mer_type::in) is semidet.
@@ -649,6 +653,16 @@
         type_is_var(Arg)
     ).
 
+:- pred type_vars_are_distinct(list(mer_type)::in) is semidet.
+
+type_vars_are_distinct(Types) :-
+    promise_equivalent_solutions [NumVars, VarsWithoutDups] (
+        solutions.unsorted_solutions(type_list_contains_var(Types), Vars),
+        list.length(Vars, NumVars),
+        list.sort_and_remove_dups(Vars, VarsWithoutDups)
+    ),
+    list.length(VarsWithoutDups, NumVars).
+
 :- pred parse_non_empty_instance(module_name::in, term::in, term::in,
     varset::in, tvarset::in, maybe1(item)::out) is det.
 
Index: tests/hard_coded/typeclasses/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/tests/hard_coded/typeclasses/Mmakefile,v
retrieving revision 1.57
diff -u -r1.57 Mmakefile
--- tests/hard_coded/typeclasses/Mmakefile	7 Jun 2006 14:37:39 -0000	1.57
+++ tests/hard_coded/typeclasses/Mmakefile	19 Oct 2006 07:08:38 -0000
@@ -37,7 +37,6 @@
 	impure_methods \
 	instance_clauses \
 	instance_unconstrained_tvar \
-	instance_unconstrained_tvar_dup \
 	instance_unconstrained_tvar_type_spec \
 	inference_test \
 	inference_test_2 \
@@ -97,6 +96,10 @@
 	test_default_func_mode \
 	typeclass_test_5
 
+# We don't support duplicated type variables in instance declarations yet.
+# When we do, this test case should be enabled.
+#	instance_unconstrained_tvar_dup
+
 ifneq "$(findstring java,$(GRADE))" ""
 	PROGS=$(JAVA_TYPECLASSES_PROGS)
 else
Index: tests/invalid/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/tests/invalid/Mmakefile,v
retrieving revision 1.198
diff -u -r1.198 Mmakefile
--- tests/invalid/Mmakefile	9 Oct 2006 06:40:27 -0000	1.198
+++ tests/invalid/Mmakefile	19 Oct 2006 05:34:40 -0000
@@ -100,6 +100,7 @@
 	inline_conflict \
 	inst_list_dup \
 	instance_bug \
+	instance_dup_var \
 	invalid_export_detism \
 	invalid_import_detism \
 	invalid_main \
Index: tests/invalid/instance_dup_var.err_exp
===================================================================
RCS file: tests/invalid/instance_dup_var.err_exp
diff -N tests/invalid/instance_dup_var.err_exp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/invalid/instance_dup_var.err_exp	19 Oct 2006 05:35:15 -0000
@@ -0,0 +1,2 @@
+instance_dup_var.m:012: Error: types in instance declarations must be functors with distinct variables as arguments: baz(foo(_1, _1), bar).
+instance_dup_var.m:015: Error: types in instance declarations must be functors with distinct variables as arguments: baz(foo(_1, _2), foo(_3, _1)).
Index: tests/invalid/instance_dup_var.m
===================================================================
RCS file: tests/invalid/instance_dup_var.m
diff -N tests/invalid/instance_dup_var.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/invalid/instance_dup_var.m	19 Oct 2006 05:16:30 -0000
@@ -0,0 +1,16 @@
+:- module instance_dup_var.
+:- interface.
+
+:- type foo(A, B) ---> foo(A, B).
+:- type bar ---> bar.
+
+:- typeclass baz(X, Y) where [].
+
+:- implementation.
+
+	% Error: T is duplicated.
+:- instance baz(foo(T, T), bar) where [].
+
+	% Error: A is duplicated.
+:- instance baz(foo(A, B), foo(C, A)) where [].
+
Index: tests/invalid/range_restrict.err_exp
===================================================================
RCS file: /home/mercury1/repository/tests/invalid/range_restrict.err_exp,v
retrieving revision 1.3
diff -u -r1.3 range_restrict.err_exp
--- tests/invalid/range_restrict.err_exp	13 Oct 2006 04:52:38 -0000	1.3
+++ tests/invalid/range_restrict.err_exp	19 Oct 2006 07:20:03 -0000
@@ -1,8 +1,4 @@
-range_restrict.m:011: In instance for typeclass `range_restrict.foo'/2:
-range_restrict.m:011:   functional dependency not satisfied: type variable Y
-range_restrict.m:011:   occurs in the range of the functional dependency, but
-range_restrict.m:011:   is not in the domain.
-range_restrict.m:012: In instance for typeclass `range_restrict.foo'/2:
-range_restrict.m:012:   functional dependency not satisfied: type variables Y
-range_restrict.m:012:   and Z occur in the range of the functional dependency,
-range_restrict.m:012:   but are not in the domain.
+range_restrict.m:010: In instance for typeclass `range_restrict.foo'/2:
+range_restrict.m:010:   functional dependency not satisfied: type variables Y
+range_restrict.m:010:   and Z occur in the range of the functional dependency,
+range_restrict.m:010:   but are not in the domain.
Index: tests/invalid/range_restrict.m
===================================================================
RCS file: /home/mercury1/repository/tests/invalid/range_restrict.m,v
retrieving revision 1.1
diff -u -r1.1 range_restrict.m
--- tests/invalid/range_restrict.m	20 Apr 2005 12:57:46 -0000	1.1
+++ tests/invalid/range_restrict.m	19 Oct 2006 07:10:35 -0000
@@ -6,8 +6,10 @@
 :- implementation.
 :- import_module list, map.
 
-	% Errors: range-restrictedness
-
-:- instance foo(list(X), map(X, Y)) where [].
+	% Error: range-restrictedness
 :- instance foo(map(W, X), map(Y, Z)) where [].
 
+	% This is also a range-restrictedness error, but since we don't
+	% support duplicated type vars in instance declarations yet, we
+	% can't test for it.
+% :- instance foo(list(X), map(X, Y)) where [].
Index: tests/valid/mpj5.m
===================================================================
RCS file: /home/mercury1/repository/tests/valid/mpj5.m,v
retrieving revision 1.1
diff -u -r1.1 mpj5.m
--- tests/valid/mpj5.m	20 Apr 2005 12:57:59 -0000	1.1
+++ tests/valid/mpj5.m	19 Oct 2006 07:13:57 -0000
@@ -11,28 +11,31 @@
 :- type w(T) ---> w(T).
 :- type cf(T) ---> cf(func(T) = bool).
 
-:- instance coll(w(T), list(T)).
-:- instance coll(w(T), cf(T)).
 :- instance coll(int, int).
 
+% We don't support duplicated type vars in instances yet, so these cases
+% are disabled for the moment.
+% :- instance coll(w(T), list(T)).
+% :- instance coll(w(T), cf(T)).
+
 :- implementation.
 :- import_module int.
 
-:- instance coll(w(T), list(T)) where [
-	(e = []),
-	(i(w(E), L) = [E | L]),
-	(m(w(E), L) :- list__member(E, L))
-].
-
-:- instance coll(w(T), cf(T)) where [
-	(e = cf(func(_) = no)),
-	(i(w(E), cf(F)) = cf(func(X) = ( X = E -> yes ; F(X) ))),
-	(m(w(E), cf(F)) :- F(E) = yes)
-].
-
 :- instance coll(int, int) where [
 	(e = 0),
 	(i(N, B) = B \/ (1 << N)),
 	(m(N, B) :- B /\ (1 << N) \= 0)
 ].
 
+% :- instance coll(w(T), list(T)) where [
+% 	(e = []),
+% 	(i(w(E), L) = [E | L]),
+% 	(m(w(E), L) :- list__member(E, L))
+% ].
+
+% :- instance coll(w(T), cf(T)) where [
+% 	(e = cf(func(_) = no)),
+% 	(i(w(E), cf(F)) = cf(func(X) = ( X = E -> yes ; F(X) ))),
+% 	(m(w(E), cf(F)) :- F(E) = yes)
+% ].
+
--------------------------------------------------------------------------
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