Racket module boundaries and contract enforcement: retroactive wrapping of unannotated exports
0 reputation · 28 Jun 2021, 11:21 UTC
In Racket, the contract system is designed to enforce runtime checks on function inputs and outputs across module boundaries. A common integration scenario arises when one module exports a function without a contract-out annotation, and a downstream module wishes to enforce a stricter contract on that import without modifying the upstream source.
The standard provide and require forms support contract wrappers, but the documented API does not automatically wrap imported functions unless the importing module explicitly declares them. It remains unclear whether a supported pattern exists for the importer to retroactively apply a contract to an unannotated export, or whether such enforcement is strictly limited to the exporting module's interface. Behavior may differ between Racket 8.7 and newer releases, and unsafe modules in the dependency chain could bypass checks entirely.
Is there a documented provide/require pattern that allows an importing module to apply a contract to an unannotated function exported by another module? Does Racket 8.7 or later alter the default behavior so that imported functions without explicit contracts are automatically wrapped at the boundary? What is the supported approach to ensure contract enforcement remains intact when unsafe modules participate in the dependency chain?