[m-rev.] for prelim review: check instance declaration compatibility
Peter Ross
pro at missioncriticalit.com
Fri May 18 15:33:42 AEST 2007
Hi,
This code still needs to boot check, and for a test case to be
added to the test suite, but I am submitting it for prelim review
now, as I don't have time to do the rest today.
===================================================================
Estimated hours taken: 1
Branches: main
The following code causes code to be generated which seg-faults
:- interface
:- instance tc(list(T)).
:- implementation.
:- instance tc(list(T)) <= tc(T) where [...].
because the exported instance declaration doesn't contain the
typeclass constraint.
compiler/add_class.m:
Check that for all the "same" instance declarations
the instance constraints are exactly the same on each
declaration.
Index: compiler/add_class.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/add_class.m,v
retrieving revision 1.26
diff -u -r1.26 add_class.m
--- compiler/add_class.m 19 Jan 2007 07:04:07 -0000 1.26
+++ compiler/add_class.m 18 May 2007 05:27:42 -0000
@@ -461,8 +461,11 @@
NewInstanceDefn = hlds_instance_defn(InstanceModuleName, Status,
Context, Constraints, Types, Body, no, VarSet, Empty),
map.lookup(Instances0, ClassId, InstanceDefns),
+
check_for_overlapping_instances(NewInstanceDefn, InstanceDefns,
ClassId, !Specs),
+ check_instance_constraints(NewInstanceDefn, InstanceDefns, !Specs),
+
map.det_update(Instances0, ClassId,
[NewInstanceDefn | InstanceDefns], Instances),
module_info_set_instance_table(Instances, !ModuleInfo)
@@ -508,6 +511,88 @@
Msg2 = error_msg(yes(OtherContext), yes, 0, [always(Pieces2)]),
Spec = error_spec(severity_error, phase_parse_tree_to_hlds, [Msg1, Msg2]),
!:Specs = [Spec | !.Specs].
+
+
+:- pred check_instance_constraints(hlds_instance_defn::in,
+ list(hlds_instance_defn)::in,
+ list(error_spec)::in, list(error_spec)::out) is det.
+
+check_instance_constraints(InstanceDefn, InstanceDefns, !Specs) :-
+ list.filter_map(
+ (pred(ID::in, {ID, R}::out) is semidet :-
+ same_type_hlds_instance_defn(InstanceDefn, ID, R)
+ ), InstanceDefns, EquivInstanceDefns),
+ list.foldl(check_instance_constraint(InstanceDefn),
+ EquivInstanceDefns, !Specs).
+
+:- pred check_instance_constraint(hlds_instance_defn::in,
+ {hlds_instance_defn, tvar_renaming}::in,
+ list(error_spec)::in, list(error_spec)::out) is det.
+
+check_instance_constraint(InstanceDefnA, {InstanceDefnB, Renaming}, !Specs) :-
+ ConstraintsA = InstanceDefnA ^ instance_constraints,
+ ConstraintsB = InstanceDefnB ^ instance_constraints,
+ ( same_prog_constraint_list(Renaming, ConstraintsA, ConstraintsB) ->
+ true
+ ;
+ ContextA = InstanceDefnA ^ instance_context,
+ TxtA = always([string_to_words_piece("instance constraints incompatible")]),
+ MsgA = simple_msg(ContextA, [TxtA]),
+
+ ContextB = InstanceDefnB ^ instance_context,
+ TxtB = always([string_to_words_piece("with instance constraints here.")]),
+ MsgB = simple_msg(ContextB, [TxtB]),
+
+ Spec = error_spec(severity_error, phase_parse_tree_to_hlds, [MsgA, MsgB]),
+ !:Specs = [Spec | !.Specs]
+ ).
+
+ %
+ % Do two hlds_instance_defn refer to the same type?
+ % eg "instance tc(f(T))" compares equal to "instance tc(f(U))"
+ %
+ % Note we don't check that the constraits of the declarations are the
+ % same.
+ %
+:- pred same_type_hlds_instance_defn(hlds_instance_defn::in,
+ hlds_instance_defn::in, tvar_renaming::out) is semidet.
+
+same_type_hlds_instance_defn(InstanceDefnA, InstanceDefnB, Renaming) :-
+ TypesA = InstanceDefnA ^ instance_types,
+ TypesB = InstanceDefnB ^ instance_types,
+
+ VarSetA = InstanceDefnA ^ instance_tvarset,
+ VarSetB = InstanceDefnB ^ instance_tvarset,
+
+ tvarset_merge_renaming(VarSetA, VarSetB, _NewVarSet, Renaming),
+ apply_variable_renaming_to_type_list(Renaming, TypesB, NewTypesB),
+ type_list_subsumes(TypesA, NewTypesB, _).
+
+ % same_prog_constraint_list(R, CsA, CsB)
+ %
+ % checks that the constraints list, CsB, is exactly the same
+ % as the list, CsA, after the type variables in CsB have
+ % been renamed using R.
+ %
+ % Note by the same we also mean the constraints are listed
+ % in the same order.
+ %
+:- pred same_prog_constraint_list(tvar_renaming::in,
+ list(prog_constraint)::in, list(prog_constraint)::in) is semidet.
+
+same_prog_constraint_list(_, [], []).
+same_prog_constraint_list(RenamingForB,
+ [ConstraintA | ConstraintsA], [ConstraintB | ConstraintsB]) :-
+ apply_variable_renaming_to_prog_constraint(RenamingForB,
+ ConstraintB, NewConstraintB),
+ same_constraint(ConstraintA, NewConstraintB),
+ same_prog_constraint_list(RenamingForB, ConstraintsA, ConstraintsB).
+
+:- pred same_constraint(prog_constraint::in, prog_constraint::in) is semidet.
+
+same_constraint(constraint(NameA, TypesA), constraint(NameB, TypesB)) :-
+ NameA = NameB,
+ type_list_subsumes(TypesA, TypesB, _).
do_produce_instance_method_clauses(InstanceProcDefn, PredOrFunc, PredArity,
ArgTypes, Markers, Context, Status, ClausesInfo, !ModuleInfo,
--------------------------------------------------------------------------
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