Split out of the review of PR #351 (#339), where the class became visible.
The class
A crate's artifact identity (compute_crate_hash, _pyo3_wrapper_build_env) is computed from more than files. RUSTFLAGS, PYO3_PYTHON, RUSTCALL_PYTHON_LIBDIR, a PYO3_CONFIG_FILE that now points at a different file, and the rest of the artifact_build_env allowlist all change what is built.
Julia invalidates a precompile image from files: Base.include_dependency tracks a file's content (or a directory's entry list), and that is the only lever a generated module has. So after #351 the image is invalidated by an edit to the crate, to a path dependency, to .cargo/config.toml, to PYO3_CONFIG_FILE itself, and by a file appearing or disappearing in any of those directories — but not by the environment changing. Every tracked file is then still byte-for-byte what it was, the image stays valid, and the package loads a library built for the other environment.
#351 makes the module record the environment it was generated under and @warn from __init__ when it no longer matches, naming the variables. That converts silence into a message; it does not invalidate anything.
What a real fix would need
Something the image can carry that changes when a non-file input does. Options, none of them free:
- a stamp file per (crate, environment) under RustCall's cache whose content is the artifact key, declared with
include_dependency — the difficulty is that only a re-precompile rewrites it, which is the step being skipped, so the stamp has to be written by something that runs on every load, or keyed so that a new environment names a path that does not exist yet;
Base.CacheFlags-style participation, if Julia gains a hook for package-defined invalidation predicates;
- refusing to load instead of warning, which is honest but breaks a workflow where the difference is deliberate.
Acceptance
Split out of the review of PR #351 (#339), where the class became visible.
The class
A crate's artifact identity (
compute_crate_hash,_pyo3_wrapper_build_env) is computed from more than files.RUSTFLAGS,PYO3_PYTHON,RUSTCALL_PYTHON_LIBDIR, aPYO3_CONFIG_FILEthat now points at a different file, and the rest of theartifact_build_envallowlist all change what is built.Julia invalidates a precompile image from files:
Base.include_dependencytracks a file's content (or a directory's entry list), and that is the only lever a generated module has. So after #351 the image is invalidated by an edit to the crate, to apathdependency, to.cargo/config.toml, toPYO3_CONFIG_FILEitself, and by a file appearing or disappearing in any of those directories — but not by the environment changing. Every tracked file is then still byte-for-byte what it was, the image stays valid, and the package loads a library built for the other environment.#351 makes the module record the environment it was generated under and
@warnfrom__init__when it no longer matches, naming the variables. That converts silence into a message; it does not invalidate anything.What a real fix would need
Something the image can carry that changes when a non-file input does. Options, none of them free:
include_dependency— the difficulty is that only a re-precompile rewrites it, which is the step being skipped, so the stamp has to be written by something that runs on every load, or keyed so that a new environment names a path that does not exist yet;Base.CacheFlags-style participation, if Julia gains a hook for package-defined invalidation predicates;Acceptance
PYO3_PYTHONand loaded with another either rebuilds or refuses, rather than warning and continuing;RUSTFLAGS;@rust_crateprecompile testsets already pin that an unchanged crate is not re-precompiled;docs/src/crate_bindings.mddescribes whatever rule replaces the warning.