[m-rev.] for review: unused imports analysis

Peter Ross pro at missioncriticalit.com
Tue Sep 19 00:53:26 AEST 2006


Hi,


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


Estimated hours taken: 8
Branches: main

Fix an XXX in the unused_imports implementation.
Rather than approximating the set of modules which have been
used due to equivalence types having been expanded by the
time unused_imports analysis is run, we now determine exactly
which modules have been used during equivalence type expansion
in expand_eqv_types.

compiler/equiv_type.m:
	Thread used_modules and location through this code.
	The location type is used to determine whenever we expand
	a type whether that expansion occured in the interface or
	implementation, or in some-other imported module.
	
compiler/hlds_module.m:
	Replace the parent used modules with the used_modules 
	which will hold the equivalence type expansions as well
	as the imports inherited from the parents.

compiler/make_hlds.m:
compiler/make_hlds_passes.m:
compiler/mercury_compile.m:
	Pass the used_modules calculated by expand_eqv_types
	to the code which creates the hlds, and set them
	in the module_info.

compiler/prog_data.m:
compiler/unused_imports.m:
	Move the used_modules type to prog_data as this type
	is now used in the parse_tree modules.

compiler/unused_imports.m:
	Delete the code which approximated the set of modules
	used to expand equivalence types.

Index: compiler/equiv_type.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/equiv_type.m,v
retrieving revision 1.68
diff -U5 -r1.68 equiv_type.m
--- compiler/equiv_type.m	7 Sep 2006 05:50:53 -0000	1.68
+++ compiler/equiv_type.m	18 Sep 2006 14:41:41 -0000
@@ -49,11 +49,11 @@
     % while processing each item are recorded in the recompilation_info,
     % for use by smart recompilation.
     %
 :- pred expand_eqv_types(module_name::in,
     list(item_and_context)::in, list(item_and_context)::out,
-    bool::out, eqv_map::out,
+    bool::out, eqv_map::out, used_modules::out,
     maybe(recompilation_info)::in, maybe(recompilation_info)::out,
     io::di, io::uo) is det.
 
     % Replace equivalence types in a given type.
     % The bool output is `yes' if anything changed.
@@ -89,12 +89,13 @@
 
     % For smart recompilation we need to record which items were
     % expanded in each declaration.  Any items which depend on
     % that declaration also depend on the expanded items.
     %
-:- pred maybe_record_expanded_items(module_name::in, sym_name::in,
-    maybe(recompilation_info)::in, equiv_type_info::out) is det.
+:- pred maybe_record_expanded_items(module_name::in,
+    sym_name::in, maybe(recompilation_info)::in,
+    equiv_type_info::out) is det.
 
     % Record all the expanded items in the recompilation_info.
     %
 :- pred finish_recording_expanded_items(item_id::in,
     equiv_type_info::in, maybe(recompilation_info)::in,
@@ -123,19 +124,30 @@
 :- import_module varset.
 
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
 
+:- type location
+    --->    out_of_module
+    ;       module_interface
+    ;       module_implementation
+    .
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+
     % First we build up a mapping which records the equivalence type
     % definitions.  Then we go through the item list and replace them.
     %
-expand_eqv_types(ModuleName, Items0, Items, Error, EqvMap, !Info, !IO) :-
+expand_eqv_types(ModuleName,
+        Items0, Items, Error, EqvMap, UsedModules, !Info, !IO) :-
     map.init(EqvMap0),
     map.init(EqvInstMap0),
     build_eqv_map(Items0, EqvMap0, EqvMap, EqvInstMap0, EqvInstMap),
-    replace_in_item_list(ModuleName, Items0, EqvMap, EqvInstMap,
-        [], RevItems, [], ErrorList, !Info),
+    replace_in_item_list(ModuleName, out_of_module, Items0,
+        EqvMap, EqvInstMap, [], RevItems, [], ErrorList, !Info,
+        used_modules_init, UsedModules),
     list.reverse(RevItems, Items),
     (
         ErrorList = [],
         Error = no
     ;
@@ -233,23 +245,59 @@
     % The following predicate replace_in_item_list performs substitution
     % of equivalence types on a list of items. Similarly the replace_in_<foo>
     % predicates that follow perform substitution of equivalence types
     % on <foo>s.
     %
-:- pred replace_in_item_list(module_name::in,
+:- pred replace_in_item_list(module_name::in, location::in,
     list(item_and_context)::in, eqv_map::in, eqv_inst_map::in,
     list(item_and_context)::in, list(item_and_context)::out,
     list(eqv_error)::in, list(eqv_error)::out,
-    maybe(recompilation_info)::in, maybe(recompilation_info)::out) is det.
+    maybe(recompilation_info)::in, maybe(recompilation_info)::out,
+    used_modules::in, used_modules::out) is det.
 
-replace_in_item_list(_, [], _, _, !Items, !Errors, !Info).
-replace_in_item_list(ModuleName, [ItemAndContext0 | Items0],
-        EqvMap, EqvInstMap, !ReplItems, !Errors, !Info) :-
+replace_in_item_list(_, _, [], _, _, !Items, !Errors, !Info, !UsedModules).
+replace_in_item_list(ModuleName, Location0, [ItemAndContext0 | Items0],
+        EqvMap, EqvInstMap, !ReplItems, !Errors, !Info, !UsedModules) :-
     ItemAndContext0 = Item0 - Context,
+    ( Item0 = item_module_defn(_, ModuleDefn) ->
+        ( ModuleDefn = md_interface,
+            Location = module_interface
+        ;
+            ( ModuleDefn = md_implementation
+            ; ModuleDefn = md_private_interface
+            ),
+            Location = module_implementation
+        ;
+
+            ( ModuleDefn = md_imported(_)
+            ; ModuleDefn = md_used(_)
+            ; ModuleDefn = md_abstract_imported
+            ; ModuleDefn = md_opt_imported
+            ; ModuleDefn = md_transitively_imported
+                % XXX I'm not sure what these two are
+                % so they may not signify that we've
+                % finished processing the module.
+            ; ModuleDefn = md_external(_, _)
+            ; ModuleDefn = md_export(_)
+            ),
+            Location = out_of_module
+        ; 
+            ( ModuleDefn = md_module(_)
+            ; ModuleDefn = md_end_module(_)
+            ; ModuleDefn = md_import(_)
+            ; ModuleDefn = md_use(_)
+            ; ModuleDefn = md_include_module(_)
+            ; ModuleDefn = md_version_numbers(_, _)
+            ),
+            Location = Location0
+        )
+    ;
+        Location = Location0
+    ),
     (
-        replace_in_item(ModuleName, Item0, Context, EqvMap,
-            EqvInstMap, Item, NewErrors, !Info)
+        replace_in_item(ModuleName, Location, Item0, Context, EqvMap,
+            EqvInstMap, Item, NewErrors, !Info, !UsedModules)
     ->
         ItemAndContext = Item - Context,
 
         % Discard the item if there were any errors.
         (
@@ -261,75 +309,75 @@
         !:Errors = NewErrors ++ !.Errors
     ;
         ItemAndContext = ItemAndContext0,
         !:ReplItems = [ItemAndContext | !.ReplItems]
     ),
-    replace_in_item_list(ModuleName, Items0, EqvMap, EqvInstMap,
-        !ReplItems, !Errors, !Info).
+    replace_in_item_list(ModuleName, Location, Items0, EqvMap, EqvInstMap,
+        !ReplItems, !Errors, !Info, !UsedModules).
 
-:- pred replace_in_item(module_name::in, item::in,
+:- pred replace_in_item(module_name::in, location::in, item::in,
     prog_context::in, eqv_map::in, eqv_inst_map::in, item::out,
     list(eqv_error)::out,
-    maybe(recompilation_info)::in, maybe(recompilation_info)::out) is semidet.
+    maybe(recompilation_info)::in, maybe(recompilation_info)::out,
+    used_modules::in, used_modules::out) is semidet.
 
-replace_in_item(ModuleName,
+replace_in_item(ModuleName, Location,
         item_type_defn(VarSet0, Name, TArgs, TypeDefn0, Cond) @ Item,
         Context, EqvMap, _EqvInstMap,
         item_type_defn(VarSet, Name, TArgs, TypeDefn, Cond),
-        Error, !Info) :-
+        Error, !Info, !UsedModules) :-
     list.length(TArgs, Arity),
     maybe_record_expanded_items(ModuleName, Name, !.Info, UsedTypeCtors0),
-    replace_in_type_defn(EqvMap, type_ctor(Name, Arity), TypeDefn0,
+    replace_in_type_defn(Location, EqvMap, type_ctor(Name, Arity), TypeDefn0,
         TypeDefn, ContainsCirc, VarSet0, VarSet,
-        UsedTypeCtors0, UsedTypeCtors),
+        UsedTypeCtors0, UsedTypeCtors, !UsedModules),
     (
         ContainsCirc = yes,
         Error = [circular_equivalence(Item) - Context]
     ;
         ContainsCirc = no,
         Error = []
     ),
     ItemId = item_id(type_body_item, item_name(Name, Arity)),
     finish_recording_expanded_items(ItemId, UsedTypeCtors, !Info).
 
-replace_in_item(ModuleName,
+replace_in_item(ModuleName, Location,
         item_pred_or_func(Origin, TypeVarSet0, InstVarSet, ExistQVars,
             PredOrFunc, PredName, TypesAndModes0, MaybeWithType0,
             MaybeWithInst0, Det0, Cond, Purity, ClassContext0),
         Context, EqvMap, EqvInstMap,
         item_pred_or_func(Origin, TypeVarSet, InstVarSet, ExistQVars,
             PredOrFunc, PredName, TypesAndModes, MaybeWithType,
             MaybeWithInst, Det, Cond, Purity, ClassContext),
-        Errors, !Info) :-
-    maybe_record_expanded_items(ModuleName, PredName,
-        !.Info, ExpandedItems0),
+        Errors, !Info, !UsedModules) :-
+    maybe_record_expanded_items(ModuleName, PredName, !.Info, ExpandedItems0),
 
-    replace_in_pred_type(PredName, PredOrFunc, Context, EqvMap,
+    replace_in_pred_type(Location, PredName, PredOrFunc, Context, EqvMap,
         EqvInstMap, ClassContext0, ClassContext,
         TypesAndModes0, TypesAndModes, TypeVarSet0, TypeVarSet,
         MaybeWithType0, MaybeWithType, MaybeWithInst0, MaybeWithInst,
-        Det0, Det, ExpandedItems0, ExpandedItems, Errors),
+        Det0, Det, ExpandedItems0, ExpandedItems, !UsedModules, Errors),
 
     ItemType = pred_or_func_to_item_type(PredOrFunc),
     list.length(TypesAndModes, Arity),
     adjust_func_arity(PredOrFunc, OrigArity, Arity),
     ItemId = item_id(ItemType, item_name(PredName, OrigArity)),
     finish_recording_expanded_items(ItemId, ExpandedItems, !Info).
 
-replace_in_item(ModuleName,
+replace_in_item(ModuleName, Location,
         item_pred_or_func_mode(InstVarSet, MaybePredOrFunc0, PredName,
             Modes0, WithInst0, Det0, Cond),
         Context, _EqvMap, EqvInstMap,
         item_pred_or_func_mode(InstVarSet, MaybePredOrFunc, PredName,
             Modes, WithInst, Det, Cond),
-        Errors, !Info) :-
+        Errors, !Info, !UsedModules) :-
     maybe_record_expanded_items(ModuleName, PredName, !.Info, ExpandedItems0),
 
-    replace_in_pred_mode(PredName, length(Modes0), Context,
+    replace_in_pred_mode(Location, PredName, length(Modes0), Context,
         mode_decl, EqvInstMap, MaybePredOrFunc0, MaybePredOrFunc,
         ExtraModes, WithInst0, WithInst, Det0, Det,
-        ExpandedItems0, ExpandedItems, Errors),
+        ExpandedItems0, ExpandedItems, !UsedModules, Errors),
     (
         ExtraModes = [],
         Modes = Modes0
     ;
         ExtraModes = [_ | _],
@@ -344,106 +392,107 @@
         finish_recording_expanded_items(ItemId, ExpandedItems, !Info)
     ;
         MaybePredOrFunc = no
     ).
 
-replace_in_item(ModuleName,
+replace_in_item(ModuleName, Location,
         item_typeclass(Constraints0, FunDeps, ClassName, Vars,
             ClassInterface0, VarSet0),
         _Context, EqvMap, EqvInstMap,
         item_typeclass(Constraints, FunDeps, ClassName, Vars,
             ClassInterface, VarSet),
-        Errors, !Info) :-
+        Errors, !Info, !UsedModules) :-
     list.length(Vars, Arity),
-    maybe_record_expanded_items(ModuleName, ClassName,
-        !.Info, ExpandedItems0),
-    replace_in_prog_constraint_list(EqvMap,
+    maybe_record_expanded_items(ModuleName, ClassName, !.Info, ExpandedItems0),
+    replace_in_prog_constraint_list(Location, EqvMap,
         Constraints0, Constraints, VarSet0, VarSet,
-        ExpandedItems0, ExpandedItems1),
+        ExpandedItems0, ExpandedItems1, !UsedModules),
     (
         ClassInterface0 = abstract,
         ClassInterface = abstract,
         ExpandedItems = ExpandedItems1,
         Errors = []
     ;
         ClassInterface0 = concrete(Methods0),
-        replace_in_class_interface(Methods0, EqvMap, EqvInstMap,
-            Methods, [], Errors, ExpandedItems1, ExpandedItems),
+        replace_in_class_interface(Location, Methods0, EqvMap, EqvInstMap,
+            Methods, [], Errors, ExpandedItems1, ExpandedItems, !UsedModules),
         ClassInterface = concrete(Methods)
     ),
     ItemId = item_id(typeclass_item, item_name(ClassName, Arity)),
     finish_recording_expanded_items(ItemId, ExpandedItems, !Info).
 
-replace_in_item(ModuleName,
+replace_in_item(ModuleName, Location,
         item_instance(Constraints0, ClassName, Ts0, InstanceBody, VarSet0,
             ModName),
         _Context, EqvMap, _EqvInstMap,
         item_instance(Constraints, ClassName, Ts, InstanceBody, VarSet,
             ModName),
-        [], !Info) :-
+        [], !Info, !UsedModules) :-
     (
         ( !.Info = no
         ; ModName = ModuleName
         )
     ->
         UsedTypeCtors0 = no
     ;
         UsedTypeCtors0 = yes(ModuleName - set.init)
     ),
-    replace_in_prog_constraint_list(EqvMap,
+    replace_in_prog_constraint_list(Location, EqvMap,
         Constraints0, Constraints, VarSet0, VarSet1,
-        UsedTypeCtors0, UsedTypeCtors1),
-    replace_in_type_list(EqvMap, Ts0, Ts, _, _,
-        VarSet1, VarSet, UsedTypeCtors1, UsedTypeCtors),
+        UsedTypeCtors0, UsedTypeCtors1, !UsedModules),
+    replace_in_type_list(Location, EqvMap, Ts0, Ts, _, _,
+        VarSet1, VarSet, UsedTypeCtors1, UsedTypeCtors, !UsedModules),
     list.length(Ts0, Arity),
     ItemId = item_id(typeclass_item, item_name(ClassName, Arity)),
     finish_recording_expanded_items(ItemId, UsedTypeCtors, !Info).
 
-replace_in_item(ModuleName,
+replace_in_item(ModuleName, Location,
         item_pragma(Origin, pragma_type_spec(PredName, B, Arity, D, E,
             Subst0, VarSet0, ItemIds0)),
         _Context, EqvMap, _EqvInstMap,
         item_pragma(Origin, pragma_type_spec(PredName, B, Arity, D, E,
             Subst, VarSet, ItemIds)),
-        [], !Info) :-
+        [], !Info, !UsedModules) :-
     (
         ( !.Info = no
         ; PredName = qualified(ModuleName, _)
         )
     ->
         ExpandedItems0 = no
     ;
         ExpandedItems0 = yes(ModuleName - ItemIds0)
     ),
-    replace_in_subst(EqvMap, Subst0, Subst, VarSet0, VarSet,
-        ExpandedItems0, ExpandedItems),
+    replace_in_subst(Location, EqvMap, Subst0, Subst, VarSet0, VarSet,
+        ExpandedItems0, ExpandedItems, !UsedModules),
     (
         ExpandedItems = no,
         ItemIds = ItemIds0
     ;
         ExpandedItems = yes(_ - ItemIds)
     ).
 
-replace_in_item(ModuleName,
+replace_in_item(ModuleName, Location,
         item_pragma(Origin, pragma_foreign_proc(Attrs0, PName, PredOrFunc, 
             ProcVars, ProcVarset, ProcInstVarset, ProcImpl)),
         _Context, EqvMap, _EqvInstMap,
         item_pragma(Origin, pragma_foreign_proc(Attrs, PName, PredOrFunc, 
             ProcVars, ProcVarset, ProcInstVarset, ProcImpl)),
-        [], !Info) :-
+        [], !Info, !UsedModules) :-
     some [!EquivTypeInfo] (
-        maybe_record_expanded_items(ModuleName, PName, !.Info, 
-            !:EquivTypeInfo),
+        maybe_record_expanded_items(ModuleName, PName,
+            !.Info, !:EquivTypeInfo),
         UserSharing0 = get_user_annotated_sharing(Attrs0), 
         (   
             UserSharing0 = user_sharing(Sharing0, MaybeTypes0),
             MaybeTypes0 = yes(user_type_info(Types0, TVarset0))
         ->
-            replace_in_type_list(EqvMap, Types0, Types, _AnythingChanged, 
-                TVarset0, TVarset, !EquivTypeInfo),
-            replace_in_structure_sharing_domain(EqvMap, Sharing0, Sharing,
-                TVarset0, !EquivTypeInfo),
+            replace_in_type_list(Location,
+                EqvMap, Types0, Types, _AnythingChanged, 
+                TVarset0, TVarset, !EquivTypeInfo, !UsedModules),
+            replace_in_structure_sharing_domain(Location,
+                EqvMap, Sharing0, Sharing,
+                TVarset0, !EquivTypeInfo, !UsedModules),
             MaybeTypes = yes(user_type_info(Types, TVarset)),
             UserSharing = user_sharing(Sharing, MaybeTypes),
             set_user_annotated_sharing(UserSharing, Attrs0, Attrs)
         ;
             Attrs = Attrs0
@@ -451,112 +500,147 @@
         ItemId = item_id(foreign_proc_item, item_name(PName, 
             list.length(ProcVars))),
         finish_recording_expanded_items(ItemId, !.EquivTypeInfo, !Info)
     ). 
 
-replace_in_item(ModuleName,
+replace_in_item(ModuleName, Location,
         item_mutable(MutName, Type0, InitValue, Inst0, Attrs, Varset),
         _Context, EqvMap, EqvInstMap,
         item_mutable(MutName, Type, InitValue, Inst, Attrs, Varset),
-        [], !Info) :-
+        [], !Info, !UsedModules) :-
     QualName = qualified(ModuleName, MutName),
     maybe_record_expanded_items(ModuleName, QualName, !.Info, ExpandedItems0),
     TVarSet0 = varset.init,
-    replace_in_type(EqvMap, Type0, Type, _TypeChanged, TVarSet0, _TVarSet,
-        ExpandedItems0, ExpandedItems1),
-    replace_in_inst(Inst0, EqvInstMap, Inst,
-        ExpandedItems1, ExpandedItems),
+    replace_in_type(Location,
+        EqvMap, Type0, Type, _TypeChanged, TVarSet0, _TVarSet,
+        ExpandedItems0, ExpandedItems1, !UsedModules),
+    replace_in_inst(Location, Inst0, EqvInstMap, Inst,
+        ExpandedItems1, ExpandedItems, !UsedModules),
     ItemId = item_id(mutable_item, item_name(QualName, 0)),
     finish_recording_expanded_items(ItemId, ExpandedItems, !Info).
 
-:- pred replace_in_type_defn(eqv_map::in, type_ctor::in,
+:- pred replace_in_type_defn(location::in, eqv_map::in, type_ctor::in,
     type_defn::in, type_defn::out, bool::out, tvarset::in, tvarset::out,
-    equiv_type_info::in, equiv_type_info::out) is semidet.
+    equiv_type_info::in, equiv_type_info::out,
+    used_modules::in, used_modules::out) is semidet.
 
-replace_in_type_defn(EqvMap, TypeCtor, parse_tree_eqv_type(TBody0),
-        parse_tree_eqv_type(TBody), ContainsCirc, !VarSet, !Info) :-
-    replace_in_type_2(EqvMap, [TypeCtor], TBody0, TBody,
-        _, ContainsCirc, !VarSet, !Info).
+replace_in_type_defn(Location, EqvMap, TypeCtor, parse_tree_eqv_type(TBody0),
+        parse_tree_eqv_type(TBody), ContainsCirc,
+        !VarSet, !Info, !UsedModules) :-
+    replace_in_type_2(Location, EqvMap, [TypeCtor], TBody0, TBody,
+        _, ContainsCirc, !VarSet, !Info, !UsedModules).
 
-replace_in_type_defn(EqvMap, _,
+replace_in_type_defn(Location, EqvMap, _,
         parse_tree_du_type(TBody0, EqPred),
-        parse_tree_du_type(TBody, EqPred), no, !VarSet, !Info) :-
-    replace_in_ctors(EqvMap, TBody0, TBody, !VarSet, !Info).
+        parse_tree_du_type(TBody, EqPred), no, !VarSet, !Info, !UsedModules) :-
+    replace_in_ctors(Location,
+            EqvMap, TBody0, TBody, !VarSet, !Info, !UsedModules).
 
-replace_in_type_defn(EqvMap, TypeCtor,
+replace_in_type_defn(Location, EqvMap, TypeCtor,
         parse_tree_solver_type(SolverTypeDetails0, MaybeUserEqComp),
         parse_tree_solver_type(SolverTypeDetails,  MaybeUserEqComp),
-        ContainsCirc, !VarSet, !Info) :-
+        ContainsCirc, !VarSet, !Info, !UsedModules) :-
     SolverTypeDetails0 = solver_type_details(RepresentationType0, InitPred,
         GroundInst, AnyInst, MutableItems),
-    replace_in_type_2(EqvMap, [TypeCtor], 
+    replace_in_type_2(Location, EqvMap, [TypeCtor], 
         RepresentationType0, RepresentationType,
-        _, ContainsCirc, !VarSet, !Info),
+        _, ContainsCirc, !VarSet, !Info, !UsedModules),
     SolverTypeDetails = solver_type_details(RepresentationType, InitPred,
         GroundInst, AnyInst, MutableItems).
 
 %-----------------------------------------------------------------------------%
 
 replace_in_prog_constraints(EqvMap, Cs0, Cs, !VarSet, !Info) :-
+    replace_in_prog_constraints(out_of_module,
+            EqvMap, Cs0, Cs, !VarSet, !Info, used_modules_init, _).
+
+:- pred replace_in_prog_constraints(location::in, eqv_map::in,
+    prog_constraints::in, prog_constraints::out,
+    tvarset::in, tvarset::out, equiv_type_info::in, equiv_type_info::out,
+    used_modules::in, used_modules::out) is det.
+
+replace_in_prog_constraints(Location,
+        EqvMap, Cs0, Cs, !VarSet, !Info, !UsedModules) :-
     Cs0 = constraints(UnivCs0, ExistCs0),
     Cs = constraints(UnivCs, ExistCs),
-    replace_in_prog_constraint_list(EqvMap, UnivCs0, UnivCs, !VarSet, !Info),
-    replace_in_prog_constraint_list(EqvMap, ExistCs0, ExistCs, !VarSet, !Info).
+    replace_in_prog_constraint_list(Location,
+            EqvMap, UnivCs0, UnivCs, !VarSet, !Info, !UsedModules),
+    replace_in_prog_constraint_list(Location,
+            EqvMap, ExistCs0, ExistCs, !VarSet, !Info, !UsedModules).
 
-:- pred replace_in_prog_constraint_list(eqv_map::in,
+:- pred replace_in_prog_constraint_list(location::in, eqv_map::in,
     list(prog_constraint)::in, list(prog_constraint)::out,
-    tvarset::in, tvarset::out, equiv_type_info::in, equiv_type_info::out)
+    tvarset::in, tvarset::out, equiv_type_info::in, equiv_type_info::out,
+    used_modules::in, used_modules::out)
     is det.
 
-replace_in_prog_constraint_list(EqvMap, !Cs, !VarSet, !Info) :-
-    list.map_foldl2(replace_in_prog_constraint(EqvMap), !Cs, !VarSet, !Info).
+replace_in_prog_constraint_list(Location,
+        EqvMap, !Cs, !VarSet, !Info, !UsedModules) :-
+    list.map_foldl3(replace_in_prog_constraint(Location, EqvMap),
+            !Cs, !VarSet, !Info, !UsedModules).
 
 replace_in_prog_constraint(EqvMap, Constraint0, Constraint, !VarSet, !Info) :-
+    replace_in_prog_constraint(out_of_module, 
+            EqvMap, Constraint0, Constraint, !VarSet, !Info,
+            used_modules_init, _).
+
+:- pred replace_in_prog_constraint(location::in, eqv_map::in,
+    prog_constraint::in, prog_constraint::out, tvarset::in, tvarset::out,
+    equiv_type_info::in, equiv_type_info::out,
+    used_modules::in, used_modules::out) is det.
+
+replace_in_prog_constraint(Location,
+        EqvMap, Constraint0, Constraint, !VarSet, !Info, !UsedModules) :-
     Constraint0 = constraint(ClassName, Ts0),
-    replace_in_type_list(EqvMap, Ts0, Ts, _, _, !VarSet, !Info),
+    replace_in_type_list(Location,
+            EqvMap, Ts0, Ts, _, _, !VarSet, !Info, !UsedModules),
     Constraint = constraint(ClassName, Ts).
 
 %-----------------------------------------------------------------------------%
 
-:- pred replace_in_class_interface(class_methods::in,
+:- pred replace_in_class_interface(location::in, class_methods::in,
     eqv_map::in, eqv_inst_map::in, class_methods::out,
     list(eqv_error)::in, list(eqv_error)::out,
-    equiv_type_info::in, equiv_type_info::out) is det.
+    equiv_type_info::in, equiv_type_info::out,
+    used_modules::in, used_modules::out) is det.
 
-replace_in_class_interface(ClassInterface0, EqvMap, EqvInstMap,
-        ClassInterface, !Errors, !Info) :-
-    list.map_foldl2(replace_in_class_method(EqvMap, EqvInstMap),
-        ClassInterface0, ClassInterface, !Errors, !Info).
+replace_in_class_interface(Location, ClassInterface0, EqvMap, EqvInstMap,
+        ClassInterface, !Errors, !Info, !UsedModules) :-
+    list.map_foldl3(replace_in_class_method(Location, EqvMap, EqvInstMap),
+        ClassInterface0, ClassInterface, !Errors, !Info, !UsedModules).
 
-:- pred replace_in_class_method(eqv_map::in, eqv_inst_map::in,
+:- pred replace_in_class_method(location::in, eqv_map::in, eqv_inst_map::in,
     class_method::in, class_method::out,
     list(eqv_error)::in, list(eqv_error)::out,
-    equiv_type_info::in, equiv_type_info::out) is det.
+    equiv_type_info::in, equiv_type_info::out,
+    used_modules::in, used_modules::out) is det.
 
-replace_in_class_method(EqvMap, EqvInstMap,
+replace_in_class_method(Location, EqvMap, EqvInstMap,
         method_pred_or_func(TypeVarSet0, InstVarSet, ExistQVars, PredOrFunc,
             PredName, TypesAndModes0, WithType0, WithInst0,
             Det0, Cond, Purity, ClassContext0, Context),
         method_pred_or_func(TypeVarSet, InstVarSet, ExistQVars, PredOrFunc,
             PredName, TypesAndModes, WithType, WithInst,
             Det, Cond, Purity, ClassContext, Context),
-        !Errors, !Info) :-
-    replace_in_pred_type(PredName, PredOrFunc, Context, EqvMap,
+        !Errors, !Info, !UsedModules) :-
+    replace_in_pred_type(Location, PredName, PredOrFunc, Context, EqvMap,
         EqvInstMap, ClassContext0, ClassContext,
         TypesAndModes0, TypesAndModes, TypeVarSet0, TypeVarSet,
-        WithType0, WithType, WithInst0, WithInst, Det0, Det, !Info, NewErrors),
+        WithType0, WithType, WithInst0, WithInst, Det0, Det,
+        !Info, !UsedModules, NewErrors),
     !:Errors = NewErrors ++ !.Errors.
 
-replace_in_class_method(_, EqvInstMap,
+replace_in_class_method(Location, _, EqvInstMap,
         method_pred_or_func_mode(InstVarSet, MaybePredOrFunc0, PredName,
             Modes0, WithInst0, Det0, Cond, Context),
         method_pred_or_func_mode(InstVarSet, MaybePredOrFunc, PredName,
             Modes, WithInst, Det, Cond, Context),
-        !Errors, !Info) :-
-    replace_in_pred_mode(PredName, length(Modes0), Context,
+        !Errors, !Info, !UsedModules) :-
+    replace_in_pred_mode(Location, PredName, length(Modes0), Context,
         mode_decl, EqvInstMap, MaybePredOrFunc0, MaybePredOrFunc,
-        ExtraModes, WithInst0, WithInst, Det0, Det, !Info, NewErrors),
+        ExtraModes, WithInst0, WithInst, Det0, Det,
+        !Info, !UsedModules, NewErrors),
     (
         ExtraModes = [],
         Modes = Modes0
     ;
         ExtraModes = [_ | _],
@@ -564,65 +648,93 @@
     ),
     !:Errors = NewErrors ++ !.Errors.
 
 %-----------------------------------------------------------------------------%
 
-:- pred replace_in_subst(eqv_map::in,
+:- pred replace_in_subst(location::in, eqv_map::in,
     assoc_list(tvar, mer_type)::in, assoc_list(tvar, mer_type)::out,
-    tvarset::in, tvarset::out, equiv_type_info::in, equiv_type_info::out)
-    is det.
+    tvarset::in, tvarset::out, equiv_type_info::in, equiv_type_info::out,
+    used_modules::in, used_modules::out) is det.
 
-replace_in_subst(_EqvMap, [], [], !VarSet, !Info).
-replace_in_subst(EqvMap, [Var - Type0 | Subst0],
-        [Var - Type | Subst], !VarSet, !Info) :-
-    replace_in_type(EqvMap, Type0, Type, _, !VarSet, !Info),
-    replace_in_subst(EqvMap, Subst0, Subst, !VarSet, !Info).
+replace_in_subst(_Location, _EqvMap, [], [], !VarSet, !Info, !UsedModules).
+replace_in_subst(Location, EqvMap, [Var - Type0 | Subst0],
+        [Var - Type | Subst], !VarSet, !Info, !UsedModules) :-
+    replace_in_type(Location,
+            EqvMap, Type0, Type, _, !VarSet, !Info, !UsedModules),
+    replace_in_subst(Location,
+            EqvMap, Subst0, Subst, !VarSet, !Info, !UsedModules).
 
 %-----------------------------------------------------------------------------%
 
 replace_in_ctors(EqvMap, !Ctors, !VarSet, !Info) :-
-    list.map_foldl2(replace_in_ctor(EqvMap), !Ctors, !VarSet, !Info).
+    replace_in_ctors(out_of_module, EqvMap,
+            !Ctors, !VarSet, !Info, used_modules_init, _).
+
+:- pred replace_in_ctors(location::in, eqv_map::in,
+    list(constructor)::in, list(constructor)::out,
+    tvarset::in, tvarset::out, equiv_type_info::in, equiv_type_info::out,
+    used_modules::in, used_modules::out) is det.
 
-:- pred replace_in_ctor(eqv_map::in,
+replace_in_ctors(Location, EqvMap, !Ctors, !VarSet, !Info, !UsedModules) :-
+    list.map_foldl3(replace_in_ctor(Location, EqvMap),
+            !Ctors, !VarSet, !Info, !UsedModules).
+
+:- pred replace_in_ctor(location::in, eqv_map::in,
     constructor::in, constructor::out, tvarset::in, tvarset::out,
-    equiv_type_info::in, equiv_type_info::out) is det.
+    equiv_type_info::in, equiv_type_info::out,
+    used_modules::in, used_modules::out) is det.
 
-replace_in_ctor(EqvMap,
+replace_in_ctor(Location, EqvMap,
         ctor(ExistQVars, Constraints0, TName, Targs0),
-        ctor(ExistQVars, Constraints, TName, Targs), !VarSet, !Info) :-
-    replace_in_ctor_arg_list(EqvMap, Targs0, Targs, _, !VarSet, !Info),
-    replace_in_prog_constraint_list(EqvMap,
-        Constraints0, Constraints, !VarSet, !Info).
+        ctor(ExistQVars, Constraints, TName, Targs),
+        !VarSet, !Info, !UsedModules) :-
+    replace_in_ctor_arg_list(Location,
+            EqvMap, Targs0, Targs, _, !VarSet, !Info, !UsedModules),
+    replace_in_prog_constraint_list(Location, EqvMap,
+            Constraints0, Constraints, !VarSet, !Info, !UsedModules).
 
 %-----------------------------------------------------------------------------%
 
 replace_in_type_list(EqvMap, !Ts, Changed, !VarSet, !Info) :-
-    replace_in_type_list_2(EqvMap, [], !Ts, Changed, no, _, !VarSet, !Info).
+    replace_in_type_list(out_of_module,
+            EqvMap, !Ts, Changed, !VarSet, !Info, used_modules_init, _).
 
-:- pred replace_in_type_list(eqv_map::in,
+:- pred replace_in_type_list(location::in, eqv_map::in,
+    list(mer_type)::in, list(mer_type)::out, bool::out,
+    tvarset::in, tvarset::out,
+    equiv_type_info::in, equiv_type_info::out,
+    used_modules::in, used_modules::out) is det.
+
+replace_in_type_list(Location,
+        EqvMap, !Ts, Changed, !VarSet, !Info, !UsedModules) :-
+    replace_in_type_list_2(Location,
+            EqvMap, [], !Ts, Changed, no, _, !VarSet, !Info, !UsedModules).
+
+:- pred replace_in_type_list(location::in, eqv_map::in,
     list(mer_type)::in, list(mer_type)::out, bool::out, bool::out,
-    tvarset::in, tvarset::out, equiv_type_info::in, equiv_type_info::out)
-    is det.
+    tvarset::in, tvarset::out, equiv_type_info::in, equiv_type_info::out,
+    used_modules::in, used_modules::out) is det.
 
-replace_in_type_list(EqvMap, !Ts, Changed, ContainsCirc, !VarSet, !Info) :-
-    replace_in_type_list_2(EqvMap, [], !Ts, Changed, no,
-        ContainsCirc, !VarSet, !Info).
+replace_in_type_list(Location,
+        EqvMap, !Ts, Changed, ContainsCirc, !VarSet, !Info, !UsedModules) :-
+    replace_in_type_list_2(Location, EqvMap, [], !Ts, Changed, no,
+        ContainsCirc, !VarSet, !Info, !UsedModules).
 
-:- pred replace_in_type_list_2(eqv_map::in, list(type_ctor)::in,
+:- pred replace_in_type_list_2(location::in, eqv_map::in, list(type_ctor)::in,
     list(mer_type)::in, list(mer_type)::out, bool::out, bool::in, bool::out,
-    tvarset::in, tvarset::out, equiv_type_info::in, equiv_type_info::out)
-    is det.
+    tvarset::in, tvarset::out, equiv_type_info::in, equiv_type_info::out,
+    used_modules::in, used_modules::out) is det.
 
-replace_in_type_list_2(_EqvMap, _Seen, [], [], no,
-        !ContainsCirc, !VarSet, !Info).
-replace_in_type_list_2(EqvMap, Seen, List0 @ [T0 | Ts0], List,
-        Changed, !Circ, !VarSet, !Info) :-
-    replace_in_type_2(EqvMap, Seen, T0, T, Changed0, ContainsCirc,
-        !VarSet, !Info),
+replace_in_type_list_2(_Location, _EqvMap, _Seen, [], [], no,
+        !ContainsCirc, !VarSet, !Info, !UsedModules).
+replace_in_type_list_2(Location, EqvMap, Seen, List0 @ [T0 | Ts0], List,
+        Changed, !Circ, !VarSet, !Info, !UsedModules) :-
+    replace_in_type_2(Location, EqvMap, Seen, T0, T, Changed0, ContainsCirc,
+        !VarSet, !Info, !UsedModules),
     !:Circ = ContainsCirc `or` !.Circ,
-    replace_in_type_list_2(EqvMap, Seen, Ts0, Ts,
-        Changed1, !Circ, !VarSet, !Info),
+    replace_in_type_list_2(Location, EqvMap, Seen, Ts0, Ts,
+        Changed1, !Circ, !VarSet, !Info, !UsedModules),
     (
         ( Changed0 = yes
         ; Changed1 = yes
         )
     ->
@@ -633,75 +745,95 @@
         List = List0
     ).
 
 %-----------------------------------------------------------------------------%
 
-:- pred replace_in_ctor_arg_list(eqv_map::in,
+:- pred replace_in_ctor_arg_list(location::in, eqv_map::in,
     list(constructor_arg)::in, list(constructor_arg)::out, bool::out,
-    tvarset::in, tvarset::out, equiv_type_info::in, equiv_type_info::out)
-    is det.
+    tvarset::in, tvarset::out, equiv_type_info::in, equiv_type_info::out,
+    used_modules::in, used_modules::out) is det.
 
-replace_in_ctor_arg_list(EqvMap, !As, ContainsCirc, !VarSet, !Info) :-
-    replace_in_ctor_arg_list_2(EqvMap, [], !As, no, ContainsCirc,
-        !VarSet, !Info).
+replace_in_ctor_arg_list(Location,
+        EqvMap, !As, ContainsCirc, !VarSet, !Info, !UsedModules) :-
+    replace_in_ctor_arg_list_2(Location, EqvMap, [], !As, no, ContainsCirc,
+        !VarSet, !Info, !UsedModules).
 
-:- pred replace_in_ctor_arg_list_2(eqv_map::in, list(type_ctor)::in,
+:- pred replace_in_ctor_arg_list_2(location::in,
+    eqv_map::in, list(type_ctor)::in,
     list(constructor_arg)::in, list(constructor_arg)::out,
     bool::in, bool::out, tvarset::in, tvarset::out,
-    equiv_type_info::in, equiv_type_info::out) is det.
+    equiv_type_info::in, equiv_type_info::out,
+    used_modules::in, used_modules::out) is det.
 
-replace_in_ctor_arg_list_2(_EqvMap, _Seen, [], [],
-        !Circ, !VarSet, !Info).
-replace_in_ctor_arg_list_2(EqvMap, Seen, [N - T0 | As0], [N - T | As],
-        !Circ, !VarSet, !Info) :-
-    replace_in_type_2(EqvMap, Seen, T0, T, _, ContainsCirc, !VarSet, !Info),
+replace_in_ctor_arg_list_2(_Location, _EqvMap, _Seen, [], [],
+        !Circ, !VarSet, !Info, !UsedModules).
+replace_in_ctor_arg_list_2(Location,
+        EqvMap, Seen, [N - T0 | As0], [N - T | As],
+        !Circ, !VarSet, !Info, !UsedModules) :-
+    replace_in_type_2(Location, EqvMap,
+            Seen, T0, T, _, ContainsCirc, !VarSet, !Info, !UsedModules),
     !:Circ = !.Circ `or` ContainsCirc,
-    replace_in_ctor_arg_list_2(EqvMap, Seen, As0, As, !Circ, !VarSet, !Info).
+    replace_in_ctor_arg_list_2(Location, EqvMap,
+            Seen, As0, As, !Circ, !VarSet, !Info, !UsedModules).
 
 %-----------------------------------------------------------------------------%
 
 replace_in_type(EqvMap, Type0, Type, Changed, !VarSet, !Info) :-
-    replace_in_type_2(EqvMap, [], Type0, Type, Changed, _,
-        !VarSet, !Info).
+    replace_in_type(out_of_module,
+            EqvMap, Type0, Type, Changed,
+            !VarSet, !Info, used_modules_init, _).
+
+:- pred replace_in_type(location::in,
+    eqv_map::in, mer_type::in, mer_type::out,
+    bool::out, tvarset::in, tvarset::out,
+    equiv_type_info::in, equiv_type_info::out,
+    used_modules::in, used_modules::out) is det.
+
+replace_in_type(Location,
+        EqvMap, Type0, Type, Changed, !VarSet, !Info, !UsedModules) :-
+    replace_in_type_2(Location,
+        EqvMap, [], Type0, Type, Changed, _, !VarSet, !Info, !UsedModules).
 
     % Replace all equivalence types in a given type, detecting
     % any circularities.
     %
-:- pred replace_in_type_2(eqv_map::in, list(type_ctor)::in,
+:- pred replace_in_type_2(location::in, eqv_map::in, list(type_ctor)::in,
     mer_type::in, mer_type::out, bool::out, bool::out,
-    tvarset::in, tvarset::out, equiv_type_info::in, equiv_type_info::out)
-    is det.
+    tvarset::in, tvarset::out, equiv_type_info::in, equiv_type_info::out,
+    used_modules::in, used_modules::out) is det.
 
-replace_in_type_2(EqvMap, TypeCtorsAlreadyExpanded, Type0, Type,
-        Changed, Circ, !VarSet, !Info) :-
+replace_in_type_2(Location, EqvMap, TypeCtorsAlreadyExpanded, Type0, Type,
+        Changed, Circ, !VarSet, !Info, !UsedModules) :-
     (
         Type0 = type_variable(Var, Kind),
         Type = type_variable(Var, Kind),
         Changed = no,
         Circ = no
     ;
         Type0 = defined_type(SymName, TArgs0, Kind),
-        replace_in_type_list_2(EqvMap, TypeCtorsAlreadyExpanded,
-            TArgs0, TArgs, ArgsChanged, no, Circ0, !VarSet, !Info),
+        replace_in_type_list_2(Location, EqvMap, TypeCtorsAlreadyExpanded,
+            TArgs0, TArgs, ArgsChanged, no, Circ0,
+            !VarSet, !Info, !UsedModules),
         Arity = list.length(TArgs),
         TypeCtor = type_ctor(SymName, Arity),
-        replace_type_ctor(EqvMap, TypeCtorsAlreadyExpanded,
+        replace_type_ctor(Location, EqvMap, TypeCtorsAlreadyExpanded,
             Type0, TypeCtor, TArgs, Kind, Type, ArgsChanged, Changed,
-            Circ0, Circ, !VarSet, !Info)
+            Circ0, Circ, !VarSet, !Info, !UsedModules)
     ;
         Type0 = builtin_type(_),
         Type = Type0,
         Changed = no,
         Circ = no
     ;
         Type0 = higher_order_type(Args0, MaybeRet0, Purity, EvalMethod),
-        replace_in_type_list_2(EqvMap, TypeCtorsAlreadyExpanded,
-            Args0, Args, ArgsChanged, no, ArgsCirc, !VarSet, !Info),
+        replace_in_type_list_2(Location, EqvMap, TypeCtorsAlreadyExpanded,
+            Args0, Args, ArgsChanged, no, ArgsCirc,
+            !VarSet, !Info, !UsedModules),
         (
             MaybeRet0 = yes(Ret0),
-            replace_in_type_2(EqvMap, TypeCtorsAlreadyExpanded,
-                Ret0, Ret, RetChanged, RetCirc, !VarSet, !Info),
+            replace_in_type_2(Location, EqvMap, TypeCtorsAlreadyExpanded,
+                Ret0, Ret, RetChanged, RetCirc, !VarSet, !Info, !UsedModules),
             MaybeRet = yes(Ret),
             Changed = bool.or(ArgsChanged, RetChanged),
             Circ = bool.or(ArgsCirc, RetCirc)
         ;
             MaybeRet0 = no,
@@ -716,50 +848,52 @@
             Changed = no,
             Type = Type0
         )
     ;
         Type0 = tuple_type(Args0, Kind),
-        replace_in_type_list_2(EqvMap, TypeCtorsAlreadyExpanded,
-            Args0, Args, Changed, no, Circ, !VarSet, !Info),
+        replace_in_type_list_2(Location, EqvMap, TypeCtorsAlreadyExpanded,
+            Args0, Args, Changed, no, Circ, !VarSet, !Info, !UsedModules),
         (
             Changed = yes,
             Type = tuple_type(Args, Kind)
         ;
             Changed = no,
             Type = Type0
         )
     ;
         Type0 = apply_n_type(Var, Args0, Kind),
-        replace_in_type_list_2(EqvMap, TypeCtorsAlreadyExpanded,
-            Args0, Args, Changed, no, Circ, !VarSet, !Info),
+        replace_in_type_list_2(Location, EqvMap, TypeCtorsAlreadyExpanded,
+            Args0, Args, Changed, no, Circ, !VarSet, !Info, !UsedModules),
         (
             Changed = yes,
             Type = apply_n_type(Var, Args, Kind)
         ;
             Changed = no,
             Type = Type0
         )
     ;
         Type0 = kinded_type(RawType0, Kind),
-        replace_in_type_2(EqvMap, TypeCtorsAlreadyExpanded,
-            RawType0, RawType, Changed, Circ, !VarSet, !Info),
+        replace_in_type_2(Location, EqvMap, TypeCtorsAlreadyExpanded,
+            RawType0, RawType, Changed, Circ, !VarSet, !Info, !UsedModules),
         (
             Changed = yes,
             Type = kinded_type(RawType, Kind)
         ;
             Changed = no,
             Type = Type0
         )
     ).
 
-:- pred replace_type_ctor(eqv_map::in, list(type_ctor)::in,
+:- pred replace_type_ctor(location::in, eqv_map::in, list(type_ctor)::in,
     mer_type::in, type_ctor::in, list(mer_type)::in, kind::in, mer_type::out,
     bool::in, bool::out, bool::in, bool::out, tvarset::in, tvarset::out,
-    equiv_type_info::in, equiv_type_info::out) is det.
+    equiv_type_info::in, equiv_type_info::out,
+    used_modules::in, used_modules::out) is det.
 
-replace_type_ctor(EqvMap, TypeCtorsAlreadyExpanded, Type0,
-        TypeCtor, TArgs, Kind, Type, !Changed, !Circ, !VarSet, !Info) :-
+replace_type_ctor(Location, EqvMap, TypeCtorsAlreadyExpanded, Type0,
+        TypeCtor, TArgs, Kind, Type,
+        !Changed, !Circ, !VarSet, !Info, !UsedModules) :-
     ( list.member(TypeCtor, TypeCtorsAlreadyExpanded) ->
         AlreadyExpanded = yes
     ;
         AlreadyExpanded = no
     ),
@@ -777,19 +911,22 @@
         tvarset_merge_renaming_without_names(!.VarSet, EqvVarSet, !:VarSet,
             Renaming),
         !.Circ = no,
         AlreadyExpanded = no
     ->
+        type_ctor_used_modules(Location, TypeCtor, !UsedModules),
+
         !:Changed = yes,
         map.apply_to_list(Args0, Renaming, Args),
         apply_variable_renaming_to_type(Renaming, Body0, Body1),
         TypeCtorItem = type_ctor_to_item_name(TypeCtor),
         record_expanded_item(item_id(type_item, TypeCtorItem), !Info),
         map.from_corresponding_lists(Args, TArgs, Subst),
         apply_subst_to_type(Subst, Body1, Body),
-        replace_in_type_2(EqvMap, [TypeCtor | TypeCtorsAlreadyExpanded], Body,
-            Type, _, !:Circ, !VarSet, !Info)
+        replace_in_type_2(Location,
+            EqvMap, [TypeCtor | TypeCtorsAlreadyExpanded], Body,
+            Type, _, !:Circ, !VarSet, !Info, !UsedModules)
     ;
         (
             !.Changed = yes,
             TypeCtor = type_ctor(SymName, _Arity),
             Type = defined_type(SymName, TArgs, Kind)
@@ -798,21 +935,38 @@
             Type = Type0
         ),
         bool.or(AlreadyExpanded, !Circ)
     ).
 
-:- pred replace_in_inst(mer_inst::in, eqv_inst_map::in, mer_inst::out,
-    equiv_type_info::in, equiv_type_info::out) is det.
+:- pred type_ctor_used_modules(location::in, type_ctor::in,
+    used_modules::in, used_modules::out) is det.
 
-replace_in_inst(Inst0, EqvInstMap, Inst, !Info) :-
-    replace_in_inst(Inst0, EqvInstMap, set.init, Inst, !Info).
+type_ctor_used_modules(out_of_module, _, !UsedModules).
+type_ctor_used_modules(module_interface, type_ctor(Name, _), !UsedModules) :-
+    add_sym_name_module(visibility_public, Name, !UsedModules).
+type_ctor_used_modules(module_implementation,
+        type_ctor(Name, _), !UsedModules) :-
+    add_sym_name_module(visibility_private, Name, !UsedModules).
+
+:- pred replace_in_inst(location::in,
+    mer_inst::in, eqv_inst_map::in, mer_inst::out,
+    equiv_type_info::in, equiv_type_info::out,
+    used_modules::in, used_modules::out) is det.
+
+replace_in_inst(Location, Inst0, EqvInstMap, Inst, !Info, !UsedModules) :-
+    replace_in_inst(Location,
+            Inst0, EqvInstMap, set.init, Inst, !Info, !UsedModules).
 
-:- pred replace_in_inst(mer_inst::in, eqv_inst_map::in,
+:- pred replace_in_inst(location::in, mer_inst::in, eqv_inst_map::in,
     set(inst_id)::in, mer_inst::out,
-    equiv_type_info::in, equiv_type_info::out) is det.
+    equiv_type_info::in, equiv_type_info::out,
+    used_modules::in, used_modules::out) is det.
 
-replace_in_inst(Inst0, EqvInstMap, ExpandedInstIds, Inst, !Info) :-
+replace_in_inst(Location,
+        Inst0, EqvInstMap, ExpandedInstIds, Inst, !Info, !UsedModules) :-
+
+        % XXX Need to record the used modules
     ( Inst0 = defined_inst(user_inst(SymName, ArgInsts)) ->
         InstId = inst_id(SymName, length(ArgInsts)),
         (
             set.member(InstId, ExpandedInstIds)
         ->
@@ -822,41 +976,47 @@
                 eqv_inst_body(_, EqvInstParams, EqvInst))
         ->
             inst_substitute_arg_list(EqvInstParams, ArgInsts, EqvInst, Inst1),
             InstIdItem = inst_id_to_item_name(InstId),
             record_expanded_item(item_id(inst_item, InstIdItem), !Info),
-            replace_in_inst(Inst1, EqvInstMap,
-                set.insert(ExpandedInstIds, InstId), Inst, !Info)
+            replace_in_inst(Location, Inst1, EqvInstMap,
+                set.insert(ExpandedInstIds, InstId), Inst, !Info, !UsedModules)
         ;
             Inst = Inst0
         )
     ;
         Inst = Inst0
     ).
 
 %-----------------------------------------------------------------------------%
 
-:- pred replace_in_pred_type(sym_name::in, pred_or_func::in,
+:- pred replace_in_pred_type(location::in, sym_name::in, pred_or_func::in,
     prog_context::in, eqv_map::in, eqv_inst_map::in,
     prog_constraints::in, prog_constraints::out,
     list(type_and_mode)::in, list(type_and_mode)::out,
     tvarset::in, tvarset::out,
     maybe(mer_type)::in, maybe(mer_type)::out,
     maybe(mer_inst)::in, maybe(mer_inst)::out,
     maybe(determinism)::in, maybe(determinism)::out,
-    equiv_type_info::in, equiv_type_info::out, list(eqv_error)::out) is det.
+    equiv_type_info::in, equiv_type_info::out,
+    used_modules::in, used_modules::out,
+    list(eqv_error)::out) is det.
 
-replace_in_pred_type(PredName, PredOrFunc, Context, EqvMap, EqvInstMap,
+replace_in_pred_type(Location,
+        PredName, PredOrFunc, Context, EqvMap, EqvInstMap,
         ClassContext0, ClassContext, TypesAndModes0, TypesAndModes,
         !TypeVarSet, MaybeWithType0, MaybeWithType,
-        MaybeWithInst0, MaybeWithInst, Det0, Det, !Info, Errors) :-
-    replace_in_prog_constraints(EqvMap, ClassContext0, ClassContext,
-        !TypeVarSet, !Info),
-    replace_in_tms(EqvMap, TypesAndModes0, TypesAndModes1, !TypeVarSet, !Info),
+        MaybeWithInst0, MaybeWithInst,
+        Det0, Det, !Info, !UsedModules, Errors) :-
+    replace_in_prog_constraints(Location, EqvMap, ClassContext0, ClassContext,
+        !TypeVarSet, !Info, !UsedModules),
+    replace_in_tms(Location, EqvMap,
+            TypesAndModes0, TypesAndModes1, !TypeVarSet, !Info, !UsedModules),
     (
         MaybeWithType0 = yes(WithType0),
-        replace_in_type(EqvMap, WithType0, WithType, _, !TypeVarSet, !Info),
+        replace_in_type(Location, EqvMap,
+                WithType0, WithType, _, !TypeVarSet, !Info, !UsedModules),
         (
             type_is_higher_order(WithType, _Purity, PredOrFunc,
                 _EvalMethod, ExtraTypes0)
         ->
             ExtraTypes = ExtraTypes0,
@@ -869,13 +1029,13 @@
         MaybeWithType0 = no,
         ExtraTypes = [],
         Errors0 = []
     ),
 
-    replace_in_pred_mode(PredName, length(TypesAndModes0),
+    replace_in_pred_mode(Location, PredName, length(TypesAndModes0),
         Context, type_decl, EqvInstMap, yes(PredOrFunc), _, ExtraModes,
-        MaybeWithInst0, _, Det0, Det, !Info, ModeErrors),
+        MaybeWithInst0, _, Det0, Det, !Info, !UsedModules, ModeErrors),
     Errors1 = Errors0 ++ ModeErrors,
 
     ( Errors1 = [_ | _] ->
         Errors = Errors1,
         ExtraTypesAndModes = []
@@ -917,23 +1077,27 @@
             item_name(PredName, list.length(TypesAndModes0))),
         record_expanded_item(OrigItemId, !Info),
         TypesAndModes = TypesAndModes1 ++ ExtraTypesAndModes
     ).
 
-:- pred replace_in_pred_mode(sym_name::in, arity::in,
+:- pred replace_in_pred_mode(location::in, sym_name::in, arity::in,
     prog_context::in, pred_or_func_decl_type::in, eqv_inst_map::in,
     maybe(pred_or_func)::in, maybe(pred_or_func)::out,
     list(mer_mode)::out, maybe(mer_inst)::in, maybe(mer_inst)::out,
     maybe(determinism)::in, maybe(determinism)::out,
-    equiv_type_info::in, equiv_type_info::out, list(eqv_error)::out) is det.
+    equiv_type_info::in, equiv_type_info::out,
+    used_modules::in, used_modules::out,
+    list(eqv_error)::out) is det.
 
-replace_in_pred_mode(PredName, OrigArity, Context, DeclType,
+replace_in_pred_mode(Location, PredName, OrigArity, Context, DeclType,
         EqvInstMap, MaybePredOrFunc0, MaybePredOrFunc, ExtraModes,
-        MaybeWithInst0, MaybeWithInst, Det0, Det, !Info, Errors) :-
+        MaybeWithInst0, MaybeWithInst, Det0, Det,
+        !Info, !UsedModules, Errors) :-
     (
         MaybeWithInst0 = yes(WithInst0),
-        replace_in_inst(WithInst0, EqvInstMap, WithInst, !Info),
+        replace_in_inst(Location,
+                WithInst0, EqvInstMap, WithInst, !Info, !UsedModules),
         (
             WithInst = ground(_, higher_order(pred_inst_info(
                 PredOrFunc, ExtraModes0, DetPrime))),
             ( MaybePredOrFunc0 = no
             ; MaybePredOrFunc0 = yes(PredOrFunc)
@@ -970,71 +1134,88 @@
         Errors = [],
         Det = Det0,
         ExtraModes = []
     ).
 
-:- pred replace_in_tms(eqv_map::in,
+:- pred replace_in_tms(location::in, eqv_map::in,
     list(type_and_mode)::in, list(type_and_mode)::out,
-    tvarset::in, tvarset::out, equiv_type_info::in, equiv_type_info::out)
-    is det.
+    tvarset::in, tvarset::out, equiv_type_info::in, equiv_type_info::out,
+    used_modules::in, used_modules::out) is det.
 
-replace_in_tms(EqvMap, !TMs, !VarSet, !Info) :-
-    list.map_foldl2(replace_in_tm(EqvMap), !TMs, !VarSet, !Info).
+replace_in_tms(Location, EqvMap, !TMs, !VarSet, !Info, !UsedModules) :-
+    list.map_foldl3(replace_in_tm(Location, EqvMap),
+            !TMs, !VarSet, !Info, !UsedModules).
 
-:- pred replace_in_tm(eqv_map::in,
+:- pred replace_in_tm(location::in, eqv_map::in,
     type_and_mode::in, type_and_mode::out, tvarset::in, tvarset::out,
-    equiv_type_info::in, equiv_type_info::out) is det.
+    equiv_type_info::in, equiv_type_info::out,
+    used_modules::in, used_modules::out) is det.
 
-replace_in_tm(EqvMap, type_only(Type0),
-        type_only(Type), !VarSet, !Info) :-
-    replace_in_type(EqvMap, Type0, Type, _, !VarSet, !Info).
-
-replace_in_tm(EqvMap, type_and_mode(Type0, Mode),
-        type_and_mode(Type, Mode), !VarSet, !Info) :-
-    replace_in_type(EqvMap, Type0, Type, _, !VarSet, !Info).
+replace_in_tm(Location, EqvMap, type_only(Type0),
+        type_only(Type), !VarSet, !Info, !UsedModules) :-
+    replace_in_type(Location,
+            EqvMap, Type0, Type, _, !VarSet, !Info, !UsedModules).
+
+replace_in_tm(Location, EqvMap, type_and_mode(Type0, Mode),
+        type_and_mode(Type, Mode), !VarSet, !Info, !UsedModules) :-
+    replace_in_type(Location,
+            EqvMap, Type0, Type, _, !VarSet, !Info, !UsedModules).
 
 %-----------------------------------------------------------------------------%
 %
-:- pred replace_in_structure_sharing_domain(eqv_map::in, 
+:- pred replace_in_structure_sharing_domain(location::in, eqv_map::in, 
     structure_sharing_domain::in, structure_sharing_domain::out, 
-    tvarset::in, equiv_type_info::in, equiv_type_info::out) is det.
+    tvarset::in, equiv_type_info::in, equiv_type_info::out,
+    used_modules::in, used_modules::out) is det.
 
-replace_in_structure_sharing_domain(_, X @ structure_sharing_bottom,
-    X, _TVarset, !EquivTypeInfo).
-replace_in_structure_sharing_domain(_, X @ structure_sharing_top(_), 
-    X, _TVarset, !EquivTypeInfo).
-replace_in_structure_sharing_domain(EqvMap, 
+replace_in_structure_sharing_domain(_, _, X @ structure_sharing_bottom,
+    X, _TVarset, !EquivTypeInfo, !UsedModules).
+replace_in_structure_sharing_domain(_, _, X @ structure_sharing_top(_), 
+    X, _TVarset, !EquivTypeInfo, !UsedModules).
+replace_in_structure_sharing_domain(Location, EqvMap, 
         structure_sharing_real(SharingPairs0),
-        structure_sharing_real(SharingPairs), TVarset, !EquivTypeInfo) :- 
-    list.map_foldl(replace_in_structure_sharing_pair(EqvMap, TVarset), 
-        SharingPairs0, SharingPairs, !EquivTypeInfo).
+        structure_sharing_real(SharingPairs),
+        TVarset, !EquivTypeInfo, !UsedModules) :- 
+    list.map_foldl2(
+        replace_in_structure_sharing_pair(Location, EqvMap, TVarset), 
+        SharingPairs0, SharingPairs, !EquivTypeInfo, !UsedModules).
 
-:- pred replace_in_structure_sharing_pair(eqv_map::in, tvarset::in, 
+:- pred replace_in_structure_sharing_pair(location::in,
+    eqv_map::in, tvarset::in, 
     structure_sharing_pair::in, structure_sharing_pair::out,
-    equiv_type_info::in, equiv_type_info::out) is det.
-
-replace_in_structure_sharing_pair(EqvMap, TVarset, Data10 - Data20, 
-        Data1 - Data2, !EquivTypeInfo) :- 
-    replace_in_datastruct(EqvMap, TVarset, Data10, Data1, !EquivTypeInfo),
-    replace_in_datastruct(EqvMap, TVarset, Data20, Data2, !EquivTypeInfo).
+    equiv_type_info::in, equiv_type_info::out,
+    used_modules::in, used_modules::out) is det.
 
-:- pred replace_in_datastruct(eqv_map::in, tvarset::in, datastruct::in,
-    datastruct::out, equiv_type_info::in, equiv_type_info::out) is det.
+replace_in_structure_sharing_pair(Location, EqvMap, TVarset, Data10 - Data20, 
+        Data1 - Data2, !EquivTypeInfo, !UsedModules) :- 
+    replace_in_datastruct(Location,
+            EqvMap, TVarset, Data10, Data1, !EquivTypeInfo, !UsedModules),
+    replace_in_datastruct(Location,
+            EqvMap, TVarset, Data20, Data2, !EquivTypeInfo, !UsedModules).
+
+:- pred replace_in_datastruct(location::in,
+    eqv_map::in, tvarset::in, datastruct::in,
+    datastruct::out, equiv_type_info::in, equiv_type_info::out,
+    used_modules::in, used_modules::out) is det.
 
-replace_in_datastruct(EqvMap, TVarset, Data0, Data, !EquivTypeInfo) :- 
+replace_in_datastruct(Location,
+        EqvMap, TVarset, Data0, Data, !EquivTypeInfo, !UsedModules) :- 
     Sel0 = Data0 ^ sc_selector,
-    list.map_foldl(replace_in_unit_selector(EqvMap, TVarset), Sel0, Sel, 
-        !EquivTypeInfo), 
+    list.map_foldl2(replace_in_unit_selector(Location, EqvMap, TVarset),
+            Sel0, Sel, !EquivTypeInfo, !UsedModules), 
     Data = Data0 ^ sc_selector := Sel.
 
-:- pred replace_in_unit_selector(eqv_map::in, tvarset::in, unit_selector::in,
-    unit_selector::out, equiv_type_info::in, equiv_type_info::out) is det.
-
-replace_in_unit_selector(_, _, X @ termsel(_, _), X, !EquivTypeInfo).
-replace_in_unit_selector(EqvMap, TVarset, typesel(Type0), typesel(Type),
-        !EquivTypeInfo) :-
-    replace_in_type(EqvMap, Type0, Type, _, TVarset, _, !EquivTypeInfo).
+:- pred replace_in_unit_selector(location::in,
+    eqv_map::in, tvarset::in, unit_selector::in,
+    unit_selector::out, equiv_type_info::in, equiv_type_info::out,
+    used_modules::in, used_modules::out) is det.
+
+replace_in_unit_selector(_, _, _, X @ termsel(_, _), X, !EquivTypeInfo, !UMs).
+replace_in_unit_selector(Location, EqvMap, TVarset,
+        typesel(Type0), typesel(Type), !EquivTypeInfo, !UsedModules) :-
+    replace_in_type(Location,
+            EqvMap, Type0, Type, _, TVarset, _, !EquivTypeInfo, !UsedModules).
 
 %-----------------------------------------------------------------------------%
 
 :- type expanded_item_set == pair(module_name, set(item_id)).
 
Index: compiler/hlds_module.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/hlds_module.m,v
retrieving revision 1.141
diff -U5 -r1.141 hlds_module.m
--- compiler/hlds_module.m	15 Sep 2006 11:14:32 -0000	1.141
+++ compiler/hlds_module.m	18 Sep 2006 14:41:42 -0000
@@ -488,14 +488,17 @@
     structure_reuse_map::out) is det.
 
 :- pred module_info_set_structure_reuse_map(structure_reuse_map::in,
     module_info::in, module_info::out) is det.
 
-:- pred module_info_get_parent_used_modules(module_info::in,
-    list(module_name)::out) is det.
+:- pred module_info_get_used_modules(module_info::in,
+    used_modules::out) is det.
 
-:- pred module_info_add_parent_used_modules(list(module_name)::in,
+:- pred module_info_set_used_modules(used_modules::in,
+    module_info::in, module_info::out) is det.
+
+:- pred module_info_add_parents_to_used_modules(list(module_name)::in,
     module_info::in, module_info::out) is det.
 
 :- pred module_info_get_interface_module_specifiers(module_info::in,
     set(module_name)::out) is det.
 
@@ -754,13 +757,15 @@
                 user_final_pred_c_names     :: assoc_list(sym_name, string),
 
                 % Information about which procedures implement structure reuse.
                 structure_reuse_map         :: structure_reuse_map,
 
-                % The list of modules used in the parent modules of the current
-                % module
-                parent_used_modules         :: list(module_name),
+                % The modules which have already been calculated as being
+                % used.  Currently this is the module imports inherited from
+                % the parent modules plus those calculated during expansion
+                % of equivalence types and insts.
+                used_modules                :: used_modules,
 
                 % All the directly imported module specifiers in the interface.
                 % (Used by unused_imports analysis).
                 interface_module_specifiers :: set(module_specifier)
             ).
@@ -803,11 +808,12 @@
     map.init(NoTagTypes),
     ModuleSubInfo = module_sub_info(Name, Globals, no, [], [], [], [], no, 0,
         [], [], StratPreds, UnusedArgInfo, ExceptionInfo, TrailingInfo,
         MM_TablingInfo, map.init, counter.init(1), ImportedModules,
         IndirectlyImportedModules, TypeSpecInfo, NoTagTypes, no, [],
-        init_analysis_info(mmc), [], [], map.init, [], set.init),
+        init_analysis_info(mmc), [], [],
+        map.init, used_modules_init, set.init),
     ModuleInfo = module_info(ModuleSubInfo, PredicateTable, Requests,
         UnifyPredMap, QualifierInfo, Types, Insts, Modes, Ctors,
         ClassTable, SuperClassTable, InstanceTable, AssertionTable,
         ExclusiveTable, FieldNameTable, RecompInfo).
 
@@ -890,14 +896,12 @@
 module_info_get_analysis_info(MI, MI ^ sub_info ^ analysis_info).
 module_info_get_maybe_complexity_proc_map(MI,
     MI ^ sub_info ^ maybe_complexity_proc_map).
 module_info_get_complexity_proc_infos(MI,
     MI ^ sub_info ^ complexity_proc_infos).
-module_info_get_structure_reuse_map(MI,
-    MI ^ sub_info ^ structure_reuse_map).
-module_info_get_parent_used_modules(MI,
-    MI ^ sub_info ^ parent_used_modules).
+module_info_get_structure_reuse_map(MI, MI ^ sub_info ^ structure_reuse_map).
+module_info_get_used_modules(MI, MI ^ sub_info ^ used_modules).
 module_info_get_interface_module_specifiers(MI,
     MI ^ sub_info ^ interface_module_specifiers).
 
     % XXX There is some debate as to whether duplicate initialise directives
     % in the same module should constitute an error. Currently it is not, but
@@ -1017,15 +1021,18 @@
     MI ^ sub_info ^ maybe_complexity_proc_map := NewVal).
 module_info_set_complexity_proc_infos(NewVal, MI,
     MI ^ sub_info ^ complexity_proc_infos := NewVal).
 module_info_set_structure_reuse_map(ReuseMap, MI,
     MI ^ sub_info ^ structure_reuse_map := ReuseMap).
+module_info_set_used_modules(UsedModules, MI,
+    MI ^ sub_info ^ used_modules := UsedModules).
 
-module_info_add_parent_used_modules(Modules, MI,
-        MI ^ sub_info ^ parent_used_modules := UsedModules) :-
-    module_info_get_parent_used_modules(MI, UsedModules0),
-    UsedModules = list.sort_and_remove_dups(Modules ++ UsedModules0).
+module_info_add_parents_to_used_modules(Modules, MI,
+        MI ^ sub_info ^ used_modules := UsedModules) :-
+    module_info_get_used_modules(MI, UsedModules0),
+    list.foldl(add_all_modules(visibility_public),
+            Modules, UsedModules0, UsedModules).
         
 
 %-----------------------------------------------------------------------------%
 
     % Various predicates which do simple things that are nevertheless
Index: compiler/make_hlds.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/make_hlds.m,v
retrieving revision 1.526
diff -U5 -r1.526 make_hlds.m
--- compiler/make_hlds.m	10 Sep 2006 23:39:00 -0000	1.526
+++ compiler/make_hlds.m	18 Sep 2006 14:41:42 -0000
@@ -43,24 +43,24 @@
 :- import_module maybe.
 :- import_module term.
 
 :- type make_hlds_qual_info.
 
-    % parse_tree_to_hlds(ParseTree, MQInfo, EqvMap, HLDS, QualInfo,
-    %   InvalidTypes, InvalidModes):
+    % parse_tree_to_hlds(ParseTree, MQInfo, EqvMap, UsedModules,
+    %   HLDS, QualInfo, InvalidTypes, InvalidModes):
     %
-    % Given MQInfo (returned by module_qual.m) and EqvMap (returned by
-    % equiv_type.m), converts ParseTree to HLDS. Any errors found are
-    % recorded in the HLDS num_errors field.
+    % Given MQInfo (returned by module_qual.m) and EqvMap and UsedModules
+    % (returned by equiv_type.m), converts ParseTree to HLDS. Any errors found
+    % are recorded in the HLDS num_errors field.
     % Returns InvalidTypes = yes if undefined types found.
     % Returns InvalidModes = yes if undefined or cyclic insts or modes
     % found. QualInfo is an abstract type that is then passed back to
     % produce_instance_method_clauses (see below).
     %
 :- pred parse_tree_to_hlds(compilation_unit::in, mq_info::in, eqv_map::in,
-    module_info::out, make_hlds_qual_info::out, bool::out, bool::out,
-    io::di, io::uo) is det.
+    used_modules::in, module_info::out, make_hlds_qual_info::out,
+    bool::out, bool::out, io::di, io::uo) is det.
 
 :- pred add_new_proc(inst_varset::in, arity::in, list(mer_mode)::in,
     maybe(list(mer_mode))::in, maybe(list(is_live))::in,
     maybe(determinism)::in, prog_context::in, is_address_taken::in,
     pred_info::in, pred_info::out, proc_id::out) is det.
@@ -136,13 +136,13 @@
 
 %-----------------------------------------------------------------------------%
 
 :- type make_hlds_qual_info == hlds.make_hlds.qual_info.qual_info.
 
-parse_tree_to_hlds(Module, MQInfo0, EqvMap, ModuleInfo,
+parse_tree_to_hlds(Module, MQInfo0, EqvMap, UsedModules, ModuleInfo,
         QualInfo, InvalidTypes, InvalidModes, !IO) :-
-    do_parse_tree_to_hlds(Module, MQInfo0, EqvMap, ModuleInfo,
+    do_parse_tree_to_hlds(Module, MQInfo0, EqvMap, UsedModules, ModuleInfo,
         QualInfo, InvalidTypes, InvalidModes, !IO).
 
 add_new_proc(InstVarSet, Arity, ArgModes, MaybeDeclaredArgModes,
         MaybeArgLives, MaybeDet, Context, IsAddressTaken, PredInfo0, PredInfo,
         ModeId) :-
Index: compiler/make_hlds_passes.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/make_hlds_passes.m,v
retrieving revision 1.54
diff -U5 -r1.54 make_hlds_passes.m
--- compiler/make_hlds_passes.m	15 Sep 2006 11:14:33 -0000	1.54
+++ compiler/make_hlds_passes.m	18 Sep 2006 14:41:42 -0000
@@ -28,24 +28,24 @@
     % When adding an item to the HLDS we need to know both its
     % import_status and whether uses of it must be module qualified.
 :- type item_status
     ---> item_status(import_status, need_qualifier).
 
-    % do_parse_tree_to_hlds(ParseTree, MQInfo, EqvMap, HLDS, QualInfo,
-    %   InvalidTypes, InvalidModes):
+    % do_parse_tree_to_hlds(ParseTree, MQInfo, EqvMap, UsedModules
+    %   HLDS, QualInfo, InvalidTypes, InvalidModes):
     %
-    % Given MQInfo (returned by module_qual.m) and EqvMap (returned by
-    % equiv_type.m), converts ParseTree to HLDS. Any errors found are
-    % recorded in the HLDS num_errors field.
+    % Given MQInfo (returned by module_qual.m) and EqvMap and UsedModules
+    % (both returned by equiv_type.m), converts ParseTree to HLDS. Any errors
+    % found are recorded in the HLDS num_errors field.
     % Returns InvalidTypes = yes if undefined types found.
     % Returns InvalidModes = yes if undefined or cyclic insts or modes
     % found. QualInfo is an abstract type that is then passed back to
     % produce_instance_method_clauses (see below).
     %
 :- pred do_parse_tree_to_hlds(compilation_unit::in, mq_info::in, eqv_map::in,
-    module_info::out, qual_info::out, bool::out, bool::out, io::di, io::uo)
-    is det.
+    used_modules::in, module_info::out, qual_info::out,
+    bool::out, bool::out, io::di, io::uo) is det.
 
     % The bool records whether any cyclic insts or modes were detected.
     %
 :- pred add_item_decl_pass_1(item::in, prog_context::in,
     item_status::in, item_status::out, module_info::in, module_info::out,
@@ -131,16 +131,17 @@
 :- import_module string.
 :- import_module varset.
 
 %-----------------------------------------------------------------------------%
 
-do_parse_tree_to_hlds(unit_module(Name, Items), MQInfo0, EqvMap, ModuleInfo,
-        QualInfo, InvalidTypes, InvalidModes, !IO) :-
+do_parse_tree_to_hlds(unit_module(Name, Items), MQInfo0, EqvMap, UsedModules,
+        ModuleInfo, QualInfo, InvalidTypes, InvalidModes, !IO) :-
     some [!Module, !Specs] (
         globals.io_get_globals(Globals, !IO),
         mq_info_get_partial_qualifier_info(MQInfo0, PQInfo),
         module_info_init(Name, Items, Globals, PQInfo, no, !:Module),
+        module_info_set_used_modules(UsedModules, !Module),
         !:Specs = [],
         add_item_list_decls_pass_1(Items,
             item_status(status_local, may_be_unqualified), !Module,
             no, InvalidModes0, !Specs),
         globals.io_lookup_bool_option(statistics, Statistics, !IO),
@@ -552,11 +553,11 @@
     ; IStat = status_imported(import_locn_ancestor_private_interface) ->
         module_add_imported_module_specifiers(IStat, Specifiers, !ModuleInfo),
 
             % Any import_module which comes from a private interface
             % must by definition be a module used by the parent module.
-        module_info_add_parent_used_modules(Specifiers, !ModuleInfo)
+        module_info_add_parents_to_used_modules(Specifiers, !ModuleInfo)
     ;
         module_add_indirectly_imported_module_specifiers(Specifiers,
             !ModuleInfo)
     ).
 
Index: compiler/mercury_compile.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/mercury_compile.m,v
retrieving revision 1.403
diff -U5 -r1.403 mercury_compile.m
--- compiler/mercury_compile.m	15 Sep 2006 11:14:34 -0000	1.403
+++ compiler/mercury_compile.m	18 Sep 2006 14:41:42 -0000
@@ -1717,15 +1717,16 @@
     invoke_module_qualify_items(Items1, Items2, Module, Verbose, Stats,
         MQInfo0, UndefTypes0, UndefModes0, !IO),
 
     mq_info_get_recompilation_info(MQInfo0, RecompInfo0),
     expand_equiv_types(Module, Items2, Verbose, Stats, Items, CircularTypes,
-        EqvMap, RecompInfo0, RecompInfo, !IO),
+        EqvMap, UsedModules, RecompInfo0, RecompInfo, !IO),
     mq_info_set_recompilation_info(RecompInfo, MQInfo0, MQInfo),
     bool.or(UndefTypes0, CircularTypes, UndefTypes1),
 
-    make_hlds(Module, Items, MQInfo, EqvMap, Verbose, Stats, HLDS0, QualInfo,
+    make_hlds(Module, Items, MQInfo, EqvMap, UsedModules,
+        Verbose, Stats, HLDS0, QualInfo,
         UndefTypes2, UndefModes2, FoundError, !IO),
 
     bool.or(UndefTypes1, UndefTypes2, UndefTypes),
     bool.or(UndefModes0, UndefModes2, UndefModes),
 
@@ -1854,33 +1855,34 @@
         )
     ),
     bool.or(Error1, Error2, Error).
 
 :- pred expand_equiv_types(module_name::in, item_list::in, bool::in, bool::in,
-    item_list::out, bool::out, eqv_map::out,
+    item_list::out, bool::out, eqv_map::out, used_modules::out,
     maybe(recompilation_info)::in, maybe(recompilation_info)::out,
     io::di, io::uo) is det.
 
 expand_equiv_types(ModuleName, Items0, Verbose, Stats, Items, CircularTypes,
-    EqvMap, RecompInfo0, RecompInfo, !IO) :-
+    EqvMap, UsedModules, RecompInfo0, RecompInfo, !IO) :-
     maybe_write_string(Verbose, "% Expanding equivalence types...", !IO),
     maybe_flush_output(Verbose, !IO),
     equiv_type.expand_eqv_types(ModuleName, Items0, Items, CircularTypes,
-        EqvMap, RecompInfo0, RecompInfo, !IO),
+        EqvMap, UsedModules, RecompInfo0, RecompInfo, !IO),
     maybe_write_string(Verbose, " done.\n", !IO),
     maybe_report_stats(Stats, !IO).
 
 :- pred make_hlds(module_name::in, item_list::in, mq_info::in,
-    eqv_map::in, bool::in, bool::in, module_info::out,
+    eqv_map::in, used_modules::in, bool::in, bool::in, module_info::out,
     make_hlds_qual_info::out, bool::out, bool::out, bool::out, io::di, io::uo)
     is det.
 
-make_hlds(Module, Items, MQInfo, EqvMap, Verbose, Stats, HLDS, QualInfo,
+make_hlds(Module, Items, MQInfo, EqvMap, UsedModules,
+        Verbose, Stats, HLDS, QualInfo,
         UndefTypes, UndefModes, FoundSemanticError, !IO) :-
     maybe_write_string(Verbose, "% Converting parse tree to hlds...\n", !IO),
     Prog = unit_module(Module, Items),
-    parse_tree_to_hlds(Prog, MQInfo, EqvMap, HLDS, QualInfo,
+    parse_tree_to_hlds(Prog, MQInfo, EqvMap, UsedModules, HLDS, QualInfo,
         UndefTypes, UndefModes, !IO),
     module_info_get_num_errors(HLDS, NumErrors),
     io.get_exit_status(Status, !IO),
     (
         ( Status \= 0
Index: compiler/prog_data.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/prog_data.m,v
retrieving revision 1.175
diff -U5 -r1.175 prog_data.m
--- compiler/prog_data.m	10 Sep 2006 23:39:06 -0000	1.175
+++ compiler/prog_data.m	18 Sep 2006 14:41:43 -0000
@@ -1513,10 +1513,44 @@
     ;       may_be_unqualified.
 
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
 
+
+:- type item_visibility
+    --->    visibility_public
+    ;       visibility_private.
+
+:- type used_modules
+    --->    used_modules(
+                    % The modules used in the interface and implementation.
+                int_used_modules    :: set(module_name),
+                impl_used_modules   :: set(module_name)
+            ).
+
+    %
+    % Initialize the used_modules structure.
+    %
+:- func used_modules_init = used_modules.
+
+    %
+    % Given a sym_name call add_all_modules on the module part of the name.
+    %
+:- pred add_sym_name_module(item_visibility::in, sym_name::in,
+    used_modules::in, used_modules::out) is det.
+
+    %
+    % Given a module name add the module and all of its parent modules
+    % to the used_modules.
+    %
+:- pred add_all_modules(item_visibility::in, sym_name::in,
+    used_modules::in, used_modules::out) is det.
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+
 :- implementation.
 
 :- import_module libs.compiler_util.
 
 :- import_module string.
@@ -1932,10 +1966,38 @@
 get_type_kind(higher_order_type(_, _, _, _)) = kind_star.
 get_type_kind(tuple_type(_, Kind)) = Kind.
 get_type_kind(apply_n_type(_, _, Kind)) = Kind.
 get_type_kind(kinded_type(_, Kind)) = Kind.
 
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+
+used_modules_init = used_modules(set.init, set.init).
+
+%-----------------------------------------------------------------------------%
+
+add_sym_name_module(_Status, unqualified(_), !UsedModules).
+add_sym_name_module(Visibility, qualified(ModuleName, _), !UsedModules) :-
+    add_all_modules(Visibility, ModuleName, !UsedModules).
+
+add_all_modules(Visibility, ModuleName @ unqualified(_), !UsedModules) :-
+    add_module(Visibility, ModuleName, !UsedModules).
+add_all_modules(Visibility, ModuleName @ qualified(Parent, _), !UsedModules) :-
+    add_module(Visibility, ModuleName, !UsedModules),
+    add_all_modules(Visibility, Parent, !UsedModules).
+
+:- pred add_module(item_visibility::in, module_name::in,
+    used_modules::in, used_modules::out) is det.
+
+add_module(visibility_public, Module, !UsedModules) :-
+    !:UsedModules = !.UsedModules ^ int_used_modules :=
+            set.insert(!.UsedModules ^ int_used_modules, Module).
+add_module(visibility_private, Module, !UsedModules) :-
+    !:UsedModules = !.UsedModules ^ impl_used_modules :=
+            set.insert(!.UsedModules ^ impl_used_modules, Module).
+
+%-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
 
 :- func this_file = string.
 
 this_file = "prog_data.m".
Index: compiler/unused_imports.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/unused_imports.m,v
retrieving revision 1.1
diff -U5 -r1.1 unused_imports.m
--- compiler/unused_imports.m	15 Sep 2006 11:14:37 -0000	1.1
+++ compiler/unused_imports.m	18 Sep 2006 14:41:43 -0000
@@ -31,28 +31,29 @@
     %
 :- pred unused_imports(module_info::in, module_info::out,
     io::di, io::uo) is det.
 
 %-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
 
 :- implementation.
 
 :- import_module hlds.
 :- import_module hlds.hlds_clauses.
 :- import_module hlds.hlds_data.
 :- import_module hlds.hlds_goal.
 :- import_module hlds.hlds_pred.
 
+:- import_module mdbcomp.
+:- import_module mdbcomp.prim_data.
+
 :- import_module parse_tree.
 :- import_module parse_tree.error_util.
 :- import_module parse_tree.modules.
 :- import_module parse_tree.prog_data.
 :- import_module parse_tree.prog_type.
 
-:- import_module mdbcomp.
-:- import_module mdbcomp.prim_data.
-
 :- import_module libs.
 :- import_module libs.compiler_util.
 
 :- import_module bool.
 :- import_module list.
@@ -63,33 +64,10 @@
 :- import_module set.
 :- import_module string.
 :- import_module svset.
 :- import_module term.
 
-:- type item_visibility
-    --->    visibility_public
-    ;       visibility_private.
-
-:- type used_modules
-    --->    used_modules(
-                    % The modules used in the interface and implementation.
-                int_used_modules    :: set(module_name),
-                impl_used_modules   :: set(module_name),
-
-                    % The types used in the interface and implementation.
-                int_used_types      :: set(type_ctor),
-                impl_used_types     :: set(type_ctor),
-
-                    % :- type map(K, V) == tree234(K, V)
-                    %
-                    % will appear in the relation as tree234/2 -> map/2.
-                    % Thus the transitive closure from the tree234/2
-                    % will include all the possible equivalence types
-                    % of tree234/2.
-                eqv_types           :: relation(type_ctor)
-            ).
-
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
 
 unused_imports(!ModuleInfo, !IO) :-
         
@@ -107,16 +85,14 @@
         mercury_private_builtin_module,
         mercury_table_builtin_module,
         mercury_profiling_builtin_module,
         mercury_term_size_prof_builtin_module,
         mercury_par_builtin_module],
-    module_info_get_parent_used_modules(!.ModuleInfo, ParentImports),
-    UsedModules0 = used_modules(
-            set(ImplicitImports ++ ParentImports),
-            set.init, set.init, set.init, relation.init),
-    used_modules(!.ModuleInfo, UsedModules0, UsedModules),
-
+    module_info_get_used_modules(!.ModuleInfo, UsedModules0),
+    list.foldl(add_all_modules(visibility_public), ImplicitImports,
+            UsedModules0, UsedModules1),
+    used_modules(!.ModuleInfo, UsedModules1, UsedModules),
         
         %
         % The unused imports is simply the set of imports minus all the
         % used modules.
         %
@@ -215,61 +191,19 @@
 
     module_info_get_instance_table(ModuleInfo, InstanceTable),
     map.foldl(instance_used_modules, InstanceTable, !UsedModules),
 
     module_info_preds(ModuleInfo, PredTable),
-    map.foldl(pred_info_used_modules, PredTable, !UsedModules),
-
-        %
-        % Handle the fact that equivalence types have been expanded by now.
-        %
-    set.fold(add_eqv_type_used_modules(visibility_public),
-            !.UsedModules ^ int_used_types, !UsedModules),
-    set.fold(add_eqv_type_used_modules(visibility_private),
-            !.UsedModules ^ impl_used_types, !UsedModules).
-
-%-----------------------------------------------------------------------------%
-%-----------------------------------------------------------------------------%
-
-    %
-    % As equivalence types have already been expanded by now we have to take
-    % each type used by the system and determine with which other types this
-    % type may be equivalent to, and add the modules where these types come
-    % from as being used as the type may have been actually imported using
-    % this name.
-    %
-    % XXX I think a better way would be to modify equiv_types.m to record
-    % for the interface and implementation section exactly which type_ctor's
-    % were expanded.  I looked into this but didn't have enough time to do it.
-    %
-:- pred add_eqv_type_used_modules(item_visibility::in, type_ctor::in,
-    used_modules::in, used_modules::out) is det.
-
-add_eqv_type_used_modules(Visibility, TypeCtor, !UsedModules) :-
-    Relation = !.UsedModules ^ eqv_types,
-    ( relation.search_element(Relation, TypeCtor, Key) ->
-        EqvTypeKeys = relation.dfs(Relation, Key),
-        EqvTypes = list.map(relation.lookup_key(Relation), EqvTypeKeys),
-        list.foldl(type_ctor_used_modules(Visibility), EqvTypes, !UsedModules)
-    ;
-        true
-    ).
-
-
-:- pred type_ctor_used_modules(item_visibility::in, type_ctor::in,
-    used_modules::in, used_modules::out) is det.
-
-type_ctor_used_modules(Visibility, type_ctor(Name, _), !UsedModules) :-
-    add_sym_name_module(Visibility, Name, !UsedModules).
+    map.foldl(pred_info_used_modules, PredTable, !UsedModules).
 
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
 
 :- pred type_used_modules(type_ctor::in, hlds_type_defn::in,
     used_modules::in, used_modules::out) is det.
 
-type_used_modules(TypeCtor, TypeDefn, !UsedModules) :-
+type_used_modules(_TypeCtor, TypeDefn, !UsedModules) :-
     get_type_defn_status(TypeDefn, ImportStatus),
     get_type_defn_body(TypeDefn, TypeBody),
 
     ( status_defined_in_this_module(ImportStatus) = yes ->
         Visibility = item_visibility(ImportStatus),
@@ -284,23 +218,10 @@
             ),
             true
         )
     ;
         true
-    ),
-
-        % Determine all the type_ctors which are equivalent.
-    ( TypeBody = hlds_eqv_type(EType) ->
-        ( type_to_ctor_and_args(EType, EqvTypeCtor, _) ->
-            relation.add_values(!.UsedModules ^ eqv_types,
-                    EqvTypeCtor, TypeCtor, EqvTypes),
-            !:UsedModules = !.UsedModules ^ eqv_types := EqvTypes
-        ;
-            true
-        )
-    ;
-        true
     ).
 
 :- pred ctor_used_modules(item_visibility::in, constructor::in,
     used_modules::in, used_modules::out) is det.
 
@@ -546,17 +467,11 @@
 
 :- pred mer_type_used_modules(item_visibility::in, mer_type::in,
     used_modules::in, used_modules::out) is det.
 
 mer_type_used_modules(Visibility, Type, !UsedModules) :-
-    mer_type_used_modules_2(Visibility, Type, !UsedModules),
-    ( type_to_ctor_and_args(Type, TypeCtor, Args) ->
-        add_type_ctor(Visibility, TypeCtor, !UsedModules),
-        list.foldl(mer_type_used_modules(Visibility), Args, !UsedModules)
-    ;
-        true
-    ).
+    mer_type_used_modules_2(Visibility, Type, !UsedModules).
 
 :- pred mer_type_used_modules_2(item_visibility::in, mer_type::in,
     used_modules::in, used_modules::out) is det.
 
 mer_type_used_modules_2(_Status, type_variable(_, _), !UsedModules).
@@ -682,60 +597,8 @@
     ( status_is_exported_to_non_submodules(ImportStatus) = yes ->
         visibility_public
     ;
         visibility_private
     ).
-
-%-----------------------------------------------------------------------------%
-%-----------------------------------------------------------------------------%
-
-    %
-    % Given a sym_name add all the module qualifiers to the used_modules.
-    %
-:- pred add_sym_name_module(item_visibility::in, sym_name::in,
-    used_modules::in, used_modules::out) is det.
-
-add_sym_name_module(_Status, unqualified(_), !UsedModules).
-add_sym_name_module(Visibility, qualified(ModuleName, _), !UsedModules) :-
-    add_all_modules(Visibility, ModuleName, !UsedModules).
-
-    %
-    % Given a module name add the module and all of its parent modules
-    % to the used_modules.
-    %
-:- pred add_all_modules(item_visibility::in, sym_name::in,
-    used_modules::in, used_modules::out) is det.
-
-add_all_modules(Visibility, ModuleName @ unqualified(_), !UsedModules) :-
-    add_module(Visibility, ModuleName, !UsedModules).
-add_all_modules(Visibility, ModuleName @ qualified(Parent, _), !UsedModules) :-
-    add_module(Visibility, ModuleName, !UsedModules),
-    add_all_modules(Visibility, Parent, !UsedModules).
-
-:- pred add_module(item_visibility::in, module_name::in,
-    used_modules::in, used_modules::out) is det.
-
-add_module(visibility_public, Module, !UsedModules) :-
-    !:UsedModules = !.UsedModules ^ int_used_modules :=
-            set.insert(!.UsedModules ^ int_used_modules, Module).
-add_module(visibility_private, Module, !UsedModules) :-
-    !:UsedModules = !.UsedModules ^ impl_used_modules :=
-            set.insert(!.UsedModules ^ impl_used_modules, Module).
-
-%-----------------------------------------------------------------------------%
-%-----------------------------------------------------------------------------%
-
-    %
-    % Add the type_ctor to the used_modules.
-    %
-:- pred add_type_ctor(item_visibility::in, type_ctor::in,
-    used_modules::in, used_modules::out) is det.
-
-add_type_ctor(visibility_public, TypeCtor, !UsedModules) :-
-    !:UsedModules = !.UsedModules ^ int_used_types :=
-            set.insert(!.UsedModules ^ int_used_types, TypeCtor).
-add_type_ctor(visibility_private, TypeCtor, !UsedModules) :-
-    !:UsedModules = !.UsedModules ^ impl_used_types :=
-            set.insert(!.UsedModules ^ impl_used_types, TypeCtor).
 
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%

--------------------------------------------------------------------------
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