[m-rev.] for review: Accept code depending on shadowed ancestor imports.

Peter Wang novalazy at gmail.com
Wed Aug 26 15:58:41 AEST 2026


In commit a5f5f7dbc7, two changes were made to module visibility rules.
The second of the changes was this:

  - If a module contains `:- import_module` or `:- use_module` declarations
    that import module `M`, visibility of M's exports within that module
    will be determined only by those declarations, not by import or use
    declarations in any ancestor module.

We can say that the declarations in the ancestor modules are
"shadowed" by the declarations in the current module.

To smoothen the transition, this commit allows the compiler to accept
code written prior to the rule change, but generate a warning if an
entity can only be resolved due to a shadowed ancestor import.
The warning can be disabled with the option
`--no-warn-old-submodule-visibility-rule'.

compiler/module_qual.id_set.m:
    Change the representation of whether an entity can be used or not,
    to support more complex situations such as when an entity:
    - is permitted WITH qualification due to a use_module declaration
      in the current module, but also,
    - is permitted WITHOUT qualification due to a shadowed import_module
      declaration in an ancestor module. Since the ancestor import
      declaration is shadowed, we also need to remember to
      generate a warning if that permission is actually used.

compiler/prog_parse_tree.m:
    Add a field to direct_int1 and direct_int3_spec to record if the
    interface file is also read due to a shadowed ancestor import
    declaration.

compiler/grab_modules.m:
    When grabbing .int or .int3 files, for any modules imported by
    shadowed ancestor import declarations, record that as a secondary
    reason for reading the module's interface file in the
    aug_make_int_unit or aug_compilation_unit structure.

compiler/module_qual.collect_mq_info.m:
    When collecting permissions for entities from .int or .int files,
    if the interface was also read due to a shadowed ancestor import,
    let that grant visibility to entities that would not be visible
    otherwise, with a warning attached to the permission.

    Conform to the change in permission representation.

compiler/module_qual.qual_errors.m:
    Make report_old_submodule_visibility_match optionally warn if a
    shadowed ancestor import declaration was used.

    Add "warning:" to the start of the warning message.

compiler/build_eqv_maps.m:
compiler/check_import_accessibility.m:
compiler/d_file_deps.m:
compiler/decide_type_repn.m:
compiler/equiv_type_parse_tree.m:
compiler/get_dependencies.m:
compiler/make_hlds_separate_items.m:
compiler/parse_tree_out.m:
    Conform to changes.

tests/invalid_submodules/bug584.err_exp:
tests/invalid_submodules/sub_visibility_*.*:
    Update expected test outputs.

NEWS.md:
    Announce change.

diff --git a/NEWS.md b/NEWS.md
index 731c2646c0..82037853e8 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -10,16 +10,17 @@ Changes that may break compatibility
     in the implementation section of a module will make the declarations
     in the interface section of `M` visible in the implementation sections
     of its submodules only. Previously, the declarations would also be also
-    visible in the submodules' interface sections. Code depending on the
-    old behaviour will be accepted for now with a warning message.
-    The warning can be disabled with the
-    `--no-warn-old-submodule-visibility-rule` option.
+    visible in the submodules' interface sections.
 
   - If a module contains `:- import_module` or `:- use_module` declarations
     that import module `M`, visibility of M's exports within that module
     will be determined only by those declarations, not by import or use
     declarations in any ancestor module.
 
+  Code depending on the old behaviours will be accepted for now with
+  a warning message. The warnings can be disabled with the
+  `--no-warn-old-submodule-visibility-rule` option.
+
 * The predicates `read_term/3`, `read_term/4`, `read_term_with_op_table/4`,
   `read_term_with_op_table/5` have been removed from the `term_io` module
   of the Mercury standard library.
diff --git a/compiler/build_eqv_maps.m b/compiler/build_eqv_maps.m
index 531736c84b..fa70d78fc6 100644
--- a/compiler/build_eqv_maps.m
+++ b/compiler/build_eqv_maps.m
@@ -122,7 +122,8 @@ build_eqv_maps_in_ancestor_int_spec(AncestorIntSpec,
 
 build_eqv_maps_in_direct_int1_spec(DirectIntSpec,
         !TypeEqvMap, !InstEqvMap) :-
-    DirectIntSpec = direct_int1(ParseTreeInt1, ReadWhy1),
+    DirectIntSpec = direct_int1(ParseTreeInt1, ReadWhy1,
+        _MaybeShadowedReadWhy1),
     build_eqv_maps_in_parse_tree_int1(ReadWhy1, ParseTreeInt1,
         !TypeEqvMap, !InstEqvMap).
 
diff --git a/compiler/check_import_accessibility.m b/compiler/check_import_accessibility.m
index 2e21216f5c..bf53197f07 100644
--- a/compiler/check_import_accessibility.m
+++ b/compiler/check_import_accessibility.m
@@ -290,7 +290,8 @@ record_includes_imports_uses_in_ancestor_int_spec(Ancestors,
 
 record_includes_imports_uses_in_direct_int1_spec(Ancestors,
         DirectSpec, !ReadModules, !InclMap) :-
-    DirectSpec = direct_int1(ParseTreeInt1, ReadWhyInt1),
+    DirectSpec = direct_int1(ParseTreeInt1, ReadWhyInt1,
+        _MaybeShadowedReadWhy1),
     record_includes_imports_uses_in_parse_tree_int1(Ancestors,
         ParseTreeInt1, ReadWhyInt1, !ReadModules, !InclMap).
 
@@ -312,7 +313,8 @@ record_includes_imports_uses_in_indirect_int2_spec(Ancestors,
 
 record_includes_imports_uses_in_direct_int3_spec(Ancestors,
         IndirectSpec, !ReadModules, !InclMap) :-
-    IndirectSpec = direct_int3(ParseTreeInt3, _ReadWhyInt3),
+    IndirectSpec = direct_int3(ParseTreeInt3, _ReadWhyInt3,
+        _MaybeShadowedReadWhy3),
     record_includes_imports_uses_in_parse_tree_int3(Ancestors,
         ParseTreeInt3, non_abstract_section, !ReadModules, !InclMap).
 
diff --git a/compiler/d_file_deps.m b/compiler/d_file_deps.m
index 976a5ea4f1..a6eaee4a2c 100644
--- a/compiler/d_file_deps.m
+++ b/compiler/d_file_deps.m
@@ -543,7 +543,8 @@ gather_fim_specs_in_ancestor_int_spec(AncestorIntSpec, !FIMSpecs) :-
     set(fim_spec)::in, set(fim_spec)::out) is det.
 
 gather_fim_specs_in_direct_int1_spec(DirectInt1Spec, !FIMSpecs) :-
-    DirectInt1Spec = direct_int1(ParseTreeInt1, _ReadWhy1),
+    DirectInt1Spec = direct_int1(ParseTreeInt1, _ReadWhy1,
+        _MaybeShadowedReadWhy1),
     gather_fim_specs_in_parse_tree_int1(ParseTreeInt1, !FIMSpecs).
 
 :- pred gather_fim_specs_in_indirect_int2_spec(indirect_int2_spec::in,
diff --git a/compiler/decide_type_repn.m b/compiler/decide_type_repn.m
index c5dff71016..23cb4b6924 100644
--- a/compiler/decide_type_repn.m
+++ b/compiler/decide_type_repn.m
@@ -664,7 +664,8 @@ item_type_repn_info_eqv_to_eqv_type_body(ItemTypeRepnInfoEqv, EqvBody) :-
 
 record_type_repns_in_direct_int3_spec(DirectInt3Spec,
         !EqvRepnMap, !SubtypeMap, !SimpleDuMap, !WordAlignedTypeCtorsC) :-
-    DirectInt3Spec = direct_int3(ParseTreeInt3, _ReadWhy3),
+    DirectInt3Spec = direct_int3(ParseTreeInt3, _ReadWhy3,
+        _MaybeShadowedReadWhy3),
     record_type_repns_in_parse_tree_int3(ParseTreeInt3,
         !EqvRepnMap, !SubtypeMap, !SimpleDuMap, !WordAlignedTypeCtorsC).
 
diff --git a/compiler/equiv_type_parse_tree.m b/compiler/equiv_type_parse_tree.m
index 072f28c3a4..180c97bd5f 100644
--- a/compiler/equiv_type_parse_tree.m
+++ b/compiler/equiv_type_parse_tree.m
@@ -325,10 +325,12 @@ replace_in_ancestor_int_spec(Params, AncestorIntSpec0, AncestorIntSpec,
 
 replace_in_direct_int1_spec(Params, DirectIntSpec0, DirectIntSpec,
         !RecompInfo, !UsedModules, !Specs) :-
-    DirectIntSpec0 = direct_int1(OrigParseTree1, ReadWhy1),
+    DirectIntSpec0 = direct_int1(OrigParseTree1, ReadWhy1,
+        MaybeShadowedReadWhy1),
     replace_in_parse_tree_int1(Params, OrigParseTree1, ParseTree1,
         !RecompInfo, !UsedModules, !Specs),
-    DirectIntSpec = direct_int1(ParseTree1, ReadWhy1).
+    DirectIntSpec = direct_int1(ParseTree1, ReadWhy1,
+        MaybeShadowedReadWhy1).
 
 :- pred replace_in_indirect_int2_spec(equiv_params::in,
     indirect_int2_spec::in, indirect_int2_spec::out,
diff --git a/compiler/get_dependencies.m b/compiler/get_dependencies.m
index cc7da52ace..5fcc9935c3 100644
--- a/compiler/get_dependencies.m
+++ b/compiler/get_dependencies.m
@@ -404,7 +404,7 @@ acc_implicit_avail_needs_in_ancestor_int_spec(AncestorIntSpec,
 
 acc_implicit_avail_needs_in_direct_int1_spec(DirectInt1Spec,
         !ImplicitAvailNeeds) :-
-    DirectInt1Spec = direct_int1(ParseTreeInt1, _),
+    DirectInt1Spec = direct_int1(ParseTreeInt1, _, _),
     acc_implicit_avail_needs_in_parse_tree_int1(ParseTreeInt1,
         !ImplicitAvailNeeds).
 
diff --git a/compiler/grab_modules.m b/compiler/grab_modules.m
index a391b9868c..12756763a7 100644
--- a/compiler/grab_modules.m
+++ b/compiler/grab_modules.m
@@ -239,21 +239,28 @@ grab_unqual_imported_modules_make_int(ProgressStream, Globals,
             set.init, AncestorIntUses0, set.init, AncestorImpUses0,
             !HaveParseTreeMaps, !Baggage, !AugMakeIntUnit, !IO),
 
-        % Any modules that are explicitly imported or used by declarations in
-        % the current module have visibility determined by those declarations,
-        % instead of inheriting their visibility from ancestor modules.
+        % Commit a5f5f7dbc7 introduced a new rule:
+        %
+        % - If a module contains :- import_module or :- use_module
+        %   declarations that import module M, visibility of M's exports
+        %   within that module will be determined only by those declarations,
+        %   not by import or use declarations in any ancestor module.
+        %
+        % During a transition period, we will accept code written prior to the
+        % rule change, but generate a warning if an entity can only be resolved
+        % using a "shadowed" ancestor import.
         import_and_or_use_map_to_item_avails(do_not_include_implicit,
             ImportAndOrUseMap0, ExplicitIntAvails, ExplicitImpAvails),
         avail_module_names(ExplicitIntAvails ++ ExplicitImpAvails,
             ExplicitAvailModules),
-        set.difference(AncestorIntImports0, ExplicitAvailModules,
-            AncestorIntImports),
-        set.difference(AncestorImpImports0, ExplicitAvailModules,
-            AncestorImpImports),
-        set.difference(AncestorIntUses0, ExplicitAvailModules,
-            AncestorIntUses),
-        set.difference(AncestorImpUses0, ExplicitAvailModules,
-            AncestorImpUses),
+        set.divide_by_set(ExplicitAvailModules, AncestorIntImports0,
+            ShadowedAncestorIntImports, AncestorIntImports),
+        set.divide_by_set(ExplicitAvailModules, AncestorImpImports0,
+            ShadowedAncestorImpImports, AncestorImpImports),
+        set.divide_by_set(ExplicitAvailModules, AncestorIntUses0,
+            ShadowedAncestorIntUses, AncestorIntUses),
+        set.divide_by_set(ExplicitAvailModules, AncestorImpUses0,
+            ShadowedAncestorImpUses, AncestorImpUses),
 
         % Get the .int3 files of the modules imported using `import_module'.
         set.init(!:IntIndirectImported),
@@ -309,6 +316,26 @@ grab_unqual_imported_modules_make_int(ProgressStream, Globals,
             !IntIndirectImported, !HaveParseTreeMaps,
             !Baggage, !AugMakeIntUnit, !IO),
 
+        % For any modules imported both by the current module and an ancestor
+        % modules, add the shadowed ancestor import as a secondary reason
+        % why the .int3 file of the module is read.
+        amend_shadow_imported_module_int3_files(
+            rwi3_direct_ancestor_int_import,
+            set.to_sorted_list(ShadowedAncestorIntImports),
+            !AugMakeIntUnit),
+        amend_shadow_imported_module_int3_files(
+            rwi3_direct_ancestor_imp_import,
+            set.to_sorted_list(ShadowedAncestorImpImports),
+            !AugMakeIntUnit),
+        amend_shadow_imported_module_int3_files(
+            rwi3_direct_ancestor_int_use,
+            set.to_sorted_list(ShadowedAncestorIntUses),
+            !AugMakeIntUnit),
+        amend_shadow_imported_module_int3_files(
+            rwi3_direct_ancestor_imp_use,
+            set.to_sorted_list(ShadowedAncestorImpUses),
+            !AugMakeIntUnit),
+
         % Get the .int3 files of the modules imported in .int3 files.
         grab_module_int3_files_transitively(ProgressStream, Globals,
             "unqual_int_indirect_imported", rwi3_indirect_int_use,
@@ -511,21 +538,20 @@ grab_qual_imported_modules_augment(ProgressStream, Globals, MaybeTimestamp,
             set.init, AncestorImpImports0, set.init, AncestorImpUses0,
             !HaveParseTreeMaps, !Baggage, !AugCompUnit, !IO),
 
-        % Any modules that are explicitly imported or used by declarations in
-        % the current module have visibility determined by those declarations,
-        % instead of inheriting their visibility from ancestor modules.
+        % See the comment in grab_unqual_imported_modules_make_int
+        % regarding shadowed ancestor imports.
         import_and_or_use_map_to_item_avails(do_not_include_implicit,
             ImportUseMap, ExplicitIntAvails, ExplicitImpAvails),
         avail_module_names(ExplicitIntAvails ++ ExplicitImpAvails,
             ExplicitAvailModules),
-        set.difference(AncestorIntImports0, ExplicitAvailModules,
-            AncestorIntImports),
-        set.difference(AncestorImpImports0, ExplicitAvailModules,
-            AncestorImpImports),
-        set.difference(AncestorIntUses0, ExplicitAvailModules,
-            AncestorIntUses),
-        set.difference(AncestorImpUses0, ExplicitAvailModules,
-            AncestorImpUses),
+        set.divide_by_set(ExplicitAvailModules, AncestorIntImports0,
+            ShadowedAncestorIntImports, AncestorIntImports),
+        set.divide_by_set(ExplicitAvailModules, AncestorImpImports0,
+            ShadowedAncestorImpImports, AncestorImpImports),
+        set.divide_by_set(ExplicitAvailModules, AncestorIntUses0,
+            ShadowedAncestorIntUses, AncestorIntUses),
+        set.divide_by_set(ExplicitAvailModules, AncestorImpUses0,
+            ShadowedAncestorImpUses, AncestorImpUses),
 
         % Get the .int files of the modules imported using `import_module'.
         set.init(!:IntIndirectImported),
@@ -583,6 +609,26 @@ grab_qual_imported_modules_augment(ProgressStream, Globals, MaybeTimestamp,
             !IntIndirectImported, !IntImpIndirectImported,
             !HaveParseTreeMaps, !Baggage, !AugCompUnit, !IO),
 
+        % For any modules imported both by the current module and an ancestor
+        % modules, add the shadowed ancestor import as a secondary reason
+        % why the .int file of the module is read.
+        amend_shadow_imported_module_int1_files(
+            rwi1_ancestor_int_import,
+            set.to_sorted_list(ShadowedAncestorIntImports),
+            !AugCompUnit),
+        amend_shadow_imported_module_int1_files(
+            rwi1_ancestor_imp_import,
+            set.to_sorted_list(ShadowedAncestorImpImports),
+            !AugCompUnit),
+        amend_shadow_imported_module_int1_files(
+            rwi1_ancestor_int_use,
+            set.to_sorted_list(ShadowedAncestorIntUses),
+            !AugCompUnit),
+        amend_shadow_imported_module_int1_files(
+            rwi1_ancestor_imp_use,
+            set.to_sorted_list(ShadowedAncestorImpUses),
+            !AugCompUnit),
+
         % Get the .int2 files of the modules imported in .int files.
         grab_module_int2_files_transitively(ProgressStream, Globals,
             "int_indirect_imported", rwi2_int_use,
@@ -1200,7 +1246,7 @@ grab_module_int1_file(ProgressStream, Globals, ReadWhy1, ModuleName,
                 ReadWhy1 = rwi1_int_use_imp_import,
                 RecompAvail = recomp_avail_int_use_imp_import
             ),
-            DirectIntSpec = direct_int1(ParseTreeInt1, ReadWhy1),
+            DirectIntSpec = direct_int1(ParseTreeInt1, ReadWhy1, no),
             aug_compilation_unit_add_direct_int1_spec(DirectIntSpec,
                 !AugCompUnit),
             module_baggage_add_errors(Errors, !Baggage)
@@ -1321,7 +1367,7 @@ grab_module_int3_file(ProgressStream, Globals, ReadWhy3, ModuleName,
                 ReadWhy3 = rwi3_direct_int_use_imp_import,
                 RecompAvail = recomp_avail_int_use_imp_import
             ),
-            DirectIntSpec = direct_int3(ParseTreeInt3, ReadWhy3),
+            DirectIntSpec = direct_int3(ParseTreeInt3, ReadWhy3, no),
             aug_make_int_unit_add_direct_int3_spec(DirectIntSpec,
                 !AugMakeIntUnit)
         ;
@@ -1348,6 +1394,32 @@ grab_module_int3_file(ProgressStream, Globals, ReadWhy3, ModuleName,
 
 %---------------------------------------------------------------------------%
 
+:- pred amend_shadow_imported_module_int1_files(shadowed_read_why_int1::in,
+    list(module_name)::in,
+    aug_compilation_unit::in, aug_compilation_unit::out) is det.
+
+amend_shadow_imported_module_int1_files(_ReadWhy1, [], !AugCompUnit).
+amend_shadow_imported_module_int1_files(ReadWhy1, [ModuleName | ModuleNames],
+        !AugCompUnit) :-
+    aug_compilation_unit_amend_direct_int1_shadowed_reason(ModuleName,
+        ReadWhy1, !AugCompUnit),
+    amend_shadow_imported_module_int1_files(ReadWhy1, ModuleNames,
+        !AugCompUnit).
+
+:- pred amend_shadow_imported_module_int3_files(shadowed_read_why_int3::in,
+    list(module_name)::in, aug_make_int_unit::in, aug_make_int_unit::out)
+    is det.
+
+amend_shadow_imported_module_int3_files(_ReadWhy3, [], !AugMakeIntUnit).
+amend_shadow_imported_module_int3_files(ReadWhy3, [ModuleName | ModuleNames],
+        !AugMakeIntUnit) :-
+    aug_make_int_unit_amend_direct_int3_shadowed_reason(ModuleName, ReadWhy3,
+        !AugMakeIntUnit),
+    amend_shadow_imported_module_int3_files(ReadWhy3, ModuleNames,
+        !AugMakeIntUnit).
+
+%---------------------------------------------------------------------------%
+
 :- type read_decision
     --->    decided_not_to_read
     ;       decided_to_read.
@@ -1698,6 +1770,9 @@ report_any_errors_in_read_opt_file(ModuleErrors, !BlockErrSpecs, !WarnSpecs) :-
     aug_compilation_unit::in, aug_compilation_unit::out) is det.
 :- pred aug_compilation_unit_add_direct_int1_spec(direct_int1_spec::in,
     aug_compilation_unit::in, aug_compilation_unit::out) is det.
+:- pred aug_compilation_unit_amend_direct_int1_shadowed_reason(module_name::in,
+    shadowed_read_why_int1::in,
+    aug_compilation_unit::in, aug_compilation_unit::out) is det.
 :- pred aug_compilation_unit_add_indirect_int2_spec(indirect_int2_spec::in,
     aug_compilation_unit::in, aug_compilation_unit::out) is det.
 :- pred aug_compilation_unit_add_plain_opt(parse_tree_plain_opt::in,
@@ -1723,10 +1798,25 @@ aug_compilation_unit_add_ancestor_int_spec(X, !AugCompUnit) :-
 
 aug_compilation_unit_add_direct_int1_spec(X, !AugCompUnit) :-
     Map0 = !.AugCompUnit ^ acu_direct_int1s,
-    X = direct_int1(PT1, _), MN = PT1 ^ pti1_module_name,
+    X = direct_int1(PT1, _, _), MN = PT1 ^ pti1_module_name,
     map.det_insert(MN, X, Map0, Map),
     !AugCompUnit ^ acu_direct_int1s := Map.
 
+aug_compilation_unit_amend_direct_int1_shadowed_reason(MN, ShadowedReadWhy1,
+        !AugCompUnit) :-
+    Map0 = !.AugCompUnit ^ acu_direct_int1s,
+    map.lookup(Map0, MN, X0),
+    X0 = direct_int1(PT, OldReadWhy1, MaybeOldShadowedReadWhy1),
+    (
+        MaybeOldShadowedReadWhy1 = no,
+        X = direct_int1(PT, OldReadWhy1, yes(ShadowedReadWhy1)),
+        map.det_update(MN, X, Map0, Map)
+    ;
+        MaybeOldShadowedReadWhy1 = yes(_),
+        Map = Map0
+    ),
+    !AugCompUnit ^ acu_direct_int1s := Map.
+
 aug_compilation_unit_add_indirect_int2_spec(X, !AugCompUnit) :-
     Map0 = !.AugCompUnit ^ acu_indirect_int2s,
     X = indirect_int2(PT2, _), MN = PT2 ^ pti2_module_name,
@@ -1792,6 +1882,9 @@ init_aug_make_int_unit(ParseTreeModuleSrc, AugMakeIntUnit) :-
     aug_make_int_unit::in, aug_make_int_unit::out) is det.
 :- pred aug_make_int_unit_add_direct_int3_spec(direct_int3_spec::in,
     aug_make_int_unit::in, aug_make_int_unit::out) is det.
+:- pred aug_make_int_unit_amend_direct_int3_shadowed_reason(module_name::in,
+    shadowed_read_why_int3::in, aug_make_int_unit::in, aug_make_int_unit::out)
+    is det.
 :- pred aug_make_int_unit_add_indirect_int3_spec(indirect_int3_spec::in,
     aug_make_int_unit::in, aug_make_int_unit::out) is det.
 :- pred aug_make_int_unit_maybe_add_module_version_numbers(
@@ -1808,10 +1901,25 @@ aug_make_int_unit_add_ancestor_int(PT0, !AugMakeIntUnit) :-
 
 aug_make_int_unit_add_direct_int3_spec(X, !AugMakeIntUnit) :-
     Map0 = !.AugMakeIntUnit ^ amiu_direct_int3s,
-    X = direct_int3(PT3, _), MN = PT3 ^ pti3_module_name,
+    X = direct_int3(PT3, _, _), MN = PT3 ^ pti3_module_name,
     map.det_insert(MN, X, Map0, Map),
     !AugMakeIntUnit ^ amiu_direct_int3s := Map.
 
+aug_make_int_unit_amend_direct_int3_shadowed_reason(MN, ShadowedReadWhy3,
+        !AugMakeIntUnit) :-
+    Map0 = !.AugMakeIntUnit ^ amiu_direct_int3s,
+    map.lookup(Map0, MN, X0),
+    X0 = direct_int3(PT, OldReadWhy3, MaybeOldShadowedReadWhy3),
+    (
+        MaybeOldShadowedReadWhy3 = no,
+        X = direct_int3(PT, OldReadWhy3, yes(ShadowedReadWhy3)),
+        map.det_update(MN, X, Map0, Map)
+    ;
+        MaybeOldShadowedReadWhy3 = yes(_),
+        Map = Map0
+    ),
+    !AugMakeIntUnit ^ amiu_direct_int3s := Map.
+
 aug_make_int_unit_add_indirect_int3_spec(X, !AugMakeIntUnit) :-
     Map0 = !.AugMakeIntUnit ^ amiu_indirect_int3s,
     X = indirect_int3(PT3, _), MN = PT3 ^ pti3_module_name,
diff --git a/compiler/make_hlds_separate_items.m b/compiler/make_hlds_separate_items.m
index 43c026ed9c..381ca678f1 100644
--- a/compiler/make_hlds_separate_items.m
+++ b/compiler/make_hlds_separate_items.m
@@ -369,7 +369,8 @@ acc_ancestor_int_spec(AncestorIntSpec, !Acc) :-
     item_accumulator::in, item_accumulator::out) is det.
 
 acc_direct_int1_spec(DirectInt1Spec, !Acc) :-
-    DirectInt1Spec = direct_int1(ParseTreeInt1, ReadWhy1),
+    DirectInt1Spec = direct_int1(ParseTreeInt1, ReadWhy1,
+        _MaybeShadowedReadWhy1),
     acc_parse_tree_int1(ParseTreeInt1, ReadWhy1, !Acc).
 
 :- pred acc_indirect_int2_spec(indirect_int2_spec::in,
diff --git a/compiler/module_qual.collect_mq_info.m b/compiler/module_qual.collect_mq_info.m
index 1f434ace4a..1b891583bf 100644
--- a/compiler/module_qual.collect_mq_info.m
+++ b/compiler/module_qual.collect_mq_info.m
@@ -20,7 +20,11 @@
 
 :- type int3_role
     --->    int3_as_src
-    ;       int3_as_direct_int(read_why_int3).
+    ;       int3_as_direct_int(read_why_int3, maybe_shadowed_import).
+
+:- type maybe_shadowed_import
+    --->    not_shadowed_import
+    ;       is_shadowed_import.
 
     % Pass over the given parse tree collecting all defined module, type,
     % inst, mode and class ids, together with their permissions.
@@ -66,9 +70,9 @@
 %---------------------------------------------------------------------------%
 
 collect_mq_info_in_parse_tree_module_src(ParseTreeModuleSrc, !Info) :-
-    IntPermInInt = may_use_in_int(may_be_unqualified),
-    ImpPermInInt = may_not_use_in_int,
-    PermInImp = may_use_in_imp(may_be_unqualified),
+    IntPermInInt = perm_in_int(permitted, permitted),
+    ImpPermInInt = perm_in_int(not_permitted, not_permitted),
+    PermInImp = perm_in_imp(permitted, permitted),
     IntPermissions = module_permissions(IntPermInInt, PermInImp),
     ImpPermissions = module_permissions(ImpPermInInt, PermInImp),
 
@@ -203,13 +207,31 @@ collect_mq_info_in_ancestor_int_spec(AncestorIntSpec, !Info) :-
     collect_mq_info_in_parse_tree_int0(ReadWhy0, ParseTreeInt0, !Info).
 
 collect_mq_info_in_direct_int1_spec(DirectInt1Spec, !Info) :-
-    DirectInt1Spec = direct_int1(ParseTreeInt1, ReadWhy1),
-    collect_mq_info_in_parse_tree_int1(ReadWhy1, ParseTreeInt1, !Info).
+    DirectInt1Spec = direct_int1(ParseTreeInt1, ReadWhy1,
+        MaybeShadowedReadWhy1),
+    collect_mq_info_in_parse_tree_int1(ReadWhy1, not_shadowed_import,
+        ParseTreeInt1, !Info),
+    (
+        MaybeShadowedReadWhy1 = yes(ShadowedReadWhy1),
+        collect_mq_info_in_parse_tree_int1(coerce(ShadowedReadWhy1),
+            is_shadowed_import, ParseTreeInt1, !Info)
+    ;
+        MaybeShadowedReadWhy1 = no
+    ).
 
 collect_mq_info_in_direct_int3_spec(DirectInt3Spec, !Info) :-
-    DirectInt3Spec = direct_int3(ParseTreeInt3, ReadWhy3),
-    Role = int3_as_direct_int(ReadWhy3),
-    collect_mq_info_in_parse_tree_int3(Role, ParseTreeInt3, !Info).
+    DirectInt3Spec = direct_int3(ParseTreeInt3, ReadWhy3,
+        MaybeShadowedReadWhy3),
+    RoleA = int3_as_direct_int(ReadWhy3, not_shadowed_import),
+    collect_mq_info_in_parse_tree_int3(RoleA, ParseTreeInt3, !Info),
+    (
+        MaybeShadowedReadWhy3 = yes(ShadowedReadWhy3),
+        RoleB = int3_as_direct_int(coerce(ShadowedReadWhy3),
+            is_shadowed_import),
+        collect_mq_info_in_parse_tree_int3(RoleB, ParseTreeInt3, !Info)
+    ;
+        MaybeShadowedReadWhy3 = no
+    ).
 
 %---------------------------------------------------------------------------%
 
@@ -221,10 +243,10 @@ collect_mq_info_in_parse_tree_int0(ReadWhy0, ParseTreeInt0, !Info) :-
         % the ancestor imported that mq_id in its INTERFACE or not.
         % Since we don't know where that import was, this is a
         % conservative approximation.
-        IntPermInInt = may_use_in_int(may_be_unqualified),
-        IntPermInImp = may_use_in_imp(may_be_unqualified),
-        ImpPermInInt = may_use_in_int(may_be_unqualified),
-        ImpPermInImp = may_use_in_imp(may_be_unqualified),
+        IntPermInInt = perm_in_int(permitted, permitted),
+        IntPermInImp = perm_in_imp(permitted, permitted),
+        ImpPermInInt = perm_in_int(permitted, permitted),
+        ImpPermInImp = perm_in_imp(permitted, permitted),
 
         IntPermissions = module_permissions(IntPermInInt, IntPermInImp),
         ImpPermissions = module_permissions(ImpPermInInt, ImpPermInImp)
@@ -288,50 +310,53 @@ collect_mq_info_in_parse_tree_int0(ReadWhy0, ParseTreeInt0, !Info) :-
 %---------------------------------------------------------------------------%
 
 :- pred collect_mq_info_in_parse_tree_int1(read_why_int1::in,
-    parse_tree_int1::in, mq_info::in, mq_info::out) is det.
+    maybe_shadowed_import::in, parse_tree_int1::in, mq_info::in, mq_info::out)
+    is det.
 
-collect_mq_info_in_parse_tree_int1(ReadWhy1, ParseTreeInt1, !Info) :-
+collect_mq_info_in_parse_tree_int1(ReadWhy1, IsShadowed, ParseTreeInt1,
+        !Info) :-
     (
         ( ReadWhy1 = rwi1_ancestor_int_import
         ; ReadWhy1 = rwi1_int_import
         ),
-        IntPermInInt = may_use_in_int(may_be_unqualified),
-        IntPermInImp = may_use_in_imp(may_be_unqualified)
+        IntPermInInt0 = perm_in_int(permitted, permitted),
+        IntPermInImp0 = perm_in_imp(permitted, permitted)
     ;
         % Under the new submodule visibility rule,
         % ReadWhy1 = rwi1_ancestor_imp_import should be handled here.
         ReadWhy1 = rwi1_imp_import,
-        IntPermInInt = may_not_use_in_int,
-        IntPermInImp = may_use_in_imp(may_be_unqualified)
+        IntPermInInt0 = perm_in_int(not_permitted, not_permitted),
+        IntPermInImp0 = perm_in_imp(permitted, permitted)
     ;
         ( ReadWhy1 = rwi1_ancestor_int_use
         ; ReadWhy1 = rwi1_int_use
         ),
-        IntPermInInt = may_use_in_int(must_be_qualified),
-        IntPermInImp = may_use_in_imp(must_be_qualified)
+        IntPermInInt0 = perm_in_int(permitted, not_permitted),
+        IntPermInImp0 = perm_in_imp(permitted, not_permitted)
     ;
         % Under the new submodule visibility rule,
         % ReadWhy1 = rwi1_ancestor_imp_use should be handled here.
         ReadWhy1 = rwi1_imp_use,
-        IntPermInInt = may_not_use_in_int,
-        IntPermInImp = may_use_in_imp(must_be_qualified)
+        IntPermInInt0 = perm_in_int(not_permitted, not_permitted),
+        IntPermInImp0 = perm_in_imp(permitted, not_permitted)
     ;
         % Old submodule visibility rule: during the transition,
         % allow entities imported in an ancestor implementation section
         % to be visible in the interface section, but generate a warning
         % if that is how an entity is used.
         ReadWhy1 = rwi1_ancestor_imp_import,
-        IntPermInInt = may_use_in_int_warn(may_be_unqualified),
-        IntPermInImp = may_use_in_imp(may_be_unqualified)
+        IntPermInInt0 = perm_in_int(permitted_with_warning,
+            permitted_with_warning),
+        IntPermInImp0 = perm_in_imp(permitted, permitted)
     ;
         % Old submodule visibility rule: as above.
         ReadWhy1 = rwi1_ancestor_imp_use,
-        IntPermInInt = may_use_in_int_warn(must_be_qualified),
-        IntPermInImp = may_use_in_imp(must_be_qualified)
+        IntPermInInt0 = perm_in_int(permitted_with_warning, not_permitted),
+        IntPermInImp0 = perm_in_imp(permitted, not_permitted)
     ;
         ReadWhy1 = rwi1_int_use_imp_import,
-        IntPermInInt = may_use_in_int(must_be_qualified),
-        IntPermInImp = may_use_in_imp(may_be_unqualified)
+        IntPermInInt0 = perm_in_int(permitted, not_permitted),
+        IntPermInImp0 = perm_in_imp(permitted, permitted)
     ;
         ReadWhy1 = rwi1_opt,
         % Since we do not collect module qual info for int_for_opt_specs,
@@ -343,6 +368,15 @@ collect_mq_info_in_parse_tree_int1(ReadWhy1, ParseTreeInt1, !Info) :-
         % we should never encounter this value of ReadWhy1.
         unexpected($pred, "rwi1_opt")
     ),
+    (
+        IsShadowed = not_shadowed_import,
+        IntPermInInt = IntPermInInt0,
+        IntPermInImp = IntPermInImp0
+    ;
+        IsShadowed = is_shadowed_import,
+        IntPermInInt = add_warn_shadowed_import_int(IntPermInInt0),
+        IntPermInImp = add_warn_shadowed_import_imp(IntPermInImp0)
+    ),
     IntPermissions = module_permissions(IntPermInInt, IntPermInImp),
     % The implementation section of a .int1 file is abstract imported,
     % which means we have no permission for any item defined there.
@@ -625,55 +659,65 @@ collect_mq_info_in_int_mode_defn(IntPermissions, ModeCtor, CheckedDefn,
 collect_mq_info_in_parse_tree_int3(Role, ParseTreeInt3, !Info) :-
     (
         Role = int3_as_src,
-        PermInInt = may_use_in_int(may_be_unqualified),
-        PermInImp = may_use_in_imp(may_be_unqualified)
+        PermInInt = perm_in_int(permitted, permitted),
+        PermInImp = perm_in_imp(permitted, permitted)
     ;
-        Role = int3_as_direct_int(ReadWhy3),
+        Role = int3_as_direct_int(ReadWhy3, IsShadowed),
         (
             ( ReadWhy3 = rwi3_direct_ancestor_int_import
             ; ReadWhy3 = rwi3_direct_int_import
             ),
-            PermInInt = may_use_in_int(may_be_unqualified),
-            PermInImp = may_use_in_imp(may_be_unqualified)
+            PermInInt0 = perm_in_int(permitted, permitted),
+            PermInImp0 = perm_in_imp(permitted, permitted)
         ;
             ( ReadWhy3 = rwi3_direct_ancestor_int_use
             ; ReadWhy3 = rwi3_direct_int_use
             ; ReadWhy3 = rwi3_indirect_int_use
             ),
-            PermInInt = may_use_in_int(must_be_qualified),
-            PermInImp = may_use_in_imp(must_be_qualified)
+            PermInInt0 = perm_in_int(permitted, not_permitted),
+            PermInImp0 = perm_in_imp(permitted, not_permitted)
         ;
             % Under the new submodule visibility rule,
             % ReadWhy3 = rwi3_direct_ancestor_imp_import should be handled
             % here.
             ReadWhy3 = rwi3_direct_imp_import,
-            PermInInt = may_not_use_in_int,
-            PermInImp = may_use_in_imp(may_be_unqualified)
+            PermInInt0 = perm_in_int(not_permitted, not_permitted),
+            PermInImp0 = perm_in_imp(permitted, permitted)
         ;
             % Old submodule visibility rule: during the transition,
             % allow entities imported in an ancestor implementation section
             % to be visible in the interface section, but generate a warning
             % if that is how an entity is used.
             ReadWhy3 = rwi3_direct_ancestor_imp_import,
-            PermInInt = may_use_in_int_warn(may_be_unqualified),
-            PermInImp = may_use_in_imp(may_be_unqualified)
+            PermInInt0 = perm_in_int(
+                permitted_with_warning, permitted_with_warning),
+            PermInImp0 = perm_in_imp(permitted, permitted)
         ;
             % Under the new submodule visibility rule,
             % ReadWhy3 = rwi3_direct_ancestor_imp_use should be handled here.
             ( ReadWhy3 = rwi3_direct_imp_use
             ; ReadWhy3 = rwi3_indirect_imp_use
             ),
-            PermInInt = may_not_use_in_int,
-            PermInImp = may_use_in_imp(must_be_qualified)
+            PermInInt0 = perm_in_int(not_permitted, not_permitted),
+            PermInImp0 = perm_in_imp(permitted, not_permitted)
         ;
             % Old submodule visibility rule: as above.
             ReadWhy3 = rwi3_direct_ancestor_imp_use,
-            PermInInt = may_use_in_int_warn(must_be_qualified),
-            PermInImp = may_use_in_imp(must_be_qualified)
+            PermInInt0 = perm_in_int(permitted_with_warning, not_permitted),
+            PermInImp0 = perm_in_imp(permitted, not_permitted)
         ;
             ReadWhy3 = rwi3_direct_int_use_imp_import,
-            PermInInt = may_use_in_int(must_be_qualified),
-            PermInImp = may_use_in_imp(may_be_unqualified)
+            PermInInt0 = perm_in_int(permitted, not_permitted),
+            PermInImp0 = perm_in_imp(permitted, permitted)
+        ),
+        (
+            IsShadowed = not_shadowed_import,
+            PermInInt = PermInInt0,
+            PermInImp = PermInImp0
+        ;
+            IsShadowed = is_shadowed_import,
+            PermInInt = add_warn_shadowed_import_int(PermInInt0),
+            PermInImp = add_warn_shadowed_import_imp(PermInImp0)
         )
     ),
     Permissions = module_permissions(PermInInt, PermInImp),
@@ -714,6 +758,40 @@ collect_mq_info_in_parse_tree_int3(Role, ParseTreeInt3, !Info) :-
 
 %---------------------------------------------------------------------------%
 
+:- func add_warn_shadowed_import_int(perm_in_int) = perm_in_int.
+
+add_warn_shadowed_import_int(PermInInt0) = PermInInt :-
+    PermInInt0 = perm_in_int(PermQual0, PermUnqual0),
+    PermInInt = perm_in_int(
+        add_warn_shadowed_import_perm(PermQual0),
+        add_warn_shadowed_import_perm(PermUnqual0)
+    ).
+
+:- func add_warn_shadowed_import_imp(perm_in_imp) = perm_in_imp.
+
+add_warn_shadowed_import_imp(PermInImp0) = PermInImp :-
+    PermInImp0 = perm_in_imp(PermQual0, PermUnqual0),
+    PermInImp = perm_in_imp(
+        add_warn_shadowed_import_perm(PermQual0),
+        add_warn_shadowed_import_perm(PermUnqual0)
+    ).
+
+:- func add_warn_shadowed_import_perm(permitted_or_not) = permitted_or_not.
+
+add_warn_shadowed_import_perm(Permission0) = Permission :-
+    (
+        Permission0 = not_permitted,
+        Permission = not_permitted
+    ;
+        ( Permission0 = permitted
+        ; Permission0 = permitted_with_warning
+        ; Permission0 = permitted_with_warning_shadowed
+        ),
+        Permission = permitted_with_warning_shadowed
+    ).
+
+%---------------------------------------------------------------------------%
+
 :- func type_ctor_to_mq_id(type_ctor) = mq_id.
 
 type_ctor_to_mq_id(TypeCtor) = Id :-
diff --git a/compiler/module_qual.id_set.m b/compiler/module_qual.id_set.m
index 623ebc66fa..ab2375d847 100644
--- a/compiler/module_qual.id_set.m
+++ b/compiler/module_qual.id_set.m
@@ -17,7 +17,6 @@
 :- import_module mdbcomp.sym_name.
 :- import_module parse_tree.module_qual.mq_info.
 :- import_module parse_tree.module_qual.qual_errors.
-:- import_module parse_tree.prog_data.
 
 :- import_module list.
 
@@ -66,12 +65,28 @@
             ).
 
 :- type perm_in_int
-    --->    may_not_use_in_int
-    ;       may_use_in_int(need_qualifier)
-    ;       may_use_in_int_warn(need_qualifier).
+    --->    perm_in_int(
+                perm_qual           :: permitted_or_not,
+                perm_unqual         :: permitted_or_not
+            ).
 
 :- type perm_in_imp
-    --->    may_use_in_imp(need_qualifier).
+    --->    perm_in_imp(
+                perm_in_imp_qual    :: permitted_or_not,
+                perm_in_imp_unqual  :: permitted_or_not
+            ).
+
+:- type permitted_or_not
+    --->    not_permitted
+    ;       permitted
+    ;       permitted_with_warning
+            % Permitted under deprecated visibility rule, where the interface
+            % section of a submodule inherits visibility from imports made in
+            % the implementation section of an ancestor module.
+    ;       permitted_with_warning_shadowed.
+            % Permitted under the deprecated visibility rule above, but also
+            % depends on an ancestor import declaration that would be shadowed
+            % by an import declaration in the current module.
 
     % When we process types, typeclasses, insts or modes, we need to know
     % whether they occur in the interface of the current module. This is
@@ -146,6 +161,7 @@
 :- implementation.
 
 :- import_module parse_tree.error_spec.
+:- import_module parse_tree.prog_data.
 :- import_module recompilation.
 :- import_module recompilation.item_types.
 :- import_module recompilation.record_uses.
@@ -242,41 +258,18 @@ insert_into_permissions_map(NewPermissions, ModuleName, !PermissionsMap) :-
         % NewPermissions.
         OldPermissions = module_permissions(OldPermInt, OldPermImp),
         NewPermissions = module_permissions(NewPermInt, NewPermImp),
-        (
-            OldPermInt = may_not_use_in_int,
-            PermInt = NewPermInt
-        ;
-            (
-                OldPermInt = may_use_in_int(OldIntNeedQual),
-                OldWarn = no
-            ;
-                OldPermInt = may_use_in_int_warn(OldIntNeedQual),
-                OldWarn = yes
-            ),
-            (
-                NewPermInt = may_not_use_in_int,
-                PermInt = OldPermInt
-            ;
-                (
-                    NewPermInt = may_use_in_int(NewIntNeedQual),
-                    NewWarn = no
-                ;
-                    NewPermInt = may_use_in_int_warn(NewIntNeedQual),
-                    NewWarn = yes
-                ),
-                need_qual_only_if_both(OldIntNeedQual, NewIntNeedQual,
-                    IntNeedQual),
-                ( if NewWarn = yes, OldWarn = yes then
-                    PermInt = may_use_in_int_warn(IntNeedQual)
-                else
-                    PermInt = may_use_in_int(IntNeedQual)
-                )
-            )
+        OldPermInt = perm_in_int(OldIntQual, OldIntUnqual),
+        NewPermInt = perm_in_int(NewIntQual, NewIntUnqual),
+        OldPermImp = perm_in_imp(OldImpQual, OldImpUnqual),
+        NewPermImp = perm_in_imp(NewImpQual, NewImpUnqual),
+        PermInt = perm_in_int(
+            update_permission(OldIntQual, NewIntQual),
+            update_permission(OldIntUnqual, NewIntUnqual)
+        ),
+        PermImp = perm_in_imp(
+            update_permission(OldImpQual, NewImpQual),
+            update_permission(OldImpUnqual, NewImpUnqual)
         ),
-        OldPermImp = may_use_in_imp(OldImpNeedQual),
-        NewPermImp = may_use_in_imp(NewImpNeedQual),
-        need_qual_only_if_both(OldImpNeedQual, NewImpNeedQual, ImpNeedQual),
-        PermImp = may_use_in_imp(ImpNeedQual),
 
         % Update the entry only if it changed.
         ( if
@@ -292,17 +285,24 @@ insert_into_permissions_map(NewPermissions, ModuleName, !PermissionsMap) :-
         map.det_insert(ModuleName, NewPermissions, !PermissionsMap)
     ).
 
-:- pred need_qual_only_if_both(need_qualifier::in, need_qualifier::in,
-    need_qualifier::out) is det.
+:- func update_permission(permitted_or_not, permitted_or_not) =
+    permitted_or_not.
 
-need_qual_only_if_both(NeedQualA, NeedQualB, NeedQual) :-
-    ( if
-        NeedQualA = must_be_qualified,
-        NeedQualB = must_be_qualified
-    then
-        NeedQual = must_be_qualified
-    else
-        NeedQual = may_be_unqualified
+update_permission(OldPermission, NewPermission) = Result :-
+    (
+        OldPermission = not_permitted,
+        Result = NewPermission
+    ;
+        OldPermission = permitted,
+        Result = permitted
+    ;
+        ( OldPermission = permitted_with_warning
+        ; OldPermission = permitted_with_warning_shadowed
+        ),
+        % permitted_with_warning and permitted_with_warning_shadowed will be
+        % used during a transition period. We do not expect to reach this
+        % point.
+        Result = OldPermission
     ).
 
 %---------------------------------------------------------------------------%
@@ -370,9 +370,9 @@ find_unique_match(InInt, ErrorContext, IdSet, IdType, Id0, SymName, !Info) :-
         (
             UniqMatchType = match(UniqModuleName)
         ;
-            UniqMatchType = match_with_warning(UniqModuleName),
+            UniqMatchType = match_with_warning(UniqModuleName, WarnType),
             report_old_submodule_visibility_match(ErrorContext, Id0, IdType,
-                UniqModuleName, WarnSpec),
+                UniqModuleName, WarnType, WarnSpec),
             mq_info_record_warning(WarnSpec, !Info)
         ),
         SymName = qualified(UniqModuleName, BaseName),
@@ -444,12 +444,15 @@ convert_used_item_type(qual_id_class) = used_typeclass.
 
 :- type module_match_type
     --->    match(module_name)
-    ;       match_with_warning(module_name).
+    ;       match_with_warning(
+                module_name,
+                old_submodule_visibility_rule_warning
+            ).
 
 :- func matched_module_name(module_match_type) = module_name.
 
 matched_module_name(match(ModuleName)) = ModuleName.
-matched_module_name(match_with_warning(ModuleName)) = ModuleName.
+matched_module_name(match_with_warning(ModuleName, _WarnType)) = ModuleName.
 
 :- pred id_set_search_sym_arity(mq_in_interface::in, id_set::in,
     sym_name::in, string::in, int::in, list(module_match_type)::out,
@@ -529,53 +532,44 @@ add_matching_and_nearmiss_modules_int(InInt, FullyModuleQualified,
     Permissions = module_permissions(PermInInt, PermInImp),
     (
         InInt = mq_used_in_interface,
-        (
-            PermInInt = may_not_use_in_int,
-            !:IntMismatches = [ModuleName | !.IntMismatches]
-        ;
-            (
-                PermInInt = may_use_in_int(NeedQual),
-                MaybeWarn = do_not_warn
-            ;
-                PermInInt = may_use_in_int_warn(NeedQual),
-                MaybeWarn = warn_if_matching
-            ),
-            add_matching_and_nearmiss_modules_qual(FullyModuleQualified,
-                NeedQual, ModuleName, MaybeWarn, !Matches, !QualMismatches)
-        )
+        PermInInt = perm_in_int(PermQual, PermUnqual)
     ;
         InInt = mq_not_used_in_interface,
-        PermInImp = may_use_in_imp(NeedQual),
-        add_matching_and_nearmiss_modules_qual(FullyModuleQualified,
-            NeedQual, ModuleName, do_not_warn, !Matches, !QualMismatches)
-    ).
-
-:- type maybe_warn_if_matching
-    --->    do_not_warn
-    ;       warn_if_matching.
-
-:- pred add_matching_and_nearmiss_modules_qual(bool::in, need_qualifier::in,
-    module_name::in, maybe_warn_if_matching::in,
-    list(module_match_type)::in, list(module_match_type)::out,
-    list(module_name)::in, list(module_name)::out) is det.
-
-add_matching_and_nearmiss_modules_qual(FullyModuleQualified, NeedQual,
-        ModuleName, MaybeWarn, !Matches, !QualMismatches) :-
-    ( if
-        ( FullyModuleQualified = yes
-        ; NeedQual = may_be_unqualified
-        )
-    then
+        PermInImp = perm_in_imp(PermQual, PermUnqual)
+    ),
+    (
+        FullyModuleQualified = yes,
+        Permission = PermQual,
+        OtherPermission = PermUnqual
+    ;
+        FullyModuleQualified = no,
+        Permission = PermUnqual,
+        OtherPermission = PermQual
+    ),
+    (
+        Permission = permitted,
+        !:Matches = [match(ModuleName) | !.Matches]
+    ;
         (
-            MaybeWarn = do_not_warn,
-            MatchType = match(ModuleName)
+            Permission = permitted_with_warning,
+            WarnType = no_warn_shadowed_ancestor_import
         ;
-            MaybeWarn = warn_if_matching,
-            MatchType = match_with_warning(ModuleName)
+            Permission = permitted_with_warning_shadowed,
+            WarnType = also_warn_shadowed_ancestor_import
         ),
-        !:Matches = [MatchType | !.Matches]
-    else
-        !:QualMismatches = [ModuleName | !.QualMismatches]
+        !:Matches = [match_with_warning(ModuleName, WarnType) | !.Matches]
+    ;
+        Permission = not_permitted,
+        (
+            OtherPermission = not_permitted,
+            !:IntMismatches = [ModuleName | !.IntMismatches]
+        ;
+            ( OtherPermission = permitted
+            ; OtherPermission = permitted_with_warning
+            ; OtherPermission = permitted_with_warning_shadowed
+            ),
+            !:QualMismatches = [ModuleName | !.QualMismatches]
+        )
     ).
 
 %---------------------------------------------------------------------------%
@@ -632,10 +626,20 @@ parent_module_is_imported(InInt, ModuleIdSet, ParentModule, ChildModule) :-
     ParentModulePermissions = module_permissions(PermInInt, PermInImp),
     (
         InInt = mq_used_in_interface,
-        PermInInt = may_use_in_int(may_be_unqualified)
+        PermInInt = perm_in_int(_PermQual, PermUnqual)
     ;
         InInt = mq_not_used_in_interface,
-        PermInImp = may_use_in_imp(may_be_unqualified)
+        PermInImp = perm_in_imp(_PermQual, PermUnqual)
+    ),
+    require_complete_switch [PermUnqual]
+    (
+        ( PermUnqual = permitted
+        ; PermUnqual = permitted_with_warning
+        ; PermUnqual = permitted_with_warning_shadowed
+        )
+    ;
+        PermUnqual = not_permitted,
+        fail
     ).
 
     % Given a module name, possibly module-qualified, return the name
diff --git a/compiler/module_qual.qual_errors.m b/compiler/module_qual.qual_errors.m
index 526e6d452d..ca2d07e8a1 100644
--- a/compiler/module_qual.qual_errors.m
+++ b/compiler/module_qual.qual_errors.m
@@ -195,16 +195,19 @@
     qual_id_kind::in,
     list(module_name)::in, list(module_name)::in, err_spec::out) is det.
 
+:- type old_submodule_visibility_rule_warning
+    --->    no_warn_shadowed_ancestor_import
+    ;       also_warn_shadowed_ancestor_import.
+
     % report_old_submodule_visibility_match(ErrorContext, Id, IdType,
-    %   ModuleName, Spec):
+    %   ModuleName, WarnType, Spec):
     %
-    % Report a warning where an entity was matched but used the deprecated
-    % submodule visibility rule where entities imported in the implementation
-    % section of an ancestor are made visible in the interface section of its
-    % descendant modules.
+    % Report a warning where an entity was matched but used a deprecated
+    % submodule visibility rule.
     %
 :- pred report_old_submodule_visibility_match(mq_error_context::in, mq_id::in,
-    qual_id_kind::in, module_name::in, warn_spec::out) is det.
+    qual_id_kind::in, module_name::in,
+    old_submodule_visibility_rule_warning::in, warn_spec::out) is det.
 
     % Output an error message about an ill-formed user_inst.
     %
@@ -459,19 +462,39 @@ report_ambiguous_match(ErrorContext, Id, IdType,
     Spec = gen_spec($pred, severity_error, phase_pt2h, [Msg]).
 
 report_old_submodule_visibility_match(ErrorContext, Id, IdType, ModuleName,
-        Spec) :-
+        WarnType, Spec) :-
     mq_error_context_to_pieces(ErrorContext, Context, _ShouldUnqualId,
         ErrorContextPieces),
     qual_id_kind_to_string(IdType, IdTypeStr),
-    Pieces = [words("In")] ++ ErrorContextPieces ++ [suffix(":"), nl,
-        words("the"), fixed(IdTypeStr)] ++
-        color_as_subject([wrap_qual_id(Id)]) ++
-        [words("is only visible here due to an import of")] ++
-        color_as_subject([wrap_module_name(ModuleName)]) ++
-        [words("in an ancestor module's implementation section."),
-        words("This behaviour is")] ++
-        color_as_incorrect([words("deprecated.")]) ++
-        [nl],
+    (
+        WarnType = no_warn_shadowed_ancestor_import,
+        Pieces = [words("In")] ++ ErrorContextPieces ++ [suffix(":"), nl,
+            words("warning: the"), fixed(IdTypeStr)] ++
+            color_as_subject([wrap_qual_id(Id)]) ++
+            [words("is only visible here due to an import of")] ++
+            color_as_subject([wrap_module_name(ModuleName)]) ++
+            [words("in an ancestor module's implementation section."),
+            words("This behaviour is")] ++
+            color_as_incorrect([words("deprecated.")]) ++
+            [nl]
+    ;
+        WarnType = also_warn_shadowed_ancestor_import,
+        % In this case, we cannot be sure that the ancestor import that was
+        % used is located in the implementation section of an ancestor module.
+        Pieces = [words("In")] ++ ErrorContextPieces ++ [suffix(":"), nl,
+            words("warning: the"), fixed(IdTypeStr)] ++
+            color_as_subject([wrap_qual_id(Id)]) ++
+            [words("is only visible here under a")] ++
+            color_as_incorrect([words("deprecated")]) ++
+            [words("visibility rule."),
+            words("Under the new rule, the visibility of")] ++
+            color_as_subject([wrap_qual_id(Id)]) ++
+            [words("is determined solely by the import of")] ++
+            color_as_subject([wrap_module_name(ModuleName)]) ++
+            [words("in this module, regardless of any"),
+            words("import declarations in ancestor modules."),
+            nl]
+    ),
     Severity = severity_warning(warn_old_submodule_visibility_rule),
     Spec = spec($pred, Severity, phase_pt2h, Context, Pieces).
 
diff --git a/compiler/parse_tree_out.m b/compiler/parse_tree_out.m
index 758d3f637a..1ecdb2e083 100644
--- a/compiler/parse_tree_out.m
+++ b/compiler/parse_tree_out.m
@@ -515,11 +515,11 @@ mercury_output_ancestor_int_spec(Info, Stream, AncestorIntSpec, !IO) :-
     mercury_output_parse_tree_int0(Info, Stream, ParseTreeInt0, !IO).
 
 mercury_output_direct_int1_spec(Info, Stream, DirectInt1Spec, !IO) :-
-    DirectInt1Spec = direct_int1(ParseTreeInt1, _),
+    DirectInt1Spec = direct_int1(ParseTreeInt1, _, _),
     mercury_output_parse_tree_int1(Info, Stream, ParseTreeInt1, !IO).
 
 mercury_output_direct_int3_spec(Info, Stream, DirectInt3Spec, !IO) :-
-    DirectInt3Spec = direct_int3(ParseTreeInt3, _),
+    DirectInt3Spec = direct_int3(ParseTreeInt3, _, _),
     mercury_output_parse_tree_int3(Info, Stream, ParseTreeInt3, !IO).
 
 mercury_output_indirect_int2_spec(Info, Stream, IndirectInt2Spec, !IO) :-
diff --git a/compiler/prog_parse_tree.m b/compiler/prog_parse_tree.m
index e010dab647..e7e83dd085 100644
--- a/compiler/prog_parse_tree.m
+++ b/compiler/prog_parse_tree.m
@@ -861,10 +861,18 @@
     --->    ancestor_int0(parse_tree_int0, read_why_int0).
 
 :- type direct_int1_spec
-    --->    direct_int1(parse_tree_int1, read_why_int1).
+    --->    direct_int1(
+                parse_tree_int1,
+                read_why_int1,
+                maybe(shadowed_read_why_int1)
+            ).
 
 :- type direct_int3_spec
-    --->    direct_int3(parse_tree_int3, read_why_int3).
+    --->    direct_int3(
+                parse_tree_int3,
+                read_why_int3,
+                maybe(shadowed_read_why_int3)
+            ).
 
 :- type indirect_int2_spec
     --->    indirect_int2(parse_tree_int2, read_why_int2).
@@ -941,6 +949,12 @@
             % on interface files that are needed only for type representation
             % information.
 
+:- type shadowed_read_why_int1 =< read_why_int1
+    --->    rwi1_ancestor_int_import
+    ;       rwi1_ancestor_int_use
+    ;       rwi1_ancestor_imp_import
+    ;       rwi1_ancestor_imp_use.
+
     % All these record recomp_avail_imp_use as recompilation reason.
 :- type read_why_int2
     --->    rwi2_int_use
@@ -999,6 +1013,12 @@
             % Record recomp_avail_imp_use as recompilation reason.
             % (Since there is no recomp_avail_indirect_use_imp, yet).
 
+:- type shadowed_read_why_int3 =< read_why_int3
+    --->    rwi3_direct_ancestor_int_import
+    ;       rwi3_direct_ancestor_imp_import
+    ;       rwi3_direct_ancestor_int_use
+    ;       rwi3_direct_ancestor_imp_use.
+
 %---------------------------------------------------------------------------%
 
 :- type module_section
diff --git a/tests/invalid_submodules/bug584.err_exp b/tests/invalid_submodules/bug584.err_exp
index 08d2c308db..00b5a3645c 100644
--- a/tests/invalid_submodules/bug584.err_exp
+++ b/tests/invalid_submodules/bug584.err_exp
@@ -1,11 +1,12 @@
 bug584_helper_1.m:018: In the second argument of function symbol `struct'
 bug584_helper_1.m:018:   (field name `f2') of the type `struct'/0:
-bug584_helper_1.m:018:   the type `foo'/0 is only visible here due to an import
-bug584_helper_1.m:018:   of `bug584_helper_1.sub2' in an ancestor module's
-bug584_helper_1.m:018:   implementation section. This behaviour is deprecated.
+bug584_helper_1.m:018:   warning: the type `foo'/0 is only visible here due to
+bug584_helper_1.m:018:   an import of `bug584_helper_1.sub2' in an ancestor
+bug584_helper_1.m:018:   module's implementation section. This behaviour is
+bug584_helper_1.m:018:   deprecated.
 bug584_helper_1.m:019: In the third argument of function symbol `struct' (field
 bug584_helper_1.m:019:   name `f3') of the type `struct'/0:
-bug584_helper_1.m:019:   the type `bug584_helper_1.sub2.foo'/0 is only visible
-bug584_helper_1.m:019:   here due to an import of `bug584_helper_1.sub2' in an
-bug584_helper_1.m:019:   ancestor module's implementation section. This
-bug584_helper_1.m:019:   behaviour is deprecated.
+bug584_helper_1.m:019:   warning: the type `bug584_helper_1.sub2.foo'/0 is only
+bug584_helper_1.m:019:   visible here due to an import of
+bug584_helper_1.m:019:   `bug584_helper_1.sub2' in an ancestor module's
+bug584_helper_1.m:019:   implementation section. This behaviour is deprecated.
diff --git a/tests/invalid_submodules/sub_visibility_a2.err_exp b/tests/invalid_submodules/sub_visibility_a2.err_exp
index b4377a7d3c..4b3e732163 100644
--- a/tests/invalid_submodules/sub_visibility_a2.err_exp
+++ b/tests/invalid_submodules/sub_visibility_a2.err_exp
@@ -1,13 +1,20 @@
+sub_visibility_a2.m:013: In module `sub_visibility_a2':
+sub_visibility_a2.m:013:   warning: module `sub_visibility_a2.sub2' is imported
+sub_visibility_a2.m:013:   in the interface, but it is not used in the
+sub_visibility_a2.m:013:   interface.
 sub_visibility_a2.m:022: In the first argument of function symbol `int_uq' of
 sub_visibility_a2.m:022:   the type `int_uq'/0:
-sub_visibility_a2.m:022:   error: the type `foo'/0 is undefined.
-sub_visibility_a2.m:022:   (Only fully module qualified names may refer to the
-sub_visibility_a2.m:022:   entities defined in module 
-sub_visibility_a2.m:022:   `sub_visibility_a2.sub2'.)
+sub_visibility_a2.m:022:   warning: the type `foo'/0 is only visible here under
+sub_visibility_a2.m:022:   a deprecated visibility rule. Under the new rule,
+sub_visibility_a2.m:022:   the visibility of `foo'/0 is determined solely by
+sub_visibility_a2.m:022:   the import of `sub_visibility_a2.sub2' in this
+sub_visibility_a2.m:022:   module, regardless of any import declarations in
+sub_visibility_a2.m:022:   ancestor modules.
 sub_visibility_a2.m:035: In the first argument of function symbol `imp_uq' of
 sub_visibility_a2.m:035:   the type `imp_uq'/0:
-sub_visibility_a2.m:035:   error: the type `foo'/0 is undefined.
-sub_visibility_a2.m:035:   (Only fully module qualified names may refer to the
-sub_visibility_a2.m:035:   entities defined in module 
-sub_visibility_a2.m:035:   `sub_visibility_a2.sub2'.)
-`sub_visibility_a2.sub1.int' and `sub_visibility_a2.sub1.int2' not written.
+sub_visibility_a2.m:035:   warning: the type `foo'/0 is only visible here under
+sub_visibility_a2.m:035:   a deprecated visibility rule. Under the new rule,
+sub_visibility_a2.m:035:   the visibility of `foo'/0 is determined solely by
+sub_visibility_a2.m:035:   the import of `sub_visibility_a2.sub2' in this
+sub_visibility_a2.m:035:   module, regardless of any import declarations in
+sub_visibility_a2.m:035:   ancestor modules.
diff --git a/tests/invalid_submodules/sub_visibility_a2.err_exp2 b/tests/invalid_submodules/sub_visibility_a2.err_exp2
deleted file mode 100644
index b83c2ff272..0000000000
--- a/tests/invalid_submodules/sub_visibility_a2.err_exp2
+++ /dev/null
@@ -1,14 +0,0 @@
-sub_visibility_a2.m:022: In the first argument of function symbol `int_uq' of
-sub_visibility_a2.m:022:   the type `int_uq'/0:
-sub_visibility_a2.m:022:   error: the type `foo'/0 is undefined.
-sub_visibility_a2.m:022:   (Only fully module qualified names may refer to the
-sub_visibility_a2.m:022:   entities defined in module 
-sub_visibility_a2.m:022:   `sub_visibility_a2.sub2'.)
-sub_visibility_a2.m:035: In the first argument of function symbol `imp_uq' of
-sub_visibility_a2.m:035:   the type `imp_uq'/0:
-sub_visibility_a2.m:035:   error: the type `foo'/0 is undefined.
-sub_visibility_a2.m:035:   (Only fully module qualified names may refer to the
-sub_visibility_a2.m:035:   entities defined in module 
-sub_visibility_a2.m:035:   `sub_visibility_a2.sub2'.)
-`Mercury/ints/sub_visibility_a2.sub1.int' and
-  `Mercury/int2s/sub_visibility_a2.sub1.int2' not written.
diff --git a/tests/invalid_submodules/sub_visibility_a2.m b/tests/invalid_submodules/sub_visibility_a2.m
index 79f007385e..fce69325d7 100644
--- a/tests/invalid_submodules/sub_visibility_a2.m
+++ b/tests/invalid_submodules/sub_visibility_a2.m
@@ -19,7 +19,7 @@
 
     :- use_module sub_visibility_a2.sub2. % overrides decl in parent
 
-    :- type int_uq ---> int_uq(foo). % error
+    :- type int_uq ---> int_uq(foo). % deprecated
     :- type int_fq ---> int_fq(sub_visibility_a2.sub2.foo). % ok
 
     :- end_module sub1.
@@ -32,7 +32,7 @@
     :- module sub1.
     :- implementation.
 
-    :- type imp_uq ---> imp_uq(foo). % error
+    :- type imp_uq ---> imp_uq(foo). % deprecated
     :- type imp_fq ---> imp_fq(sub_visibility_a2.sub2.foo). % ok
 
     :- end_module sub1.
diff --git a/tests/invalid_submodules/sub_visibility_a3.err_exp b/tests/invalid_submodules/sub_visibility_a3.err_exp
index 9a1971e1d5..15dc27c1f5 100644
--- a/tests/invalid_submodules/sub_visibility_a3.err_exp
+++ b/tests/invalid_submodules/sub_visibility_a3.err_exp
@@ -1,12 +1,21 @@
+sub_visibility_a3.m:013: In module `sub_visibility_a3':
+sub_visibility_a3.m:013:   warning: module `sub_visibility_a3.sub2' is imported
+sub_visibility_a3.m:013:   in the interface, but it is not used in the
+sub_visibility_a3.m:013:   interface.
 sub_visibility_a3.m:020: In the first argument of function symbol `int_uq' of
 sub_visibility_a3.m:020:   the type `int_uq'/0:
-sub_visibility_a3.m:020:   error: the type `foo'/0 is undefined.
-sub_visibility_a3.m:020:   (The module `sub_visibility_a3.sub2' has not been
-sub_visibility_a3.m:020:   imported in the interface.)
+sub_visibility_a3.m:020:   warning: the type `foo'/0 is only visible here under
+sub_visibility_a3.m:020:   a deprecated visibility rule. Under the new rule,
+sub_visibility_a3.m:020:   the visibility of `foo'/0 is determined solely by
+sub_visibility_a3.m:020:   the import of `sub_visibility_a3.sub2' in this
+sub_visibility_a3.m:020:   module, regardless of any import declarations in
+sub_visibility_a3.m:020:   ancestor modules.
 sub_visibility_a3.m:021: In the first argument of function symbol `int_fq' of
 sub_visibility_a3.m:021:   the type `int_fq'/0:
-sub_visibility_a3.m:021:   error: the type `sub_visibility_a3.sub2.foo'/0 is
-sub_visibility_a3.m:021:   undefined.
-sub_visibility_a3.m:021:   (The module `sub_visibility_a3.sub2' has not been
-sub_visibility_a3.m:021:   imported in the interface.)
-`sub_visibility_a3.sub1.int' and `sub_visibility_a3.sub1.int2' not written.
+sub_visibility_a3.m:021:   warning: the type `sub_visibility_a3.sub2.foo'/0 is
+sub_visibility_a3.m:021:   only visible here under a deprecated visibility
+sub_visibility_a3.m:021:   rule. Under the new rule, the visibility of
+sub_visibility_a3.m:021:   `sub_visibility_a3.sub2.foo'/0 is determined solely
+sub_visibility_a3.m:021:   by the import of `sub_visibility_a3.sub2' in this
+sub_visibility_a3.m:021:   module, regardless of any import declarations in
+sub_visibility_a3.m:021:   ancestor modules.
diff --git a/tests/invalid_submodules/sub_visibility_a3.err_exp2 b/tests/invalid_submodules/sub_visibility_a3.err_exp2
deleted file mode 100644
index 443e19bdf9..0000000000
--- a/tests/invalid_submodules/sub_visibility_a3.err_exp2
+++ /dev/null
@@ -1,13 +0,0 @@
-sub_visibility_a3.m:020: In the first argument of function symbol `int_uq' of
-sub_visibility_a3.m:020:   the type `int_uq'/0:
-sub_visibility_a3.m:020:   error: the type `foo'/0 is undefined.
-sub_visibility_a3.m:020:   (The module `sub_visibility_a3.sub2' has not been
-sub_visibility_a3.m:020:   imported in the interface.)
-sub_visibility_a3.m:021: In the first argument of function symbol `int_fq' of
-sub_visibility_a3.m:021:   the type `int_fq'/0:
-sub_visibility_a3.m:021:   error: the type `sub_visibility_a3.sub2.foo'/0 is
-sub_visibility_a3.m:021:   undefined.
-sub_visibility_a3.m:021:   (The module `sub_visibility_a3.sub2' has not been
-sub_visibility_a3.m:021:   imported in the interface.)
-`Mercury/ints/sub_visibility_a3.sub1.int' and
-  `Mercury/int2s/sub_visibility_a3.sub1.int2' not written.
diff --git a/tests/invalid_submodules/sub_visibility_a3.m b/tests/invalid_submodules/sub_visibility_a3.m
index acd3637198..32f37f2a39 100644
--- a/tests/invalid_submodules/sub_visibility_a3.m
+++ b/tests/invalid_submodules/sub_visibility_a3.m
@@ -17,8 +17,8 @@
     :- module sub1.
     :- interface.
 
-    :- type int_uq ---> int_uq(foo). % error
-    :- type int_fq ---> int_fq(sub_visibility_a3.sub2.foo). % error
+    :- type int_uq ---> int_uq(foo). % deprecated
+    :- type int_fq ---> int_fq(sub_visibility_a3.sub2.foo). % deprecated
 
     :- end_module sub1.
 
diff --git a/tests/invalid_submodules/sub_visibility_a4.err_exp b/tests/invalid_submodules/sub_visibility_a4.err_exp
index ceee8197b0..7cbea37233 100644
--- a/tests/invalid_submodules/sub_visibility_a4.err_exp
+++ b/tests/invalid_submodules/sub_visibility_a4.err_exp
@@ -1,18 +1,29 @@
+sub_visibility_a4.m:013: In module `sub_visibility_a4':
+sub_visibility_a4.m:013:   warning: module `sub_visibility_a4.sub2' is imported
+sub_visibility_a4.m:013:   in the interface, but it is not used in the
+sub_visibility_a4.m:013:   interface.
 sub_visibility_a4.m:020: In the first argument of function symbol `int_uq' of
 sub_visibility_a4.m:020:   the type `int_uq'/0:
-sub_visibility_a4.m:020:   error: the type `foo'/0 is undefined.
-sub_visibility_a4.m:020:   (The module `sub_visibility_a4.sub2' has not been
-sub_visibility_a4.m:020:   imported in the interface.)
+sub_visibility_a4.m:020:   warning: the type `foo'/0 is only visible here under
+sub_visibility_a4.m:020:   a deprecated visibility rule. Under the new rule,
+sub_visibility_a4.m:020:   the visibility of `foo'/0 is determined solely by
+sub_visibility_a4.m:020:   the import of `sub_visibility_a4.sub2' in this
+sub_visibility_a4.m:020:   module, regardless of any import declarations in
+sub_visibility_a4.m:020:   ancestor modules.
 sub_visibility_a4.m:021: In the first argument of function symbol `int_fq' of
 sub_visibility_a4.m:021:   the type `int_fq'/0:
-sub_visibility_a4.m:021:   error: the type `sub_visibility_a4.sub2.foo'/0 is
-sub_visibility_a4.m:021:   undefined.
-sub_visibility_a4.m:021:   (The module `sub_visibility_a4.sub2' has not been
-sub_visibility_a4.m:021:   imported in the interface.)
+sub_visibility_a4.m:021:   warning: the type `sub_visibility_a4.sub2.foo'/0 is
+sub_visibility_a4.m:021:   only visible here under a deprecated visibility
+sub_visibility_a4.m:021:   rule. Under the new rule, the visibility of
+sub_visibility_a4.m:021:   `sub_visibility_a4.sub2.foo'/0 is determined solely
+sub_visibility_a4.m:021:   by the import of `sub_visibility_a4.sub2' in this
+sub_visibility_a4.m:021:   module, regardless of any import declarations in
+sub_visibility_a4.m:021:   ancestor modules.
 sub_visibility_a4.m:035: In the first argument of function symbol `imp_uq' of
 sub_visibility_a4.m:035:   the type `imp_uq'/0:
-sub_visibility_a4.m:035:   error: the type `foo'/0 is undefined.
-sub_visibility_a4.m:035:   (Only fully module qualified names may refer to the
-sub_visibility_a4.m:035:   entities defined in module 
-sub_visibility_a4.m:035:   `sub_visibility_a4.sub2'.)
-`sub_visibility_a4.sub1.int' and `sub_visibility_a4.sub1.int2' not written.
+sub_visibility_a4.m:035:   warning: the type `foo'/0 is only visible here under
+sub_visibility_a4.m:035:   a deprecated visibility rule. Under the new rule,
+sub_visibility_a4.m:035:   the visibility of `foo'/0 is determined solely by
+sub_visibility_a4.m:035:   the import of `sub_visibility_a4.sub2' in this
+sub_visibility_a4.m:035:   module, regardless of any import declarations in
+sub_visibility_a4.m:035:   ancestor modules.
diff --git a/tests/invalid_submodules/sub_visibility_a4.err_exp2 b/tests/invalid_submodules/sub_visibility_a4.err_exp2
deleted file mode 100644
index 8b33cbc1d1..0000000000
--- a/tests/invalid_submodules/sub_visibility_a4.err_exp2
+++ /dev/null
@@ -1,19 +0,0 @@
-sub_visibility_a4.m:020: In the first argument of function symbol `int_uq' of
-sub_visibility_a4.m:020:   the type `int_uq'/0:
-sub_visibility_a4.m:020:   error: the type `foo'/0 is undefined.
-sub_visibility_a4.m:020:   (The module `sub_visibility_a4.sub2' has not been
-sub_visibility_a4.m:020:   imported in the interface.)
-sub_visibility_a4.m:021: In the first argument of function symbol `int_fq' of
-sub_visibility_a4.m:021:   the type `int_fq'/0:
-sub_visibility_a4.m:021:   error: the type `sub_visibility_a4.sub2.foo'/0 is
-sub_visibility_a4.m:021:   undefined.
-sub_visibility_a4.m:021:   (The module `sub_visibility_a4.sub2' has not been
-sub_visibility_a4.m:021:   imported in the interface.)
-sub_visibility_a4.m:035: In the first argument of function symbol `imp_uq' of
-sub_visibility_a4.m:035:   the type `imp_uq'/0:
-sub_visibility_a4.m:035:   error: the type `foo'/0 is undefined.
-sub_visibility_a4.m:035:   (Only fully module qualified names may refer to the
-sub_visibility_a4.m:035:   entities defined in module 
-sub_visibility_a4.m:035:   `sub_visibility_a4.sub2'.)
-`Mercury/ints/sub_visibility_a4.sub1.int' and
-  `Mercury/int2s/sub_visibility_a4.sub1.int2' not written.
diff --git a/tests/invalid_submodules/sub_visibility_a4.m b/tests/invalid_submodules/sub_visibility_a4.m
index e6a778b2f4..3422cf9e61 100644
--- a/tests/invalid_submodules/sub_visibility_a4.m
+++ b/tests/invalid_submodules/sub_visibility_a4.m
@@ -17,8 +17,8 @@
     :- module sub1.
     :- interface.
 
-    :- type int_uq ---> int_uq(foo). % error
-    :- type int_fq ---> int_fq(sub_visibility_a4.sub2.foo). % error
+    :- type int_uq ---> int_uq(foo). % deprecated
+    :- type int_fq ---> int_fq(sub_visibility_a4.sub2.foo). % deprecated
 
     :- end_module sub1.
 
@@ -32,7 +32,7 @@
 
     :- use_module sub_visibility_a4.sub2. % overrides decl in parent
 
-    :- type imp_uq ---> imp_uq(foo). % error
+    :- type imp_uq ---> imp_uq(foo). % deprecated
     :- type imp_fq ---> imp_fq(sub_visibility_a4.sub2.foo). % ok
 
     :- end_module sub1.
diff --git a/tests/invalid_submodules/sub_visibility_b3.err_exp b/tests/invalid_submodules/sub_visibility_b3.err_exp
index eb2ab23cdf..afca797e91 100644
--- a/tests/invalid_submodules/sub_visibility_b3.err_exp
+++ b/tests/invalid_submodules/sub_visibility_b3.err_exp
@@ -1,12 +1,7 @@
 sub_visibility_b3.m:020: In the first argument of function symbol `int_uq' of
 sub_visibility_b3.m:020:   the type `int_uq'/0:
 sub_visibility_b3.m:020:   error: the type `foo'/0 is undefined.
-sub_visibility_b3.m:020:   (The module `sub_visibility_b3.sub2' has not been
-sub_visibility_b3.m:020:   imported in the interface.)
-sub_visibility_b3.m:021: In the first argument of function symbol `int_fq' of
-sub_visibility_b3.m:021:   the type `int_fq'/0:
-sub_visibility_b3.m:021:   error: the type `sub_visibility_b3.sub2.foo'/0 is
-sub_visibility_b3.m:021:   undefined.
-sub_visibility_b3.m:021:   (The module `sub_visibility_b3.sub2' has not been
-sub_visibility_b3.m:021:   imported in the interface.)
+sub_visibility_b3.m:020:   (Only fully module qualified names may refer to the
+sub_visibility_b3.m:020:   entities defined in module 
+sub_visibility_b3.m:020:   `sub_visibility_b3.sub2'.)
 `sub_visibility_b3.sub1.int' and `sub_visibility_b3.sub1.int2' not written.
diff --git a/tests/invalid_submodules/sub_visibility_b3.err_exp2 b/tests/invalid_submodules/sub_visibility_b3.err_exp2
index 5df9c2481f..b20d71e351 100644
--- a/tests/invalid_submodules/sub_visibility_b3.err_exp2
+++ b/tests/invalid_submodules/sub_visibility_b3.err_exp2
@@ -1,13 +1,8 @@
 sub_visibility_b3.m:020: In the first argument of function symbol `int_uq' of
 sub_visibility_b3.m:020:   the type `int_uq'/0:
 sub_visibility_b3.m:020:   error: the type `foo'/0 is undefined.
-sub_visibility_b3.m:020:   (The module `sub_visibility_b3.sub2' has not been
-sub_visibility_b3.m:020:   imported in the interface.)
-sub_visibility_b3.m:021: In the first argument of function symbol `int_fq' of
-sub_visibility_b3.m:021:   the type `int_fq'/0:
-sub_visibility_b3.m:021:   error: the type `sub_visibility_b3.sub2.foo'/0 is
-sub_visibility_b3.m:021:   undefined.
-sub_visibility_b3.m:021:   (The module `sub_visibility_b3.sub2' has not been
-sub_visibility_b3.m:021:   imported in the interface.)
+sub_visibility_b3.m:020:   (Only fully module qualified names may refer to the
+sub_visibility_b3.m:020:   entities defined in module 
+sub_visibility_b3.m:020:   `sub_visibility_b3.sub2'.)
 `Mercury/ints/sub_visibility_b3.sub1.int' and
   `Mercury/int2s/sub_visibility_b3.sub1.int2' not written.
diff --git a/tests/invalid_submodules/sub_visibility_b3.m b/tests/invalid_submodules/sub_visibility_b3.m
index 2b75736200..63137bc451 100644
--- a/tests/invalid_submodules/sub_visibility_b3.m
+++ b/tests/invalid_submodules/sub_visibility_b3.m
@@ -18,7 +18,7 @@
     :- interface.
 
     :- type int_uq ---> int_uq(foo). % error
-    :- type int_fq ---> int_fq(sub_visibility_b3.sub2.foo). % error
+    :- type int_fq ---> int_fq(sub_visibility_b3.sub2.foo). % deprecated
 
     :- end_module sub1.
 
diff --git a/tests/invalid_submodules/sub_visibility_b4.err_exp b/tests/invalid_submodules/sub_visibility_b4.err_exp
index fb5f72108d..3a204cb6e4 100644
--- a/tests/invalid_submodules/sub_visibility_b4.err_exp
+++ b/tests/invalid_submodules/sub_visibility_b4.err_exp
@@ -1,14 +1,9 @@
 sub_visibility_b4.m:020: In the first argument of function symbol `int_uq' of
 sub_visibility_b4.m:020:   the type `int_uq'/0:
 sub_visibility_b4.m:020:   error: the type `foo'/0 is undefined.
-sub_visibility_b4.m:020:   (The module `sub_visibility_b4.sub2' has not been
-sub_visibility_b4.m:020:   imported in the interface.)
-sub_visibility_b4.m:021: In the first argument of function symbol `int_fq' of
-sub_visibility_b4.m:021:   the type `int_fq'/0:
-sub_visibility_b4.m:021:   error: the type `sub_visibility_b4.sub2.foo'/0 is
-sub_visibility_b4.m:021:   undefined.
-sub_visibility_b4.m:021:   (The module `sub_visibility_b4.sub2' has not been
-sub_visibility_b4.m:021:   imported in the interface.)
+sub_visibility_b4.m:020:   (Only fully module qualified names may refer to the
+sub_visibility_b4.m:020:   entities defined in module 
+sub_visibility_b4.m:020:   `sub_visibility_b4.sub2'.)
 sub_visibility_b4.m:035: In the first argument of function symbol `imp_uq' of
 sub_visibility_b4.m:035:   the type `imp_uq'/0:
 sub_visibility_b4.m:035:   error: the type `foo'/0 is undefined.
diff --git a/tests/invalid_submodules/sub_visibility_b4.err_exp2 b/tests/invalid_submodules/sub_visibility_b4.err_exp2
index 27a459ae8e..aebf32a2b4 100644
--- a/tests/invalid_submodules/sub_visibility_b4.err_exp2
+++ b/tests/invalid_submodules/sub_visibility_b4.err_exp2
@@ -1,14 +1,9 @@
 sub_visibility_b4.m:020: In the first argument of function symbol `int_uq' of
 sub_visibility_b4.m:020:   the type `int_uq'/0:
 sub_visibility_b4.m:020:   error: the type `foo'/0 is undefined.
-sub_visibility_b4.m:020:   (The module `sub_visibility_b4.sub2' has not been
-sub_visibility_b4.m:020:   imported in the interface.)
-sub_visibility_b4.m:021: In the first argument of function symbol `int_fq' of
-sub_visibility_b4.m:021:   the type `int_fq'/0:
-sub_visibility_b4.m:021:   error: the type `sub_visibility_b4.sub2.foo'/0 is
-sub_visibility_b4.m:021:   undefined.
-sub_visibility_b4.m:021:   (The module `sub_visibility_b4.sub2' has not been
-sub_visibility_b4.m:021:   imported in the interface.)
+sub_visibility_b4.m:020:   (Only fully module qualified names may refer to the
+sub_visibility_b4.m:020:   entities defined in module 
+sub_visibility_b4.m:020:   `sub_visibility_b4.sub2'.)
 sub_visibility_b4.m:035: In the first argument of function symbol `imp_uq' of
 sub_visibility_b4.m:035:   the type `imp_uq'/0:
 sub_visibility_b4.m:035:   error: the type `foo'/0 is undefined.
diff --git a/tests/invalid_submodules/sub_visibility_b4.m b/tests/invalid_submodules/sub_visibility_b4.m
index 71153c7a6f..77f193ae59 100644
--- a/tests/invalid_submodules/sub_visibility_b4.m
+++ b/tests/invalid_submodules/sub_visibility_b4.m
@@ -18,7 +18,7 @@
     :- interface.
 
     :- type int_uq ---> int_uq(foo). % error
-    :- type int_fq ---> int_fq(sub_visibility_b4.sub2.foo). % error
+    :- type int_fq ---> int_fq(sub_visibility_b4.sub2.foo). % deprecated
 
     :- end_module sub1.
 
diff --git a/tests/invalid_submodules/sub_visibility_c2.err_exp b/tests/invalid_submodules/sub_visibility_c2.err_exp
index cefbc5e377..4e4360f544 100644
--- a/tests/invalid_submodules/sub_visibility_c2.err_exp
+++ b/tests/invalid_submodules/sub_visibility_c2.err_exp
@@ -1,13 +1,16 @@
 sub_visibility_c2.m:018: In the first argument of function symbol `int_uq' of
 sub_visibility_c2.m:018:   the type `int_uq'/0:
-sub_visibility_c2.m:018:   error: the type `foo'/0 is undefined.
-sub_visibility_c2.m:018:   (Only fully module qualified names may refer to the
-sub_visibility_c2.m:018:   entities defined in module 
-sub_visibility_c2.m:018:   `sub_visibility_c2.sub2'.)
+sub_visibility_c2.m:018:   warning: the type `foo'/0 is only visible here under
+sub_visibility_c2.m:018:   a deprecated visibility rule. Under the new rule,
+sub_visibility_c2.m:018:   the visibility of `foo'/0 is determined solely by
+sub_visibility_c2.m:018:   the import of `sub_visibility_c2.sub2' in this
+sub_visibility_c2.m:018:   module, regardless of any import declarations in
+sub_visibility_c2.m:018:   ancestor modules.
 sub_visibility_c2.m:035: In the first argument of function symbol `imp_uq' of
 sub_visibility_c2.m:035:   the type `imp_uq'/0:
-sub_visibility_c2.m:035:   error: the type `foo'/0 is undefined.
-sub_visibility_c2.m:035:   (Only fully module qualified names may refer to the
-sub_visibility_c2.m:035:   entities defined in module 
-sub_visibility_c2.m:035:   `sub_visibility_c2.sub2'.)
-`sub_visibility_c2.sub1.int' and `sub_visibility_c2.sub1.int2' not written.
+sub_visibility_c2.m:035:   warning: the type `foo'/0 is only visible here under
+sub_visibility_c2.m:035:   a deprecated visibility rule. Under the new rule,
+sub_visibility_c2.m:035:   the visibility of `foo'/0 is determined solely by
+sub_visibility_c2.m:035:   the import of `sub_visibility_c2.sub2' in this
+sub_visibility_c2.m:035:   module, regardless of any import declarations in
+sub_visibility_c2.m:035:   ancestor modules.
diff --git a/tests/invalid_submodules/sub_visibility_c2.err_exp2 b/tests/invalid_submodules/sub_visibility_c2.err_exp2
deleted file mode 100644
index 11643160bb..0000000000
--- a/tests/invalid_submodules/sub_visibility_c2.err_exp2
+++ /dev/null
@@ -1,14 +0,0 @@
-sub_visibility_c2.m:018: In the first argument of function symbol `int_uq' of
-sub_visibility_c2.m:018:   the type `int_uq'/0:
-sub_visibility_c2.m:018:   error: the type `foo'/0 is undefined.
-sub_visibility_c2.m:018:   (Only fully module qualified names may refer to the
-sub_visibility_c2.m:018:   entities defined in module 
-sub_visibility_c2.m:018:   `sub_visibility_c2.sub2'.)
-sub_visibility_c2.m:035: In the first argument of function symbol `imp_uq' of
-sub_visibility_c2.m:035:   the type `imp_uq'/0:
-sub_visibility_c2.m:035:   error: the type `foo'/0 is undefined.
-sub_visibility_c2.m:035:   (Only fully module qualified names may refer to the
-sub_visibility_c2.m:035:   entities defined in module 
-sub_visibility_c2.m:035:   `sub_visibility_c2.sub2'.)
-`Mercury/ints/sub_visibility_c2.sub1.int' and
-  `Mercury/int2s/sub_visibility_c2.sub1.int2' not written.
diff --git a/tests/invalid_submodules/sub_visibility_c2.m b/tests/invalid_submodules/sub_visibility_c2.m
index 85ca169518..46955768e5 100644
--- a/tests/invalid_submodules/sub_visibility_c2.m
+++ b/tests/invalid_submodules/sub_visibility_c2.m
@@ -15,7 +15,7 @@
 
     :- use_module sub_visibility_c2.sub2. % overrides decl in parent
 
-    :- type int_uq ---> int_uq(foo). % error
+    :- type int_uq ---> int_uq(foo). % deprecated
     :- type int_fq ---> int_fq(sub_visibility_c2.sub2.foo). % ok
 
     :- end_module sub1.
@@ -32,7 +32,7 @@
     :- module sub1.
     :- implementation.
 
-    :- type imp_uq ---> imp_uq(foo). % error
+    :- type imp_uq ---> imp_uq(foo). % deprecated
     :- type imp_fq ---> imp_fq(sub_visibility_c2.sub2.foo). % ok
 
     :- end_module sub1.
diff --git a/tests/invalid_submodules/sub_visibility_c3.err_exp b/tests/invalid_submodules/sub_visibility_c3.err_exp
index f86c53d6ea..6d2b0fb009 100644
--- a/tests/invalid_submodules/sub_visibility_c3.err_exp
+++ b/tests/invalid_submodules/sub_visibility_c3.err_exp
@@ -1,12 +1,17 @@
 sub_visibility_c3.m:016: In the first argument of function symbol `int_uq' of
 sub_visibility_c3.m:016:   the type `int_uq'/0:
-sub_visibility_c3.m:016:   error: the type `foo'/0 is undefined.
-sub_visibility_c3.m:016:   (The module `sub_visibility_c3.sub2' has not been
-sub_visibility_c3.m:016:   imported in the interface.)
+sub_visibility_c3.m:016:   warning: the type `foo'/0 is only visible here under
+sub_visibility_c3.m:016:   a deprecated visibility rule. Under the new rule,
+sub_visibility_c3.m:016:   the visibility of `foo'/0 is determined solely by
+sub_visibility_c3.m:016:   the import of `sub_visibility_c3.sub2' in this
+sub_visibility_c3.m:016:   module, regardless of any import declarations in
+sub_visibility_c3.m:016:   ancestor modules.
 sub_visibility_c3.m:017: In the first argument of function symbol `int_fq' of
 sub_visibility_c3.m:017:   the type `int_fq'/0:
-sub_visibility_c3.m:017:   error: the type `sub_visibility_c3.sub2.foo'/0 is
-sub_visibility_c3.m:017:   undefined.
-sub_visibility_c3.m:017:   (The module `sub_visibility_c3.sub2' has not been
-sub_visibility_c3.m:017:   imported in the interface.)
-`sub_visibility_c3.sub1.int' and `sub_visibility_c3.sub1.int2' not written.
+sub_visibility_c3.m:017:   warning: the type `sub_visibility_c3.sub2.foo'/0 is
+sub_visibility_c3.m:017:   only visible here under a deprecated visibility
+sub_visibility_c3.m:017:   rule. Under the new rule, the visibility of
+sub_visibility_c3.m:017:   `sub_visibility_c3.sub2.foo'/0 is determined solely
+sub_visibility_c3.m:017:   by the import of `sub_visibility_c3.sub2' in this
+sub_visibility_c3.m:017:   module, regardless of any import declarations in
+sub_visibility_c3.m:017:   ancestor modules.
diff --git a/tests/invalid_submodules/sub_visibility_c3.err_exp2 b/tests/invalid_submodules/sub_visibility_c3.err_exp2
deleted file mode 100644
index 95c02136e6..0000000000
--- a/tests/invalid_submodules/sub_visibility_c3.err_exp2
+++ /dev/null
@@ -1,13 +0,0 @@
-sub_visibility_c3.m:016: In the first argument of function symbol `int_uq' of
-sub_visibility_c3.m:016:   the type `int_uq'/0:
-sub_visibility_c3.m:016:   error: the type `foo'/0 is undefined.
-sub_visibility_c3.m:016:   (The module `sub_visibility_c3.sub2' has not been
-sub_visibility_c3.m:016:   imported in the interface.)
-sub_visibility_c3.m:017: In the first argument of function symbol `int_fq' of
-sub_visibility_c3.m:017:   the type `int_fq'/0:
-sub_visibility_c3.m:017:   error: the type `sub_visibility_c3.sub2.foo'/0 is
-sub_visibility_c3.m:017:   undefined.
-sub_visibility_c3.m:017:   (The module `sub_visibility_c3.sub2' has not been
-sub_visibility_c3.m:017:   imported in the interface.)
-`Mercury/ints/sub_visibility_c3.sub1.int' and
-  `Mercury/int2s/sub_visibility_c3.sub1.int2' not written.
diff --git a/tests/invalid_submodules/sub_visibility_c3.m b/tests/invalid_submodules/sub_visibility_c3.m
index 1d0037f225..5377bf358a 100644
--- a/tests/invalid_submodules/sub_visibility_c3.m
+++ b/tests/invalid_submodules/sub_visibility_c3.m
@@ -13,8 +13,8 @@
     :- module sub1.
     :- interface.
 
-    :- type int_uq ---> int_uq(foo). % error
-    :- type int_fq ---> int_fq(sub_visibility_c3.sub2.foo). % error
+    :- type int_uq ---> int_uq(foo). % deprecated
+    :- type int_fq ---> int_fq(sub_visibility_c3.sub2.foo). % deprecated
 
     :- end_module sub1.
 
diff --git a/tests/invalid_submodules/sub_visibility_c4.err_exp b/tests/invalid_submodules/sub_visibility_c4.err_exp
index f8df6177c8..02b4f782aa 100644
--- a/tests/invalid_submodules/sub_visibility_c4.err_exp
+++ b/tests/invalid_submodules/sub_visibility_c4.err_exp
@@ -1,18 +1,25 @@
 sub_visibility_c4.m:016: In the first argument of function symbol `int_uq' of
 sub_visibility_c4.m:016:   the type `int_uq'/0:
-sub_visibility_c4.m:016:   error: the type `foo'/0 is undefined.
-sub_visibility_c4.m:016:   (The module `sub_visibility_c4.sub2' has not been
-sub_visibility_c4.m:016:   imported in the interface.)
+sub_visibility_c4.m:016:   warning: the type `foo'/0 is only visible here under
+sub_visibility_c4.m:016:   a deprecated visibility rule. Under the new rule,
+sub_visibility_c4.m:016:   the visibility of `foo'/0 is determined solely by
+sub_visibility_c4.m:016:   the import of `sub_visibility_c4.sub2' in this
+sub_visibility_c4.m:016:   module, regardless of any import declarations in
+sub_visibility_c4.m:016:   ancestor modules.
 sub_visibility_c4.m:017: In the first argument of function symbol `int_fq' of
 sub_visibility_c4.m:017:   the type `int_fq'/0:
-sub_visibility_c4.m:017:   error: the type `sub_visibility_c4.sub2.foo'/0 is
-sub_visibility_c4.m:017:   undefined.
-sub_visibility_c4.m:017:   (The module `sub_visibility_c4.sub2' has not been
-sub_visibility_c4.m:017:   imported in the interface.)
+sub_visibility_c4.m:017:   warning: the type `sub_visibility_c4.sub2.foo'/0 is
+sub_visibility_c4.m:017:   only visible here under a deprecated visibility
+sub_visibility_c4.m:017:   rule. Under the new rule, the visibility of
+sub_visibility_c4.m:017:   `sub_visibility_c4.sub2.foo'/0 is determined solely
+sub_visibility_c4.m:017:   by the import of `sub_visibility_c4.sub2' in this
+sub_visibility_c4.m:017:   module, regardless of any import declarations in
+sub_visibility_c4.m:017:   ancestor modules.
 sub_visibility_c4.m:035: In the first argument of function symbol `imp_uq' of
 sub_visibility_c4.m:035:   the type `imp_uq'/0:
-sub_visibility_c4.m:035:   error: the type `foo'/0 is undefined.
-sub_visibility_c4.m:035:   (Only fully module qualified names may refer to the
-sub_visibility_c4.m:035:   entities defined in module 
-sub_visibility_c4.m:035:   `sub_visibility_c4.sub2'.)
-`sub_visibility_c4.sub1.int' and `sub_visibility_c4.sub1.int2' not written.
+sub_visibility_c4.m:035:   warning: the type `foo'/0 is only visible here under
+sub_visibility_c4.m:035:   a deprecated visibility rule. Under the new rule,
+sub_visibility_c4.m:035:   the visibility of `foo'/0 is determined solely by
+sub_visibility_c4.m:035:   the import of `sub_visibility_c4.sub2' in this
+sub_visibility_c4.m:035:   module, regardless of any import declarations in
+sub_visibility_c4.m:035:   ancestor modules.
diff --git a/tests/invalid_submodules/sub_visibility_c4.err_exp2 b/tests/invalid_submodules/sub_visibility_c4.err_exp2
deleted file mode 100644
index 748c72c05f..0000000000
--- a/tests/invalid_submodules/sub_visibility_c4.err_exp2
+++ /dev/null
@@ -1,19 +0,0 @@
-sub_visibility_c4.m:016: In the first argument of function symbol `int_uq' of
-sub_visibility_c4.m:016:   the type `int_uq'/0:
-sub_visibility_c4.m:016:   error: the type `foo'/0 is undefined.
-sub_visibility_c4.m:016:   (The module `sub_visibility_c4.sub2' has not been
-sub_visibility_c4.m:016:   imported in the interface.)
-sub_visibility_c4.m:017: In the first argument of function symbol `int_fq' of
-sub_visibility_c4.m:017:   the type `int_fq'/0:
-sub_visibility_c4.m:017:   error: the type `sub_visibility_c4.sub2.foo'/0 is
-sub_visibility_c4.m:017:   undefined.
-sub_visibility_c4.m:017:   (The module `sub_visibility_c4.sub2' has not been
-sub_visibility_c4.m:017:   imported in the interface.)
-sub_visibility_c4.m:035: In the first argument of function symbol `imp_uq' of
-sub_visibility_c4.m:035:   the type `imp_uq'/0:
-sub_visibility_c4.m:035:   error: the type `foo'/0 is undefined.
-sub_visibility_c4.m:035:   (Only fully module qualified names may refer to the
-sub_visibility_c4.m:035:   entities defined in module 
-sub_visibility_c4.m:035:   `sub_visibility_c4.sub2'.)
-`Mercury/ints/sub_visibility_c4.sub1.int' and
-  `Mercury/int2s/sub_visibility_c4.sub1.int2' not written.
diff --git a/tests/invalid_submodules/sub_visibility_c4.m b/tests/invalid_submodules/sub_visibility_c4.m
index b03c74297e..3b06b7bb89 100644
--- a/tests/invalid_submodules/sub_visibility_c4.m
+++ b/tests/invalid_submodules/sub_visibility_c4.m
@@ -13,8 +13,8 @@
     :- module sub1.
     :- interface.
 
-    :- type int_uq ---> int_uq(foo). % error
-    :- type int_fq ---> int_fq(sub_visibility_c4.sub2.foo). % error
+    :- type int_uq ---> int_uq(foo). % deprecated
+    :- type int_fq ---> int_fq(sub_visibility_c4.sub2.foo). % deprecated
 
     :- end_module sub1.
 
@@ -32,7 +32,7 @@
 
     :- use_module sub_visibility_c4.sub2. % overrides decl in parent
 
-    :- type imp_uq ---> imp_uq(foo). % error
+    :- type imp_uq ---> imp_uq(foo). % deprecated
     :- type imp_fq ---> imp_fq(sub_visibility_c4.sub2.foo). % ok
 
     :- end_module sub1.
diff --git a/tests/invalid_submodules/sub_visibility_d3.err_exp b/tests/invalid_submodules/sub_visibility_d3.err_exp
index 2d4e9975b7..89b89c2cb8 100644
--- a/tests/invalid_submodules/sub_visibility_d3.err_exp
+++ b/tests/invalid_submodules/sub_visibility_d3.err_exp
@@ -1,12 +1,7 @@
 sub_visibility_d3.m:016: In the first argument of function symbol `int_uq' of
 sub_visibility_d3.m:016:   the type `int_uq'/0:
 sub_visibility_d3.m:016:   error: the type `foo'/0 is undefined.
-sub_visibility_d3.m:016:   (The module `sub_visibility_d3.sub2' has not been
-sub_visibility_d3.m:016:   imported in the interface.)
-sub_visibility_d3.m:017: In the first argument of function symbol `int_fq' of
-sub_visibility_d3.m:017:   the type `int_fq'/0:
-sub_visibility_d3.m:017:   error: the type `sub_visibility_d3.sub2.foo'/0 is
-sub_visibility_d3.m:017:   undefined.
-sub_visibility_d3.m:017:   (The module `sub_visibility_d3.sub2' has not been
-sub_visibility_d3.m:017:   imported in the interface.)
+sub_visibility_d3.m:016:   (Only fully module qualified names may refer to the
+sub_visibility_d3.m:016:   entities defined in module 
+sub_visibility_d3.m:016:   `sub_visibility_d3.sub2'.)
 `sub_visibility_d3.sub1.int' and `sub_visibility_d3.sub1.int2' not written.
diff --git a/tests/invalid_submodules/sub_visibility_d3.err_exp2 b/tests/invalid_submodules/sub_visibility_d3.err_exp2
index 3b896356c8..a3ba53db78 100644
--- a/tests/invalid_submodules/sub_visibility_d3.err_exp2
+++ b/tests/invalid_submodules/sub_visibility_d3.err_exp2
@@ -1,13 +1,8 @@
 sub_visibility_d3.m:016: In the first argument of function symbol `int_uq' of
 sub_visibility_d3.m:016:   the type `int_uq'/0:
 sub_visibility_d3.m:016:   error: the type `foo'/0 is undefined.
-sub_visibility_d3.m:016:   (The module `sub_visibility_d3.sub2' has not been
-sub_visibility_d3.m:016:   imported in the interface.)
-sub_visibility_d3.m:017: In the first argument of function symbol `int_fq' of
-sub_visibility_d3.m:017:   the type `int_fq'/0:
-sub_visibility_d3.m:017:   error: the type `sub_visibility_d3.sub2.foo'/0 is
-sub_visibility_d3.m:017:   undefined.
-sub_visibility_d3.m:017:   (The module `sub_visibility_d3.sub2' has not been
-sub_visibility_d3.m:017:   imported in the interface.)
+sub_visibility_d3.m:016:   (Only fully module qualified names may refer to the
+sub_visibility_d3.m:016:   entities defined in module 
+sub_visibility_d3.m:016:   `sub_visibility_d3.sub2'.)
 `Mercury/ints/sub_visibility_d3.sub1.int' and
   `Mercury/int2s/sub_visibility_d3.sub1.int2' not written.
diff --git a/tests/invalid_submodules/sub_visibility_d3.m b/tests/invalid_submodules/sub_visibility_d3.m
index a835529198..7d750cb3cc 100644
--- a/tests/invalid_submodules/sub_visibility_d3.m
+++ b/tests/invalid_submodules/sub_visibility_d3.m
@@ -14,7 +14,7 @@
     :- interface.
 
     :- type int_uq ---> int_uq(foo). % error
-    :- type int_fq ---> int_fq(sub_visibility_d3.sub2.foo). % error
+    :- type int_fq ---> int_fq(sub_visibility_d3.sub2.foo). % deprecated
 
     :- end_module sub1.
 
diff --git a/tests/invalid_submodules/sub_visibility_d4.err_exp b/tests/invalid_submodules/sub_visibility_d4.err_exp
index 6f2178472f..ebf8b49d97 100644
--- a/tests/invalid_submodules/sub_visibility_d4.err_exp
+++ b/tests/invalid_submodules/sub_visibility_d4.err_exp
@@ -1,14 +1,9 @@
 sub_visibility_d4.m:016: In the first argument of function symbol `int_uq' of
 sub_visibility_d4.m:016:   the type `int_uq'/0:
 sub_visibility_d4.m:016:   error: the type `foo'/0 is undefined.
-sub_visibility_d4.m:016:   (The module `sub_visibility_d4.sub2' has not been
-sub_visibility_d4.m:016:   imported in the interface.)
-sub_visibility_d4.m:017: In the first argument of function symbol `int_fq' of
-sub_visibility_d4.m:017:   the type `int_fq'/0:
-sub_visibility_d4.m:017:   error: the type `sub_visibility_d4.sub2.foo'/0 is
-sub_visibility_d4.m:017:   undefined.
-sub_visibility_d4.m:017:   (The module `sub_visibility_d4.sub2' has not been
-sub_visibility_d4.m:017:   imported in the interface.)
+sub_visibility_d4.m:016:   (Only fully module qualified names may refer to the
+sub_visibility_d4.m:016:   entities defined in module 
+sub_visibility_d4.m:016:   `sub_visibility_d4.sub2'.)
 sub_visibility_d4.m:035: In the first argument of function symbol `imp_uq' of
 sub_visibility_d4.m:035:   the type `imp_uq'/0:
 sub_visibility_d4.m:035:   error: the type `foo'/0 is undefined.
diff --git a/tests/invalid_submodules/sub_visibility_d4.err_exp2 b/tests/invalid_submodules/sub_visibility_d4.err_exp2
index 7ec0e45955..1b43979150 100644
--- a/tests/invalid_submodules/sub_visibility_d4.err_exp2
+++ b/tests/invalid_submodules/sub_visibility_d4.err_exp2
@@ -1,14 +1,9 @@
 sub_visibility_d4.m:016: In the first argument of function symbol `int_uq' of
 sub_visibility_d4.m:016:   the type `int_uq'/0:
 sub_visibility_d4.m:016:   error: the type `foo'/0 is undefined.
-sub_visibility_d4.m:016:   (The module `sub_visibility_d4.sub2' has not been
-sub_visibility_d4.m:016:   imported in the interface.)
-sub_visibility_d4.m:017: In the first argument of function symbol `int_fq' of
-sub_visibility_d4.m:017:   the type `int_fq'/0:
-sub_visibility_d4.m:017:   error: the type `sub_visibility_d4.sub2.foo'/0 is
-sub_visibility_d4.m:017:   undefined.
-sub_visibility_d4.m:017:   (The module `sub_visibility_d4.sub2' has not been
-sub_visibility_d4.m:017:   imported in the interface.)
+sub_visibility_d4.m:016:   (Only fully module qualified names may refer to the
+sub_visibility_d4.m:016:   entities defined in module 
+sub_visibility_d4.m:016:   `sub_visibility_d4.sub2'.)
 sub_visibility_d4.m:035: In the first argument of function symbol `imp_uq' of
 sub_visibility_d4.m:035:   the type `imp_uq'/0:
 sub_visibility_d4.m:035:   error: the type `foo'/0 is undefined.
diff --git a/tests/invalid_submodules/sub_visibility_d4.m b/tests/invalid_submodules/sub_visibility_d4.m
index 1557cda6e2..2d748ce989 100644
--- a/tests/invalid_submodules/sub_visibility_d4.m
+++ b/tests/invalid_submodules/sub_visibility_d4.m
@@ -14,7 +14,7 @@
     :- interface.
 
     :- type int_uq ---> int_uq(foo). % error
-    :- type int_fq ---> int_fq(sub_visibility_d4.sub2.foo). % error
+    :- type int_fq ---> int_fq(sub_visibility_d4.sub2.foo). % deprecated
 
     :- end_module sub1.
 
-- 
2.54.0



More information about the reviews mailing list