Summary
When a subtype declaration appears inside a section and depends on a section-declared free type, the resulting type does not get generalized over that type at section close, even though the auto-generated operations and axioms are. The result is an inconsistent state where the operations/axioms are polymorphic but the underlying type is shared across all instantiations — a soundness gap.
Repro
section.
declare type c.
subtype carrier = { x : int * c | true }.
end section.
print carrier.
print to_carrier.
After section close:
carrier is bound with tyd_params = [] — a single, shared type for all 'c.
to_carrier / of_carrier / the auto-axioms (to_carrierN, of_carrierP, of_carrierK) are correctly polymorphic over 'c.
The same carrier type is shared across every instantiation of 'c, while the operations claim to take 'c as a parameter. The conjunction is unsound: from an axiom about carrier derived under one 'c you can specialise the operations at a different 'c.
Why
generalize_tydecl at section close uses tydecl_fv to find which section-declared types a tydecl depends on. For a subtype, tyd_type is an opaque Abstract marker — it does not contain the carrier expression or the predicate, so tydecl_fv returned an empty fv set. The auto-generated ops/axioms, in contrast, contain the carrier and predicate explicitly in their type/spec, so the section-close pass correctly added tparams to them.
Expected
After section close, the subtype is generalized over every section-declared free type its carrier or predicate mentions, matching the generalization of its auto-generated ops and axioms.
Summary
When a
subtypedeclaration appears inside asectionand depends on a section-declared free type, the resulting type does not get generalized over that type at section close, even though the auto-generated operations and axioms are. The result is an inconsistent state where the operations/axioms are polymorphic but the underlying type is shared across all instantiations — a soundness gap.Repro
After section close:
carrieris bound withtyd_params = []— a single, shared type for all'c.to_carrier/of_carrier/ the auto-axioms (to_carrierN,of_carrierP,of_carrierK) are correctly polymorphic over'c.The same
carriertype is shared across every instantiation of'c, while the operations claim to take'cas a parameter. The conjunction is unsound: from an axiom aboutcarrierderived under one'cyou can specialise the operations at a different'c.Why
generalize_tydeclat section close usestydecl_fvto find which section-declared types atydecldepends on. For asubtype,tyd_typeis an opaqueAbstractmarker — it does not contain the carrier expression or the predicate, sotydecl_fvreturned an empty fv set. The auto-generated ops/axioms, in contrast, contain the carrier and predicate explicitly in their type/spec, so the section-close pass correctly added tparams to them.Expected
After section close, the subtype is generalized over every section-declared free type its carrier or predicate mentions, matching the generalization of its auto-generated ops and axioms.