diff --git a/compiler/add_type.m b/compiler/add_type.m index a68bd1901..edf519a47 100644 --- a/compiler/add_type.m +++ b/compiler/add_type.m @@ -942,24 +942,49 @@ add_du_ctors_check_subtype_check_foreign_type(TypeTable, TypeCtor, TypeDefn, % save a pass over the type table. ( MaybeSuperType = subtype_of(SuperType), - check_subtype_defn(TypeTable, TVarSet, TypeCtor, TypeDefn, BodyDu, + FileName = Context ^ context_filename, + ( if string.suffix(FileName, ".int2") then + % Consider what happens when, in the process of compiling + % module A, mmc reads B.int, which refers to module C, + % requiring C.int2 to be read. If C.int2 contains a subtype + % definition whose supertype is defined in module D, and + % module D is not imported by module A, then the check + % of the subtype read from C.int2 will fail with an error. + % + % We *must* include the subtype definition in C.int2, because + % any failure to do so would screw up any references + % to the subtype that happen via shorter import chains. + % This is why we avoid performing subtype tests that may + % refer to subtypes in modules like D that whose contents + % we do not see. + % + % This should be ok, since any errors that we could discover + % here if we *did* see D definitely will be discovered + % when compiling modules that get to D via shorter + % import chains. + true + else + check_subtype_defn(TypeTable, TVarSet, + TypeCtor, TypeDefn, BodyDu, SuperType, MaybeSetSubtypeNoncanon, !InvalidTypeSpecs, !WarnSpecs), ( MaybeSetSubtypeNoncanon = do_not_set_subtype_noncanon ; MaybeSetSubtypeNoncanon = set_subtype_noncanon, - % Set noncanonical flag on subtype definition if the base type - % is noncanonical. + % Set noncanonical flag on subtype definition + % if the base type is noncanonical. NoncanonBodyDu = BodyDu ^ du_type_canonical := noncanon(noncanon_subtype), NoncanonBody = hlds_du_type(NoncanonBodyDu), - set_type_defn_body(NoncanonBody, TypeDefn, NoncanonTypeDefn), + set_type_defn_body(NoncanonBody, + TypeDefn, NoncanonTypeDefn), module_info_get_type_table(!.ModuleInfo, TypeTable0), replace_type_ctor_defn(TypeCtor, NoncanonTypeDefn, TypeTable0, TypeTable1), module_info_set_type_table(TypeTable1, !ModuleInfo) ) + ) ; MaybeSuperType = not_a_subtype ), diff --git a/compiler/comp_unit_interface.m b/compiler/comp_unit_interface.m index cc2dc1e04..b9a5f8171 100644 --- a/compiler/comp_unit_interface.m +++ b/compiler/comp_unit_interface.m @@ -32,6 +32,8 @@ :- import_module list. :- import_module maybe. +%---------------------------------------------------------------------------% + % Each of the predicates % % generate_parse_tree_int3 @@ -2798,8 +2800,16 @@ restrict_type_ctor_int_defn_for_int2(TypeDefnInfo0, TypeDefnInfo, TypeDefn0 = parse_tree_sub_type(DetailsSub), DetailsSub = type_details_sub(SuperType, _Ctors), accumulate_modules_in_type(SuperType, !MaybeUnqual, !ModuleNames), - % The consideration just above about the types of constructors - % in du types applies also to subtypes. + % Consider what happens when, in the process of compiling module A, + % mmc reads B.int, which refers to module C, requiring C.int2 + % to be read. If C.int2 contains a subtype definition whose supertype + % is defined in module D, and module D is not imported by module A, + % then the check of the subtype read from C.int2 will fail + % with an error. + % + % However, we have to include the subtype definition in C.int2 + % anyway. This is because not doing so would screw up any references + % to the subtype that happen via shorter import chains. TypeDefnInfo = TypeDefnInfo0 ; TypeDefn0 = parse_tree_solver_type(_), diff --git a/compiler/options.m b/compiler/options.m index c2323bd86..4e1531fb4 100644 --- a/compiler/options.m +++ b/compiler/options.m @@ -5664,7 +5664,8 @@ optdb(oc_dev_ctrl, compiler_sufficiently_recent, bool(no), "allow-non-contig-for-2025-06-01", "subtype-int2-2025-07-07", "inrange-2025-10-01", - "scout-disj-2025-11-15"], [ + "scout-disj-2025-11-15", + "subtype-int2-2026-08-09"], [ w("Is the compiler sufficiently recent to contain the new feature"), w("or bugfix referred to by each name?")])). % These options are provided for use by implementors who want to compare diff --git a/tests/warnings/help_text.err_exp b/tests/warnings/help_text.err_exp index 0fac83544..d19f060e1 100644 --- a/tests/warnings/help_text.err_exp +++ b/tests/warnings/help_text.err_exp @@ -3721,6 +3721,7 @@ Options for developers only --subtype-int2-2025-07-07 --inrange-2025-10-01 --scout-disj-2025-11-15 + --subtype-int2-2026-08-09 Is the compiler sufficiently recent to contain the new feature or bugfix referred to by each name?