Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Prost] Remove extra generated modules and opt-in to transitively inc…
…luding deps (#2943) This PR makes two changes: 1. It removes the duplicately generated code in the prost `lib.rs`. 2. It allows opting into transitively including all of the proto deps. ## Duplicately generated code. Previously there was a bug where we generated the same code at every proto package level. This created separate Rust types for each module which made it easy to accidentally import an incompatible type. Before: ```rust // @generated pub mod b_ar { pub mod b_az { pub mod qaz { pub mod qu_x { // @generated // This file is @generated by prost-build. #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct Bar { #[prost(string, tag = "1")] pub name: ::prost::alloc::string::String, #[prost(message, optional, tag = "2")] pub foo: ::core::option::Option< ::foo_proto::foo::quu_x::co_rg_e::grault::ga_rply::Foo, >, #[prost(message, optional, tag = "3")] pub nested_foo: ::core::option::Option< ::foo_proto::foo::quu_x::co_rg_e::grault::ga_rply::foo::NestedFoo, >, } /// Nested message and enum types in `Bar`. pub mod bar { #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct Baz { #[prost(string, tag = "4")] pub name: ::prost::alloc::string::String, } } // @@protoc_insertion_point(module) } } } } pub mod b_az { pub mod qaz { pub mod qu_x { // @generated // This file is @generated by prost-build. #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct Bar { #[prost(string, tag = "1")] pub name: ::prost::alloc::string::String, #[prost(message, optional, tag = "2")] pub foo: ::core::option::Option<::foo_proto::foo::quu_x::co_rg_e::grault::ga_rply::Foo>, #[prost(message, optional, tag = "3")] pub nested_foo: ::core::option::Option< ::foo_proto::foo::quu_x::co_rg_e::grault::ga_rply::foo::NestedFoo, >, } /// Nested message and enum types in `Bar`. pub mod bar { #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct Baz { #[prost(string, tag = "4")] pub name: ::prost::alloc::string::String, } } // @@protoc_insertion_point(module) } } } pub mod qaz { pub mod qu_x { // @generated // This file is @generated by prost-build. #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct Bar { #[prost(string, tag = "1")] pub name: ::prost::alloc::string::String, #[prost(message, optional, tag = "2")] pub foo: ::core::option::Option<::foo_proto::foo::quu_x::co_rg_e::grault::ga_rply::Foo>, #[prost(message, optional, tag = "3")] pub nested_foo: ::core::option::Option< ::foo_proto::foo::quu_x::co_rg_e::grault::ga_rply::foo::NestedFoo, >, } /// Nested message and enum types in `Bar`. pub mod bar { #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct Baz { #[prost(string, tag = "4")] pub name: ::prost::alloc::string::String, } } // @@protoc_insertion_point(module) } } pub mod qu_x { // @generated // This file is @generated by prost-build. #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct Bar { #[prost(string, tag = "1")] pub name: ::prost::alloc::string::String, #[prost(message, optional, tag = "2")] pub foo: ::core::option::Option<::foo_proto::foo::quu_x::co_rg_e::grault::ga_rply::Foo>, #[prost(message, optional, tag = "3")] pub nested_foo: ::core::option::Option< ::foo_proto::foo::quu_x::co_rg_e::grault::ga_rply::foo::NestedFoo, >, } /// Nested message and enum types in `Bar`. pub mod bar { #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct Baz { #[prost(string, tag = "4")] pub name: ::prost::alloc::string::String, } } // @@protoc_insertion_point(module) } ``` Now: ```rust // @generated pub use foo_proto; pub mod b_ar { pub mod b_az { pub mod qaz { pub mod qu_x { // @generated // This file is @generated by prost-build. #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct Bar { #[prost(string, tag = "1")] pub name: ::prost::alloc::string::String, #[prost(message, optional, tag = "2")] pub foo: ::core::option::Option< ::foo_proto::foo::quu_x::co_rg_e::grault::ga_rply::Foo, >, #[prost(message, optional, tag = "3")] pub nested_foo: ::core::option::Option< ::foo_proto::foo::quu_x::co_rg_e::grault::ga_rply::foo::NestedFoo, >, } /// Nested message and enum types in `Bar`. pub mod bar { #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct Baz { #[prost(string, tag = "4")] pub name: ::prost::alloc::string::String, } } // @@protoc_insertion_point(module) } } } } ``` ## Including transitive depenencies. Because the proto rules rely on aspects, we are compiling targets which may not be directly accessible as a label in Bazel. Out of convenience, the original implementation automatically included all transitive dependencies to the `rust_library` or `rust_binary` that depended on the proto crate. As an example, let's say we have the following hierarchy: ``` my_crate -> a.proto a.proto -> b.proto b.proto -> c.proto ``` The previous setup made it possible for `my_crate` to directly import `a_proto`, `b_proto`, and `c_proto`. This is problematic though because it leads to significant crate dependency bloat. `my_crate` may only use `a_proto` directly but it now also depends on the unused crates `b_proto` and `c_proto`. This PR makes every generated crate re-export its direct dependencies. So, for the same example we now can import via those reexports: ```rust //! my_crate use a_proto::A; use a_proto::b_proto::B; use a_proto::b_proto::c_proto::C; ``` This means that you can also add the rustc flag `-Dunused_crate_dependencies` to ensure you're not depending on crates which are unused. In our monorepo we've had to disable this flag for crates depending on protos. If you need to depend on an intermediate crate directly, you can just add a `rust_prost_library` definition and since it's all generated with aspects, it will be the identical underlying crate. Finally, if you really want the extra crates included, you can set the flag `include_transitive_deps` on the prost toolchain and that will bring back the previous behavior.
- Loading branch information