[rust-axum] fix: box recursive model fields
Fixes #25295
rust-axum generates model fields that hold another model without any indirection. When a model leads back to itself, the generated type has infinite size and the crate fails to compile with E0072. Examples: parent: Node; a nullable self reference via anyOf/oneOf with null or nullable + allOf; a cycle such as Employee -> Department -> Employee; or a cycle through a oneOf enum such as Circle.inner -> Shape -> Circle.
Changes
- New option
boxRecursiveModels(defaultfalse). Without it the generated code is exactly what master produces today; with it, the boxing below is applied. RustAxumServerCodegen.postProcessAllModels: checks every struct field that holds a model directly (not inside a container). If that model can lead back to the current one, the field getsx-is-boxed. The check follows direct model fields and the oneOf/anyOf variants of enum models.models.mustache: forx-is-boxedfields, wraps the type inBox<...>in the struct field and innew(), and boxes the parsed value in theFromStrimplementation.- Non-recursive fields are not changed. All existing rust-axum samples are byte-identical after regeneration.
- New spec
3_1/rust-axum/rust-axum-recursive-models.yamland sample configrust-axum-recursive-models(withboxRecursiveModels: true).
Not covered
- rust-server (#5950) and rust-salvo, which have the same issue.
Testing
- New
RustAxumServerCodegenTest#testRecursiveModelFieldsAreBoxed. It checks direct, nullable (anyOf/oneOf null), indirect and oneOf-variant recursion. It also checks thatVecand non-recursive references are not boxed. The test fails without the fix. - New
RustAxumServerCodegenTest#testRecursiveModelFieldsAreNotBoxedByDefault: without the option, nothing is boxed. mvn integration-test -f samples/server/petstore/rust-axum/pom.xmlpasses.- New sample
samples/server/petstore/rust-axum/output/rust-axum-recursive-models. These pass on it:cargo build --all-targets --all-features,cargo build --all-targets --no-default-features,cargo test,cargo clippy --all-targets --all-features. Before the fix, the same spec failscargo checkwith E0072.
PR checklist
- Read the contribution guidelines.
- Run the following to build the project and update samples:
Regenerated all rust-axum samples with./mvnw clean package || exit ./bin/generate-samples.sh ./bin/configs/*.yaml || exit ./bin/utils/export_docs_generators.sh || exitRUST_POST_PROCESS_FILE=$PWD/samples/server/petstore/rust-axum/rustfmt-2021.sh ./bin/generate-samples.sh bin/configs/manual/rust-axum*(17 configs, including the newrust-axum-recursive-models). The only change is the new sample.docs/generators/rust-axum.mdwas regenerated withexport_docs_generators.shfor the new option. - If your PR is targeting a particular programming language, @mention the technical committee members, so they are more likely to review the pull request.
cc @frol @farcaller @richardwhiuk @paladinzh @jacob-pro @dsteeley
Summary by cubic
Fixes recursive model fields in the rust-axum generator so models that reference themselves, directly or through other models, compile without E0072. Fields that would create an infinitely sized type are now wrapped in Box<...> behind the new boxRecursiveModels option (default false), so existing generated code stays byte-identical.
- Detects cycles in
postProcessAllModelsand marks the offending fields withx-is-boxed. - Updates
models.mustacheto emitBox<...>for those fields in the struct,new(), andFromStr. - Only direct model references are boxed; containers like
Vecand non-recursive references are unchanged. - Adds a new sample (
rust-axum-recursive-models) and unit tests covering direct, nullable, indirect, andoneOfrecursion.