tokio-rs / prost

PROST! a Protocol Buffers implementation for the Rust Language
Apache License 2.0
3.95k stars 508 forks source link

too many leading `super` keywords while using google.rpc.status #727

Open mvanotti opened 2 years ago

mvanotti commented 2 years ago

Hi!

I am trying to build a simple example with three protos, but I keep getting this weird error. I am probably holding it wrong, so any advice on how to fix this would be appreciated :)

My example contains basically, items.proto + google.rpc.status + google.protobuf.any:

syntax = "proto3";

package snazzy.items;

import "google/rpc/status.proto";

// A snazzy new shirt!
message Shirt {
    enum Size {
        SMALL = 0;
        MEDIUM = 1;
        LARGE = 2;
    }

    string color = 1;
    Size size = 2;
    google.rpc.Status error = 4;
}
$ tree
.
├── build.rs
├── Cargo.lock
├── Cargo.toml
└── src
    ├── google
    │   ├── protobuf
    │   │   └── any.proto
    │   └── rpc
    │       └── status.proto
    ├── items.proto
    └── main.rs

My build.rs:

use std::io::Result;

fn main() -> Result<()> {
    prost_build::compile_protos(&["src/items.proto"], &["src/"])?;
    Ok(())
}

main.rs:

pub mod items {
    include!(concat!(env!("OUT_DIR"), "/google.rpc.rs"));
    include!(concat!(env!("OUT_DIR"), "/google.protobuf.rs"));
    include!(concat!(env!("OUT_DIR"), "/snazzy.items.rs"));
}

pub fn create_large_shirt(color: String) -> items::Shirt {
    let mut shirt = items::Shirt::default();
    shirt.color = color;
    shirt.set_size(items::shirt::Size::Large);
    shirt
}

fn main() {
    println!("Hello, world!");
    let shirt = create_large_shirt("BLUE".to_string());
    println!("shirt: {:?}", shirt);
}

And this is the error I am getting:

error[E0433]: failed to resolve: there are too many leading `super` keywords
 --> /home/mvanotti/rust/snazzy/target/debug/build/snazzy-e49e8cd9095ad904/out/snazzy.items.rs:9:46
  |
9 |     pub error: ::core::option::Option<super::super::google::rpc::Status>,
  |                                              ^^^^^ there are too many leading `super` keywords

error[E0283]: type annotations needed
 --> /home/mvanotti/rust/snazzy/target/debug/build/snazzy-e49e8cd9095ad904/out/snazzy.items.rs:2:28
  |
2 | #[derive(Clone, PartialEq, ::prost::Message)]
  |                            ^^^^^^^^^^^^^^^^ cannot infer type
  |
  = note: cannot satisfy `_: Default`
  = note: this error originates in the derive macro `::prost::Message` (in Nightly builds, run with -Z macro-backtrace for more info)

Some errors have detailed explanations: E0283, E0433.
For more information about an error, try `rustc --explain E0283`.
error: could not compile `snazzy` due to 2 previous errors

Similar issues were reported multiple times, but I couldn't figure out how to fix this problem based on the responses 😅

LucioFranco commented 2 years ago

Its likely the way you are importing your files. Prost expects them to be under specific mods. What you can do is use the include_file config item and only import that file. It will ensure the modules are all up to date.

mvanotti commented 2 years ago

Hi Lucio,

Thanks for your answer! That solved the issue :). It took me some time to find the right documentation and understand how to use it. Maybe it would be nice to add a note mentioning how the mods should be defined (and suggesting using include_file to help with the boilerplate.

My code ended up looking like this:

build.rs

use std::io::Result;

fn main() -> Result<()> {
    let mut prost_build = prost_build::Config::new();
    prost_build.include_file("_includes.rs");
    prost_build.compile_protos(&["src/items.proto"], &["src/"])?;
    Ok(())
}

main.rs

include!(concat!(env!("OUT_DIR"), "/_includes.rs"));

use snazzy::items;

pub fn create_large_shirt(color: String) -> items::Shirt {
    let mut shirt = items::Shirt::default();
    shirt.color = color;
    shirt.set_size(items::shirt::Size::Large);
    shirt
}

fn main() {
    let shirt = create_large_shirt("BLUE".to_string());
    println!("shirt: {:?}", shirt);
}
$ tree
.
├── build.rs
├── Cargo.lock
├── Cargo.toml
└── src
    ├── google
    │   ├── protobuf
    │   │   └── any.proto
    │   └── rpc
    │       └── status.proto
    ├── items.proto
    └── main.rs

The contents of _includes.rs are:

pub mod google {
    pub mod rpc {
        include!(concat!(env!("OUT_DIR"), "/google.rpc.rs"));
    }
    pub mod protobuf {
        include!(concat!(env!("OUT_DIR"), "/google.protobuf.rs"));
    }
}
pub mod snazzy {
    pub mod items {
        include!(concat!(env!("OUT_DIR"), "/snazzy.items.rs"));
    }
}

I think the problem with the super was because in my first attempt, I was not adding pub mod snazzy.

Lucio, should I send a PR updating the example to add the pub mod snazzy? Probably also mention there using the config + include_file

Yingming29 commented 4 months ago

Thanks a lot! rly helpful