[m-rev.] for review: fix existential typeclass reordering bug
Simon Taylor
stayl at cs.mu.OZ.AU
Wed Jun 12 01:54:24 AEST 2002
Estimated hours taken: 1.5
Branches: main, release
compiler/polymorphism.m:
Previously, we assumed that when a type variable had not
been seen before, a type_info would be produced for
it by a later goal. This didn't work when the type_info
was contained in a typeclass_info produced by the later
goal. Now whenever an existential typeclass_info is produced
by a call or deconstruction unification, the type_info_varmap
entries for such type variables are updated to point to the
type_class_info, and code is generated to extract the type_info
from the typeclass_info.
tests/hard_coded/Mmakefile:
tests/hard_coded/existential_reordering_class.{m,exp}:
Before this change, the compiler reported a spurious mode
error for this test case.
Index: compiler/polymorphism.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/polymorphism.m,v
retrieving revision 1.224
diff -u -u -r1.224 polymorphism.m
--- compiler/polymorphism.m 11 Jun 2002 09:30:49 -0000 1.224
+++ compiler/polymorphism.m 11 Jun 2002 15:50:27 -0000
@@ -1580,17 +1580,11 @@
;
IsConstruction = no,
% assume it's a deconstruction
- polymorphism__make_typeclass_info_head_vars(
- ExistentialConstraints,
- ExtraTypeClassVars,
- PolyInfo1, PolyInfo2),
- ExtraTypeClassGoals = [],
- polymorphism__update_typeclass_infos(
+ polymorphism__make_existq_typeclass_info_vars(
ExistentialConstraints, ExtraTypeClassVars,
- PolyInfo2, PolyInfo3)
+ ExtraTypeClassGoals, PolyInfo1, PolyInfo3)
),
-
%
% Compute the set of _unconstrained_ existentially quantified type
% variables, and then apply the type bindings to those type variables
@@ -1950,12 +1944,9 @@
% insert them into the typeclass_info map
apply_rec_subst_to_constraint_list(TypeSubst,
ExistentialConstraints1, ExistentialConstraints),
- polymorphism__make_typeclass_info_head_vars(
- ExistentialConstraints, ExistTypeClassVars,
- Info2, Info3),
- polymorphism__update_typeclass_infos(
+ polymorphism__make_existq_typeclass_info_vars(
ExistentialConstraints, ExistTypeClassVars,
- Info3, Info4),
+ ExtraExistClassGoals, Info2, Info4),
list__append(UnivTypeClassVars, ExistTypeClassVars,
ExtraTypeClassVars),
@@ -1975,10 +1966,9 @@
Info4, Info),
list__append(ExtraTypeClassVars, ArgVars0, ArgVars1),
list__append(ExtraTypeInfoVars, ArgVars1, ArgVars),
- list__append(ExtraTypeClassGoals, ExtraTypeInfoGoals,
- ExtraGoals),
- list__append(ExtraTypeClassVars, ExtraTypeInfoVars,
- ExtraVars),
+ ExtraGoals = ExtraTypeClassGoals ++ ExtraExistClassGoals
+ ++ ExtraTypeInfoGoals,
+ ExtraVars = ExtraTypeClassVars ++ ExtraTypeInfoVars,
%
% update the non-locals
@@ -2613,6 +2603,60 @@
maybe_insert_var(no, Vars, Vars).
maybe_insert_var(yes(Var), Vars, [Var | Vars]).
+%-----------------------------------------------------------------------------%
+
+ % Produce the typeclass_infos for the existential class
+ % constraints for a call or deconstruction unification.
+:- pred polymorphism__make_existq_typeclass_info_vars(
+ list(class_constraint), list(prog_var), list(hlds_goal),
+ poly_info, poly_info).
+:- mode polymorphism__make_existq_typeclass_info_vars(in, out, out,
+ in, out) is det.
+
+polymorphism__make_existq_typeclass_info_vars(
+ ExistentialConstraints, ExtraTypeClassVars,
+ ExtraGoals, PolyInfo0, PolyInfo) :-
+ poly_info_get_type_info_map(PolyInfo0, OldTypeInfoMap),
+ polymorphism__make_typeclass_info_head_vars(ExistentialConstraints,
+ ExtraTypeClassVars, PolyInfo0, PolyInfo1),
+ polymorphism__update_typeclass_infos(ExistentialConstraints,
+ ExtraTypeClassVars, PolyInfo1, PolyInfo2),
+
+ constraint_list_get_tvars(ExistentialConstraints, TVars0),
+ list__sort_and_remove_dups(TVars0, TVars),
+
+ %
+ % For code which requires mode reordering, we may have
+ % already seen some of the type-infos produced by this
+ % call. The type-info locations for those variables will
+ % be a type-info
+ %
+ list__foldl2(polymorphism__maybe_extract_type_info(OldTypeInfoMap),
+ TVars, [], ExtraGoals, PolyInfo2, PolyInfo).
+
+:- pred polymorphism__maybe_extract_type_info(type_info_varmap,
+ tvar, list(hlds_goal), list(hlds_goal),
+ poly_info, poly_info).
+:- mode polymorphism__maybe_extract_type_info(in, in, in, out, in, out) is det.
+
+polymorphism__maybe_extract_type_info(OldTypeInfoMap, TVar,
+ ExtraGoals0, ExtraGoals, Info0, Info) :-
+ poly_info_get_type_info_map(Info0, TypeInfoMap),
+ (
+ map__search(OldTypeInfoMap, TVar, type_info(TypeInfoVar0)),
+ map__search(TypeInfoMap, TVar,
+ typeclass_info(TypeClassInfoVar, Index))
+ ->
+ extract_type_info(TVar, TypeClassInfoVar,
+ Index, ExtraGoals1, TypeInfoVar1, Info0, Info),
+ polymorphism__assign_var(TypeInfoVar0,
+ TypeInfoVar1, AssignGoal),
+ ExtraGoals = ExtraGoals1 ++ [AssignGoal | ExtraGoals0]
+ ;
+ ExtraGoals = ExtraGoals0,
+ Info = Info0
+ ).
+
%---------------------------------------------------------------------------%
% Given a list of types, create a list of variables to hold the type_info
@@ -3231,10 +3275,22 @@
First, _),
- % Work out which ones haven't been seen before
+ % Work out which type variables we haven't seen
+ % before, or which we assumed earlier would be
+ % produced in a type-info (this can happen for
+ % code which needs mode reordering and which calls
+ % existentially quantified predicates or
+ % deconstructs existentially quantified terms).
IsNew = (pred(TypeVar0::in) is semidet :-
TypeVar0 = TypeVar - _Index,
- \+ map__search(TypeInfoMap0, TypeVar, _)
+ (
+ map__search(TypeInfoMap0,
+ TypeVar, TypeInfoLocn)
+ ->
+ TypeInfoLocn = type_info(_)
+ ;
+ true
+ )
),
list__filter(IsNew, ClassTypeVars, NewClassTypeVars),
Index: tests/hard_coded/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/tests/hard_coded/Mmakefile,v
retrieving revision 1.153
diff -u -u -r1.153 Mmakefile
--- tests/hard_coded/Mmakefile 11 Jun 2002 09:30:53 -0000 1.153
+++ tests/hard_coded/Mmakefile 11 Jun 2002 11:05:59 -0000
@@ -46,6 +46,7 @@
existential_bound_tvar \
existential_float \
existential_reordering \
+ existential_reordering_class \
existential_type_switch_opt \
existential_types_test \
expand \
Index: tests/hard_coded/existential_reordering_class.exp
===================================================================
RCS file: tests/hard_coded/existential_reordering_class.exp
diff -N tests/hard_coded/existential_reordering_class.exp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/hard_coded/existential_reordering_class.exp 13 Jan 2001 02:30:30 -0000
@@ -0,0 +1 @@
+univ_cons([])
Index: tests/hard_coded/existential_reordering_class.m
===================================================================
RCS file: tests/hard_coded/existential_reordering_class.m
diff -N tests/hard_coded/existential_reordering_class.m
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/hard_coded/existential_reordering_class.m 11 Jun 2002 10:15:06 -0000
@@ -0,0 +1,29 @@
+% This module tests the use of existential types,
+% including type inference.
+
+:- module existential_reordering_class.
+:- interface.
+
+:- import_module io.
+
+:- pred main(io__state::di, state::uo) is det.
+
+:- implementation.
+:- import_module enum, int, std_util, list.
+
+main -->
+ % do something which requires knowing the type of L
+ { L = [] },
+ { Univ = univ(L) },
+ write(Univ),
+ nl,
+
+ % now do something which binds the type of L
+ { same_type(L, [my_exist_t]) }.
+
+:- pred same_type(T::unused, T::unused) is det.
+same_type(_, _).
+
+:- some [T] func my_exist_t = T => enum(T).
+
+my_exist_t = 42.
--------------------------------------------------------------------------
mercury-reviews mailing list
post: mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------
More information about the reviews
mailing list