mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-15 09:23:44 +00:00
Make --warn-unused-imports more effective.
Specifically, make it warn about interface imports that are not used
in the initial HLDS, even if they *are* used after the expansion of
type-, inst- and mode-equivalences.
compiler/hlds_module.m:
Add a slot to the HLDS to store the set of modules that are
imported in the interface but are unused there when the HLDS
is first constructed.
compiler/module_qual.qualify_items.m:
Compute this set, and return it to mercury_compile_make_hlds.m.
Make the code module qualifying aug_compilation_units warn about
unused interface imports only if unused_imports.m won't do the same later.
compiler/mercury_compile_make_hlds.m:
Pass the set to make_hlds_passes.m.
compiler/make_hlds_passes.m:
Store the set in the initial HLDS.
compiler/prog_data_used_modules.m:
Replace set_ordlists with set_tree234s.
compiler/unused_imports.m:
Consider an interface-imported module unused in the interface
if module_qual.qualify_items.m considered it unused, even if
changes made by equiv_type.m has added uses of it later.
compiler/handle_options.m:
Stop making --warn-unused-imports imply --no-warn-unused-interface-imports,
since new logic in module_qual.qualify_items.m makes this unnecessary.
compiler/make_module_file_names.m:
compiler/type_inst_mode_map.m:
compiler/write_deps_file.m:
Move imports from the interface section to the implementation section,
in response to the new, more thorough warnings.
This commit is contained in:
@@ -1760,7 +1760,6 @@ handle_stack_layout_options(!Globals, OT_OptDups0, OT_OptDups,
|
||||
% smart_recompilation
|
||||
% transitive_optimization
|
||||
% warn_wrong_module_name
|
||||
% warn_unused_interface_imports
|
||||
% inform_generated_type_spec_pragmas
|
||||
% detect_stdlib_grades
|
||||
%
|
||||
@@ -1951,7 +1950,6 @@ turn_off_all_only_codegen_warnings(HaltAtWarnSrcOpt, !Globals) :-
|
||||
% use_trans_opt_files
|
||||
% verbose_recompilation
|
||||
% warn_missing_trans_opt_files
|
||||
% warn_unused_interface_imports
|
||||
%
|
||||
:- pred handle_option_to_option_implications(op_mode::in,
|
||||
globals::in, globals::out) is det.
|
||||
@@ -2025,17 +2023,7 @@ handle_option_to_option_implications(OpMode, !Globals) :-
|
||||
% is done when making the `.opt' file. With `--use-opt-files',
|
||||
% that doesn't happen.
|
||||
% XXX Should that be "with `--no-use-opt-files'"?
|
||||
globals.set_option(use_opt_files, bool(no), !Globals),
|
||||
|
||||
globals.lookup_bool_option(!.Globals, warn_unused_imports, UnusedImports),
|
||||
(
|
||||
UnusedImports = no
|
||||
;
|
||||
UnusedImports = yes,
|
||||
% warn_unused_interface_imports does *part* of the job
|
||||
% of warn_unused_imports.
|
||||
globals.set_option(warn_unused_interface_imports, bool(no), !Globals)
|
||||
).
|
||||
globals.set_option(use_opt_files, bool(no), !Globals).
|
||||
|
||||
% --use-opt-files implies --no-warn-missing-opt-files since
|
||||
% we are expecting some to be missing.
|
||||
|
||||
@@ -246,7 +246,8 @@
|
||||
% compilation unit.
|
||||
%
|
||||
:- pred module_info_init(globals::in, module_name::in, prog_context::in,
|
||||
string::in, include_module_map::in, used_modules::in, set(module_name)::in,
|
||||
string::in, include_module_map::in,
|
||||
used_modules::in, set(module_name)::in, set_tree234(module_name)::in,
|
||||
partial_qualifier_info::in, maybe(recompilation_info)::in,
|
||||
type_repn_decision_data::in, module_info::out) is det.
|
||||
|
||||
@@ -369,6 +370,8 @@
|
||||
avail_module_map::out) is det.
|
||||
:- pred module_info_get_used_modules(module_info::in,
|
||||
used_modules::out) is det.
|
||||
:- pred module_info_get_unused_interface_imports(module_info::in,
|
||||
set_tree234(module_name)::out) is det.
|
||||
:- pred module_info_get_maybe_complexity_proc_map(module_info::in,
|
||||
maybe(pair(int, complexity_proc_map))::out) is det.
|
||||
:- pred module_info_get_complexity_proc_infos(module_info::in,
|
||||
@@ -987,6 +990,8 @@
|
||||
% imports/uses of those modules.
|
||||
mri_used_modules :: used_modules,
|
||||
|
||||
mri_unused_interface_imports :: set_tree234(module_name),
|
||||
|
||||
% Information about the procedures we are performing
|
||||
% complexity experiments on.
|
||||
mri_maybe_complexity_proc_map :: maybe(pair(int,
|
||||
@@ -1122,7 +1127,7 @@
|
||||
%---------------------------------------------------------------------------%
|
||||
|
||||
module_info_init(Globals, ModuleName, ModuleNameContext, DumpBaseFileName,
|
||||
InclMap, UsedModules, ImplicitlyUsedModules,
|
||||
InclMap, UsedModules, ImplicitlyUsedModules, UnusedInterfaceImports,
|
||||
QualifierInfo, MaybeRecompInfo, TypeRepnDec, ModuleInfo) :-
|
||||
SpecialPredMaps = special_pred_maps(map.init, map.init, map.init),
|
||||
map.init(ClassTable),
|
||||
@@ -1246,6 +1251,7 @@ module_info_init(Globals, ModuleName, ModuleNameContext, DumpBaseFileName,
|
||||
AvailModuleMap,
|
||||
AvailModuleSets,
|
||||
UsedModules,
|
||||
UnusedInterfaceImports,
|
||||
MaybeComplexityMap,
|
||||
ComplexityProcInfos,
|
||||
ProcAnalysisKinds,
|
||||
@@ -1430,6 +1436,8 @@ module_info_get_avail_module_sets(MI, X) :-
|
||||
X = MI ^ mi_rare_info ^ mri_avail_module_sets.
|
||||
module_info_get_used_modules(MI, X) :-
|
||||
X = MI ^ mi_rare_info ^ mri_used_modules.
|
||||
module_info_get_unused_interface_imports(MI, X) :-
|
||||
X = MI ^ mi_rare_info ^ mri_unused_interface_imports.
|
||||
module_info_get_maybe_complexity_proc_map(MI, X) :-
|
||||
X = MI ^ mi_rare_info ^ mri_maybe_complexity_proc_map.
|
||||
module_info_get_complexity_proc_infos(MI, X) :-
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
:- import_module hlds.make_hlds.qual_info.
|
||||
:- import_module libs.
|
||||
:- import_module libs.globals.
|
||||
:- import_module mdbcomp.
|
||||
:- import_module mdbcomp.sym_name.
|
||||
:- import_module parse_tree.
|
||||
:- import_module parse_tree.equiv_type.
|
||||
:- import_module parse_tree.error_spec.
|
||||
@@ -30,23 +32,27 @@
|
||||
|
||||
:- import_module io.
|
||||
:- import_module list.
|
||||
:- import_module set_tree234.
|
||||
|
||||
%---------------------------------------------------------------------------%
|
||||
|
||||
% parse_tree_to_hlds(ProgressStream, AugCompUnit, Globals,
|
||||
% DumpBaseFileName, MQInfo, TypeEqvMap, UsedModules, QualInfo,
|
||||
% InvalidTypes, InvalidModes, HLDS, Specs):
|
||||
% DumpBaseFileName, MQInfo0, TypeEqvMap,
|
||||
% UsedModules, UnusedInterfaceImports,
|
||||
% QualInfo, InvalidType, InvalidInstOrMode, HLDS, Specs):
|
||||
%
|
||||
% Given MQInfo (returned by module_qual.m) and TypeEqvMap and UsedModules
|
||||
% (both returned by equiv_type.m), convert AugCompUnit to HLDS.
|
||||
% Return any errors found in Specs.
|
||||
% Return InvalidTypes = yes if we found undefined types.
|
||||
% Return InvalidModes = yes if we found undefined or cyclic insts or modes.
|
||||
% Return InvalidType = yes if we found undefined types.
|
||||
% Return InvalidInstOrMode = yes if we found undefined or cyclic
|
||||
% insts or modes.
|
||||
% QualInfo is an abstract type that check_typeclass.m will later pass
|
||||
% to produce_instance_method_clauses.
|
||||
%
|
||||
:- pred parse_tree_to_hlds(io.text_output_stream::in, aug_compilation_unit::in,
|
||||
globals::in, string::in, mq_info::in, type_eqv_map::in, used_modules::in,
|
||||
globals::in, string::in, mq_info::in, type_eqv_map::in,
|
||||
used_modules::in, set_tree234(module_name)::in,
|
||||
qual_info::out, found_invalid_type::out, found_invalid_inst_or_mode::out,
|
||||
module_info::out, list(error_spec)::out) is det.
|
||||
|
||||
@@ -77,10 +83,8 @@
|
||||
:- import_module hlds.special_pred.
|
||||
:- import_module hlds.status.
|
||||
:- import_module libs.options.
|
||||
:- import_module mdbcomp.
|
||||
:- import_module mdbcomp.builtin_modules.
|
||||
:- import_module mdbcomp.prim_data.
|
||||
:- import_module mdbcomp.sym_name.
|
||||
:- import_module parse_tree.error_util.
|
||||
:- import_module parse_tree.get_dependencies.
|
||||
:- import_module parse_tree.maybe_error.
|
||||
@@ -105,7 +109,6 @@
|
||||
:- import_module pair.
|
||||
:- import_module require.
|
||||
:- import_module set.
|
||||
:- import_module set_tree234.
|
||||
:- import_module term_context.
|
||||
:- import_module term_subst.
|
||||
:- import_module varset.
|
||||
@@ -113,7 +116,7 @@
|
||||
%---------------------------------------------------------------------------%
|
||||
|
||||
parse_tree_to_hlds(ProgressStream, AugCompUnit, Globals, DumpBaseFileName,
|
||||
MQInfo0, TypeEqvMap, UsedModules, !:QualInfo,
|
||||
MQInfo0, TypeEqvMap, UsedModules, UnusedInterfaceImports, !:QualInfo,
|
||||
!:FoundInvalidType, !:FoundInvalidInstOrMode, !:ModuleInfo, !:Specs) :-
|
||||
ParseTreeModuleSrc = AugCompUnit ^ acu_module_src,
|
||||
maybe_warn_include_and_non_include(Globals, ParseTreeModuleSrc, InclSpecs),
|
||||
@@ -218,8 +221,8 @@ parse_tree_to_hlds(ProgressStream, AugCompUnit, Globals, DumpBaseFileName,
|
||||
TypeRepnDec = type_repn_decision_data(TypeRepnMap, DirectArgMap,
|
||||
ForeignEnums, ForeignExportEnums),
|
||||
module_info_init(Globals, ModuleName, ModuleNameContext, DumpBaseFileName,
|
||||
InclMap, UsedModules, ImplicitlyUsedModules, PQInfo, no, TypeRepnDec,
|
||||
!:ModuleInfo),
|
||||
InclMap, UsedModules, ImplicitlyUsedModules, UnusedInterfaceImports,
|
||||
PQInfo, no, TypeRepnDec, !:ModuleInfo),
|
||||
|
||||
% The old pass 1.
|
||||
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
|
||||
:- import_module io.
|
||||
:- import_module list.
|
||||
:- import_module map.
|
||||
:- import_module set.
|
||||
|
||||
%---------------------------------------------------------------------------%
|
||||
@@ -66,6 +65,7 @@
|
||||
|
||||
:- implementation.
|
||||
|
||||
:- import_module map.
|
||||
:- import_module string.
|
||||
:- import_module uint.
|
||||
|
||||
|
||||
@@ -170,7 +170,7 @@ make_hlds_pass(ProgressStream, ErrorStream, Globals,
|
||||
"% Module qualifying items...\n", !IO),
|
||||
maybe_flush_output(ProgressStream, Verbose, !IO),
|
||||
module_qualify_aug_comp_unit(Globals, AugCompUnit1, AugCompUnit2,
|
||||
EventSpecMap0, EventSpecMap1, EventSetFileName, MQInfo0,
|
||||
EventSpecMap0, EventSpecMap1, EventSetFileName, MQInfo0, UnusedImports,
|
||||
MQUndefTypes, MQUndefInsts, MQUndefModes, MQUndefTypeClasses,
|
||||
[], QualifySpecs),
|
||||
!:Specs = QualifySpecs ++ !.Specs,
|
||||
@@ -194,8 +194,8 @@ make_hlds_pass(ProgressStream, ErrorStream, Globals,
|
||||
|
||||
EventSet = event_set(EventSetName, EventSpecMap),
|
||||
make_hlds(ProgressStream, ErrorStream, Globals, AugCompUnit, EventSet,
|
||||
MQInfo, TypeEqvMap, UsedModules, Verbose, Stats, HLDS0, QualInfo,
|
||||
MakeHLDSFoundInvalidType, MakeHLDSFoundInvalidInstOrMode,
|
||||
MQInfo, TypeEqvMap, UsedModules, UnusedImports, Verbose, Stats, HLDS0,
|
||||
QualInfo, MakeHLDSFoundInvalidType, MakeHLDSFoundInvalidInstOrMode,
|
||||
FoundSemanticError, !Specs, !IO),
|
||||
bool.or(FoundSemanticError, IntermodError, PreHLDSErrors),
|
||||
maybe_write_definitions(ProgressStream,
|
||||
@@ -610,14 +610,14 @@ maybe_grab_plain_and_trans_opt_files(ProgressStream, ErrorStream, Globals,
|
||||
|
||||
:- pred make_hlds(io.text_output_stream::in, io.text_output_stream::in,
|
||||
globals::in, aug_compilation_unit::in, event_set::in, mq_info::in,
|
||||
type_eqv_map::in, used_modules::in, bool::in, bool::in,
|
||||
module_info::out, qual_info::out,
|
||||
type_eqv_map::in, used_modules::in, set_tree234(module_name)::in,
|
||||
bool::in, bool::in, module_info::out, qual_info::out,
|
||||
found_invalid_type::out, found_invalid_inst_or_mode::out, bool::out,
|
||||
list(error_spec)::in, list(error_spec)::out, io::di, io::uo) is det.
|
||||
|
||||
make_hlds(ProgressStream, ErrorStream, Globals, AugCompUnit, EventSet, MQInfo,
|
||||
TypeEqvMap, UsedModules, Verbose, Stats, !:HLDS, QualInfo,
|
||||
FoundInvalidType, FoundInvalidInstOrMode,
|
||||
TypeEqvMap, UsedModules, UnusedImports, Verbose, Stats, !:HLDS,
|
||||
QualInfo, FoundInvalidType, FoundInvalidInstOrMode,
|
||||
FoundSemanticError, !Specs, !IO) :-
|
||||
maybe_write_out_errors(ErrorStream, Verbose, Globals, !Specs, !IO),
|
||||
maybe_write_string(ProgressStream, Verbose,
|
||||
@@ -627,7 +627,7 @@ make_hlds(ProgressStream, ErrorStream, Globals, AugCompUnit, EventSet, MQInfo,
|
||||
module_name_to_cur_dir_file_name(ext_cur_user_hlds_dump,
|
||||
ModuleName, DumpBaseFileName),
|
||||
parse_tree_to_hlds(ProgressStream, AugCompUnit, Globals, DumpBaseFileName,
|
||||
MQInfo, TypeEqvMap, UsedModules, QualInfo,
|
||||
MQInfo, TypeEqvMap, UsedModules, UnusedImports, QualInfo,
|
||||
FoundInvalidType, FoundInvalidInstOrMode, !:HLDS, MakeSpecs),
|
||||
!:Specs = MakeSpecs ++ !.Specs,
|
||||
module_info_set_event_set(EventSet, !HLDS),
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
|
||||
:- import_module libs.
|
||||
:- import_module libs.globals.
|
||||
:- import_module mdbcomp.
|
||||
:- import_module mdbcomp.sym_name.
|
||||
:- import_module parse_tree.error_spec.
|
||||
:- import_module parse_tree.module_qual.id_set.
|
||||
:- import_module parse_tree.module_qual.mq_info.
|
||||
@@ -33,7 +35,8 @@
|
||||
|
||||
% module_qualify_aug_comp_unit(Globals, AugCompUnit0, AugCompUnit,
|
||||
% EventSpecMap0, EventSpecMap, MaybeContext, EventSpecFileName, MQ_Info,
|
||||
% UndefTypes, UndefInsts, UndefModes, UndefTypeClasses, !Specs):
|
||||
% UnusedImportsSet, UndefTypes, UndefInsts, UndefModes,
|
||||
% UndefTypeClasses, !Specs):
|
||||
%
|
||||
% AugCompUnit is AugCompUnit0 with all items module qualified
|
||||
% as much as possible; likewise for EventSpecMap0 and EventSpecMap.
|
||||
@@ -43,6 +46,7 @@
|
||||
:- pred module_qualify_aug_comp_unit(globals::in,
|
||||
aug_compilation_unit::in, aug_compilation_unit::out,
|
||||
event_spec_map::in, event_spec_map::out, string::in, mq_info::out,
|
||||
set_tree234(module_name)::out,
|
||||
set_tree234(type_ctor)::out, set_tree234(inst_ctor)::out,
|
||||
set_tree234(mode_ctor)::out, set_tree234(sym_name_arity)::out,
|
||||
list(error_spec)::in, list(error_spec)::out) is det.
|
||||
@@ -88,8 +92,6 @@
|
||||
:- implementation.
|
||||
|
||||
:- import_module libs.options.
|
||||
:- import_module mdbcomp.
|
||||
:- import_module mdbcomp.sym_name.
|
||||
:- import_module parse_tree.module_qual.collect_mq_info.
|
||||
:- import_module parse_tree.module_qual.qual_errors.
|
||||
:- import_module parse_tree.prog_data_foreign.
|
||||
@@ -115,7 +117,8 @@
|
||||
|
||||
module_qualify_aug_comp_unit(Globals, AugCompUnit0, AugCompUnit,
|
||||
EventSpecMap0, EventSpecMap, EventSpecFileName, !:Info,
|
||||
UndefTypes, UndefInsts, UndefModes, UndefTypeClasses, !Specs) :-
|
||||
UnusedImportsSet, UndefTypes, UndefInsts, UndefModes,
|
||||
UndefTypeClasses, !Specs) :-
|
||||
AugCompUnit0 = aug_compilation_unit(ParseTreeModuleSrc0,
|
||||
AncestorIntSpecs, DirectInt1Specs, IndirectInt2Specs,
|
||||
PlainOptSpecs, TransOptSpecs, IntForOptSpecs, TypeRepnSpecs,
|
||||
@@ -143,7 +146,34 @@ module_qualify_aug_comp_unit(Globals, AugCompUnit0, AugCompUnit,
|
||||
mq_info_get_undef_insts(!.Info, UndefInsts),
|
||||
mq_info_get_undef_modes(!.Info, UndefModes),
|
||||
mq_info_get_undef_typeclasses(!.Info, UndefTypeClasses),
|
||||
maybe_report_qual_warnings(Globals, !.Info, ModuleName, !Specs).
|
||||
|
||||
globals.lookup_bool_option(Globals, warn_unused_interface_imports,
|
||||
WarnUnusedInterfaceImports),
|
||||
globals.lookup_bool_option(Globals, warn_unused_imports,
|
||||
WarnUnusedImports),
|
||||
( if
|
||||
( WarnUnusedInterfaceImports = yes
|
||||
; WarnUnusedImports = yes
|
||||
)
|
||||
then
|
||||
get_unused_imports_map(!.Info, UnusedImportsMap),
|
||||
map.keys(UnusedImportsMap, UnusedImports),
|
||||
set_tree234.sorted_list_to_set(UnusedImports, UnusedImportsSet),
|
||||
(
|
||||
WarnUnusedImports = yes
|
||||
% The unused imports will be reported later by unused_imports.m.
|
||||
% That is why we return UnusedImportsSet to our caller, to be
|
||||
% stored in the HLDS until unused_imports.m can look at it.
|
||||
;
|
||||
WarnUnusedImports = no,
|
||||
% We can get here only if WarnUnusedInterfaceImports is yes.
|
||||
map.to_assoc_list(UnusedImportsMap, UnusedImportsAL),
|
||||
list.foldl(warn_unused_interface_import(ModuleName),
|
||||
UnusedImportsAL, !Specs)
|
||||
)
|
||||
else
|
||||
UnusedImportsSet = set_tree234.init
|
||||
).
|
||||
|
||||
%---------------------%
|
||||
|
||||
@@ -166,12 +196,24 @@ module_qualify_aug_make_int_unit(Globals, AugMakeIntUnit0, AugMakeIntUnit,
|
||||
AugMakeIntUnit = aug_make_int_unit(ParseTreeModuleSrc, DelayedSpecs0,
|
||||
AncestorInt0s, DirectInt3Specs, IndirectInt3Specs,
|
||||
ModuleVersionNumbers),
|
||||
maybe_report_qual_warnings(Globals, !.Info, ModuleName, !Specs)
|
||||
globals.lookup_bool_option(Globals, warn_interface_imports,
|
||||
WarnInterfaceImports),
|
||||
(
|
||||
WarnInterfaceImports = no
|
||||
;
|
||||
WarnInterfaceImports = yes,
|
||||
get_unused_imports_map(!.Info, UnusedImportsMap),
|
||||
map.to_assoc_list(UnusedImportsMap, UnusedImports),
|
||||
list.foldl(warn_unused_interface_import(ModuleName), UnusedImports,
|
||||
!Specs)
|
||||
)
|
||||
).
|
||||
|
||||
%---------------------%
|
||||
|
||||
% Warn about any unused module imports in the interface.
|
||||
% Compute the set of unused module imports in the interface,
|
||||
% so we can warn about them.
|
||||
%
|
||||
% There is a special case involving type class instances that
|
||||
% we need to handle here. Consider:
|
||||
%
|
||||
@@ -196,30 +238,19 @@ module_qualify_aug_make_int_unit(Globals, AugMakeIntUnit0, AugMakeIntUnit,
|
||||
% the interface of the importing module, except if the importing
|
||||
% module itself exports _no_ type class instances.
|
||||
%
|
||||
:- pred maybe_report_qual_warnings(globals::in, mq_info::in, module_name::in,
|
||||
list(error_spec)::in, list(error_spec)::out) is det.
|
||||
:- pred get_unused_imports_map(mq_info::in, module_names_contexts::out) is det.
|
||||
|
||||
maybe_report_qual_warnings(Globals, Info, ModuleName, !Specs) :-
|
||||
globals.lookup_bool_option(Globals, warn_interface_imports,
|
||||
WarnInterfaceImports),
|
||||
get_unused_imports_map(Info, UnusedImportsMap) :-
|
||||
mq_info_get_as_yet_unused_interface_modules(Info, UnusedImportsMap0),
|
||||
mq_info_get_exported_instances_flag(Info, ModuleExportsInstances),
|
||||
(
|
||||
WarnInterfaceImports = no
|
||||
ModuleExportsInstances = yes,
|
||||
mq_info_get_imported_instance_modules(Info, InstanceImports),
|
||||
map.delete_list(set_tree234.to_sorted_list(InstanceImports),
|
||||
UnusedImportsMap0, UnusedImportsMap)
|
||||
;
|
||||
WarnInterfaceImports = yes,
|
||||
mq_info_get_as_yet_unused_interface_modules(Info, UnusedImportsMap0),
|
||||
mq_info_get_exported_instances_flag(Info, ModuleExportsInstances),
|
||||
(
|
||||
ModuleExportsInstances = yes,
|
||||
mq_info_get_imported_instance_modules(Info, InstanceImports),
|
||||
map.delete_list(set_tree234.to_sorted_list(InstanceImports),
|
||||
UnusedImportsMap0, UnusedImportsMap)
|
||||
;
|
||||
ModuleExportsInstances = no,
|
||||
UnusedImportsMap = UnusedImportsMap0
|
||||
),
|
||||
map.to_assoc_list(UnusedImportsMap, UnusedImports),
|
||||
list.foldl(warn_unused_interface_import(ModuleName), UnusedImports,
|
||||
!Specs)
|
||||
ModuleExportsInstances = no,
|
||||
UnusedImportsMap = UnusedImportsMap0
|
||||
).
|
||||
|
||||
%---------------------%
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
%---------------------------------------------------------------------------%
|
||||
% vim: ft=mercury ts=4 sw=4 et
|
||||
%---------------------------------------------------------------------------%
|
||||
% Copyright (C) 2016, 2022 The Mercury team.
|
||||
% Copyright (C) 2016, 2022, 2025 The Mercury team.
|
||||
% This file may only be copied under the terms of the GNU General
|
||||
% Public License - see the file COPYING in the Mercury distribution.
|
||||
%---------------------------------------------------------------------------%
|
||||
@@ -16,15 +16,15 @@
|
||||
:- import_module mdbcomp.
|
||||
:- import_module mdbcomp.sym_name.
|
||||
|
||||
:- import_module set.
|
||||
:- import_module set_tree234.
|
||||
|
||||
%---------------------------------------------------------------------------%
|
||||
|
||||
:- type used_modules
|
||||
---> used_modules(
|
||||
% The modules used in the interface and implementation.
|
||||
int_used_modules :: set(module_name),
|
||||
imp_used_modules :: set(module_name)
|
||||
int_used_modules :: set_tree234(module_name),
|
||||
imp_used_modules :: set_tree234(module_name)
|
||||
).
|
||||
|
||||
:- type item_visibility
|
||||
@@ -58,7 +58,7 @@
|
||||
|
||||
:- import_module list.
|
||||
|
||||
used_modules_init = used_modules(set.init, set.init).
|
||||
used_modules_init = used_modules(set_tree234.init, set_tree234.init).
|
||||
|
||||
record_sym_name_module_as_used(Visibility, SymName, !UsedModules) :-
|
||||
(
|
||||
@@ -83,10 +83,10 @@ record_module_and_ancestors_as_used(Visibility, ModuleName, !UsedModules) :-
|
||||
).
|
||||
|
||||
:- pred add_module_and_ancestors(sym_name::in,
|
||||
set(module_name)::in, set(module_name)::out) is det.
|
||||
set_tree234(module_name)::in, set_tree234(module_name)::out) is det.
|
||||
|
||||
add_module_and_ancestors(ModuleName, !UsedModuleNames) :-
|
||||
set.insert(ModuleName, !UsedModuleNames),
|
||||
set_tree234.insert(ModuleName, !UsedModuleNames),
|
||||
(
|
||||
ModuleName = unqualified(_)
|
||||
;
|
||||
@@ -98,7 +98,7 @@ record_format_modules_as_used(!UsedModules) :-
|
||||
ImpUsedModules0 = !.UsedModules ^ imp_used_modules,
|
||||
FormatModules = [mercury_string_format_module,
|
||||
mercury_string_parse_util_module, mercury_stream_module],
|
||||
set.insert_list(FormatModules, ImpUsedModules0, ImpUsedModules),
|
||||
set_tree234.insert_list(FormatModules, ImpUsedModules0, ImpUsedModules),
|
||||
!UsedModules ^ imp_used_modules := ImpUsedModules.
|
||||
|
||||
%---------------------------------------------------------------------------%
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
:- module parse_tree.type_inst_mode_map.
|
||||
:- interface.
|
||||
|
||||
:- import_module parse_tree.prog_data.
|
||||
:- import_module parse_tree.prog_item.
|
||||
|
||||
:- import_module list.
|
||||
@@ -70,6 +69,7 @@
|
||||
:- import_module mdbcomp.
|
||||
:- import_module mdbcomp.sym_name.
|
||||
:- import_module parse_tree.item_util.
|
||||
:- import_module parse_tree.prog_data.
|
||||
|
||||
:- import_module cord.
|
||||
:- import_module map.
|
||||
|
||||
@@ -78,7 +78,7 @@
|
||||
:- import_module one_or_more_map.
|
||||
:- import_module pair.
|
||||
:- import_module pretty_printer.
|
||||
:- import_module set.
|
||||
:- import_module set_tree234.
|
||||
:- import_module string.
|
||||
:- import_module term.
|
||||
|
||||
@@ -94,23 +94,65 @@ warn_about_unused_imports(ProgressStream, ModuleInfo, !:Specs) :-
|
||||
get_avail_modules_anywhere_interface(ModuleAvails,
|
||||
cord.init, AvailAnywhereCord,
|
||||
cord.init, AvailInterfaceCord),
|
||||
set.sorted_list_to_set(cord.list(AvailAnywhereCord),
|
||||
set_tree234.sorted_list_to_set(cord.list(AvailAnywhereCord),
|
||||
AvailAnywhereModules),
|
||||
set.sorted_list_to_set(cord.list(AvailInterfaceCord),
|
||||
set_tree234.sorted_list_to_set(cord.list(AvailInterfaceCord),
|
||||
AvailInterfaceModules),
|
||||
|
||||
UsedInInterface = UsedModules ^ int_used_modules,
|
||||
UsedInImplementation = UsedModules ^ imp_used_modules,
|
||||
UsedAnywhere = set.union(UsedInInterface, UsedInImplementation),
|
||||
UsedAnywhere = set_tree234.union(UsedInInterface, UsedInImplementation),
|
||||
|
||||
% The unused imports is simply the set of all imports minus all the
|
||||
% used modules.
|
||||
set.difference(AvailAnywhereModules, UsedAnywhere, UnusedAnywhereImports),
|
||||
set_tree234.difference(AvailAnywhereModules, UsedAnywhere,
|
||||
UnusedAnywhereImports),
|
||||
|
||||
% Determine the modules imported in the interface but not used in
|
||||
% the interface.
|
||||
UnusedInterfaceImports =
|
||||
set.difference(AvailInterfaceModules, UsedInInterface),
|
||||
set_tree234.difference(AvailInterfaceModules, UsedInInterface,
|
||||
UnusedInterfaceImports0),
|
||||
% As its name implies, UnusedInterfaceImports0 contains a subset
|
||||
% of the modules that are imported in the interface. Specifically,
|
||||
% it contains the subset that are not used in the interface *now*.
|
||||
% However, it misses some imports that don't need to be in the interface
|
||||
% because they are not used in the interface *when the HLDS is initially
|
||||
% constructed*.
|
||||
%
|
||||
% To see the difference, consider a module A that imports module B
|
||||
% in its interface. Module A's interface starts out containing
|
||||
% no references to anything defined in module B, but it does contain
|
||||
% a reference to a type tc, which defined in module C, which module A
|
||||
% also imports in its interface. If module C defines and exports type tc
|
||||
% as an equivalence type, *and* if the right hand side of that equivalence
|
||||
% contains a reference to a type defined by module B, then module A's
|
||||
% interface *will* contains a reference to that type from B after
|
||||
% equiv_type.m has done its job. The same thing can also happen
|
||||
% with inst and mode definitions.
|
||||
%
|
||||
% There are two obvious approaches to fixing this problem.
|
||||
%
|
||||
% Approach 1 is to extend the parse tree's representations of
|
||||
% all the items that contain types, insts and modes (including
|
||||
% type definitions, predicate and mode declarations, and typeclass
|
||||
% method declarations) with a copy of every type, inst and mode that
|
||||
% equiv_type.m would leave alone. We would then copy all those fields
|
||||
% into their HLDS equivalents, and then get find_all_non_warn_modules
|
||||
% to process those fields.
|
||||
%
|
||||
% Approach 2 is to remember which modules imported in the interface
|
||||
% are not used in the interface during a traversal that we already perform,
|
||||
% the module qualification pass (module_qual.m), which occurs *before*
|
||||
% we invoked equiv_type.m.
|
||||
%
|
||||
% We use approach 2, both because it requires a lot less code, and because
|
||||
% it imposes a much smaller memory overhead. The value returned by
|
||||
% module_info_get_unused_interface_imports is the value computed by
|
||||
% the module qualification pass.
|
||||
module_info_get_unused_interface_imports(ModuleInfo,
|
||||
UnusedInterfaceImports1),
|
||||
set_tree234.union(UnusedInterfaceImports0, UnusedInterfaceImports1,
|
||||
UnusedInterfaceImports),
|
||||
|
||||
trace [compile_time(flag("debug_unused_imports")),
|
||||
runtime(env("DEBUG_UNUSED_IMPORTS")), io(!IO)]
|
||||
@@ -192,7 +234,8 @@ get_avail_modules_anywhere_interface([ModuleEntry | ModuleEntries],
|
||||
:- type unused_avail_map ==
|
||||
one_or_more_map(unused_avail_msg_kind, unused_avail).
|
||||
|
||||
:- pred maybe_warn_about_avail(set(module_name)::in, set(module_name)::in,
|
||||
:- pred maybe_warn_about_avail(
|
||||
set_tree234(module_name)::in, set_tree234(module_name)::in,
|
||||
module_name::in, avail_module_entry::in,
|
||||
list(error_spec)::in, list(error_spec)::out,
|
||||
unused_avail_map::in, unused_avail_map::out) is det.
|
||||
@@ -217,7 +260,7 @@ maybe_warn_about_avail(UnusedAnywhereImports, UnusedInterfaceImports,
|
||||
HeadAvail = avail_module(Section, ImportOrUse, HeadCtxt),
|
||||
maybe_generate_redundant_avail_warnings(ModuleName, SortedAvails,
|
||||
[], !Specs),
|
||||
( if set.contains(UnusedAnywhereImports, ModuleName) then
|
||||
( if set_tree234.contains(UnusedAnywhereImports, ModuleName) then
|
||||
MsgKindA = unused_avail_msg_kind(aoi_anywhere, ImportOrUse),
|
||||
one_or_more_map.add(MsgKindA, unused_avail(HeadCtxt, ModuleName),
|
||||
!UnusedAvailMap),
|
||||
@@ -227,7 +270,7 @@ maybe_warn_about_avail(UnusedAnywhereImports, UnusedInterfaceImports,
|
||||
),
|
||||
( if
|
||||
Section = ms_interface,
|
||||
set.contains(UnusedInterfaceImports, ModuleName),
|
||||
set_tree234.contains(UnusedInterfaceImports, ModuleName),
|
||||
% Do not generate a report that a module is unused in the interface
|
||||
% if we have generated a report that it is unused *anywhere*.
|
||||
AnywhereWarning = no
|
||||
@@ -506,36 +549,36 @@ find_all_non_warn_modules(ProgressStream, ModuleInfo, !:UsedModules) :-
|
||||
"instances" - UsedModulesInstance,
|
||||
"builtin" - UsedModulesBuiltin
|
||||
],
|
||||
dump_used_modules_history(ProgressStream, set.init, set.init,
|
||||
UsedModulesHistory, !IO)
|
||||
dump_used_modules_history(ProgressStream,
|
||||
set_tree234.init, set_tree234.init, UsedModulesHistory, !IO)
|
||||
).
|
||||
|
||||
:- pred dump_used_modules_history(io.text_output_stream::in,
|
||||
set(module_name)::in, set(module_name)::in,
|
||||
set_tree234(module_name)::in, set_tree234(module_name)::in,
|
||||
assoc_list(string, used_modules)::in, io::di, io::uo) is det.
|
||||
|
||||
dump_used_modules_history(_, _, _, [], !IO).
|
||||
dump_used_modules_history(ProgressStream, !.IntUsed, !.ImpUsed,
|
||||
[Head | Tail], !IO) :-
|
||||
Head = HeadStr - used_modules(HeadInt, HeadImp),
|
||||
set.difference(HeadInt, !.IntUsed, NewHeadInt),
|
||||
set.difference(HeadImp, !.ImpUsed, NewHeadImp),
|
||||
set_tree234.difference(HeadInt, !.IntUsed, NewHeadInt),
|
||||
set_tree234.difference(HeadImp, !.ImpUsed, NewHeadImp),
|
||||
io.format(ProgressStream, "modules added at stage %s\n\n",
|
||||
[s(HeadStr)], !IO),
|
||||
( if set.is_empty(NewHeadInt) then
|
||||
( if set_tree234.is_empty(NewHeadInt) then
|
||||
true
|
||||
else
|
||||
io.write_string(ProgressStream, "interface:\n", !IO),
|
||||
output_module_name_set_nl(ProgressStream, NewHeadInt, !IO)
|
||||
),
|
||||
( if set.is_empty(NewHeadImp) then
|
||||
( if set_tree234.is_empty(NewHeadImp) then
|
||||
true
|
||||
else
|
||||
io.write_string(ProgressStream, "implementation:\n", !IO),
|
||||
output_module_name_set_nl(ProgressStream, NewHeadImp, !IO)
|
||||
),
|
||||
set.union(HeadInt, !IntUsed),
|
||||
set.union(HeadImp, !ImpUsed),
|
||||
set_tree234.union(HeadInt, !IntUsed),
|
||||
set_tree234.union(HeadImp, !ImpUsed),
|
||||
dump_used_modules_history(ProgressStream, !.IntUsed, !.ImpUsed, Tail, !IO).
|
||||
|
||||
%-----------------------------------------------------------------------------%
|
||||
@@ -759,8 +802,9 @@ const_struct_used_modules(ProgressStream, ConstNum - ConstStruct,
|
||||
FinalUsedModules = !.UsedModules,
|
||||
InitUsedModules = used_modules(_InitIntModules, InitImpModules),
|
||||
FinalUsedModules = used_modules(_FinalIntModules, FinalImpModules),
|
||||
set.difference(FinalImpModules, InitImpModules, NewImpModules),
|
||||
( if set.is_empty(NewImpModules) then
|
||||
set_tree234.difference(FinalImpModules, InitImpModules,
|
||||
NewImpModules),
|
||||
( if set_tree234.is_empty(NewImpModules) then
|
||||
true
|
||||
else
|
||||
ConstStructDoc = pretty_printer.format(ConstStruct),
|
||||
@@ -834,16 +878,18 @@ pred_info_used_modules(ProgressStream, PredId, PredInfo, !UsedModules) :-
|
||||
FinalUsedModules = !.UsedModules,
|
||||
InitUsedModules = used_modules(InitIntModules, InitImpModules),
|
||||
FinalUsedModules = used_modules(FinalIntModules, FinalImpModules),
|
||||
set.difference(FinalIntModules, InitIntModules, NewIntModules),
|
||||
set.difference(FinalImpModules, InitImpModules, NewImpModules),
|
||||
( if set.is_empty(NewIntModules) then
|
||||
set_tree234.difference(FinalIntModules, InitIntModules,
|
||||
NewIntModules),
|
||||
set_tree234.difference(FinalImpModules, InitImpModules,
|
||||
NewImpModules),
|
||||
( if set_tree234.is_empty(NewIntModules) then
|
||||
true
|
||||
else
|
||||
io.write_string(ProgressStream,
|
||||
"new interface modules:\n", !IO),
|
||||
output_module_name_set_nl(ProgressStream, NewIntModules, !IO)
|
||||
),
|
||||
( if set.is_empty(NewImpModules) then
|
||||
( if set_tree234.is_empty(NewImpModules) then
|
||||
true
|
||||
else
|
||||
io.write_string(ProgressStream,
|
||||
@@ -1255,11 +1301,11 @@ exported_to_visibility(Exported) = Visibility :-
|
||||
%-----------------------------------------------------------------------------%
|
||||
|
||||
:- pred output_module_name_set_nl(io.text_output_stream::in,
|
||||
set(module_name)::in, io::di, io::uo) is det.
|
||||
set_tree234(module_name)::in, io::di, io::uo) is det.
|
||||
|
||||
output_module_name_set_nl(Stream, ModuleNameSet, !IO) :-
|
||||
ModuleNameStrSet = set.map(sym_name_to_string, ModuleNameSet),
|
||||
set.to_sorted_list(ModuleNameStrSet, ModuleNameStrs),
|
||||
ModuleNameStrSet = set_tree234.map(sym_name_to_string, ModuleNameSet),
|
||||
set_tree234.to_sorted_list(ModuleNameStrSet, ModuleNameStrs),
|
||||
list.foldl(write_string_nl(Stream), ModuleNameStrs, !IO),
|
||||
io.nl(Stream, !IO).
|
||||
|
||||
|
||||
@@ -45,8 +45,6 @@
|
||||
|
||||
:- import_module libs.
|
||||
:- import_module libs.globals.
|
||||
:- import_module mdbcomp.
|
||||
:- import_module mdbcomp.sym_name.
|
||||
:- import_module parse_tree.d_file_deps.
|
||||
:- import_module parse_tree.deps_map.
|
||||
:- import_module parse_tree.error_spec.
|
||||
@@ -116,6 +114,8 @@
|
||||
:- import_module libs.file_util.
|
||||
:- import_module libs.mmakefiles.
|
||||
:- import_module libs.options.
|
||||
:- import_module mdbcomp.
|
||||
:- import_module mdbcomp.sym_name.
|
||||
:- import_module parse_tree.file_names.
|
||||
:- import_module parse_tree.make_module_file_names.
|
||||
:- import_module parse_tree.maybe_error.
|
||||
|
||||
Reference in New Issue
Block a user