prost icon indicating copy to clipboard operation
prost copied to clipboard

Failed to compile proto3 with optional field and inner message

Open kriomant opened this issue 4 years ago • 7 comments

This minimal proto/test.proto file:

syntax = "proto3";
package test;

message Message {
    message InnerMsg {}
    optional string field = 1;
}

with this build.rs:

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut prost_config = prost_build::Config::new();
    prost_config.protoc_arg("--experimental_allow_proto3_optional");

    tonic_build::configure()
        .build_server(false)
        .compile_with_config(
            prost_config,
            &["proto/test.proto"],
            &["proto"])?;
    Ok(())
}

causes prost error:

RUST_BACKTRACE=1 cargo build
   Compiling logbroker-client v0.1.0 (/Users/kriomant/Devel/flow-parser-rs/logbroker-client)
error: failed to run custom build command for `logbroker-client v0.1.0 (/Users/kriomant/Devel/flow-parser-rs/logbroker-client)`

Caused by:
  process didn't exit successfully: `/Users/kriomant/.cargo/target/debug/build/logbroker-client-d491b261d8c07990/build-script-build` (exit code: 101)
  --- stderr
  thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', /Users/kriomant/.cargo/registry/src/github.com-1ecc6299db9ec823/prost-build-0.7.0/src/code_generator.rs:259:47
  stack backtrace:
     0: rust_begin_unwind
               at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/std/src/panicking.rs:493:5
     1: core::panicking::panic_fmt
               at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/core/src/panicking.rs:92:14
     2: core::panicking::panic
               at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/core/src/panicking.rs:50:5
     3: core::option::Option<T>::unwrap
               at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/core/src/option.rs:386:21
     4: prost_build::code_generator::CodeGenerator::append_message
               at /Users/kriomant/.cargo/registry/src/github.com-1ecc6299db9ec823/prost-build-0.7.0/src/code_generator.rs:259:21
     5: prost_build::code_generator::CodeGenerator::generate
               at /Users/kriomant/.cargo/registry/src/github.com-1ecc6299db9ec823/prost-build-0.7.0/src/code_generator.rs:102:13
     6: prost_build::Config::generate
               at /Users/kriomant/.cargo/registry/src/github.com-1ecc6299db9ec823/prost-build-0.7.0/src/lib.rs:766:13
     7: prost_build::Config::compile_protos
               at /Users/kriomant/.cargo/registry/src/github.com-1ecc6299db9ec823/prost-build-0.7.0/src/lib.rs:725:23
     8: tonic_build::prost::Builder::compile_with_config
               at /Users/kriomant/.cargo/registry/src/github.com-1ecc6299db9ec823/tonic-build-0.4.1/src/prost.rs:353:9
     9: build_script_build::main
               at ./build.rs:5:5
    10: core::ops::function::FnOnce::call_once
               at /Users/kriomant/.rustup/toolchains/1.51.0-x86_64-apple-darwin/lib/rustlib/src/rust/library/core/src/ops/function.rs:227:5
  note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

If I remove anything — inner message or 'optional' specifier, it compiles fine.

kriomant avatar Apr 12 '21 06:04 kriomant

I can confirm this, just ran into the same issue.

It also happens with an inner enum instead of a message:

syntax = "proto3";
package sync;

message FooBar {
  optional string asdf = 1;

  enum Foo {
    Bar = 0;
    Baz = 1;
  }
  Foo jklo = 2;
}

If I remove either the optional keyword or the enum, it builds fine.

threema-danilo avatar Apr 13 '21 08:04 threema-danilo

While the proto2 spec supports the optional keyword, the optional keyword is not part of the proto3 spec. All fields are optional in proto3.

olix0r avatar Jun 04 '21 19:06 olix0r

@olix0r this is about explicit presence. Support for optional fields in proto3 was (re-)added in version 3.12. I assume the spec wasn't updated yet.

More details can be found here:

threema-danilo avatar Jun 07 '21 07:06 threema-danilo

Thanks for the helpful links!

Oliver Gould < @.*** >

On Mon, Jun 07, 2021 at 12:32 AM, Danilo Bargen < @.*** > wrote:

@ olix0r ( https://github.com/olix0r ) this is about explicit presence. Support for optional fields in proto3 was (re-)added in version 3.12. I assume the spec wasn't updated yet.

More details can be found here:

  • field presence ( https://github.com/protocolbuffers/protobuf/blob/master/docs/field_presence.md )
  • implementation guide ( https://github.com/protocolbuffers/protobuf/blob/master/docs/implementing_proto3_presence.md )

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub ( https://github.com/danburkert/prost/issues/457#issuecomment-855673314 ) , or unsubscribe ( https://github.com/notifications/unsubscribe-auth/AAB2YYTH73EB4IHSBLYA573TRRYXZANCNFSM42YT7SKQ ).

olix0r avatar Jun 07 '21 14:06 olix0r

+1

lacasaprivata2 avatar Jul 06 '21 05:07 lacasaprivata2

Saw this on prost-build 0.6.0. On upgrade to 0.9.0, it's gone. Without investigating, if I had to guess, it was probably taken care of by the significant refactor in 0.8.0.

kalzoo avatar Oct 29 '21 21:10 kalzoo

This is a newish proto3 feature: https://github.com/protocolbuffers/protobuf/blob/v3.12.0/docs/field_presence.md. The addresses the issue that you cannot tell in proto3 whether a scalar field was not set at all or set to its default value. By adding "optional" you can. proto compilers should add methods to query field presence in this case, see https://github.com/protocolbuffers/protobuf/blob/master/docs/implementing_proto3_presence.md.

thomas001 avatar Dec 16 '21 10:12 thomas001