Skip to content

prost-build wrongly thinks extern_path messages can #[derive(Copy)] #1301

@Sculas

Description

@Sculas

Using the following protos/test.proto file:

syntax = "proto3";
package test;
message Uuid {/* external */}

and src/types/mod.rs file:

#[derive(prost::Message, Clone, PartialEq, Eq, Hash)]
pub struct Uuid(#[prost(string, tag = "1")] String);

and build.rs file:

tonic_build::configure()
    .extern_path(".test.Uuid", "::crate::types::Uuid")
    .compile_protos(&["protos/test.proto"], &["protos"])
    .unwrap();

prost-build will think that the Uuid message is copyable, because all() defaults to true for empty iterators:

pub fn can_message_derive_copy(&self, fq_message_name: &str) -> bool {
assert_eq!(".", &fq_message_name[..1]);
self.message_graph
.get_message(fq_message_name)
.unwrap()
.field
.iter()
.all(|field| self.can_field_derive_copy(fq_message_name, field))

This is obviously wrong, since the Uuid newtype contains a String, which isn't copyable. However, prost-build isn't aware of the extern_path and only sees the empty Uuid message. The current workaround is to specify a string in the message:

syntax = "proto3";
package test;
message Uuid {/* external */ string disallow_copy = 1;}

Note: While both messages are technically the same now, this is just a minimal reproducer to show the bug :)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions