[m-rev.] diff: Delete unused imports.
Peter Wang
novalazy at gmail.com
Wed Mar 30 11:57:23 AEDT 2022
On Wed, 30 Mar 2022 06:07:17 +1100 "Zoltan Somogyi" <zoltan.somogyi at runbox.com> wrote:
>
> 2022-03-29 12:22 GMT+11:00 "Peter Wang" <novalazy at gmail.com>:
> > (I assume there is a bug in the unused imports detection.)
>
> Indeed there was. The attached diff, which I am asking you to review,
> fixes two of them. I haven't had time yet to test whether it fixes the issue
> you reported, or whether that is a separate bug. Though it could also be
> a known limitation rather than a bug, for anyone who cares about
> the distinction :-)
>
> Zoltan.
> Stop ancestor imports "shadowing" unused local imports.
>
> compiler/make_hlds_passes.m:
> We used to add all modules imported by an ancestor of the current module
> to the set of used modules. Once upon a time, this was meant to stop
> the compiler generating misleading warnings about imports being unused
> when the import wasn't even done by the current module. However, since
> we introduced structures representations of import- and use_module
structured
> declarations and taught unused_imports.m to use them, that has not been
> an issue. However, a bad side-effect remained, which was that if
> a module A imported a module B but did not use it, or it imported
> module B in its interface but did not use it its interface, then
in its interface
> any warning we could generate about that import being unused was
> suppressed by any import of module B in any of module A's ancestors.
> (The "shadowing" mentioned above.)
>
> Fix the problem by adding modules imported by ancestors of the
> current module NOT to the set of used modules, but to a new field
> in the module_info.
>
> compiler/hlds_module.m:
> Add this new field. As it happens, it is not needed right now,
> but it may be needed later.
>
> Update some documentation.
>
> Note an only-tangentially-related problem.
>
> compiler/unused_imports.m:
> Fix a bug that was hiding behind the shadowing, which was that whether
> the text of the warning message we generated for an unused local import-
> or use_module declaration could be affected by the presence of an
> import- or use_module declaration in an ancestor module.
>
> Improve debugging infrastructure.
>
> Make a predicate name more descriptive.
> diff --git a/compiler/hlds_module.m b/compiler/hlds_module.m
> index e98b3cb74..8c154398f 100644
> --- a/compiler/hlds_module.m
> +++ b/compiler/hlds_module.m
> @@ -863,25 +867,40 @@
> % the same file.
> mri_atomics_per_context :: map(prog_context, counter),
>
> - % The names of all the directly imported modules
> - % (used during type checking, and by the MLDS back-end).
> - % XXX CLEANUP The above is COMPLETELY WRONG.
> + % The add_item_avails predicate in make_hlds_passes.m fills
> + % this field with information about all the nonabstract
> + % import_module and use_module declarations in the module
> + % being compiled, and in the .in0 interface files of its
> + % ancestors.
.int0
What do you mean by "nonabstract" import_module and use_module
declarations?
> + %
> + % Each entry in the avail_module_map will specify
> + %
> + % - whether the module is imported or used in the interface
> + % of either the module or its ancestors, and
> + %
> + % - whether the module is imported (as opposed to used)
> + % in either the module or its ancestors.
> + %
> + % Each entry will also contain a list of avail_modules
> + % *for import/use_module declarations in this module only*;
> + % there won't be any entries for imports/uses in ancestors.
> %
> @@ -1666,6 +1689,13 @@ module_add_avail_module_name(ModuleName, NewSection, NewImportOrUse,
> AvailMap0 = !.MI ^ mi_rare_info ^ mri_avail_module_map,
> ( if map.search(AvailMap0, ModuleName, OldEntry) then
> OldEntry = avail_module_entry(OldSection, OldImportOrUse, OldAvails),
> + % XXX: If one of the entries (new or old) as a use_module in the
is a
> + % interface sectin, while the other is an import_module in the
section
> + % implementation section, the result *ought* to be something like
> + % the int_use_imp_import alternative of the section_import_or_use type,
> + % BUT the design of avail_module_entry has no way to express that.
> + % The code of combine_old_new_avail_attrs returns "import_module in the
> + % interface section" in such cases, which is almost certainly a bug.
> combine_old_new_avail_attrs(OldSection, NewSection,
> OldImportOrUse, NewImportOrUse, Section, ImportOrUse),
> Avails = NewAvails ++ OldAvails,
> diff --git a/compiler/make_hlds_passes.m b/compiler/make_hlds_passes.m
> index 3665d746d..1cb43a81b 100644
> --- a/compiler/make_hlds_passes.m
> +++ b/compiler/make_hlds_passes.m
> @@ -659,8 +666,7 @@ add_item_avail(ItemMercuryStatus, Avail, !ModuleInfo) :-
> % (for Section = ms_implementation), we should be able
> % to generate a warning for that when we compile the ancestor.
> % XXX We do not currently do this.
> - module_info_add_module_to_public_used_modules(ModuleName,
> - !ModuleInfo)
> + set.insert(ModuleName, !AncestorAvailModules)
> ;
> ( ImportLocn = import_locn_interface
> ; ImportLocn = import_locn_implementation
I think you should update/delete the comment above that change that says:
% We therefore record it as "used" to avoid reporting
% a warning that may be incorrect.
> diff --git a/compiler/unused_imports.m b/compiler/unused_imports.m
> index a886ef60c..c09d70e44 100644
> --- a/compiler/unused_imports.m
> +++ b/compiler/unused_imports.m
> @@ -173,17 +184,26 @@ get_avail_modules_anywhere_interface([ModuleEntry | ModuleEntries],
> maybe_warn_about_avail(TopModuleName,
> UnusedAnywhereImports, UnusedInterfaceImports,
> ModuleName, AvailEntry, !Specs) :-
> - AvailEntry = avail_module_entry(Section, ImportOrUse, Avails),
> + AvailEntry = avail_module_entry(_Section, _ImportOrUse, Avails),
> list.sort(compare_avails, Avails, SortedAvails),
> (
> SortedAvails = []
> ;
> SortedAvails = [HeadAvail | _],
> - HeadAvail = avail_module(_, _, HeadContext),
> + % NOTE: We *must* get Section and ImportOrUse from one of the elements
> + % of Avail, and *not* from AvailEntry. This is because the first two
Avail -> HeadAvail
> + % fields of AvailsEntry are affected by imports and/or uses in
AvailsEntry -> AvailEntry
> + % ancestors of the current module, while every element of Avails
> + % is derived from items in the current module. If a module is
> + % imported in the interface section of an ancestor but is imported
> + % in the implementation section of this module, we want the error
> + % message to treat the import as being the implementation section.
> + % The same reasoning applies to ImportOrUse.
> + HeadAvail = avail_module(Section, ImportOrUse, HeadContext),
> maybe_generate_redundant_avail_warnings(ModuleName, SortedAvails,
> [], !Specs),
> ( if set.member(ModuleName, UnusedAnywhereImports) then
> - AnywhereSpec = generate_unused_warning(TopModuleName,
> + AnywhereSpec = generate_unused_import_warning(TopModuleName,
> ModuleName, ImportOrUse, HeadContext, aoi_anywhere),
> !:Specs = [AnywhereSpec | !.Specs],
> AnywhereWarning = yes
That seems fine otherwise.
Peter
More information about the reviews
mailing list