[BUG][RUST] oneOf with value and array results in invalid code
Bug Report Checklist
- [x] Have you provided a full/minimal spec to reproduce the issue?
- [x] Have you validated the input using an OpenAPI validator (example)?
- [x] Have you tested with the latest master to confirm the issue still exists?
- [x] Have you searched for related issues/PRs?
- [x] What's the actual output vs expected output?
- [ ] [Optional] Sponsorship to speed up the bug fix or feature request (example)
Description
Basically, using a oneof in rust generates an enum. When actually using that enum to make a request, there is an error because the enum cannot be converted to a string because it doesn't implement the display trait.
To fix this, there are two options:
- Implement the display trait for the enum so that it converts itself into a string correctly (not ideal because you'd have to deal with url encoding when you implement the trait).
- Handle each enum variant when you are building the request (which is what I implemented - see below)
Full Error from output
error[E0599]: the method `to_string` exists for reference `&GetSystemWaypointsTraitsParameter`, but its trait bounds were not satisfied --> src/apis/systems_api.rs:256:89 | 256 | local_var_req_builder = local_var_req_builder.query(&[("traits", &local_var_str.to_string())]); | ^^^^^^^^^ method cannot be called on `&GetSystemWaypointsTraitsParameter` due to unsatisfied trait bounds | ::: src/models/get_system_waypoints_traits_parameter.rs:16:1 | 16 | pub enum GetSystemWaypointsTraitsParameter { | ------------------------------------------ doesn't satisfy `GetSystemWaypointsTraitsParameter: ToString` or `_: Display` | = note: the following trait bounds were not satisfied: `GetSystemWaypointsTraitsParameter: std::fmt::Display` which is required by `GetSystemWaypointsTraitsParameter: ToString` `&GetSystemWaypointsTraitsParameter: std::fmt::Display` which is required by `&GetSystemWaypointsTraitsParameter: ToString` note: the trait `std::fmt::Display` must be implemented --> /home/jack/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/fmt/mod.rs:705:1 | 705 | pub trait Display { | ^^^^^^^^^^^^^^^^^ = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `to_string`, perhaps you need to implement it: candidate #1: `ToString`For more information about this error, try rustc --explain E0599.
error: could not compile openapi (lib) due to 1 previous error
openapi-generator version
7.6.0 also tested with latest snapshot
OpenAPI declaration file content or url
https://raw.githubusercontent.com/SpaceTradersAPI/api-docs/main/reference/SpaceTraders.json Specific offending portion: https://github.com/SpaceTradersAPI/api-docs/blob/3ff410cbfe2ab9f05b73a7d1d92cca0593480018/reference/SpaceTraders.json#L513C11-L529C14
Generation Details
This is the command I was using
openapi-generator-cli generate -i spacetraders-api-docs-spacedust-patch/reference/SpaceTraders.json -g rust -o client-dist --additional-properties=packageName=spacedust,supportAsync=true,supportMiddleware=true
Steps to reproduce
git clone https://github.com/SpaceTradersAPI/api-docs
openapi-generator-cli generate -i api-docs/reference/SpaceTraders.json -g rust -o client-dist
cd client-dist
cargo check
Related issues/PRs
Seems to be somewhat related to this previously fixed issue: https://github.com/OpenAPITools/openapi-generator/issues/17896
Searching the issue list for rust oneof comes up with a few that seems to be somewhat similar but not the same:
https://github.com/OpenAPITools/openapi-generator/issues/18527
https://github.com/OpenAPITools/openapi-generator/issues/17210
https://github.com/OpenAPITools/openapi-generator/issues/13257
https://github.com/OpenAPITools/openapi-generator/issues/9497
https://github.com/OpenAPITools/openapi-generator/issues/7802
https://github.com/OpenAPITools/openapi-generator/issues/3297
Suggest a fix
This is what I did to fix the generated code, but I don't know how I would fix the generator.
$ diff client-dist4/src/apis/systems_api.rs client-dist2/src/apis/systems_api.rs
255,256c255,267
< if let Some(ref local_var_str) = traits {
< local_var_req_builder = local_var_req_builder.query(&[("traits", &local_var_str.to_string())]);
---
> if let Some(ref local_var_enum) = traits {
> if let models::GetSystemWaypointsTraitsParameter::Array(local_str_array) = local_var_enum {
> for local_var_str in local_str_array {
> local_var_req_builder =
> local_var_req_builder.query(&[("traits", &local_var_str.to_string())]);
> }
> } else if let models::GetSystemWaypointsTraitsParameter::WaypointTraitSymbol(
> local_var_str,
> ) = local_var_enum
> {
> local_var_req_builder =
> local_var_req_builder.query(&[("traits", &local_var_str.to_string())]);
> }
This is just something that works. I'm not necessarily recommending this because I don't know the conventions for generated code or what you have available in the generator.