Repository navigation
Conversation
There was a problem hiding this comment.
All reported issues were addressed across 18 files
Reply with feedback, questions, or to request a fix.
View guided diff | Re-trigger cubic
|
Thanks for the PR cc @linxGnu for review |
|
|
||
| // Model fields that lead back to their own model (directly or through other models) | ||
| // would make the struct infinitely sized, so they are boxed. | ||
| final Map<String, CodegenModel> models = new HashMap<>(); | ||
| for (ModelsMap modelsMap : objs.values()) { | ||
| for (ModelMap mo : modelsMap.getModels()) { | ||
| models.put(mo.getModel().classname, mo.getModel()); | ||
| } | ||
| } | ||
|
|
||
| for (CodegenModel cm : models.values()) { | ||
| for (CodegenProperty var : cm.vars) { | ||
| final String target = directModelReference(var); | ||
| if (target != null && reachesModel(target, cm.classname, models, new HashSet<>())) { | ||
| var.vendorExtensions.put("x-is-boxed", true); | ||
| } | ||
| } | ||
| } | ||
|
|
There was a problem hiding this comment.
@teovillanueva
Hi, I don't want to break existing generated code. Please feature-gate it throughout additionalProperties
There was a problem hiding this comment.
Done in 92e3fdc: the boxing is now behind a new boxRecursiveModels option (default false), so without it the generated code is the same as on master. The new rust-axum-recursive-models sample enables it, there is a test for each case, the docs are regenerated, and the integration tests pass.
linxGnu
left a comment
There was a problem hiding this comment.
LGTM. Thank you for contributing to Rust-Axum @teovillanueva
cc @wing328 to merge this PR
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 viaanyOf/oneOfwithnullornullable+allOf; a cycle such asEmployee -> Department -> Employee; or a cycle through aoneOfenum such asCircle.inner -> Shape -> Circle.Changes
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.3_1/rust-axum/rust-axum-recursive-models.yamland sample configrust-axum-recursive-models(withboxRecursiveModels: true).Not covered
Testing
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.RustAxumServerCodegenTest#testRecursiveModelFieldsAreNotBoxedByDefault: without the option, nothing is boxed.mvn integration-test -f samples/server/petstore/rust-axum/pom.xmlpasses.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
RUST_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.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 newboxRecursiveModelsoption (defaultfalse), so existing generated code stays byte-identical.postProcessAllModelsand marks the offending fields withx-is-boxed.models.mustacheto emitBox<...>for those fields in the struct,new(), andFromStr.Vecand non-recursive references are unchanged.rust-axum-recursive-models) and unit tests covering direct, nullable, indirect, andoneOfrecursion.Written for commit 92e3fdc. Summary will update on new commits.