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

Issue:
`impl ::prost::Message` for a struct shadows the user-defined type
Minimal protobuf file to reproduce:

```proto
syntax = "proto3";
enum B {
  DEFAULT = 0;
  NON_DEFAULT = 1;
}
message A { B f1 = 1; }
```

Problem is that generated `impl ::prost::Message for A` contains a generic type parameter for a number of functions, that shadows the `B` enum:
```rust
            #[allow(unused_variables)]
            fn encode_raw<B>(&self, buf: &mut B)
            where
                B: ::prost::bytes::BufMut,
            {
                if self.f1 != B::default() as i32 {
                    ::prost::encoding::int32::encode(1u32, &self.f1, buf);
                }
            }
```

The error message from the compiler, that is not clear:
```
error[E0599]: no function or associated item named `default` found for type parameter `B` in the current scope
 --> tests/../.proto_out/test.rs:3:28
  |
3 | #[derive(Clone, PartialEq, ::prost::Message)]
  |                            ^^^^^^^^^^^^^^^^
  |                            |
  |                            function or associated item not found in `B`
  |                            function or associated item `default` not found for this type parameter
  |
  = help: items from traits can only be used if the type parameter is bounded by the trait
  = note: this error originates in the derive macro `::prost::Message` (in Nightly builds, run with -Z macro-backtrace for more info)
help: the following trait defines an item `default`, perhaps you need to restrict type parameter `B` with it:
  |
3 | #[derive(Clone, PartialEq, ::prost::Message: Default)]
  |                                            +++++++++

For more information about this error, try `rustc --explain E0599`.
```

There are at least two possible solutions:
1. Rename the generic type parameter to reduce the chance of ident clashes (e.g. `<ImplProstBytesBufMut>` instead of `<B>`);
2. Add a note or a known issue regarding this problem.

Probably, there are some other similar issues that are not noticed yet.
`impl ::prost::Message` for a struct shadows the user-defined type
Minimal protobuf file to reproduce:

```proto
syntax = "proto3";
enum B {
  DEFAULT = 0;
  NON_DEFAULT = 1;
}
message A { B f1 = 1; }
```

Problem is that generated `impl ::prost::Message for A` contains a generic type parameter for a number of functions, that shadows the `B` enum:
```rust
            #[allow(unused_variables)]
            fn encode_raw<B>(&self, buf: &mut B)
            where
                B: ::prost::bytes::BufMut,
            {
                if self.f1 != B::default() as i32 {
                    ::prost::encoding::int32::encode(1u32, &self.f1, buf);
                }
            }
```

The error message from the compiler, that is not clear:
```
error[E0599]: no function or associated item named `default` found for type parameter `B` in the current scope
 --> tests/../.proto_out/test.rs:3:28
  |
3 | #[derive(Clone, PartialEq, ::prost::Message)]
  |                            ^^^^^^^^^^^^^^^^
  |                            |
  |                            function or associated item not found in `B`
  |                            function or associated item `default` not found for this type parameter
  |
  = help: items from traits can only be used if the type parameter is bounded by the trait
  = note: this error originates in the derive macro `::prost::Message` (in Nightly builds, run with -Z macro-backtrace for more info)
help: the following trait defines an item `default`, perhaps you need to restrict type parameter `B` with it:
  |
3 | #[derive(Clone, PartialEq, ::prost::Message: Default)]
  |                                            +++++++++

For more information about this error, try `rustc --explain E0599`.
```

There are at least two possible solutions:
1. Rename the generic type parameter to reduce the chance of ident clashes (e.g. `<ImplProstBytesBufMut>` instead of `<B>`);
2. Add a note or a known issue regarding this problem.

Probably, there are some other similar issues that are not noticed yet.


Discussion / hints:
So because you generate an enum B and there is a generic type B, there is a conflict. 

The simplest solution seems to change the generated function signature to: `fn encode_raw(&self, buf: &mut impl ::prost::bytes::BufMut)`. That way there is no generic parameter `B`. Are you willing to create a PR that changes all `<B>` + `where B` to a `impl Type`?
So because you generate an enum B and there is a generic type B, there is a conflict. 

The simplest solution seems to change the generated function signature to: `fn encode_raw(&self, buf: &mut impl ::prost::bytes::BufMut)`. That way there is no generic parameter `B`. Are you willing to create a PR that changes all `<B>` + `where B` to a `impl Type`?

Fix patch:
diff --git a/prost-derive/src/lib.rs b/prost-derive/src/lib.rs
index 13f0a6878..98001d049 100644
--- a/prost-derive/src/lib.rs
+++ b/prost-derive/src/lib.rs
@@ -174,19 +174,19 @@ fn try_message(input: TokenStream) -> Result<TokenStream, Error> {
     let expanded = quote! {
         impl #impl_generics ::prost::Message for #ident #ty_generics #where_clause {
             #[allow(unused_variables)]
-            fn encode_raw<B>(&self, buf: &mut B) where B: ::prost::bytes::BufMut {
+            fn encode_raw(&self, buf: &mut impl ::prost::bytes::BufMut) {
                 #(#encode)*
             }
 
             #[allow(unused_variables)]
-            fn merge_field<B>(
+            fn merge_field(
                 &mut self,
                 tag: u32,
                 wire_type: ::prost::encoding::WireType,
-                buf: &mut B,
+                buf: &mut impl ::prost::bytes::Buf,
                 ctx: ::prost::encoding::DecodeContext,
             ) -> ::core::result::Result<(), ::prost::DecodeError>
-            where B: ::prost::bytes::Buf {
+            {
                 #struct_name
                 match tag {
                     #(#merge)*
@@ -463,21 +463,21 @@ fn try_oneof(input: TokenStream) -> Result<TokenStream, Error> {
     let expanded = quote! {
         impl #impl_generics #ident #ty_generics #where_clause {
             /// Encodes the message to a buffer.
-            pub fn encode<B>(&self, buf: &mut B) where B: ::prost::bytes::BufMut {
+            pub fn encode(&self, buf: &mut impl ::prost::bytes::BufMut) {
                 match *self {
                     #(#encode,)*
                 }
             }
 
             /// Decodes an instance of the message from a buffer, and merges it into self.
-            pub fn merge<B>(
+            pub fn merge(
                 field: &mut ::core::option::Option<#ident #ty_generics>,
                 tag: u32,
                 wire_type: ::prost::encoding::WireType,
-                buf: &mut B,
+                buf: &mut impl ::prost::bytes::Buf,
                 ctx: ::prost::encoding::DecodeContext,
             ) -> ::core::result::Result<(), ::prost::DecodeError>
-            where B: ::prost::bytes::Buf {
+            {
                 match tag {
                     #(#merge,)*
                     _ => unreachable!(concat!("invalid ", stringify!(#ident), " tag: {}"), tag),
diff --git a/prost/src/encoding.rs b/prost/src/encoding.rs
index 88d4fe891..88f65e643 100644
--- a/prost/src/encoding.rs
+++ b/prost/src/encoding.rs
@@ -22,10 +22,7 @@ use crate::Message;
 /// Encodes an integer value into LEB128 variable length format, and writes it to the buffer.
 /// The buffer must have enough remaining space (maximum 10 bytes).
 #[inline]
-pub fn encode_varint<B>(mut value: u64, buf: &mut B)
-where
-    B: BufMut,
-{
+pub fn encode_varint(mut value: u64, buf: &mut impl BufMut) {
     // Varints are never more than 10 bytes
     for _ in 0..10 {
         if value < 0x80 {
@@ -40,10 +37,7 @@ where
 
 /// Decodes a LEB128-encoded variable length integer from the buffer.
 #[inline]
-pub fn decode_varint<B>(buf: &mut B) -> Result<u64, DecodeError>
-where
-    B: Buf,
-{
+pub fn decode_varint(buf: &mut impl Buf) -> Result<u64, DecodeError> {
     let bytes = buf.chunk();
     let len = bytes.len();
     if len == 0 {
@@ -163,10 +157,7 @@ fn decode_varint_slice(bytes: &[u8]) -> Result<(u64, usize), DecodeError> {
 /// [1]: https://github.com/protocolbuffers/protobuf-go/blob/v1.27.1/encoding/protowire/wire.go#L358
 #[inline(never)]
 #[cold]
-fn decode_varint_slow<B>(buf: &mut B) -> Result<u64, DecodeError>
-where
-    B: Buf,
-{
+fn decode_varint_slow(buf: &mut impl Buf) -> Result<u64, DecodeError> {
     let mut value = 0;
     for count in 0..min(10, buf.remaining()) {
         let byte = buf.get_u8();
@@ -301,10 +292,7 @@ impl TryFrom<u64> for WireType {
 /// Encodes a Protobuf field key, which consists of a wire type designator and
 /// the field tag.
 #[inline]
-pub fn encode_key<B>(tag: u32, wire_type: WireType, buf: &mut B)
-where
-    B: BufMut,
-{
+pub fn encode_key(tag: u32, wire_type: WireType, buf: &mut impl BufMut) {
     debug_assert!((MIN_TAG..=MAX_TAG).contains(&tag));
     let key = (tag << 3) | wire_type as u32;
     encode_varint(u64::from(key), buf);
@@ -313,10 +301,7 @@ where
 /// Decodes a Protobuf field key, which consists of a wire type designator and
 /// the field tag.
 #[inline(always)]
-pub fn decode_key<B>(buf: &mut B) -> Result<(u32, WireType), DecodeError>
-where
-    B: Buf,
-{
+pub fn decode_key(buf: &mut impl Buf) -> Result<(u32, WireType), DecodeError> {
     let key = decode_varint(buf)?;
     if key > u64::from(u32::MAX) {
         return Err(DecodeError::new(format!("invalid key value: {}", key)));
@@ -380,15 +365,12 @@ where
     Ok(())
 }
 
-pub fn skip_field<B>(
+pub fn skip_field(
     wire_type: WireType,
     tag: u32,
-    buf: &mut B,
+    buf: &mut impl Buf,
     ctx: DecodeContext,
-) -> Result<(), DecodeError>
-where
-    B: Buf,
-{
+) -> Result<(), DecodeError> {
     ctx.limit_reached()?;
     let len = match wire_type {
         WireType::Varint => decode_varint(buf).map(|_| 0)?,
@@ -421,10 +403,7 @@ where
 /// Helper macro which emits an `encode_repeated` function for the type.
 macro_rules! encode_repeated {
     ($ty:ty) => {
-        pub fn encode_repeated<B>(tag: u32, values: &[$ty], buf: &mut B)
-        where
-            B: BufMut,
-        {
+        pub fn encode_repeated(tag: u32, values: &[$ty], buf: &mut impl BufMut) {
             for value in values {
                 encode(tag, value, buf);
             }
@@ -438,15 +417,12 @@ macro_rules! merge_repeated_numeric {
      $wire_type:expr,
      $merge:ident,
      $merge_repeated:ident) => {
-        pub fn $merge_repeated<B>(
+        pub fn $merge_repeated(
             wire_type: WireType,
             values: &mut Vec<$ty>,
-            buf: &mut B,
+            buf: &mut impl Buf,
             ctx: DecodeContext,
-        ) -> Result<(), DecodeError>
-        where
-            B: Buf,
-        {
+        ) -> Result<(), DecodeError> {
             if wire_type == WireType::LengthDelimited {
                 // Packed.
                 merge_loop(values, buf, ctx, |values, buf, ctx| {
@@ -486,12 +462,12 @@ macro_rules! varint {
          pub mod $proto_ty {
             use crate::encoding::*;
 
-            pub fn encode<B>(tag: u32, $to_uint64_value: &$ty, buf: &mut B) where B: BufMut {
+            pub fn encode(tag: u32, $to_uint64_value: &$ty, buf: &mut impl BufMut) {
                 encode_key(tag, WireType::Varint, buf);
                 encode_varint($to_uint64, buf);
             }
 
-            pub fn merge<B>(wire_type: WireType, value: &mut $ty, buf: &mut B, _ctx: DecodeContext) -> Result<(), DecodeError> where B: Buf {
+            pub fn merge(wire_type: WireType, value: &mut $ty, buf: &mut impl Buf, _ctx: DecodeContext) -> Result<(), DecodeError> {
                 check_wire_type(WireType::Varint, wire_type)?;
                 let $from_uint64_value = decode_varint(buf)?;
                 *value = $from_uint64;
@@ -500,7 +476,7 @@ macro_rules! varint {
 
             encode_repeated!($ty);
 
-            pub fn encode_packed<B>(tag: u32, values: &[$ty], buf: &mut B) where B: BufMut {
+            pub fn encode_packed(tag: u32, values: &[$ty], buf: &mut impl BufMut) {
                 if values.is_empty() { return; }
 
                 encode_key(tag, WireType::LengthDelimited, buf);
@@ -609,23 +585,17 @@ macro_rules! fixed_width {
         pub mod $proto_ty {
             use crate::encoding::*;
 
-            pub fn encode<B>(tag: u32, value: &$ty, buf: &mut B)
-            where
-                B: BufMut,
-            {
+            pub fn encode(tag: u32, value: &$ty, buf: &mut impl BufMut) {
                 encode_key(tag, $wire_type, buf);
                 buf.$put(*value);
             }
 
-            pub fn merge<B>(
+            pub fn merge(
                 wire_type: WireType,
                 value: &mut $ty,
-                buf: &mut B,
+                buf: &mut impl Buf,
                 _ctx: DecodeContext,
-            ) -> Result<(), DecodeError>
-            where
-                B: Buf,
-            {
+            ) -> Result<(), DecodeError> {
                 check_wire_type($wire_type, wire_type)?;
                 if buf.remaining() < $width {
                     return Err(DecodeError::new("buffer underflow"));
@@ -636,10 +606,7 @@ macro_rules! fixed_width {
 
             encode_repeated!($ty);
 
-            pub fn encode_packed<B>(tag: u32, values: &[$ty], buf: &mut B)
-            where
-                B: BufMut,
-            {
+            pub fn encode_packed(tag: u32, values: &[$ty], buf: &mut impl BufMut) {
                 if values.is_empty() {
                     return;
                 }
@@ -759,15 +726,12 @@ macro_rules! length_delimited {
     ($ty:ty) => {
         encode_repeated!($ty);
 
-        pub fn merge_repeated<B>(
+        pub fn merge_repeated(
             wire_type: WireType,
             values: &mut Vec<$ty>,
-            buf: &mut B,
+            buf: &mut impl Buf,
             ctx: DecodeContext,
-        ) -> Result<(), DecodeError>
-        where
-            B: Buf,
-        {
+        ) -> Result<(), DecodeError> {
             check_wire_type(WireType::LengthDelimited, wire_type)?;
             let mut value = Default::default();
             merge(wire_type, &mut value, buf, ctx)?;
@@ -794,23 +758,18 @@ macro_rules! length_delimited {
 pub mod string {
     use super::*;
 
-    pub fn encode<B>(tag: u32, value: &String, buf: &mut B)
-    where
-        B: BufMut,
-    {
+    pub fn encode(tag: u32, value: &String, buf: &mut impl BufMut) {
         encode_key(tag, WireType::LengthDelimited, buf);
         encode_varint(value.len() as u64, buf);
         buf.put_slice(value.as_bytes());
     }
-    pub fn merge<B>(
+
+    pub fn merge(
         wire_type: WireType,
         value: &mut String,
-        buf: &mut B,
+        buf: &mut impl Buf,
         ctx: DecodeContext,
-    ) -> Result<(), DecodeError>
-    where
-        B: Buf,
-    {
+    ) -> Result<(), DecodeError> {
         // ## Unsafety
         //
         // `string::merge` reuses `bytes::merge`, with an additional check of utf-8
@@ -882,14 +841,10 @@ mod sealed {
         fn len(&self) -> usize;
 
         /// Replace contents of this buffer with the contents of another buffer.
-        fn replace_with<B>(&mut self, buf: B)
-        where
-            B: Buf;
+        fn replace_with(&mut self, buf: impl Buf);
 
         /// Appends this buffer to the (contents of) other buffer.
-        fn append_to<B>(&self, buf: &mut B)
-        where
-            B: BufMut;
+        fn append_to(&self, buf: &mut impl BufMut);
 
         fn is_empty(&self) -> bool {
             self.len() == 0
@@ -904,17 +859,11 @@ impl sealed::BytesAdapter for Bytes {
         Buf::remaining(self)
     }
 
-    fn replace_with<B>(&mut self, mut buf: B)
-    where
-        B: Buf,
-    {
+    fn replace_with(&mut self, mut buf: impl Buf) {
         *self = buf.copy_to_bytes(buf.remaining());
     }
 
-    fn append_to<B>(&self, buf: &mut B)
-    where
-        B: BufMut,
-    {
+    fn append_to(&self, buf: &mut impl BufMut) {
         buf.put(self.clone())
     }
 }
@@ -926,19 +875,13 @@ impl sealed::BytesAdapter for Vec<u8> {
         Vec::len(self)
     }
 
-    fn replace_with<B>(&mut self, buf: B)
-    where
-        B: Buf,
-    {
+    fn replace_with(&mut self, buf: impl Buf) {
         self.clear();
         self.reserve(buf.remaining());
         self.put(buf);
     }
 
-    fn append_to<B>(&self, buf: &mut B)
-    where
-        B: BufMut,
-    {
+    fn append_to(&self, buf: &mut impl BufMut) {
         buf.put(self.as_slice())
     }
 }
@@ -946,26 +889,18 @@ impl sealed::BytesAdapter for Vec<u8> {
 pub mod bytes {
     use super::*;
 
-    pub fn encode<A, B>(tag: u32, value: &A, buf: &mut B)
-    where
-        A: BytesAdapter,
-        B: BufMut,
-    {
+    pub fn encode(tag: u32, value: &impl BytesAdapter, buf: &mut impl BufMut) {
         encode_key(tag, WireType::LengthDelimited, buf);
         encode_varint(value.len() as u64, buf);
         value.append_to(buf);
     }
 
-    pub fn merge<A, B>(
+    pub fn merge(
         wire_type: WireType,
-        value: &mut A,
-        buf: &mut B,
+        value: &mut impl BytesAdapter,
+        buf: &mut impl Buf,
         _ctx: DecodeContext,
-    ) -> Result<(), DecodeError>
-    where
-        A: BytesAdapter,
-        B: Buf,
-    {
+    ) -> Result<(), DecodeError> {
         check_wire_type(WireType::LengthDelimited, wire_type)?;
         let len = decode_varint(buf)?;
         if len > buf.remaining() as u64 {
@@ -989,16 +924,12 @@ pub mod bytes {
         Ok(())
     }
 
-    pub(super) fn merge_one_copy<A, B>(
+    pub(super) fn merge_one_copy(
         wire_type: WireType,
-        value: &mut A,
-        buf: &mut B,
+        value: &mut impl BytesAdapter,
+        buf: &mut impl Buf,
         _ctx: DecodeContext,
-    ) -> Result<(), DecodeError>
-    where
-        A: BytesAdapter,
-        B: Buf,
-    {
+    ) -> Result<(), DecodeError> {
         check_wire_type(WireType::LengthDelimited, wire_type)?;
         let len = decode_varint(buf)?;
         if len > buf.remaining() as u64 {
@@ -1055,10 +986,9 @@ pub mod bytes {
 pub mod message {
     use super::*;
 
-    pub fn encode<M, B>(tag: u32, msg: &M, buf: &mut B)
+    pub fn encode<M>(tag: u32, msg: &M, buf: &mut impl BufMut)
     where
         M: Message,
-        B: BufMut,
     {
         encode_key(tag, WireType::LengthDelimited, buf);
         encode_varint(msg.encoded_len() as u64, buf);
@@ -1088,25 +1018,23 @@ pub mod message {
         )
     }
 
-    pub fn encode_repeated<M, B>(tag: u32, messages: &[M], buf: &mut B)
+    pub fn encode_repeated<M>(tag: u32, messages: &[M], buf: &mut impl BufMut)
     where
         M: Message,
-        B: BufMut,
     {
         for msg in messages {
             encode(tag, msg, buf);
         }
     }
 
-    pub fn merge_repeated<M, B>(
+    pub fn merge_repeated<M>(
         wire_type: WireType,
         messages: &mut Vec<M>,
-        buf: &mut B,
+        buf: &mut impl Buf,
         ctx: DecodeContext,
     ) -> Result<(), DecodeError>
     where
         M: Message + Default,
-        B: Buf,
     {
         check_wire_type(WireType::LengthDelimited, wire_type)?;
         let mut msg = M::default();
@@ -1141,26 +1069,24 @@ pub mod message {
 pub mod group {
     use super::*;
 
-    pub fn encode<M, B>(tag: u32, msg: &M, buf: &mut B)
+    pub fn encode<M>(tag: u32, msg: &M, buf: &mut impl BufMut)
     where
         M: Message,
-        B: BufMut,
     {
         encode_key(tag, WireType::StartGroup, buf);
         msg.encode_raw(buf);
         encode_key(tag, WireType::EndGroup, buf);
     }
 
-    pub fn merge<M, B>(
+    pub fn merge<M>(
         tag: u32,
         wire_type: WireType,
         msg: &mut M,
-        buf: &mut B,
+        buf: &mut impl Buf,
         ctx: DecodeContext,
     ) -> Result<(), DecodeError>
     where
         M: Message,
-        B: Buf,
     {
         check_wire_type(WireType::StartGroup, wire_type)?;
 
@@ -1178,26 +1104,24 @@ pub mod group {
         }
     }
 
-    pub fn encode_repeated<M, B>(tag: u32, messages: &[M], buf: &mut B)
+    pub fn encode_repeated<M>(tag: u32, messages: &[M], buf: &mut impl BufMut)
     where
         M: Message,
-        B: BufMut,
     {
         for msg in messages {
             encode(tag, msg, buf);
         }
     }
 
-    pub fn merge_repeated<M, B>(
+    pub fn merge_repeated<M>(
         tag: u32,
         wire_type: WireType,
         messages: &mut Vec<M>,
-        buf: &mut B,
+        buf: &mut impl Buf,
         ctx: DecodeContext,
     ) -> Result<(), DecodeError>
     where
         M: Message + Default,
-        B: Buf,
     {
         check_wire_type(WireType::StartGroup, wire_type)?;
         let mut msg = M::default();
diff --git a/prost/src/lib.rs b/prost/src/lib.rs
index 32b36f5cf..924928055 100644
--- a/prost/src/lib.rs
+++ b/prost/src/lib.rs
@@ -36,10 +36,7 @@ const RECURSION_LIMIT: u32 = 100;
 ///
 /// An error will be returned if the buffer does not have sufficient capacity to encode the
 /// delimiter.
-pub fn encode_length_delimiter<B>(length: usize, buf: &mut B) -> Result<(), EncodeError>
-where
-    B: BufMut,
-{
+pub fn encode_length_delimiter(length: usize, buf: &mut impl BufMut) -> Result<(), EncodeError> {
     let length = length as u64;
     let required = encoded_len_varint(length);
     let remaining = buf.remaining_mut();
@@ -69,10 +66,7 @@ pub fn length_delimiter_len(length: usize) -> usize {
 ///    input is required to decode the full delimiter.
 ///  * If the supplied buffer contains more than 10 bytes, then the buffer contains an invalid
 ///    delimiter, and typically the buffer should be considered corrupt.
-pub fn decode_length_delimiter<B>(mut buf: B) -> Result<usize, DecodeError>
-where
-    B: Buf,
-{
+pub fn decode_length_delimiter(mut buf: impl Buf) -> Result<usize, DecodeError> {
     let length = decode_varint(&mut buf)?;
     if length > usize::max_value() as u64 {
         return Err(DecodeError::new(
diff --git a/prost/src/message.rs b/prost/src/message.rs
index 98235ea9f..a38e9f38f 100644
--- a/prost/src/message.rs
+++ b/prost/src/message.rs
@@ -21,24 +21,22 @@ pub trait Message: Debug + Send + Sync {
     ///
     /// Meant to be used only by `Message` implementations.
     #[doc(hidden)]
-    fn encode_raw<B>(&self, buf: &mut B)
+    fn encode_raw(&self, buf: &mut impl BufMut)
     where
-        B: BufMut,
         Self: Sized;
 
     /// Decodes a field from a buffer, and merges it into `self`.
     ///
     /// Meant to be used only by `Message` implementations.
     #[doc(hidden)]
-    fn merge_field<B>(
+    fn merge_field(
         &mut self,
         tag: u32,
         wire_type: WireType,
-        buf: &mut B,
+        buf: &mut impl Buf,
         ctx: DecodeContext,
     ) -> Result<(), DecodeError>
     where
-        B: Buf,
         Self: Sized;
 
     /// Returns the encoded length of the message without a length delimiter.
@@ -47,9 +45,8 @@ pub trait Message: Debug + Send + Sync {
     /// Encodes the message to a buffer.
     ///
     /// An error will be returned if the buffer does not have sufficient capacity.
-    fn encode<B>(&self, buf: &mut B) -> Result<(), EncodeError>
+    fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError>
     where
-        B: BufMut,
         Self: Sized,
     {
         let required = self.encoded_len();
@@ -76,9 +73,8 @@ pub trait Message: Debug + Send + Sync {
     /// Encodes the message with a length-delimiter to a buffer.
     ///
     /// An error will be returned if the buffer does not have sufficient capacity.
-    fn encode_length_delimited<B>(&self, buf: &mut B) -> Result<(), EncodeError>
+    fn encode_length_delimited(&self, buf: &mut impl BufMut) -> Result<(), EncodeError>
     where
-        B: BufMut,
         Self: Sized,
     {
         let len = self.encoded_len();
@@ -108,9 +104,8 @@ pub trait Message: Debug + Send + Sync {
     /// Decodes an instance of the message from a buffer.
     ///
     /// The entire buffer will be consumed.
-    fn decode<B>(mut buf: B) -> Result<Self, DecodeError>
+    fn decode(mut buf: impl Buf) -> Result<Self, DecodeError>
     where
-        B: Buf,
         Self: Default,
     {
         let mut message = Self::default();
@@ -118,9 +113,8 @@ pub trait Message: Debug + Send + Sync {
     }
 
     /// Decodes a length-delimited instance of the message from the buffer.
-    fn decode_length_delimited<B>(buf: B) -> Result<Self, DecodeError>
+    fn decode_length_delimited(buf: impl Buf) -> Result<Self, DecodeError>
     where
-        B: Buf,
         Self: Default,
     {
         let mut message = Self::default();
@@ -131,9 +125,8 @@ pub trait Message: Debug + Send + Sync {
     /// Decodes an instance of the message from a buffer, and merges it into `self`.
     ///
     /// The entire buffer will be consumed.
-    fn merge<B>(&mut self, mut buf: B) -> Result<(), DecodeError>
+    fn merge(&mut self, mut buf: impl Buf) -> Result<(), DecodeError>
     where
-        B: Buf,
         Self: Sized,
     {
         let ctx = DecodeContext::default();
@@ -146,9 +139,8 @@ pub trait Message: Debug + Send + Sync {
 
     /// Decodes a length-delimited instance of the message from buffer, and
     /// merges it into `self`.
-    fn merge_length_delimited<B>(&mut self, mut buf: B) -> Result<(), DecodeError>
+    fn merge_length_delimited(&mut self, mut buf: impl Buf) -> Result<(), DecodeError>
     where
-        B: Buf,
         Self: Sized,
     {
         message::merge(
@@ -167,22 +159,16 @@ impl<M> Message for Box<M>
 where
     M: Message,
 {
-    fn encode_raw<B>(&self, buf: &mut B)
-    where
-        B: BufMut,
-    {
+    fn encode_raw(&self, buf: &mut impl BufMut) {
         (**self).encode_raw(buf)
     }
-    fn merge_field<B>(
+    fn merge_field(
         &mut self,
         tag: u32,
         wire_type: WireType,
-        buf: &mut B,
+        buf: &mut impl Buf,
         ctx: DecodeContext,
-    ) -> Result<(), DecodeError>
-    where
-        B: Buf,
-    {
+    ) -> Result<(), DecodeError> {
         (**self).merge_field(tag, wire_type, buf, ctx)
     }
     fn encoded_len(&self) -> usize {
diff --git a/prost/src/types.rs b/prost/src/types.rs
index 9aa53a9e7..6e4994bfb 100644
--- a/prost/src/types.rs
+++ b/prost/src/types.rs
@@ -22,24 +22,18 @@ use crate::{
 
 /// `google.protobuf.BoolValue`
 impl Message for bool {
-    fn encode_raw<B>(&self, buf: &mut B)
-    where
-        B: BufMut,
-    {
+    fn encode_raw(&self, buf: &mut impl BufMut) {
         if *self {
             bool::encode(1, self, buf)
         }
     }
-    fn merge_field<B>(
+    fn merge_field(
         &mut self,
         tag: u32,
         wire_type: WireType,
-        buf: &mut B,
+        buf: &mut impl Buf,
         ctx: DecodeContext,
-    ) -> Result<(), DecodeError>
-    where
-        B: Buf,
-    {
+    ) -> Result<(), DecodeError> {
         if tag == 1 {
             bool::merge(wire_type, self, buf, ctx)
         } else {
@@ -60,24 +54,18 @@ impl Message for bool {
 
 /// `google.protobuf.UInt32Value`
 impl Message for u32 {
-    fn encode_raw<B>(&self, buf: &mut B)
-    where
-        B: BufMut,
-    {
+    fn encode_raw(&self, buf: &mut impl BufMut) {
         if *self != 0 {
             uint32::encode(1, self, buf)
         }
     }
-    fn merge_field<B>(
+    fn merge_field(
         &mut self,
         tag: u32,
         wire_type: WireType,
-        buf: &mut B,
+        buf: &mut impl Buf,
         ctx: DecodeContext,
-    ) -> Result<(), DecodeError>
-    where
-        B: Buf,
-    {
+    ) -> Result<(), DecodeError> {
         if tag == 1 {
             uint32::merge(wire_type, self, buf, ctx)
         } else {
@@ -98,24 +86,18 @@ impl Message for u32 {
 
 /// `google.protobuf.UInt64Value`
 impl Message for u64 {
-    fn encode_raw<B>(&self, buf: &mut B)
-    where
-        B: BufMut,
-    {
+    fn encode_raw(&self, buf: &mut impl BufMut) {
         if *self != 0 {
             uint64::encode(1, self, buf)
         }
     }
-    fn merge_field<B>(
+    fn merge_field(
         &mut self,
         tag: u32,
         wire_type: WireType,
-        buf: &mut B,
+        buf: &mut impl Buf,
         ctx: DecodeContext,
-    ) -> Result<(), DecodeError>
-    where
-        B: Buf,
-    {
+    ) -> Result<(), DecodeError> {
         if tag == 1 {
             uint64::merge(wire_type, self, buf, ctx)
         } else {
@@ -136,24 +118,18 @@ impl Message for u64 {
 
 /// `google.protobuf.Int32Value`
 impl Message for i32 {
-    fn encode_raw<B>(&self, buf: &mut B)
-    where
-        B: BufMut,
-    {
+    fn encode_raw(&self, buf: &mut impl BufMut) {
         if *self != 0 {
             int32::encode(1, self, buf)
         }
     }
-    fn merge_field<B>(
+    fn merge_field(
         &mut self,
         tag: u32,
         wire_type: WireType,
-        buf: &mut B,
+        buf: &mut impl Buf,
         ctx: DecodeContext,
-    ) -> Result<(), DecodeError>
-    where
-        B: Buf,
-    {
+    ) -> Result<(), DecodeError> {
         if tag == 1 {
             int32::merge(wire_type, self, buf, ctx)
         } else {
@@ -174,24 +150,18 @@ impl Message for i32 {
 
 /// `google.protobuf.Int64Value`
 impl Message for i64 {
-    fn encode_raw<B>(&self, buf: &mut B)
-    where
-        B: BufMut,
-    {
+    fn encode_raw(&self, buf: &mut impl BufMut) {
         if *self != 0 {
             int64::encode(1, self, buf)
         }
     }
-    fn merge_field<B>(
+    fn merge_field(
         &mut self,
         tag: u32,
         wire_type: WireType,
-        buf: &mut B,
+        buf: &mut impl Buf,
         ctx: DecodeContext,
-    ) -> Result<(), DecodeError>
-    where
-        B: Buf,
-    {
+    ) -> Result<(), DecodeError> {
         if tag == 1 {
             int64::merge(wire_type, self, buf, ctx)
         } else {
@@ -212,24 +182,18 @@ impl Message for i64 {
 
 /// `google.protobuf.FloatValue`
 impl Message for f32 {
-    fn encode_raw<B>(&self, buf: &mut B)
-    where
-        B: BufMut,
-    {
+    fn encode_raw(&self, buf: &mut impl BufMut) {
         if *self != 0.0 {
             float::encode(1, self, buf)
         }
     }
-    fn merge_field<B>(
+    fn merge_field(
         &mut self,
         tag: u32,
         wire_type: WireType,
-        buf: &mut B,
+        buf: &mut impl Buf,
         ctx: DecodeContext,
-    ) -> Result<(), DecodeError>
-    where
-        B: Buf,
-    {
+    ) -> Result<(), DecodeError> {
         if tag == 1 {
             float::merge(wire_type, self, buf, ctx)
         } else {
@@ -250,24 +214,18 @@ impl Message for f32 {
 
 /// `google.protobuf.DoubleValue`
 impl Message for f64 {
-    fn encode_raw<B>(&self, buf: &mut B)
-    where
-        B: BufMut,
-    {
+    fn encode_raw(&self, buf: &mut impl BufMut) {
         if *self != 0.0 {
             double::encode(1, self, buf)
         }
     }
-    fn merge_field<B>(
+    fn merge_field(
         &mut self,
         tag: u32,
         wire_type: WireType,
-        buf: &mut B,
+        buf: &mut impl Buf,
         ctx: DecodeContext,
-    ) -> Result<(), DecodeError>
-    where
-        B: Buf,
-    {
+    ) -> Result<(), DecodeError> {
         if tag == 1 {
             double::merge(wire_type, self, buf, ctx)
         } else {
@@ -288,24 +246,18 @@ impl Message for f64 {
 
 /// `google.protobuf.StringValue`
 impl Message for String {
-    fn encode_raw<B>(&self, buf: &mut B)
-    where
-        B: BufMut,
-    {
+    fn encode_raw(&self, buf: &mut impl BufMut) {
         if !self.is_empty() {
             string::encode(1, self, buf)
         }
     }
-    fn merge_field<B>(
+    fn merge_field(
         &mut self,
         tag: u32,
         wire_type: WireType,
-        buf: &mut B,
+        buf: &mut impl Buf,
         ctx: DecodeContext,
-    ) -> Result<(), DecodeError>
-    where
-        B: Buf,
-    {
+    ) -> Result<(), DecodeError> {
         if tag == 1 {
             string::merge(wire_type, self, buf, ctx)
         } else {
@@ -326,24 +278,18 @@ impl Message for String {
 
 /// `google.protobuf.BytesValue`
 impl Message for Vec<u8> {
-    fn encode_raw<B>(&self, buf: &mut B)
-    where
-        B: BufMut,
-    {
+    fn encode_raw(&self, buf: &mut impl BufMut) {
         if !self.is_empty() {
             bytes::encode(1, self, buf)
         }
     }
-    fn merge_field<B>(
+    fn merge_field(
         &mut self,
         tag: u32,
         wire_type: WireType,
-        buf: &mut B,
+        buf: &mut impl Buf,
         ctx: DecodeContext,
-    ) -> Result<(), DecodeError>
-    where
-        B: Buf,
-    {
+    ) -> Result<(), DecodeError> {
         if tag == 1 {
             bytes::merge(wire_type, self, buf, ctx)
         } else {
@@ -364,24 +310,18 @@ impl Message for Vec<u8> {
 
 /// `google.protobuf.BytesValue`
 impl Message for Bytes {
-    fn encode_raw<B>(&self, buf: &mut B)
-    where
-        B: BufMut,
-    {
+    fn encode_raw(&self, buf: &mut impl BufMut) {
         if !self.is_empty() {
             bytes::encode(1, self, buf)
         }
     }
-    fn merge_field<B>(
+    fn merge_field(
         &mut self,
         tag: u32,
         wire_type: WireType,
-        buf: &mut B,
+        buf: &mut impl Buf,
         ctx: DecodeContext,
-    ) -> Result<(), DecodeError>
-    where
-        B: Buf,
-    {
+    ) -> Result<(), DecodeError> {
         if tag == 1 {
             bytes::merge(wire_type, self, buf, ctx)
         } else {
@@ -402,21 +342,14 @@ impl Message for Bytes {
 
 /// `google.protobuf.Empty`
 impl Message for () {
-    fn encode_raw<B>(&self, _buf: &mut B)
-    where
-        B: BufMut,
-    {
-    }
-    fn merge_field<B>(
+    fn encode_raw(&self, _buf: &mut impl BufMut) {}
+    fn merge_field(
         &mut self,
         tag: u32,
         wire_type: WireType,
-        buf: &mut B,
+        buf: &mut impl Buf,
         ctx: DecodeContext,
-    ) -> Result<(), DecodeError>
-    where
-        B: Buf,
-    {
+    ) -> Result<(), DecodeError> {
         skip_field(wire_type, tag, buf, ctx)
     }
     fn encoded_len(&self) -> usize {


Test patch:
diff --git a/tests/src/build.rs b/tests/src/build.rs
index 7b2c0bc5e..a1aaf78d9 100644
--- a/tests/src/build.rs
+++ b/tests/src/build.rs
@@ -71,6 +71,10 @@ fn main() {
         .compile_protos(&[src.join("oneof_attributes.proto")], includes)
         .unwrap();
 
+    config
+        .compile_protos(&[src.join("no_shadowed_types.proto")], includes)
+        .unwrap();
+
     config
         .compile_protos(&[src.join("no_unused_results.proto")], includes)
         .unwrap();
diff --git a/tests/src/lib.rs b/tests/src/lib.rs
index 00926afe0..f233d7f8d 100644
--- a/tests/src/lib.rs
+++ b/tests/src/lib.rs
@@ -43,6 +43,8 @@ mod generic_derive;
 #[cfg(test)]
 mod message_encoding;
 #[cfg(test)]
+mod no_shadowed_types;
+#[cfg(test)]
 mod no_unused_results;
 #[cfg(test)]
 #[cfg(feature = "std")]
diff --git a/tests/src/no_shadowed_types.proto b/tests/src/no_shadowed_types.proto
new file mode 100644
index 000000000..d532600f3
--- /dev/null
+++ b/tests/src/no_shadowed_types.proto
@@ -0,0 +1,10 @@
+syntax = "proto3";
+
+package no_shadowed_types;
+
+enum B {
+  DEFAULT = 0;
+  NON_DEFAULT = 1;
+}
+
+message A { B b = 1; }
diff --git a/tests/src/no_shadowed_types.rs b/tests/src/no_shadowed_types.rs
new file mode 100644
index 000000000..e66a8d705
--- /dev/null
+++ b/tests/src/no_shadowed_types.rs
@@ -0,0 +1,6 @@
+mod should_compile_successfully {
+    include!(concat!(env!("OUT_DIR"), "/no_shadowed_types.rs"));
+}
+
+#[test]
+fn dummy() {}