tokio-rs / prost

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

`prost_config::Config::boxed` generates code doesn't compile #1159

Open ldm0 opened 2 months ago

ldm0 commented 2 months ago

Version prost@0.13.2, prost-build@0.13.2

Description prost_config::Config::boxed generates code doesn't compile. I tried this code:

boxed_tests.proto:

syntax = "proto3";

package boxed_tests;

message Container {
  oneof data {
    string baz = 5;
    string boxed_baz = 6;
  }
}

build.rs:

fn main() {
    prost_build::Config::new()
        .out_dir(".")
        .boxed("Container.data.boxed_baz")
        .compile_protos(&["boxed_tests.proto"], &[""])
        .unwrap();
}

main.rs

mod boxed_tests {
    include!("../boxed_tests.rs");
}

fn main() {}

I expected to see this happen: compiled successfully

Instead, this happened: compilation failed. error message:

error[E0308]: mismatched types
  --> src/../boxed_tests.rs:9:32
   |
9  |       #[derive(Clone, PartialEq, ::prost::Oneof)]
   |                                  ^^^^^^^^^^^^^^ expected `Box<String>`, found `String`
10 |       pub enum Data {
   |  ______________-
11 | |         #[prost(string, tag = "5")]
12 | |         Baz(::prost::alloc::string::String),
13 | |         #[prost(string, tag = "6")]
14 | |         BoxedBaz(::prost::alloc::boxed::Box<::prost::alloc::string::String>),
   | |________________- arguments to this enum variant are incorrect
   |
   = note: expected struct `Box<String>`
              found struct `String`
   = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html
note: tuple variant defined here
  --> src/../boxed_tests.rs:14:9
   |
14 |         BoxedBaz(::prost::alloc::boxed::Box<::prost::alloc::string::String>),
   |         ^^^^^^^^
   = note: this error originates in the derive macro `::prost::Oneof` (in Nightly builds, run with -Z macro-backtrace for more info)

For more information about this error, try `rustc --explain E0308`.
ldm0 commented 2 months ago

The output of cargo expand reveals the issue: img_v3_02ep_24b38cde-8b28-4a7a-9ecd-17c19e6cfa0g

Type of owned_value was inferred as String(because of the function signature of prost::encoding::string::merge), while it should be Box<String> actually. image

caspermeijn commented 2 months ago

So a boxed oneof field produces invalid code.

The tests for boxed are clearly lacking. Upstream protobuf defines a TestAllTypesProto2 type. We already use that for roundtrip tests. I feel like we should do a fully boxed version of that as well.