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

trait-based APIs defined local to a function don't compile #1128

Open
davepacheco opened this issue Oct 2, 2024 · 2 comments
Open

trait-based APIs defined local to a function don't compile #1128

davepacheco opened this issue Oct 2, 2024 · 2 comments

Comments

@davepacheco
Copy link
Collaborator

I expected this to succeed:

fn main() {
    #[dropshot::api_description]
    trait MyApi {
        type Context;
    }
    let description = my_api_mod::stub_api_description().unwrap();
    let spec = description.openapi("Counter Server", "1.0.0");
    println!(
        "{}",
        serde_json::to_string_pretty(&spec.json().unwrap()).unwrap()
    );
}

Instead it fails with:

$ cargo run --example=api-trait-broken
   Compiling dropshot v0.12.1-dev (/Users/dap/oxide/dropshot-operation-id/dropshot)
error[E0405]: cannot find trait `MyApi` in this scope
 --> dropshot/examples/api-trait-broken.rs:3:11
  |
3 |     trait MyApi {
  |           ^^^^^ not found in this scope

For more information about this error, try `rustc --explain E0405`.
error: could not compile `dropshot` (example "api-trait-broken") due to 1 previous error
@sunshowers
Copy link
Contributor

Yes, this is a Rust limitation that makes me very sad:

// super::* pulls in definitions from the surrounding scope.
// This is not ideal because it means that the macro can only be
// applied to traits defined in modules, not in functions.
//
// A much better approach would be to be able to annotate the
// module and say "don't create a new scope", similar to
// `#[transparent]` as proposed in
// https://github.com/rust-lang/rust/issues/79260.
//
// There does not appear to be a workaround for this, short of
// not using a module at all. There are two other options:
//
// 1. Put the functions below into the parent scope. This adds a
// bunch of items to the scope rather than one, which seems
// worse on balance.
// 2. Make these methods on a type rather than free functions in
// a module. This approach works for functions, but not other
// items like macros we may wish to define in the future.
//
// In RFD 479, we determined that on balance, the current
// approach has the fewest downsides.

See also rust-lang/rust#79260.

@davepacheco
Copy link
Collaborator Author

Is this worth documenting, or do we figure it's too obscure?

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