Skip to content

Proto message named Option shadows core::option::Option, causing type errors on oneof fields #36

@th0114nd

Description

@th0114nd

Summary

When a proto message is named Option, buffa's codegen generates a Rust struct named Option that shadows core::option::Option. If that message also has a oneof field, the generated code emits pub value: Option<foo::Value> where Option is intended to be core::option::Option, but Rust resolves it to the proto-generated struct (which takes 0 generic arguments).

This is valid protobuf accepted by protoc. Both prost and the official Go/C++/Java codegen handle this pattern without issues.

Minimal reproducer

syntax = "proto3";
package test.option_shadow;

message Picker {
  repeated Option options = 1;

  message Option {
    string title = 1;
    oneof value {
      uint64 int_value = 2;
    }
  }
}
// build.rs
fn main() {
    buffa_build::Config::new()
        .files(&["option_shadow.proto"])
        .includes(&["."])
        .include_file("_include.rs")
        .compile()
        .unwrap();
}

Error

error[E0107]: struct takes 0 generic arguments but 1 generic argument was supplied
   --> .../option_shadow.rs:233:20
    |
233 |         pub value: Option<option::Value>,
    |                    ^^^^^^--------------- help: remove the unnecessary generics
    |                    |
    |                    expected 0 generic arguments
    |
note: struct defined here, with 0 generic parameters
   --> .../option_shadow.rs:230:16
    |
230 |     pub struct Option {
    |                ^^^^^^

Expected behavior

Code generation should produce compilable code. The codegen should fully qualify ::core::option::Option<T> wherever it uses the standard Option type, so that a proto message named Option does not shadow it.

More generally, any proto name that collides with a Rust prelude type (Option, Result, Box, String, Vec, etc.) should be handled to avoid shadowing. Option is the most commonly hit case.

Context

This pattern appears in real-world proto schemas. We currently work around it by post-processing the generated code to replace bare Option< with ::core::option::Option<.

Version

buffa 0.3.0 / buffa-build 0.3.0 (crates.io)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No fields configured for Bug.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions