Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't build Stripe's OpenAPI spec with "not yet implemented". panic from proc macro from typify-impl #850

Open
cowlicks opened this issue Jul 7, 2024 · 3 comments

Comments

@cowlicks
Copy link

cowlicks commented Jul 7, 2024

The OpenAPI spec is here.

The failure is at "typify-288d5a84bbbe6a46/25e11d8/typify-impl/src/util.rs:246:25:"

When building with the macro, the error comes from a proc macro panic which offers very little context:

    Checking redacted v0.1.0 (redacted)
error: proc macro panicked
  --> redacted/src/main.rs:40:1
   |
40 | generate_api!("../../../stripe-openapi/openapi/spec3.json");
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = help: message: not yet implemented

error: could not compile redacted` (bin "redacted") due to 1 previous error

I got more info running it from a build.rs:

 RUST_BACKTRACE=1 cargo c
warning: unused variable: `src`
 --> redacted/build.rs:6:9
  |
6 |     let src = "../../../stripe-openapi/openapi/fixtures3.json";
  |         ^^^ help: if this is intentional, prefix it with an underscore: `_src`
  |
  = note: `#[warn(unused_variables)]` on by default

warning: `redacted` (build script) generated 1 warning
   Compiling redacted v0.1.0 (redacted
error: failed to run custom build command for `redacted v0.1.0 (redacted)`
note: To improve backtraces for build dependencies, set the CARGO_PROFILE_DEV_BUILD_OVERRIDE_DEBUG=true environment variable to enable debug information generation.

Caused by:
  process didn't exit successfully: `redacted/build-script-build` (exit status: 101)
  --- stdout
  cargo:rerun-if-changed=../migrations
  cargo:rerun-if-changed=../../../stripe-openapi/openapi/spec3.json

  --- stderr
  thread 'main' panicked at /Users/nbajskansbbbelopni/.cargo/git/checkouts/typify-288d5a84bbbe6a46/25e11d8/typify-impl/src/util.rs:246:25:
  not yet implemented
  stack backtrace:
     0: rust_begin_unwind
               at /rustc/aedd173a2c086e558c2b66d3743b344f977621a7/library/std/src/panicking.rs:647:5
     1: core::panicking::panic_fmt
               at /rustc/aedd173a2c086e558c2b66d3743b344f977621a7/library/core/src/panicking.rs:72:14
     2: core::panicking::panic
               at /rustc/aedd173a2c086e558c2b66d3743b344f977621a7/library/core/src/panicking.rs:144:5
     3: typify_impl::util::schemas_mutually_exclusive
     4: typify_impl::util::all_mutually_exclusive::{{closure}}
     5: core::iter::traits::iterator::Iterator::all::check::{{closure}}
     6: core::ops::function::impls::<impl core::ops::function::FnMut<A> for &mut F>::call_mut
     7: core::iter::adapters::map::map_try_fold::{{closure}}
     8: core::iter::traits::iterator::Iterator::try_fold
     9: <core::iter::adapters::map::Map<I,F> as core::iter::traits::iterator::Iterator>::try_fold
    10: <core::iter::adapters::flatten::FlattenCompat<I,U> as core::iter::traits::iterator::Iterator>::try_fold::flatten::{{closure}}
    11: core::iter::adapters::flatten::FlattenCompat<I,U>::iter_try_fold::flatten::{{closure}}
    12: core::iter::adapters::map::map_try_fold::{{closure}}
    13: core::iter::traits::iterator::Iterator::try_fold
    14: <core::iter::adapters::map::Map<I,F> as core::iter::traits::iterator::Iterator>::try_fold
    15: <core::iter::adapters::fuse::Fuse<I> as core::iter::adapters::fuse::FuseImpl<I>>::try_fold
    16: core::iter::adapters::flatten::FlattenCompat<I,U>::iter_try_fold
    17: <core::iter::adapters::flatten::FlatMap<I,U,F> as core::iter::traits::iterator::Iterator>::try_fold
    18: core::iter::traits::iterator::Iterator::all
    19: typify_impl::util::all_mutually_exclusive
    20: typify_impl::convert::<impl typify_impl::TypeSpace>::convert_any_of
    21: typify_impl::convert::<impl typify_impl::TypeSpace>::convert_schema_object
    22: typify_impl::convert::<impl typify_impl::TypeSpace>::convert_schema
    23: typify_impl::TypeSpace::id_for_schema
    24: typify_impl::structs::<impl typify_impl::TypeSpace>::struct_property
    25: typify_impl::structs::<impl typify_impl::TypeSpace>::struct_members::{{closure}}
    26: core::iter::adapters::filter_map::filter_map_try_fold::{{closure}}
    27: core::ops::function::impls::<impl core::ops::function::FnMut<A> for &mut F>::call_mut
    28: core::iter::traits::iterator::Iterator::try_fold
    29: <core::iter::adapters::chain::Chain<A,B> as core::iter::traits::iterator::Iterator>::try_fold
    30: <core::iter::adapters::filter_map::FilterMap<I,F> as core::iter::traits::iterator::Iterator>::try_fold
    31: <core::iter::adapters::GenericShunt<I,R> as core::iter::traits::iterator::Iterator>::try_fold
    32: <core::iter::adapters::GenericShunt<I,R> as core::iter::traits::iterator::Iterator>::next
    33: alloc::vec::Vec<T,A>::extend_desugared
    34: <alloc::vec::Vec<T,A> as alloc::vec::spec_extend::SpecExtend<T,I>>::spec_extend
    35: <alloc::vec::Vec<T> as alloc::vec::spec_from_iter_nested::SpecFromIterNested<T,I>>::from_iter
    36: <alloc::vec::Vec<T> as alloc::vec::spec_from_iter::SpecFromIter<T,I>>::from_iter
    37: <alloc::vec::Vec<T> as core::iter::traits::collect::FromIterator<T>>::from_iter
    38: <core::result::Result<V,E> as core::iter::traits::collect::FromIterator<core::result::Result<A,E>>>::from_iter::{{closure}}
    39: core::iter::adapters::try_process
    40: <core::result::Result<V,E> as core::iter::traits::collect::FromIterator<core::result::Result<A,E>>>::from_iter
    41: core::iter::traits::iterator::Iterator::collect
    42: typify_impl::structs::<impl typify_impl::TypeSpace>::struct_members
    43: typify_impl::convert::<impl typify_impl::TypeSpace>::convert_object
    44: typify_impl::convert::<impl typify_impl::TypeSpace>::convert_schema_object
    45: typify_impl::convert::<impl typify_impl::TypeSpace>::convert_schema
    46: typify_impl::TypeSpace::convert_ref_type
    47: typify_impl::TypeSpace::add_ref_types_impl
    48: typify_impl::TypeSpace::add_ref_types
    49: progenitor_impl::Generator::generate_tokens
    50: build_script_build::main
    51: core::ops::function::FnOnce::call_once
  note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
@ahl
Copy link
Collaborator

ahl commented Jul 9, 2024

I think this proximate failure may be addressed by the fix for oxidecomputer/typify#616. Once I try that I get:

gen fail: UnexpectedFormat("unsupported style of query parameter DeepObject")
Error: generation experienced errors

This seems to be caused by this:

    "/v1/account": {
      "get": {
        "description": "<p>Retrieves the details of an account.</p>",
        "operationId": "GetAccount",
        "parameters": [
          {
            "description": "Specifies which fields in the response should be expanded.",
            "explode": true,
            "in": "query",
            "name": "expand",
            "required": false,
            "schema": {
              "items": {
                "maxLength": 5000,
                "type": "string"
              },
              "type": "array"
            },
            "style": "deepObject"
          }
        ],

It's a bit confusing: style: deepObject is only defined for non-nested objects; it's behavior for arrays is undefined.

I see other uses of style: deepObject that would take some work to support...

@cowlicks
Copy link
Author

cowlicks commented Jul 9, 2024

FWIW I moved on to using async-stripe, however they are using the OpenAPI spec to generate their client. That code is here: https://github.com/arlyon/async-stripe/tree/master/openapi

@ahl
Copy link
Collaborator

ahl commented Jul 10, 2024

That seems like a good option!

Some notes for myself if we get back here: async-stripe appears to be partially hand-written and tailored particularly to the Stripe API. For example, it contains special handling for this "expand" query parameter:

https://github.com/arlyon/async-stripe/blob/0a00d31894191ee0c6b4bda31e0d52d59e8e93b7/openapi/src/codegen.rs#L364-L369

It uses serde_qs, but that seems to produce output different than what the Stripe docs describe. For example:

Stripe docs:

curl https://api.stripe.com/v1/charges/ch_3LmzzQ2eZvKYlo2C0XjzUzJV \
  -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \
  -d "expand[]"=customer \
  -d "expand[]"="invoice.subscription" \
  -G

serde_qs:

#[derive(Deserialize, Serialize, Debug, Clone)]
struct Foo {
    expand: Vec<String>,
}

fn main() {
    let foo = Foo {
        expand: vec!["customer".to_string(), "invoice.subscription".to_string()],
    };

    let out = serde_qs::to_string(&foo).unwrap();
    assert_eq!(out, "expand[0]=customer&expand[1]=invoice.subscription");
 }

I'd bet that the Stripe API is using Javascript's qs or something similar so it probably accepts that as well (even though serde_qs doesn't accept the form with indices present).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants