[m-rev.] for review: improve check for invalid invalid declarations

Peter Ross pro at missioncriticalit.com
Tue Oct 2 14:32:30 AEST 2007


On Fri, Sep 28, 2007 at 06:32:28PM +1000, Mark Brown wrote:
> On 28-Sep-2007, Peter Ross <pro at missioncriticalit.com> wrote:
> > On 9/28/07, Mark Brown <mark at csse.unimelb.edu.au> wrote:
> > > On 28-Sep-2007, Peter Ross <pro at missioncriticalit.com> wrote:
> > > >
> > > > For juliensf or pwa to review.
> > > >
> > > > ===================================================================
> > > >
> > > >
> > > > Estimated hours taken: 4
> > > > Branches: main
> > > >
> > > > Improve check for invalid instance declarations.
> > > >
> > > > compiler/check_typeclass.m:
> > > >       Check that each type in the instance declaration is a type with
> > > >       no arguments of a polymorphic type whose arguments are all distinct
> > > >       type variables.
> > >
> > > Hmm, there is already code to check this in parse_underived_instance_2
> > > in prog_io_typeclass.m.  I'm a bit puzzled why it apparently isn't working.
> > > Any clue?
> > >
> > because at that point it doesn't know anything about equivalence types.
> 
> Ah, right.  I knew its error messages weren't that good, but I didn't
> know it was also missing some cases.  You should remove the check during
> parsing, and update any further test cases.
> 
> > 
> > > In any case, putting the check in the front end pass is a good idea, and
> > > is better than checking during parsing, IMHO.
> 

Here is the updated diff.

I've removed the checking during parsing, and updated the error
messages.

===================================================================


Estimated hours taken: 8
Branches: main

Improve the detection of invalid instance declarations by doing the check
during hlds checking rather than parsing, as we have more information then.

compiler/check_typeclass.m:
	Add check_instance_declaration_types/4, where we check that each type
	the instance declaration must be either a type with no arguments, a
	polymorphic type whose arguments are all distinct type variables.
	
compiler/error_util.m:
	Add nth_fixed to format_component which returns "first", "second",
	"third", "4th" depending on the given integer.

compiler/prog_io_typeclass.m:
	Remove the invalid instance check during parsing.

compiler/type_util.m:
	Fix a spelling mistake.

tests/hard_coded/typeclasses/fundeps_1.m:
tests/hard_coded/typeclasses/fundeps_2.m:
tests/invalid/ambiguous_method.m:
tests/invalid/ambiguous_method_2.m:
	Fix invalid instance declarations.

tests/invalid/bad_instance.err_exp:
tests/invalid/instance_dup_var.err_exp:
	Update to the new error messages.

tests/invalid/Mmakefile:
tests/invalid/invalid_instance_declarations.err_exp:
tests/invalid/invalid_instance_declarations.m:
	Add a check where we use equivalence types to
	hide invalid typeclass declarations.


Index: compiler/check_typeclass.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/check_typeclass.m,v
retrieving revision 1.113
diff -u -r1.113 check_typeclass.m
--- compiler/check_typeclass.m	25 Sep 2007 04:56:37 -0000	1.113
+++ compiler/check_typeclass.m	2 Oct 2007 04:11:32 -0000
@@ -70,6 +70,10 @@
 % generated, we should add the concrete definitions before this pass to
 % ensure that they get checked.
 %
+% Fifth, in check_instance_declaration_types/4, we check that each type
+% in the instance declaration must be either a type with no arguments,
+% or a polymorphic type whose arguments are all distinct type variables.
+%
 % Last, in check_typeclass_constraints/4, we check typeclass constraints on
 % predicate and function declarations and on existentially typed data
 % constructors for ambiguity, taking into consideration the information
@@ -101,6 +105,7 @@
 :- implementation.
 
 :- import_module check_hlds.typeclasses.
+:- import_module check_hlds.type_util.
 :- import_module hlds.hlds_code_util.
 :- import_module hlds.hlds_data.
 :- import_module hlds.hlds_error_util.
@@ -122,6 +127,7 @@
 :- import_module parse_tree.prog_util.
 
 :- import_module bool.
+:- import_module int.
 :- import_module map.
 :- import_module maybe.
 :- import_module multi_map.
@@ -165,8 +171,14 @@
     check_functional_dependencies(!ModuleInfo, !Specs),
 
     trace [io(!IO5)] (
-        maybe_write_string(Verbose, "% Checking typeclass constraints...\n",
-            !IO5)
+    maybe_write_string(Verbose,
+        "% Checking instance declaration types...\n", !IO5)
+    ),
+    check_instance_declaration_types(!ModuleInfo, !Specs),
+
+    trace [io(!IO6)] (
+    maybe_write_string(Verbose, "% Checking typeclass constraints...\n",
+        !IO6)
     ),
     check_typeclass_constraints(!ModuleInfo, !Specs).
 
@@ -1214,6 +1226,189 @@
     ;
         true
     ).
+
+%---------------------------------------------------------------------------%
+
+    % In check_instance_declaration_types/4, we check that each type
+    % in the instance declaration must be either a type with no arguments,
+    % or a polymorphic type whose arguments are all distinct type variables.
+    %
+:- pred check_instance_declaration_types(module_info::in, module_info::out,
+    list(error_spec)::in, list(error_spec)::out) is det.
+
+check_instance_declaration_types(!ModuleInfo, !Specs) :-
+    module_info_get_instance_table(!.ModuleInfo, InstanceTable),
+    map.foldl(check_instance_declaration_types(!.ModuleInfo),
+        InstanceTable, !Specs).
+    
+:- pred check_instance_declaration_types(module_info::in,
+    class_id::in, list(hlds_instance_defn)::in,
+    list(error_spec)::in, list(error_spec)::out) is det.
+
+check_instance_declaration_types(MI, ClassId, InstanceDefns, !Specs) :-
+    list.foldl(check_one_instance_declaration_types(MI, ClassId),
+        InstanceDefns, !Specs).
+
+:- pred check_one_instance_declaration_types(module_info::in,
+    class_id::in, hlds_instance_defn::in,
+    list(error_spec)::in, list(error_spec)::out) is det.
+
+check_one_instance_declaration_types(MI, ClassId, InstanceDefn, !Specs) :-
+    Types = InstanceDefn ^ instance_types,
+    list.foldl3(is_valid_instance_type(MI, ClassId, InstanceDefn),
+        Types, 1, _, set.init, _, !Specs).
+
+    %
+    % Each of these types in the instance declaration must be either a
+    % type with no arguments, or a polymorphic type whose arguments are
+    % all distinct type variables.
+    %
+:- pred is_valid_instance_type(module_info::in,
+    class_id::in, hlds_instance_defn::in, mer_type::in,
+    int::in, int::out, set(mer_type)::in, set(mer_type)::out,
+    list(error_spec)::in, list(error_spec)::out) is det.
+
+is_valid_instance_type(_MI, _ClassId, _InstanceDefn,
+        builtin_type(_), N, N+1, !SeenTypes, !Specs).
+is_valid_instance_type(_MI, ClassId, InstanceDefn,
+        higher_order_type(_, _, _, _), N, N+1, !SeenTypes, !Specs) :-
+    Err = [words("is a higher order type")],
+    Spec = error_message_2(ClassId, InstanceDefn, N, Err), 
+    !:Specs = [Spec | !.Specs].
+is_valid_instance_type(_MI, ClassId, InstanceDefn,
+        tuple_type(Args, _), N, N+1, !SeenTypes, !Specs) :-
+    each_arg_is_a_distinct_type_variable(!.SeenTypes, Args, 1, Result),
+    (
+        Result = no_error,
+        svset.insert_list(Args, !SeenTypes)
+    ;
+        ( Result = local_non_distinct
+        ; Result = global_non_distinct
+        ; Result = arg_not_type_variable(_)
+        ),
+        Spec = error_message(ClassId, InstanceDefn, N, Result),
+        !:Specs = [Spec | !.Specs]
+    ).
+is_valid_instance_type(_MI, ClassId, InstanceDefn,
+        apply_n_type(_, _, _), N, N+1, !SeenTypes, !Specs) :-
+    Err = [words("is a apply/N type")],
+    Spec = error_message_2(ClassId, InstanceDefn, N, Err),
+    !:Specs = [Spec | !.Specs].
+is_valid_instance_type(_MI, _ClassId, _InstanceDefn,
+        kinded_type(_, _), N, N+1, !SeenTypes, !Specs) :-
+    unexpected("check_typeclass", "kinded_type").
+is_valid_instance_type(_MI, ClassId, InstanceDefn,
+        type_variable(_, _), N, N+1, !SeenTypes, !Specs) :-
+    Err = [words("is a type variable")],
+    Spec = error_message_2(ClassId, InstanceDefn, N, Err),
+    !:Specs = [Spec | !.Specs].
+is_valid_instance_type(MI, ClassId, InstanceDefn,
+        Type @ defined_type(_, Args, _), N, N+1, !SeenTypes, !Specs) :-
+    each_arg_is_a_distinct_type_variable(!.SeenTypes, Args, 1, Result),
+    (   
+        Result = no_error,
+        svset.insert_list(Args, !SeenTypes),
+        (
+            type_to_type_defn(MI, Type, TypeDefn),
+            get_type_defn_body(TypeDefn, TypeBody),
+            TypeBody = hlds_eqv_type(EqvType)
+        ->
+            is_valid_instance_type(MI,
+                ClassId, InstanceDefn, EqvType, N, _, !SeenTypes, !Specs)
+        ;
+            true
+        )
+    ;
+        ( Result = local_non_distinct
+        ; Result = global_non_distinct
+        ; Result = arg_not_type_variable(_)
+        ),
+        Spec = error_message(ClassId, InstanceDefn, N, Result),
+        !:Specs = [Spec | !.Specs]
+    ).
+    
+
+:- type instance_arg_result
+    --->    no_error
+    ;       local_non_distinct
+    ;       global_non_distinct
+    ;       arg_not_type_variable(int)
+    .
+
+:- inst instance_arg_result_error
+    --->    local_non_distinct
+    ;       global_non_distinct
+    ;       arg_not_type_variable(ground)
+    .
+
+
+:- pred each_arg_is_a_distinct_type_variable(set(mer_type)::in,
+    list(mer_type)::in, int::in, instance_arg_result::out) is det.
+
+each_arg_is_a_distinct_type_variable(_, [], _, no_error).
+each_arg_is_a_distinct_type_variable(SeenTypes, [Type | Types], N, Result) :-
+    ( Type = type_variable(_, _) ->
+        ( Type `list.member` Types ->
+            Result = local_non_distinct
+        ; Type `set.member` SeenTypes ->
+            Result = global_non_distinct
+        ;
+            each_arg_is_a_distinct_type_variable(SeenTypes, Types, N+1, Result)
+        )
+    ;
+        Result = arg_not_type_variable(N)
+    ).
+
+:- func error_message(class_id::in, hlds_instance_defn::in, int::in,
+    instance_arg_result::in(instance_arg_result_error))
+    = (error_spec::out) is det.
+
+error_message(ClassId, InstanceDefn, N, Error) = Spec :-
+    (
+        Error = local_non_distinct,
+        Err = 
+            [words("is not a type whose arguments are distinct type variables")]
+    ;
+        Error = global_non_distinct,
+        Err = [words("contains a type variable which is used in another arg")]
+    ;
+        Error = arg_not_type_variable(ArgNum),
+        Err = [
+            words("is a type whose"), nth_fixed(ArgNum),
+            words("arg is not a variable")]
+    ),
+    Spec = error_message_2(ClassId, InstanceDefn, N, Err).
+
+:- func error_message_2(
+    class_id, hlds_instance_defn, int, format_components) = error_spec.
+
+error_message_2(ClassId, InstanceDefn, N, Pieces) = Spec :-
+    ClassId = class_id(ClassName, _),
+    ClassNameString = sym_name_to_string(ClassName),
+
+    InstanceVarSet = InstanceDefn ^ instance_tvarset,
+    InstanceTypes = InstanceDefn ^ instance_types,
+    InstanceContext = InstanceDefn ^ instance_context,
+    InstanceTypesString = mercury_type_list_to_string(InstanceVarSet,
+        InstanceTypes),
+
+    HeaderPieces =
+        [words("In instance declaration for"),
+        words("`" ++ ClassNameString ++
+            "(" ++ InstanceTypesString ++ ")':")
+        ],
+
+    VerbosePieces =
+        [words("types in instance declarations must be functors " ++
+            "with distinct variables as arguments")],
+
+    ArgNumPieces = [words("the"), nth_fixed(N), words("arg") | Pieces],
+
+    HeadingMsg = simple_msg(InstanceContext,
+        [always(HeaderPieces), always(ArgNumPieces),
+        verbose_only(VerbosePieces)]),
+    Spec = error_spec(severity_error, phase_type_check, [HeadingMsg]).
+
 %---------------------------------------------------------------------------%
 
     % Look for pred or func declarations for which the type variables in
Index: compiler/error_util.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/error_util.m,v
retrieving revision 1.64
diff -u -r1.64 error_util.m
--- compiler/error_util.m	31 Jul 2007 03:53:30 -0000	1.64
+++ compiler/error_util.m	2 Oct 2007 04:11:32 -0000
@@ -265,6 +265,11 @@
     ;       int_fixed(int)  % Convert the integer to a string, then treat
                             % as fixed.
 
+    ;       nth_fixed(int)  % Convert the integer to a string, such as
+                            % "first", "second", "third", "4th", "5th" and
+                            % then treat as fixed.
+                            % 
+
     ;       prefix(string)  % This string should appear in the output
                             % in one piece, as it is, inserted directly
                             % before the next format_component, without
@@ -958,6 +963,9 @@
         Component = int_fixed(Int),
         Str = join_string_and_tail(int_to_string(Int), Components, TailStr)
     ;
+        Component = nth_fixed(Int),
+        Str = join_string_and_tail(nth_fixed_str(Int), Components, TailStr)
+    ;
         Component = prefix(Word),
         Str = Word ++ TailStr
     ;
@@ -1004,6 +1012,19 @@
         Str = "\n\n" ++ TailStr
     ).
 
+:- func nth_fixed_str(int) = string.
+
+nth_fixed_str(N) =
+    ( N = 1 ->
+        "first"
+    ; N = 2 ->
+        "second"
+    ; N = 3 ->
+        "third"
+    ;
+        int_to_string(N) ++ "th"
+    ).
+
 :- func join_string_and_tail(string, list(format_component), string) = string.
 
 join_string_and_tail(Word, Components, TailStr) = Str :-
@@ -1056,6 +1077,9 @@
         Component = int_fixed(Int),
         RevWords1 = [plain_word(int_to_string(Int)) | RevWords0]
     ;
+        Component = nth_fixed(Int),
+        RevWords1 = [plain_word(nth_fixed_str(Int)) | RevWords0]
+    ;
         Component = prefix(Word),
         RevWords1 = [prefix_word(Word) | RevWords0]
     ;
Index: compiler/prog_io_typeclass.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/prog_io_typeclass.m,v
retrieving revision 1.59
diff -u -r1.59 prog_io_typeclass.m
--- compiler/prog_io_typeclass.m	19 Jan 2007 07:04:28 -0000	1.59
+++ compiler/prog_io_typeclass.m	2 Oct 2007 04:11:32 -0000
@@ -598,67 +598,10 @@
     maybe1(item)::out) is det.
 
 parse_underived_instance_2(_, _, error1(Errors), _, _, error1(Errors)).
-parse_underived_instance_2(ErrorTerm, ClassName, ok1(Types), TVarSet,
+parse_underived_instance_2(_, ClassName, ok1(Types), TVarSet,
         ModuleName, Result) :-
-    (
-        % Check that each type in the arguments of the instance decl
-        % 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])
-    ).
-
-:- pred type_is_functor_and_vars(mer_type::in) is semidet.
-
-type_is_functor_and_vars(defined_type(_, Args, _)) :-
-    functor_args_are_variables(Args).
-type_is_functor_and_vars(builtin_type(_)).
-type_is_functor_and_vars(higher_order_type(Args, MaybeRet, Purity,
-        EvalMethod)) :-
-    % XXX We currently allow pred types to be instance arguments, but not
-    % func types. Even then, the pred type must be pure and have a
-    % lambda_eval_method of normal. We keep this behaviour basically
-    % for backwards compatibility -- there is little point fixing this
-    % now without fixing the more general problem of having these
-    % restrictions in the first place.
-    MaybeRet = no,
-    Purity = purity_pure,
-    EvalMethod = lambda_normal,
-    functor_args_are_variables(Args).
-type_is_functor_and_vars(tuple_type(Args, _)) :-
-    functor_args_are_variables(Args).
-type_is_functor_and_vars(kinded_type(Type, _)) :-
-    type_is_functor_and_vars(Type).
-
-:- pred functor_args_are_variables(list(mer_type)::in) is semidet.
-
-functor_args_are_variables(Args) :-
-    all [Arg] (
-        list.member(Arg, Args)
-    =>
-        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).
+    Result = ok1(item_instance([], ClassName, Types,
+        instance_body_abstract, TVarSet, ModuleName)).
 
 :- pred parse_non_empty_instance(module_name::in, term::in, term::in,
     varset::in, tvarset::in, maybe1(item)::out) is det.
Index: compiler/type_util.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/type_util.m,v
retrieving revision 1.183
diff -u -r1.183 type_util.m
--- compiler/type_util.m	25 Sep 2007 04:56:43 -0000	1.183
+++ compiler/type_util.m	2 Oct 2007 04:11:40 -0000
@@ -187,7 +187,7 @@
 :- pred get_cons_id_non_existential_arg_types(module_info::in,
     mer_type::in, cons_id::in, list(mer_type)::out) is semidet.
 
-    % The same as gget_cons_id_arg_types except that the cons_id is output
+    % The same as get_cons_id_arg_types except that the cons_id is output
     % non-deterministically. The cons_id is not module-qualified.
     %
 :- pred cons_id_arg_types(module_info::in, mer_type::in,
Index: tests/hard_coded/typeclasses/fundeps_1.m
===================================================================
RCS file: /home/mercury1/repository/tests/hard_coded/typeclasses/fundeps_1.m,v
retrieving revision 1.1
diff -u -r1.1 fundeps_1.m
--- tests/hard_coded/typeclasses/fundeps_1.m	20 Apr 2005 12:57:36 -0000	1.1
+++ tests/hard_coded/typeclasses/fundeps_1.m	2 Oct 2007 04:11:43 -0000
@@ -7,7 +7,7 @@
 
 main(!S) :-
 	(
-		test([0], 1)
+		test(intcoll([0]), 1)
 	->
 		write_string("yes\n", !S)
 	;
@@ -20,13 +20,13 @@
 	pred m(E::in, C::in) is semidet
 ].
 
-:- type intcoll == list(int).
+:- type intcoll ---> intcoll(list(int)).
 
 :- instance coll(intcoll, int) where [
-	(e = []),
-	(i(Ns, N) = [N | Ns]),
-	m(N, [N | _]),
-	m(N, [_ | Ns]) :- m(N, Ns)
+	(e = intcoll([])),
+	(i(intcoll(Ns), N) = intcoll([N | Ns])),
+	m(N, intcoll([N | _])),
+	m(N, intcoll([_ | Ns])) :- m(N, intcoll(Ns))
 ].
 
 :- pred test(C, E) <= coll(C, E).
Index: tests/hard_coded/typeclasses/fundeps_2.m
===================================================================
RCS file: /home/mercury1/repository/tests/hard_coded/typeclasses/fundeps_2.m,v
retrieving revision 1.1
diff -u -r1.1 fundeps_2.m
--- tests/hard_coded/typeclasses/fundeps_2.m	20 Apr 2005 12:57:36 -0000	1.1
+++ tests/hard_coded/typeclasses/fundeps_2.m	2 Oct 2007 04:11:43 -0000
@@ -7,14 +7,14 @@
 
 main(!S) :-
 	(
-		test([0], 1)
+		test(intcoll([0]), 1)
 	->
 		write_string("yes\n", !S)
 	;
 		write_string("no\n", !S)
 	),
 	(
-		e = [1]
+		e = intcoll([1])
 	->
 		write_string("yes\n", !S)
 	;
@@ -30,13 +30,13 @@
 	pred m(E::in, C::in) is semidet
 ].
 
-:- type intcoll == list(int).
+:- type intcoll ---> intcoll(list(int)).
 
 :- instance coll(intcoll, int) where [
-	(e = []),
-	(i(Ns, N) = [N | Ns]),
-	m(N, [N | _]),
-	m(N, [_ | Ns]) :- m(N, Ns)
+	(e = intcoll([])),
+	(i(intcoll(Ns), N) = intcoll([N | Ns])),
+	m(N, intcoll([N | _])),
+	m(N, intcoll([_ | Ns])) :- m(N, intcoll(Ns))
 ].
 
 :- pred test(C, E) <= coll(C, E).
Index: tests/invalid/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/tests/invalid/Mmakefile,v
retrieving revision 1.221
diff -u -r1.221 Mmakefile
--- tests/invalid/Mmakefile	3 Sep 2007 11:44:07 -0000	1.221
+++ tests/invalid/Mmakefile	2 Oct 2007 04:11:43 -0000
@@ -114,6 +114,7 @@
 	invalid_event \
 	invalid_export_detism \
 	invalid_import_detism \
+	invalid_instance_declarations \
 	invalid_main \
 	invalid_mllibs \
 	invalid_new \
Index: tests/invalid/ambiguous_method.m
===================================================================
RCS file: /home/mercury1/repository/tests/invalid/ambiguous_method.m,v
retrieving revision 1.1
diff -u -r1.1 ambiguous_method.m
--- tests/invalid/ambiguous_method.m	20 Apr 2005 12:57:44 -0000	1.1
+++ tests/invalid/ambiguous_method.m	2 Oct 2007 04:11:43 -0000
@@ -7,7 +7,7 @@
 
 main(!S) :-
 	(
-		test([0], 1)
+		test(intcoll([0]), 1)
 	->
 		write_string("yes\n", !S)
 	;
@@ -20,13 +20,13 @@
 	pred m(E::in, C::in) is semidet
 ].
 
-:- type intcoll == list(int).
+:- type intcoll ---> intcoll(list(int)).
 
 :- instance coll(intcoll, int) where [
-	(e = []),
-	(i(Ns, N) = [N | Ns]),
-	m(N, [N | _]),
-	m(N, [_ | Ns]) :- m(N, Ns)
+	(e = intcoll([])),
+	(i(intcoll(Ns), N) = intcoll([N | Ns])),
+	m(N, intcoll([N | _])),
+	m(N, intcoll([_ | Ns])) :- m(N, intcoll(Ns))
 ].
 
 :- pred test(C, E) <= coll(C, E).
Index: tests/invalid/ambiguous_method_2.m
===================================================================
RCS file: /home/mercury1/repository/tests/invalid/ambiguous_method_2.m,v
retrieving revision 1.1
diff -u -r1.1 ambiguous_method_2.m
--- tests/invalid/ambiguous_method_2.m	20 Apr 2005 12:57:44 -0000	1.1
+++ tests/invalid/ambiguous_method_2.m	2 Oct 2007 04:11:43 -0000
@@ -7,14 +7,14 @@
 
 main(!S) :-
 	(
-		test([0], 1)
+		test(intcoll([0]), 1)
 	->
 		write_string("yes\n", !S)
 	;
 		write_string("no\n", !S)
 	),
 	(
-		e = [1]
+		e = intcoll([1])
 	->
 		write_string("yes\n", !S)
 	;
@@ -30,13 +30,13 @@
 	pred m(E::in, C::in) is semidet
 ].
 
-:- type intcoll == list(int).
+:- type intcoll ---> intcoll(list(int)).
 
 :- instance coll(intcoll, int) where [
-	(e = []),
-	(i(Ns, N) = [N | Ns]),
-	m(N, [N | _]),
-	m(N, [_ | Ns]) :- m(N, Ns)
+	(e = intcoll([])),
+	(i(intcoll(Ns), N) = intcoll([N | Ns])),
+	m(N, intcoll([N | _])),
+	m(N, intcoll([_ | Ns])) :- m(N, intcoll(Ns))
 ].
 
 :- pred test(C, E) <= coll(C, E).
Index: tests/invalid/bad_instance.err_exp
===================================================================
RCS file: /home/mercury1/repository/tests/invalid/bad_instance.err_exp,v
retrieving revision 1.2
diff -u -r1.2 bad_instance.err_exp
--- tests/invalid/bad_instance.err_exp	14 Sep 2005 05:26:42 -0000	1.2
+++ tests/invalid/bad_instance.err_exp	2 Oct 2007 04:11:43 -0000
@@ -1,2 +1,10 @@
-bad_instance.m:005: Error: types in instance declarations must be functors with distinct variables as arguments: foo(bar(_1), _2).
-bad_instance.m:011: Error: types in instance declarations must be functors with distinct variables as arguments: foo(bar(_1), _1).
+bad_instance.m:005: Error: abstract instance declaration for
+bad_instance.m:005:   `bad_instance.foo((bad_instance.bar(T)), U)' has no
+bad_instance.m:005:   corresponding concrete instance in the implementation.
+bad_instance.m:005: In instance declaration for
+bad_instance.m:005:   `bad_instance.foo((bad_instance.bar(T)), U)':
+bad_instance.m:005:   the second arg is a type variable
+bad_instance.m:011: In instance declaration for
+bad_instance.m:011:   `bad_instance.foo((bad_instance.bar(T)), T)':
+bad_instance.m:011:   the second arg is a type variable
+For more information, recompile with `-E'.
Index: tests/invalid/instance_dup_var.err_exp
===================================================================
RCS file: /home/mercury1/repository/tests/invalid/instance_dup_var.err_exp,v
retrieving revision 1.1
diff -u -r1.1 instance_dup_var.err_exp
--- tests/invalid/instance_dup_var.err_exp	19 Oct 2006 07:29:54 -0000	1.1
+++ tests/invalid/instance_dup_var.err_exp	2 Oct 2007 04:11:43 -0000
@@ -1,2 +1,11 @@
-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)).
+instance_dup_var.m:012: In instance declaration for
+instance_dup_var.m:012:   `instance_dup_var.baz((instance_dup_var.foo(T, T)),
+instance_dup_var.m:012:   (instance_dup_var.bar))':
+instance_dup_var.m:012:   the first arg is not a type whose arguments are
+instance_dup_var.m:012:   distinct type variables
+instance_dup_var.m:015: In instance declaration for
+instance_dup_var.m:015:   `instance_dup_var.baz((instance_dup_var.foo(A, B)),
+instance_dup_var.m:015:   (instance_dup_var.foo(C, A)))':
+instance_dup_var.m:015:   the second arg contains a type variable which is used
+instance_dup_var.m:015:   in another arg
+For more information, recompile with `-E'.
Index: tests/invalid/invalid_instance_declarations.err_exp
===================================================================
RCS file: tests/invalid/invalid_instance_declarations.err_exp
diff -N tests/invalid/invalid_instance_declarations.err_exp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/invalid/invalid_instance_declarations.err_exp	2 Oct 2007 04:11:43 -0000
@@ -0,0 +1,19 @@
+invalid_instance_declarations.m:015: In instance declaration for
+invalid_instance_declarations.m:015:   `invalid_instance_declarations.tc((invalid_instance_declarations.t(T,
+invalid_instance_declarations.m:015:   T)))':
+invalid_instance_declarations.m:015:   the first arg is not a type whose
+invalid_instance_declarations.m:015:   arguments are distinct type variables
+invalid_instance_declarations.m:016: In instance declaration for
+invalid_instance_declarations.m:016:   `invalid_instance_declarations.tc(((func)
+invalid_instance_declarations.m:016:   = T))':
+invalid_instance_declarations.m:016:   the first arg is a higher order type
+invalid_instance_declarations.m:017: In instance declaration for
+invalid_instance_declarations.m:017:   `invalid_instance_declarations.tc({T,
+invalid_instance_declarations.m:017:   T})':
+invalid_instance_declarations.m:017:   the first arg is not a type whose
+invalid_instance_declarations.m:017:   arguments are distinct type variables
+invalid_instance_declarations.m:018: In instance declaration for
+invalid_instance_declarations.m:018:   `invalid_instance_declarations.tc((invalid_instance_declarations.t(int)))':
+invalid_instance_declarations.m:018:   the first arg is a type whose first arg
+invalid_instance_declarations.m:018:   is not a variable
+For more information, recompile with `-E'.
Index: tests/invalid/invalid_instance_declarations.m
===================================================================
RCS file: tests/invalid/invalid_instance_declarations.m
diff -N tests/invalid/invalid_instance_declarations.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/invalid/invalid_instance_declarations.m	2 Oct 2007 04:11:43 -0000
@@ -0,0 +1,18 @@
+:- module invalid_instance_declarations.
+:- interface.
+
+:- type t(T) ---> f(T).
+:- type t(T, U) ---> f(T, U).
+
+:- typeclass tc(T) where [].
+
+:- type e(T) == t(T, T).
+:- type f(T) == ((func) = T).
+:- type g(T) == {T, T}.
+:- type h == t(int).
+
+:- implementation.
+:- instance tc(e(T)) where [].
+:- instance tc(f(T)) where [].
+:- instance tc(g(T)) where [].
+:- instance tc(h) 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