Repository: tokio-rs/prost (language: rust)

Issue:
Type error regression when using enum called Result
I am working on a project that uses Prost (via Tonic) to compile a protobuf file for use with gRPC. The file compiles fine with prost 0.11.9, but when switching to prost 0.12.0 the generated Rust file contains type errors.

The minimal protobuf file required to reproduce the problem is this one:

```proto
syntax = "proto3";

package fail;

enum Result {
  HELLO = 0;
}

message FailMessage {
  Result result = 1;
}
```

When attempting to compile the generated rust file the following errors are returned:

```
error[E0107]: enum takes 0 generic arguments but 2 generic arguments were supplied
 --> /private/tmp/tonicfail/target/debug/build/tonicfail-ca0c3cb604ffea00/out/fail.rs:2:28
  |
2 | #[derive(Clone, PartialEq, ::prost::Message)]
  |                            ^^^^^^^^^^^^^^^^- help: remove these generics
  |                            |
  |                            expected 0 generic arguments
  |
note: enum defined here, with 0 generic parameters
 --> /private/tmp/tonicfail/target/debug/build/tonicfail-ca0c3cb604ffea00/out/fail.rs:9:10
  |
9 | pub enum Result {
  |          ^^^^^^
  = note: this error originates in the derive macro `::prost::Message` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0308]: mismatched types
   --> /private/tmp/tonicfail/target/debug/build/tonicfail-ca0c3cb604ffea00/out/fail.rs:2:28
    |
2   | #[derive(Clone, PartialEq, ::prost::Message)]
    |                            ^^^^^^^^^^^^^^^^
    |                            |
    |                            expected `Result`, found `Result<_, _>`
    |                            expected due to this
    |
    = note: `std::result::Result<_, _>` and `proto::Result` have similar names, but are actually distinct types
note: `std::result::Result<_, _>` is defined in crate `core`
   --> /Users/djinn/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/src/rust/library/core/src/result.rs:502:1
    |
502 | pub enum Result<T, E> {
    | ^^^^^^^^^^^^^^^^^^^^^
note: `proto::Result` is defined in the current crate
   --> /private/tmp/tonicfail/target/debug/build/tonicfail-ca0c3cb604ffea00/out/fail.rs:9:1
    |
9   | pub enum Result {
    | ^^^^^^^^^^^^^^^
    = note: this error originates in the derive macro `::prost::Message` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0308]: mismatched types
   --> /private/tmp/tonicfail/target/debug/build/tonicfail-ca0c3cb604ffea00/out/fail.rs:2:28
    |
2   | #[derive(Clone, PartialEq, ::prost::Message)]
    |                            ^^^^^^^^^^^^^^^^
    |                            |
    |                            expected `Result`, found `Result<_, _>`
    |                            this expression has type `proto::Result`
    |
    = note: `std::result::Result<_, _>` and `proto::Result` have similar names, but are actually distinct types
note: `std::result::Result<_, _>` is defined in crate `core`
   --> /Users/djinn/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/src/rust/library/core/src/result.rs:502:1
    |
502 | pub enum Result<T, E> {
    | ^^^^^^^^^^^^^^^^^^^^^
note: `proto::Result` is defined in the current crate
   --> /private/tmp/tonicfail/target/debug/build/tonicfail-ca0c3cb604ffea00/out/fail.rs:9:1
    |
9   | pub enum Result {
    | ^^^^^^^^^^^^^^^
    = note: this error originates in the derive macro `::prost::Message` (in Nightly builds, run with -Z macro-backtrace for more info)

Some errors have detailed explanations: E0107, E0308.
For more information about an error, try `rustc --explain E0107`.
error: could not compile `tonicfail` (bin "tonicfail") due to 3 previous errors
```

If desired I can provide a minimal Rust project that demonstrates the failed compilation.


Discussion / hints:
We're also running into this in https://github.com/apache/arrow-rs/tree/master/arrow-flight
I am facing the same one, with `message Result` and I am preparing a pull request 
the issue introduced in this commit: ca73cbe4bbcbdb4f3d30455a090ff50209dc1fc3
@anstylian does your commit work? Happy to review a PR that fixes it.

Fix patch:
diff --git a/flake.nix b/flake.nix
index ac943ea47..a200020e3 100644
--- a/flake.nix
+++ b/flake.nix
@@ -14,7 +14,7 @@
       {
         devShells.default = pkgs.mkShell {
           packages = with pkgs; [ cargo rustc ];
-          buildInputs = with pkgs; [ pkg-config protobuf curl ];
+          buildInputs = with pkgs; [ pkg-config protobuf curl cmake ninja ];
         };
       });
 }
diff --git a/prost-derive/src/field/map.rs b/prost-derive/src/field/map.rs
index aabceb1f1..4855cc5c6 100644
--- a/prost-derive/src/field/map.rs
+++ b/prost-derive/src/field/map.rs
@@ -276,14 +276,14 @@ impl Field {
                 #[doc=#get_doc]
                 pub fn #get(&self, key: #key_ref_ty) -> ::core::option::Option<#ty> {
                     self.#ident.get(#take_ref key).cloned().and_then(|x| {
-                        let result: Result<#ty, _> = ::core::convert::TryFrom::try_from(x);
+                        let result: ::core::result::Result<#ty, _> = ::core::convert::TryFrom::try_from(x);
                         result.ok()
                     })
                 }
                 #[doc=#insert_doc]
                 pub fn #insert(&mut self, key: #key_ty, value: #ty) -> ::core::option::Option<#ty> {
                     self.#ident.insert(key, value as i32).and_then(|x| {
-                        let result: Result<#ty, _> = ::core::convert::TryFrom::try_from(x);
+                        let result: ::core::result::Result<#ty, _> = ::core::convert::TryFrom::try_from(x);
                         result.ok()
                     })
                 }
diff --git a/prost-derive/src/field/scalar.rs b/prost-derive/src/field/scalar.rs
index fa426b7fd..5a3dfb2ec 100644
--- a/prost-derive/src/field/scalar.rs
+++ b/prost-derive/src/field/scalar.rs
@@ -219,7 +219,7 @@ impl Field {
                 struct #wrap_name<'a>(&'a i32);
                 impl<'a> ::core::fmt::Debug for #wrap_name<'a> {
                     fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
-                        let res: Result<#ty, _> = ::core::convert::TryFrom::try_from(*self.0);
+                        let res: ::core::result::Result<#ty, _> = ::core::convert::TryFrom::try_from(*self.0);
                         match res {
                             Err(_) => ::core::fmt::Debug::fmt(&self.0, f),
                             Ok(en) => ::core::fmt::Debug::fmt(&en, f),
@@ -316,7 +316,7 @@ impl Field {
                         #[doc=#get_doc]
                         pub fn #get(&self) -> #ty {
                             self.#ident.and_then(|x| {
-                                let result: Result<#ty, _> = ::core::convert::TryFrom::try_from(x);
+                                let result: ::core::result::Result<#ty, _> = ::core::convert::TryFrom::try_from(x);
                                 result.ok()
                             }).unwrap_or(#default)
                         }
@@ -341,7 +341,7 @@ impl Field {
                             fn(i32) -> ::core::option::Option<#ty>,
                         > {
                             self.#ident.iter().cloned().filter_map(|x| {
-                                let result: Result<#ty, _> = ::core::convert::TryFrom::try_from(x);
+                                let result: ::core::result::Result<#ty, _> = ::core::convert::TryFrom::try_from(x);
                                 result.ok()
                             })
                         }


Test patch:
diff --git a/tests/src/build.rs b/tests/src/build.rs
index 2ddd397e5..bfb086a68 100644
--- a/tests/src/build.rs
+++ b/tests/src/build.rs
@@ -95,6 +95,22 @@ fn main() {
         .compile_protos(&[src.join("custom_debug.proto")], includes)
         .unwrap();
 
+    config
+        .compile_protos(&[src.join("result_enum.proto")], includes)
+        .unwrap();
+
+    config
+        .compile_protos(&[src.join("result_struct.proto")], includes)
+        .unwrap();
+
+    config
+        .compile_protos(&[src.join("option_enum.proto")], includes)
+        .unwrap();
+
+    config
+        .compile_protos(&[src.join("option_struct.proto")], includes)
+        .unwrap();
+
     prost_build::Config::new()
         .protoc_arg("--experimental_allow_proto3_optional")
         .compile_protos(&[src.join("proto3_presence.proto")], includes)
diff --git a/tests/src/lib.rs b/tests/src/lib.rs
index 4fcc45634..c03c94c10 100644
--- a/tests/src/lib.rs
+++ b/tests/src/lib.rs
@@ -45,8 +45,22 @@ mod no_unused_results;
 #[cfg(test)]
 #[cfg(feature = "std")]
 mod skip_debug;
-#[cfg(test)]
-mod well_known_types;
+
+mod test_enum_named_option_value {
+    include!(concat!(env!("OUT_DIR"), "/myenum.optionn.rs"));
+}
+
+mod test_enum_named_result_value {
+    include!(concat!(env!("OUT_DIR"), "/myenum.result.rs"));
+}
+
+mod test_result_named_option_value {
+    include!(concat!(env!("OUT_DIR"), "/mystruct.optionn.rs"));
+}
+
+mod test_result_named_result_value {
+    include!(concat!(env!("OUT_DIR"), "/mystruct.result.rs"));
+}
 
 pub mod foo {
     pub mod bar_baz {
diff --git a/tests/src/mod.rs b/tests/src/mod.rs
new file mode 100644
index 000000000..ec5996abd
--- /dev/null
+++ b/tests/src/mod.rs
@@ -0,0 +1,3 @@
+
+include!(concat!(env!("OUT_DIR"), "/myenum.result.rs"));
+include!(concat!(env!("OUT_DIR"), "/mymessage.result.rs"));
diff --git a/tests/src/option_enum.proto b/tests/src/option_enum.proto
new file mode 100644
index 000000000..5ccd6a2f5
--- /dev/null
+++ b/tests/src/option_enum.proto
@@ -0,0 +1,11 @@
+syntax = "proto3";
+package myenum.optionn;
+
+
+enum Option {
+  HELLO = 0;
+}
+
+message FailMessage {
+  Option result = 1;
+}
diff --git a/tests/src/option_struct.proto b/tests/src/option_struct.proto
new file mode 100644
index 000000000..2eedcf252
--- /dev/null
+++ b/tests/src/option_struct.proto
@@ -0,0 +1,8 @@
+syntax = "proto3";
+package mystruct.optionn;
+
+
+message Option {
+  string msg = 1;
+}
+
diff --git a/tests/src/result_enum.proto b/tests/src/result_enum.proto
new file mode 100644
index 000000000..3ce9c14cc
--- /dev/null
+++ b/tests/src/result_enum.proto
@@ -0,0 +1,11 @@
+syntax = "proto3";
+package myenum.result;
+
+
+enum Result {
+  HELLO = 0;
+}
+
+message FailMessage {
+  Result result = 1;
+}
diff --git a/tests/src/result_struct.proto b/tests/src/result_struct.proto
new file mode 100644
index 000000000..941566434
--- /dev/null
+++ b/tests/src/result_struct.proto
@@ -0,0 +1,8 @@
+syntax = "proto3";
+package mystruct.result;
+
+
+message Result {
+  string msg = 1;
+}
+