diff: some more type class improvements
Fergus Henderson
fjh at cs.mu.OZ.AU
Fri Apr 10 04:30:02 AEST 1998
Estimated hours taken: 4
A few more improvements to type class checking.
compiler/typecheck.m:
Ensure that we run a final pass of context reduction at the
end of typechecking each predicate (or function).
Change the way perform_context_reduction recovers after errors
to avoid reporting the same error more than once
(e.g. for tests/invalid/typeclass_test_1.m).
Simplify the code to check for and report unsatisfied
type class constraints.
Change write_type_assign so that it prints out the
type class constraints as well as the variable types.
tests/invalid/typeclass_test_{1,2}.err_exp:
Add a full stop that was missing at the end of
the "unsatisfied typeclass constraint" error message.
Index: typecheck.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/typecheck.m,v
retrieving revision 1.235
diff -u -u -r1.235 typecheck.m
--- typecheck.m 1998/04/09 15:29:33 1.235
+++ typecheck.m 1998/04/09 18:15:08
@@ -481,13 +481,19 @@
TypeVarSet0, VarSet, ExplicitVarTypes,
HeadTypeParams, Constraints, Status,
TypeCheckInfo1),
+ typecheck_info_get_type_assign_set(TypeCheckInfo1,
+ OrigTypeAssignSet),
typecheck_clause_list(Clauses0, HeadVars, ArgTypes0, Clauses,
TypeCheckInfo1, TypeCheckInfo2),
- typecheck_constraints(Inferring, TypeCheckInfo2,
+ % we need to perform a final pass of context reduction
+ % at the end, before checking the typeclass constraints
+ perform_context_reduction(OrigTypeAssignSet, TypeCheckInfo2,
TypeCheckInfo3),
+ typecheck_constraints(Inferring, TypeCheckInfo3,
+ TypeCheckInfo4),
typecheck_check_for_ambiguity(whole_pred, HeadVars,
- TypeCheckInfo3, TypeCheckInfo4),
- typecheck_info_get_final_info(TypeCheckInfo4, TypeVarSet,
+ TypeCheckInfo4, TypeCheckInfo5),
+ typecheck_info_get_final_info(TypeCheckInfo5, TypeVarSet,
InferredVarTypes0, InferredTypeConstraints,
ConstraintProofs),
map__optimize(InferredVarTypes0, InferredVarTypes),
@@ -2925,25 +2931,15 @@
typecheck_constraints(yes, TypeCheckInfo, TypeCheckInfo).
typecheck_constraints(no, TypeCheckInfo0, TypeCheckInfo) :-
- % get the declared constraints
- typecheck_info_get_constraints(TypeCheckInfo0, DeclaredConstraints),
-
+ % reject any type assignment whose constraints have
+ % not all been eliminated by context reduction
+ % (i.e. those chich have constraints which do not match the
+ % declared constraints and which are not redundant for any
+ % other reason)
typecheck_info_get_type_assign_set(TypeCheckInfo0, TypeAssignSet0),
-
- ConstraintsMatch = lambda([TypeAssign::in] is semidet,
- (
- type_assign_get_typeclass_constraints(TypeAssign,
- CalculatedConstraints0),
- type_assign_get_type_bindings(TypeAssign, Bindings),
- apply_rec_subst_to_constraints(Bindings,
- CalculatedConstraints0, CalculatedConstraints),
- constraints_match(CalculatedConstraints,
- DeclaredConstraints)
- )),
-
- % reject any type assignment whose constraints don't match the
- % declared ones
- list__filter(ConstraintsMatch, TypeAssignSet0, TypeAssignSet),
+ NoConstraints = lambda([TypeAssign::in] is semidet,
+ type_assign_get_typeclass_constraints(TypeAssign, [])),
+ list__filter(NoConstraints, TypeAssignSet0, TypeAssignSet),
(
% Check that we haven't just eliminated
% all the type assignments.
@@ -2958,14 +2954,6 @@
).
- % The calculated constraints must be a subset of the declared
- % constraints.
-:- pred constraints_match(list(class_constraint)::in,
- list(class_constraint)::in) is semidet.
-constraints_match(CalculatedConstraints, DeclaredConstraints) :-
- all [C] list__member(C, CalculatedConstraints) =>
- list__member(C, DeclaredConstraints).
-
%-----------------------------------------------------------------------------%
:- pred report_unsatisfied_constraints(type_assign_set, typecheck_info,
@@ -2976,8 +2964,6 @@
report_unsatisfied_constraints(TypeAssignSet, TypeCheckInfo0, TypeCheckInfo) :-
typecheck_info_get_io_state(TypeCheckInfo0, IOState0),
- typecheck_info_get_constraints(TypeCheckInfo0, DeclaredConstraints),
-
typecheck_info_get_context(TypeCheckInfo0, Context),
write_context_and_pred_id(TypeCheckInfo0, IOState0, IOState1),
prog_out__write_context(Context, IOState1, IOState2),
@@ -2994,11 +2980,9 @@
TheConstraints0, TheConstraints1),
list__sort_and_remove_dups(TheConstraints1,
TheConstraints),
- list__delete_elems(TheConstraints, DeclaredConstraints,
- Unsatisfied),
prog_out__write_context(Context, IO0, IO1),
io__write_string(" ", IO1, IO2),
- io__write_list(Unsatisfied, ", ",
+ io__write_list(TheConstraints, ", ",
mercury_output_constraint(TheVarSet), IO2, IO3),
io__write_string(".\n", IO3, IO)
)),
@@ -3045,10 +3029,11 @@
% instance declaration for that type.
%
% If all type_assigns from the typecheck_info are rejected, than an
-% appropriate error message is given, and the type_assign_set is
-% restored to the original one given by OrigTypeAssignSet.
+% appropriate error message is given, the type_assign_set is
+% restored to the original one given by OrigTypeAssignSet,
+% but without any typeclass constraints.
% The reason for this is to avoid reporting the same error at
-% every subsequent call to perform_context_reduction.
+% subsequent calls to perform_context_reduction.
:- pred perform_context_reduction(type_assign_set,
typecheck_info, typecheck_info).
@@ -3072,8 +3057,13 @@
->
report_unsatisfied_constraints(TypeAssignSet0,
TypeCheckInfo0, TypeCheckInfo1),
+ DeleteConstraints = lambda([TA0::in, TA::out] is det,
+ type_assign_set_typeclass_constraints(TA0, [], TA)
+ ),
+ list__map(DeleteConstraints, OrigTypeAssignSet,
+ NewTypeAssignSet),
typecheck_info_set_type_assign_set(TypeCheckInfo1,
- OrigTypeAssignSet, TypeCheckInfo)
+ NewTypeAssignSet, TypeCheckInfo)
;
typecheck_info_set_type_assign_set(TypeCheckInfo0,
TypeAssignSet, TypeCheckInfo)
@@ -4055,27 +4045,30 @@
write_type_assign(TypeAssign, VarSet) -->
{
type_assign_get_var_types(TypeAssign, VarTypes),
+ type_assign_get_typeclass_constraints(TypeAssign, Constraints),
type_assign_get_type_bindings(TypeAssign, TypeBindings),
type_assign_get_typevarset(TypeAssign, TypeVarSet),
map__keys(VarTypes, Vars)
},
- write_type_assign_2(Vars, VarSet, VarTypes, TypeBindings, TypeVarSet,
- no),
+ write_type_assign_types(Vars, VarSet, VarTypes,
+ TypeBindings, TypeVarSet, no),
+ write_type_assign_constraints(Constraints,
+ TypeBindings, TypeVarSet, no),
io__write_string("\n").
-:- pred write_type_assign_2(list(var), varset, map(var, type),
+:- pred write_type_assign_types(list(var), varset, map(var, type),
tsubst, tvarset, bool, io__state, io__state).
-:- mode write_type_assign_2(in, in, in, in, in, in, di, uo) is det.
+:- mode write_type_assign_types(in, in, in, in, in, in, di, uo) is det.
-write_type_assign_2([], _, _, _, _, FoundOne) -->
+write_type_assign_types([], _, _, _, _, FoundOne) -->
( { FoundOne = no } ->
io__write_string("(No variables were assigned a type)")
;
[]
).
-write_type_assign_2([Var | Vars], VarSet, VarTypes, TypeBindings, TypeVarSet,
- FoundOne) -->
+write_type_assign_types([Var | Vars], VarSet, VarTypes, TypeBindings,
+ TypeVarSet, FoundOne) -->
(
{ map__search(VarTypes, Var, Type) }
->
@@ -4087,12 +4080,30 @@
mercury_output_var(Var, VarSet, no),
io__write_string(" :: "),
write_type_b(Type, TypeVarSet, TypeBindings),
- write_type_assign_2(Vars, VarSet, VarTypes, TypeBindings,
+ write_type_assign_types(Vars, VarSet, VarTypes, TypeBindings,
TypeVarSet, yes)
;
- write_type_assign_2(Vars, VarSet, VarTypes, TypeBindings,
+ write_type_assign_types(Vars, VarSet, VarTypes, TypeBindings,
TypeVarSet, FoundOne)
).
+
+:- pred write_type_assign_constraints(list(class_constraint),
+ tsubst, tvarset, bool, io__state, io__state).
+:- mode write_type_assign_constraints(in, in, in, in, di, uo) is det.
+
+write_type_assign_constraints([], _, _, _) --> [].
+write_type_assign_constraints([Constraint | Constraints],
+ TypeBindings, TypeVarSet, FoundOne) -->
+ ( { FoundOne = no } ->
+ io__write_string("\n\t<= ")
+ ;
+ io__write_string(",\n\t ")
+ ),
+ { apply_rec_subst_to_constraint(TypeBindings, Constraint,
+ BoundConstraint) },
+ mercury_output_constraint(TypeVarSet, BoundConstraint),
+ write_type_assign_constraints(Constraints,
+ TypeBindings, TypeVarSet, yes).
% write_type_b writes out a type after applying the type bindings.
Index: typeclass_test_1.err_exp
===================================================================
RCS file: /home/mercury1/repository/tests/invalid/typeclass_test_1.err_exp,v
retrieving revision 1.2
diff -u -u -r1.2 typeclass_test_1.err_exp
--- typeclass_test_1.err_exp 1998/02/02 02:55:57 1.2
+++ typeclass_test_1.err_exp 1998/04/09 18:22:40
@@ -3,5 +3,5 @@
typeclass_test_1.m:017: Syntax error at variable `_': operator or `.' expected.
typeclass_test_1.m:007: In clause for predicate `typeclass_test_1:main/2':
typeclass_test_1.m:007: unsatisfied typeclass constraint(s):
-typeclass_test_1.m:007: typeclass_test_1:numbered_type(int)
+typeclass_test_1.m:007: typeclass_test_1:numbered_type(int).
For more information, try recompiling with `-E'.
Index: typeclass_test_2.err_exp
===================================================================
RCS file: /home/mercury1/repository/tests/invalid/typeclass_test_2.err_exp,v
retrieving revision 1.3
diff -u -u -r1.3 typeclass_test_2.err_exp
--- typeclass_test_2.err_exp 1998/03/03 17:48:02 1.3
+++ typeclass_test_2.err_exp 1998/04/09 18:22:18
@@ -4,6 +4,6 @@
typeclass_test_2.m:018: without preceding `func' declaration.
typeclass_test_2.m:008: In clause for predicate `typeclass_test_2:main/2':
typeclass_test_2.m:008: unsatisfied typeclass constraint(s):
-typeclass_test_2.m:008: typeclass_test_2:numbered_type(int)
+typeclass_test_2.m:008: typeclass_test_2:numbered_type(int).
typeclass_test_2.m:018: Inferred :- func foo_type_num(T1) = int.
For more information, try recompiling with `-E'.
--
Fergus Henderson <fjh at cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh at 128.250.37.3 | -- the last words of T. S. Garp.
More information about the developers
mailing list