diff --git a/binrw/src/binread/impls.rs b/binrw/src/binread/impls.rs index 45764f06..54a88ae3 100644 --- a/binrw/src/binread/impls.rs +++ b/binrw/src/binread/impls.rs @@ -12,9 +12,9 @@ macro_rules! binread_impl { ($($type_name:ty),*$(,)?) => { $( impl BinRead for $type_name { - type Args = (); + type Args<'a> = (); - fn read_options(reader: &mut R, endian: Endian, _: Self::Args) -> BinResult { + fn read_options(reader: &mut R, endian: Endian, _: Self::Args<'_>) -> BinResult { let mut val = [0; core::mem::size_of::<$type_name>()]; let pos = reader.stream_position()?; @@ -49,12 +49,12 @@ macro_rules! binread_nonzero_impl { ($($Ty:ty, $Int:ty),* $(,)?) => { $( impl BinRead for $Ty { - type Args = (); + type Args<'a> = (); fn read_options( reader: &mut R, endian: Endian, - _: Self::Args, + _: Self::Args<'_>, ) -> BinResult { match <$Ty>::new(<$Int>::read_options(reader, endian, ())?) { Some(x) => Ok(x), @@ -133,18 +133,27 @@ pub struct VecArgs { pub inner: Inner, } -impl BinRead for Vec { - type Args = VecArgs; +impl BinRead for Vec +where + B: BinRead + 'static, + for<'a> B::Args<'a>: Clone, +{ + type Args<'a> = VecArgs>; fn read_options( reader: &mut R, endian: Endian, - args: Self::Args, + args: Self::Args<'_>, ) -> BinResult { crate::helpers::count_with(args.count, B::read_options)(reader, endian, args.inner) } - fn after_parse(&mut self, reader: &mut R, endian: Endian, args: Self::Args) -> BinResult<()> + fn after_parse( + &mut self, + reader: &mut R, + endian: Endian, + args: Self::Args<'_>, + ) -> BinResult<()> where R: Read + Seek, { @@ -156,18 +165,27 @@ impl BinRead for Vec { } } -impl BinRead for [B; N] { - type Args = B::Args; +impl BinRead for [B; N] +where + B: BinRead, + for<'a> B::Args<'a>: Clone, +{ + type Args<'a> = B::Args<'a>; fn read_options( reader: &mut R, endian: Endian, - args: Self::Args, + args: Self::Args<'_>, ) -> BinResult { array_init::try_array_init(|_| BinRead::read_options(reader, endian, args.clone())) } - fn after_parse(&mut self, reader: &mut R, endian: Endian, args: B::Args) -> BinResult<()> + fn after_parse( + &mut self, + reader: &mut R, + endian: Endian, + args: Self::Args<'_>, + ) -> BinResult<()> where R: Read + Seek, { @@ -182,10 +200,10 @@ impl BinRead for [B; N] { macro_rules! binread_tuple_impl { ($type1:ident $(, $types:ident)*) => { #[allow(non_camel_case_types)] - impl, $($types: BinRead),*> BinRead for ($type1, $($types),*) { - type Args = Args; + impl BinRead = Args>, $($types: for<'a> BinRead = Args>),*> BinRead for ($type1, $($types),*) { + type Args<'a> = Args; - fn read_options(reader: &mut R, endian: Endian, args: Self::Args) -> BinResult { + fn read_options(reader: &mut R, endian: Endian, args: Self::Args<'_>) -> BinResult { Ok(( BinRead::read_options(reader, endian, args.clone())?, $( @@ -194,7 +212,7 @@ macro_rules! binread_tuple_impl { )) } - fn after_parse(&mut self, reader: &mut R, endian: Endian, args: Self::Args) -> BinResult<()> { + fn after_parse(&mut self, reader: &mut R, endian: Endian, args: Self::Args<'_>) -> BinResult<()> { let ($type1, $( $types ),*) = self; @@ -220,37 +238,42 @@ binread_tuple_impl!( ); impl BinRead for () { - type Args = (); + type Args<'a> = (); - fn read_options(_: &mut R, _: Endian, _: Self::Args) -> BinResult { + fn read_options(_: &mut R, _: Endian, _: Self::Args<'_>) -> BinResult { Ok(()) } } impl BinRead for Box { - type Args = T::Args; + type Args<'a> = T::Args<'a>; fn read_options( reader: &mut R, endian: Endian, - args: Self::Args, + args: Self::Args<'_>, ) -> BinResult { Ok(Box::new(T::read_options(reader, endian, args)?)) } } impl BinRead for Option { - type Args = T::Args; + type Args<'a> = T::Args<'a>; fn read_options( reader: &mut R, endian: Endian, - args: Self::Args, + args: Self::Args<'_>, ) -> BinResult { Ok(Some(T::read_options(reader, endian, args)?)) } - fn after_parse(&mut self, reader: &mut R, endian: Endian, args: Self::Args) -> BinResult<()> + fn after_parse( + &mut self, + reader: &mut R, + endian: Endian, + args: Self::Args<'_>, + ) -> BinResult<()> where R: Read + Seek, { @@ -261,10 +284,10 @@ impl BinRead for Option { } } -impl BinRead for core::marker::PhantomData { - type Args = (); +impl BinRead for core::marker::PhantomData { + type Args<'a> = (); - fn read_options(_: &mut R, _: Endian, _: Self::Args) -> BinResult { + fn read_options(_: &mut R, _: Endian, _: Self::Args<'_>) -> BinResult { Ok(core::marker::PhantomData) } } diff --git a/binrw/src/binread/mod.rs b/binrw/src/binread/mod.rs index 704ff10d..572063ad 100644 --- a/binrw/src/binread/mod.rs +++ b/binrw/src/binread/mod.rs @@ -30,7 +30,7 @@ pub use impls::VecArgs; /// [temporary fields]. /// /// [temporary fields]: crate::docs::attribute#temp -pub trait BinRead: Sized + 'static { +pub trait BinRead: Sized { /// The type used for the `args` parameter of [`read_args()`] and /// [`read_options()`]. /// @@ -46,7 +46,7 @@ pub trait BinRead: Sized + 'static { /// [`read()`]: Self::read /// [`read_args()`]: Self::read_args /// [`read_options()`]: Self::read_options - type Args: Clone; + type Args<'a>; /// Read `Self` from the reader using default arguments. /// @@ -57,7 +57,7 @@ pub trait BinRead: Sized + 'static { fn read(reader: &mut R) -> BinResult where Self: ReadEndian, - Self::Args: Required, + for<'a> Self::Args<'a>: Required, { Self::read_args(reader, Self::Args::args()) } @@ -71,7 +71,7 @@ pub trait BinRead: Sized + 'static { #[inline] fn read_be(reader: &mut R) -> BinResult where - Self::Args: Required, + for<'a> Self::Args<'a>: Required, { Self::read_be_args(reader, Self::Args::args()) } @@ -85,7 +85,7 @@ pub trait BinRead: Sized + 'static { #[inline] fn read_le(reader: &mut R) -> BinResult where - Self::Args: Required, + for<'a> Self::Args<'a>: Required, { Self::read_le_args(reader, Self::Args::args()) } @@ -98,7 +98,7 @@ pub trait BinRead: Sized + 'static { #[inline] fn read_ne(reader: &mut R) -> BinResult where - Self::Args: Required, + for<'a> Self::Args<'a>: Required, { Self::read_ne_args(reader, Self::Args::args()) } @@ -109,7 +109,7 @@ pub trait BinRead: Sized + 'static { /// /// If reading fails, an [`Error`](crate::Error) variant will be returned. #[inline] - fn read_args(reader: &mut R, args: Self::Args) -> BinResult + fn read_args(reader: &mut R, args: Self::Args<'_>) -> BinResult where Self: ReadEndian, { @@ -123,7 +123,7 @@ pub trait BinRead: Sized + 'static { /// /// If reading fails, an [`Error`](crate::Error) variant will be returned. #[inline] - fn read_be_args(reader: &mut R, args: Self::Args) -> BinResult { + fn read_be_args(reader: &mut R, args: Self::Args<'_>) -> BinResult { Self::read_options(reader, Endian::Big, args) } @@ -134,7 +134,7 @@ pub trait BinRead: Sized + 'static { /// /// If reading fails, an [`Error`](crate::Error) variant will be returned. #[inline] - fn read_le_args(reader: &mut R, args: Self::Args) -> BinResult { + fn read_le_args(reader: &mut R, args: Self::Args<'_>) -> BinResult { Self::read_options(reader, Endian::Little, args) } @@ -145,7 +145,7 @@ pub trait BinRead: Sized + 'static { /// /// If reading fails, an [`Error`](crate::Error) variant will be returned. #[inline] - fn read_ne_args(reader: &mut R, args: Self::Args) -> BinResult { + fn read_ne_args(reader: &mut R, args: Self::Args<'_>) -> BinResult { Self::read_options(reader, Endian::NATIVE, args) } @@ -158,7 +158,7 @@ pub trait BinRead: Sized + 'static { fn read_options( reader: &mut R, endian: Endian, - args: Self::Args, + args: Self::Args<'_>, ) -> BinResult; /// Runs any post-processing steps required to finalize construction of the @@ -172,7 +172,7 @@ pub trait BinRead: Sized + 'static { &mut self, _: &mut R, _: Endian, - _: Self::Args, + _: Self::Args<'_>, ) -> BinResult<()> { Ok(()) } @@ -199,9 +199,10 @@ pub trait BinReaderExt: Read + Seek + Sized { /// /// If reading fails, an [`Error`](crate::Error) variant will be returned. #[inline] - fn read_type(&mut self, endian: Endian) -> BinResult + fn read_type<'a, T>(&mut self, endian: Endian) -> BinResult where - T::Args: Required, + T: BinRead, + T::Args<'a>: Required + Clone, { self.read_type_args(endian, T::Args::args()) } @@ -212,9 +213,10 @@ pub trait BinReaderExt: Read + Seek + Sized { /// /// If reading fails, an [`Error`](crate::Error) variant will be returned. #[inline] - fn read_be(&mut self) -> BinResult + fn read_be<'a, T>(&mut self) -> BinResult where - T::Args: Required, + T: BinRead, + T::Args<'a>: Required + Clone, { self.read_type(Endian::Big) } @@ -225,9 +227,10 @@ pub trait BinReaderExt: Read + Seek + Sized { /// /// If reading fails, an [`Error`](crate::Error) variant will be returned. #[inline] - fn read_le(&mut self) -> BinResult + fn read_le<'a, T>(&mut self) -> BinResult where - T::Args: Required, + T: BinRead, + T::Args<'a>: Required + Clone, { self.read_type(Endian::Little) } @@ -238,9 +241,10 @@ pub trait BinReaderExt: Read + Seek + Sized { /// /// If reading fails, an [`Error`](crate::Error) variant will be returned. #[inline] - fn read_ne(&mut self) -> BinResult + fn read_ne<'a, T>(&mut self) -> BinResult where - T::Args: Required, + T: BinRead, + T::Args<'a>: Required + Clone, { self.read_type(Endian::NATIVE) } @@ -250,7 +254,11 @@ pub trait BinReaderExt: Read + Seek + Sized { /// # Errors /// /// If reading fails, an [`Error`](crate::Error) variant will be returned. - fn read_type_args(&mut self, endian: Endian, args: T::Args) -> BinResult { + fn read_type_args<'a, T>(&mut self, endian: Endian, args: T::Args<'a>) -> BinResult + where + T: BinRead, + T::Args<'a>: Clone, + { let mut res = T::read_options(self, endian, args.clone())?; res.after_parse(self, endian, args)?; @@ -264,7 +272,11 @@ pub trait BinReaderExt: Read + Seek + Sized { /// /// If reading fails, an [`Error`](crate::Error) variant will be returned. #[inline] - fn read_be_args(&mut self, args: T::Args) -> BinResult { + fn read_be_args<'a, T>(&mut self, args: T::Args<'a>) -> BinResult + where + T: BinRead, + T::Args<'a>: Clone, + { self.read_type_args(Endian::Big, args) } @@ -275,7 +287,11 @@ pub trait BinReaderExt: Read + Seek + Sized { /// /// If reading fails, an [`Error`](crate::Error) variant will be returned. #[inline] - fn read_le_args(&mut self, args: T::Args) -> BinResult { + fn read_le_args<'a, T>(&mut self, args: T::Args<'a>) -> BinResult + where + T: BinRead, + T::Args<'a>: Clone, + { self.read_type_args(Endian::Little, args) } @@ -286,7 +302,11 @@ pub trait BinReaderExt: Read + Seek + Sized { /// /// If reading fails, an [`Error`](crate::Error) variant will be returned. #[inline] - fn read_ne_args(&mut self, args: T::Args) -> BinResult { + fn read_ne_args<'a, T>(&mut self, args: T::Args<'a>) -> BinResult + where + T: BinRead, + T::Args<'a>: Clone, + { self.read_type_args(Endian::NATIVE, args) } } diff --git a/binrw/src/binwrite/impls.rs b/binrw/src/binwrite/impls.rs index db538c58..2337ec97 100644 --- a/binrw/src/binwrite/impls.rs +++ b/binrw/src/binwrite/impls.rs @@ -16,13 +16,13 @@ macro_rules! binwrite_num_impl { ($($type_name:ty),*$(,)?) => { $( impl BinWrite for $type_name { - type Args = (); + type Args<'a> = (); fn write_options( &self, writer: &mut W, endian: Endian, - _: Self::Args, + _: Self::Args<'_>, ) -> BinResult<()> { writer.write_all(&match endian { Endian::Big => self.to_be_bytes(), @@ -40,13 +40,13 @@ macro_rules! binwrite_nonzero_num_impl { ($($non_zero_type:ty => $type_name:ty),*$(,)?) => { $( impl BinWrite for $non_zero_type { - type Args = (); + type Args<'a> = (); fn write_options( &self, writer: &mut W, endian: Endian, - _: Self::Args, + _: Self::Args<'_>, ) -> BinResult<()> { let num = <$type_name>::from(*self); @@ -73,14 +73,18 @@ binwrite_nonzero_num_impl!( NonZeroI128 => i128, ); -impl BinWrite for [T; N] { - type Args = T::Args; +impl BinWrite for [T; N] +where + T: BinWrite + 'static, + for<'a> T::Args<'a>: Clone, +{ + type Args<'a> = T::Args<'a>; fn write_options( &self, writer: &mut W, endian: Endian, - args: Self::Args, + args: Self::Args<'_>, ) -> BinResult<()> { if let Some(this) = ::downcast_ref::<[u8; N]>(self) { writer.write_all(&this[..])?; @@ -94,14 +98,18 @@ impl BinWrite for [T; N] { } } -impl BinWrite for [T] { - type Args = T::Args; +impl BinWrite for [T] +where + T: BinWrite, + for<'a> T::Args<'a>: Clone, +{ + type Args<'a> = T::Args<'a>; fn write_options( &self, writer: &mut W, endian: Endian, - args: Self::Args, + args: Self::Args<'_>, ) -> BinResult<()> { for item in self { T::write_options(item, writer, endian, args.clone())?; @@ -111,14 +119,18 @@ impl BinWrite for [T] { } } -impl BinWrite for Vec { - type Args = T::Args; +impl BinWrite for Vec +where + T: BinWrite + 'static, + for<'a> T::Args<'a>: Clone, +{ + type Args<'a> = T::Args<'a>; fn write_options( &self, writer: &mut W, endian: Endian, - args: Self::Args, + args: Self::Args<'_>, ) -> BinResult<()> { if let Some(this) = ::downcast_ref::>(self) { writer.write_all(this)?; @@ -135,26 +147,26 @@ impl BinWrite for Vec { } impl BinWrite for &T { - type Args = T::Args; + type Args<'a> = T::Args<'a>; fn write_options( &self, writer: &mut W, endian: Endian, - args: Self::Args, + args: Self::Args<'_>, ) -> BinResult<()> { (**self).write_options(writer, endian, args) } } impl BinWrite for Box { - type Args = T::Args; + type Args<'a> = T::Args<'a>; fn write_options( &self, writer: &mut W, endian: Endian, - args: Self::Args, + args: Self::Args<'_>, ) -> BinResult<()> { if let Some(this) = ::downcast_ref::>(self) { writer.write_all(this)?; @@ -167,13 +179,13 @@ impl BinWrite for Box { } impl BinWrite for Option { - type Args = T::Args; + type Args<'a> = T::Args<'a>; fn write_options( &self, writer: &mut W, endian: Endian, - args: Self::Args, + args: Self::Args<'_>, ) -> BinResult<()> { match self { Some(inner) => inner.write_options(writer, endian, args), @@ -183,17 +195,27 @@ impl BinWrite for Option { } impl BinWrite for PhantomData { - type Args = T::Args; + type Args<'a> = T::Args<'a>; - fn write_options(&self, _: &mut W, _: Endian, _: Self::Args) -> BinResult<()> { + fn write_options( + &self, + _: &mut W, + _: Endian, + _: Self::Args<'_>, + ) -> BinResult<()> { Ok(()) } } impl BinWrite for () { - type Args = (); + type Args<'a> = (); - fn write_options(&self, _: &mut W, _: Endian, _: Self::Args) -> BinResult<()> { + fn write_options( + &self, + _: &mut W, + _: Endian, + _: Self::Args<'_>, + ) -> BinResult<()> { Ok(()) } } @@ -202,15 +224,15 @@ macro_rules! binwrite_tuple_impl { ($type1:ident $(, $types:ident)*) => { #[allow(non_camel_case_types)] impl, $($types: BinWrite),* + $type1: for<'a> BinWrite = Args>, $($types: for<'a> BinWrite = Args>),* > BinWrite for ($type1, $($types),*) { - type Args = Args; + type Args<'a> = Args; fn write_options( &self, writer: &mut W, endian: Endian, - args: Self::Args, + args: Self::Args<'_>, ) -> BinResult<()> { let ($type1, $( $types diff --git a/binrw/src/binwrite/mod.rs b/binrw/src/binwrite/mod.rs index 61e06767..5d9c567a 100644 --- a/binrw/src/binwrite/mod.rs +++ b/binrw/src/binwrite/mod.rs @@ -44,7 +44,7 @@ pub trait BinWrite { /// [`write()`]: Self::write /// [`write_args()`]: Self::write_args /// [`write_options()`]: Self::write_options - type Args: Clone; + type Args<'a>; /// Write `Self` to the writer using default arguments. /// @@ -55,7 +55,7 @@ pub trait BinWrite { fn write(&self, writer: &mut W) -> BinResult<()> where Self: crate::meta::WriteEndian, - Self::Args: Required, + for<'a> Self::Args<'a>: Required, { self.write_args(writer, Self::Args::args()) } @@ -68,7 +68,7 @@ pub trait BinWrite { #[inline] fn write_be(&self, writer: &mut W) -> BinResult<()> where - Self::Args: Required, + for<'a> Self::Args<'a>: Required, { self.write_be_args(writer, Self::Args::args()) } @@ -81,7 +81,7 @@ pub trait BinWrite { #[inline] fn write_le(&self, writer: &mut W) -> BinResult<()> where - Self::Args: Required, + for<'a> Self::Args<'a>: Required, { self.write_le_args(writer, Self::Args::args()) } @@ -92,7 +92,7 @@ pub trait BinWrite { /// /// If writing fails, an [`Error`](crate::Error) variant will be returned. #[inline] - fn write_args(&self, writer: &mut W, args: Self::Args) -> BinResult<()> + fn write_args(&self, writer: &mut W, args: Self::Args<'_>) -> BinResult<()> where Self: crate::meta::WriteEndian, { @@ -106,7 +106,11 @@ pub trait BinWrite { /// /// If reading fails, an [`Error`](crate::Error) variant will be returned. #[inline] - fn write_be_args(&self, writer: &mut W, args: Self::Args) -> BinResult<()> { + fn write_be_args( + &self, + writer: &mut W, + args: Self::Args<'_>, + ) -> BinResult<()> { self.write_options(writer, Endian::Big, args) } @@ -117,7 +121,11 @@ pub trait BinWrite { /// /// If reading fails, an [`Error`](crate::Error) variant will be returned. #[inline] - fn write_le_args(&self, writer: &mut W, args: Self::Args) -> BinResult<()> { + fn write_le_args( + &self, + writer: &mut W, + args: Self::Args<'_>, + ) -> BinResult<()> { self.write_options(writer, Endian::Little, args) } @@ -131,7 +139,7 @@ pub trait BinWrite { &self, writer: &mut W, endian: Endian, - args: Self::Args, + args: Self::Args<'_>, ) -> BinResult<()>; } @@ -159,7 +167,7 @@ pub trait BinWriterExt: Write + Seek + Sized { /// If writing fails, an [`Error`](crate::Error) variant will be returned. fn write_type(&mut self, value: &T, endian: Endian) -> BinResult<()> where - T::Args: Required, + for<'a> T::Args<'a>: Required, { self.write_type_args(value, endian, T::Args::args()) } @@ -171,7 +179,7 @@ pub trait BinWriterExt: Write + Seek + Sized { /// If writing fails, an [`Error`](crate::Error) variant will be returned. fn write_be(&mut self, value: &T) -> BinResult<()> where - T::Args: Required, + for<'a> T::Args<'a>: Required, { self.write_type(value, Endian::Big) } @@ -183,7 +191,7 @@ pub trait BinWriterExt: Write + Seek + Sized { /// If writing fails, an [`Error`](crate::Error) variant will be returned. fn write_le(&mut self, value: &T) -> BinResult<()> where - T::Args: Required, + for<'a> T::Args<'a>: Required, { self.write_type(value, Endian::Little) } @@ -195,7 +203,7 @@ pub trait BinWriterExt: Write + Seek + Sized { /// If writing fails, an [`Error`](crate::Error) variant will be returned. fn write_ne(&mut self, value: &T) -> BinResult<()> where - T::Args: Required, + for<'a> T::Args<'a>: Required, { self.write_type(value, Endian::NATIVE) } @@ -209,7 +217,7 @@ pub trait BinWriterExt: Write + Seek + Sized { &mut self, value: &T, endian: Endian, - args: T::Args, + args: T::Args<'_>, ) -> BinResult<()> { T::write_options(value, self, endian, args)?; @@ -222,7 +230,7 @@ pub trait BinWriterExt: Write + Seek + Sized { /// # Errors /// /// If writing fails, an [`Error`](crate::Error) variant will be returned. - fn write_be_args(&mut self, value: &T, args: T::Args) -> BinResult<()> { + fn write_be_args(&mut self, value: &T, args: T::Args<'_>) -> BinResult<()> { self.write_type_args(value, Endian::Big, args) } @@ -232,7 +240,7 @@ pub trait BinWriterExt: Write + Seek + Sized { /// # Errors /// /// If writing fails, an [`Error`](crate::Error) variant will be returned. - fn write_le_args(&mut self, value: &T, args: T::Args) -> BinResult<()> { + fn write_le_args(&mut self, value: &T, args: T::Args<'_>) -> BinResult<()> { self.write_type_args(value, Endian::Little, args) } @@ -242,7 +250,7 @@ pub trait BinWriterExt: Write + Seek + Sized { /// # Errors /// /// If writing fails, an [`Error`](crate::Error) variant will be returned. - fn write_ne_args(&mut self, value: &T, args: T::Args) -> BinResult<()> { + fn write_ne_args(&mut self, value: &T, args: T::Args<'_>) -> BinResult<()> { self.write_type_args(value, Endian::NATIVE, args) } } diff --git a/binrw/src/file_ptr.rs b/binrw/src/file_ptr.rs index 40e2af17..ff8074b7 100644 --- a/binrw/src/file_ptr.rs +++ b/binrw/src/file_ptr.rs @@ -77,8 +77,13 @@ pub struct FilePtr { pub value: Option, } -impl + IntoSeekFrom, Value: BinRead> BinRead for FilePtr { - type Args = FilePtrArgs; +impl BinRead for FilePtr +where + Ptr: for<'a> BinRead = ()> + IntoSeekFrom, + Value: BinRead, + for<'a> Value::Args<'a>: Clone, +{ + type Args<'a> = FilePtrArgs>; /// Reads the offset of the value from the reader. /// @@ -87,7 +92,7 @@ impl + IntoSeekFrom, Value: BinRead> BinRead for FilePtr fn read_options( reader: &mut R, endian: Endian, - _: Self::Args, + _: Self::Args<'_>, ) -> BinResult { Ok(FilePtr { ptr: Ptr::read_options(reader, endian, ())?, @@ -100,7 +105,7 @@ impl + IntoSeekFrom, Value: BinRead> BinRead for FilePtr &mut self, reader: &mut R, endian: Endian, - args: FilePtrArgs, + args: Self::Args<'_>, ) -> BinResult<()> where R: Read + Seek, @@ -115,7 +120,10 @@ impl + IntoSeekFrom, Value: BinRead> BinRead for FilePtr } } -impl + IntoSeekFrom, Value> FilePtr { +impl FilePtr +where + Ptr: for<'a> BinRead = ()> + IntoSeekFrom, +{ fn read_with_parser( parser: Parser, after_parse: AfterParse, @@ -177,7 +185,7 @@ impl + IntoSeekFrom, Value> FilePtr { pub fn parse(args: FilePtrArgs, ...) -> BinResult where Args: Clone, - Value: BinRead, + Value: for<'a> BinRead = Args>, { Ok(Self::read_with_parser( Value::read_options, diff --git a/binrw/src/helpers.rs b/binrw/src/helpers.rs index e6a5b4fd..975c4c38 100644 --- a/binrw/src/helpers.rs +++ b/binrw/src/helpers.rs @@ -31,7 +31,7 @@ pub fn until( cond: CondFn, ) -> impl Fn(&mut Reader, Endian, Arg) -> BinResult where - T: BinRead, + T: for<'a> BinRead = Arg>, Reader: Read + Seek, CondFn: Fn(&T) -> bool, Arg: Clone, @@ -123,7 +123,7 @@ pub fn until_exclusive( cond: CondFn, ) -> impl Fn(&mut Reader, Endian, Arg) -> BinResult where - T: BinRead, + T: for<'a> BinRead = Arg>, Reader: Read + Seek, CondFn: Fn(&T) -> bool, Arg: Clone, @@ -216,7 +216,7 @@ pub fn until_eof( args: Arg, ) -> BinResult where - T: BinRead, + T: for<'a> BinRead = Arg>, Reader: Read + Seek, Arg: Clone, Ret: FromIterator, @@ -300,7 +300,7 @@ where /// #[br(big)] /// struct Object { /// header: Header, -/// #[br(parse_with = args_iter(header.sizes.iter().map(|&size| -> as BinRead>::Args { +/// #[br(parse_with = args_iter(header.sizes.iter().map(|&size| -> as BinRead>::Args<'_> { /// args! { count: size.into() } /// })))] /// segments: Vec>, @@ -311,7 +311,7 @@ where /// # assert_eq!(x.segments, &[vec![3], vec![4, 5]]); pub fn args_iter(it: It) -> impl FnOnce(&mut R, Endian, ()) -> BinResult where - T: BinRead, + T: for<'a> BinRead = Arg>, R: Read + Seek, Arg: Clone, Ret: FromIterator, @@ -400,7 +400,7 @@ where /// ``` pub fn count(n: usize) -> impl Fn(&mut R, Endian, Arg) -> BinResult where - T: BinRead, + T: for<'a> BinRead = Arg>, R: Read + Seek, Arg: Clone, Ret: FromIterator + 'static, @@ -476,7 +476,10 @@ where } #[binrw::parser(reader, endian)] -fn default_reader>(args: T::Args, ...) -> BinResult { +fn default_reader<'a, T: BinRead>(args: T::Args<'a>, ...) -> BinResult +where + T::Args<'a>: Clone, +{ let mut value = T::read_options(reader, endian, args.clone())?; value.after_parse(reader, endian, args)?; Ok(value) diff --git a/binrw/src/lib.rs b/binrw/src/lib.rs index 5b76b736..ecf8e1a3 100644 --- a/binrw/src/lib.rs +++ b/binrw/src/lib.rs @@ -122,8 +122,12 @@ pub use binrw_derive::binrw; /// } /// /// #[binread] -/// #[br(import_raw(args: GlobalArgs))] -/// struct Container { +/// #[br(import_raw(args: GlobalArgs>))] +/// struct Container +/// where +/// T: BinRead + 'static, +/// for<'a> T::Args<'a>: Clone, +/// { /// #[br(temp, if(args.version > 1, 16))] /// count: u16, /// #[br(args { diff --git a/binrw/src/pos_value.rs b/binrw/src/pos_value.rs index 1ed9b2fd..02b4404e 100644 --- a/binrw/src/pos_value.rs +++ b/binrw/src/pos_value.rs @@ -30,12 +30,12 @@ pub struct PosValue { } impl BinRead for PosValue { - type Args = T::Args; + type Args<'a> = T::Args<'a>; fn read_options( reader: &mut R, endian: Endian, - args: T::Args, + args: Self::Args<'_>, ) -> BinResult { let pos = reader.stream_position()?; @@ -49,7 +49,7 @@ impl BinRead for PosValue { &mut self, reader: &mut R, endian: Endian, - args: Self::Args, + args: Self::Args<'_>, ) -> BinResult<()> { self.val.after_parse(reader, endian, args) } diff --git a/binrw/src/private.rs b/binrw/src/private.rs index d3955406..e0c50fe2 100644 --- a/binrw/src/private.rs +++ b/binrw/src/private.rs @@ -74,7 +74,14 @@ where pub fn magic(reader: &mut R, expected: B, endian: Endian) -> BinResult<()> where - B: BinRead + core::fmt::Debug + PartialEq + Sync + Send + Clone + Copy + 'static, + B: for<'a> BinRead = ()> + + core::fmt::Debug + + PartialEq + + Sync + + Send + + Clone + + Copy + + 'static, R: Read + Seek, { let pos = reader.stream_position()?; @@ -91,7 +98,6 @@ where pub fn parse_fn_type_hint(f: ParseFn) -> ParseFn where - Args: Clone, R: Read + Seek, ParseFn: FnOnce(&mut R, Endian, Args) -> BinResult, { @@ -117,14 +123,13 @@ where pub fn map_args_type_hint(_: &MapFn, args: Args) -> Args where MapFn: FnOnce(Input) -> Output, - Input: BinRead, + Input: for<'a> BinRead = Args>, { args } pub fn write_fn_type_hint(x: WriterFn) -> WriterFn where - Args: Clone, Writer: Write + Seek, WriterFn: FnOnce(&T, &mut Writer, Endian, Args) -> BinResult<()>, { @@ -134,7 +139,7 @@ where pub fn write_map_args_type_hint(_: &MapFn, args: Args) -> Args where MapFn: FnOnce(Input) -> Output, - Output: BinWrite, + Output: for<'a> BinWrite = Args>, { args } @@ -146,7 +151,7 @@ pub fn write_try_map_args_type_hint( where Error: CustomError, MapFn: FnOnce(Input) -> Result, - Output: BinWrite, + Output: for<'a> BinWrite = Args>, { args } diff --git a/binrw/src/punctuated.rs b/binrw/src/punctuated.rs index 447d3fcb..345af577 100644 --- a/binrw/src/punctuated.rs +++ b/binrw/src/punctuated.rs @@ -43,7 +43,11 @@ pub struct Punctuated { pub separators: Vec

, } -impl> Punctuated { +impl Punctuated +where + T: BinRead, + P: for<'a> BinRead = ()>, +{ /// Parses values of type `T` separated by values of type `P` without a /// trailing separator value. /// @@ -72,7 +76,10 @@ impl> Punctuated { /// # assert_eq!(y.x.separators, vec![0, 1]); /// ``` #[crate::parser(reader, endian)] - pub fn separated(args: VecArgs, ...) -> BinResult { + pub fn separated<'a>(args: VecArgs>, ...) -> BinResult + where + T::Args<'a>: Clone, + { let mut data = Vec::with_capacity(args.count); let mut separators = Vec::with_capacity(args.count.max(1) - 1); @@ -95,7 +102,10 @@ impl> Punctuated { /// /// If reading fails, an [`Error`](crate::Error) variant will be returned. #[crate::parser(reader, endian)] - pub fn separated_trailing(args: VecArgs, ...) -> BinResult { + pub fn separated_trailing<'a>(args: VecArgs>, ...) -> BinResult + where + T::Args<'a>: Clone, + { let mut data = Vec::with_capacity(args.count); let mut separators = Vec::with_capacity(args.count); diff --git a/binrw/src/strings.rs b/binrw/src/strings.rs index 02e6232a..78dd5e56 100644 --- a/binrw/src/strings.rs +++ b/binrw/src/strings.rs @@ -34,12 +34,12 @@ pub struct NullString( ); impl BinRead for NullString { - type Args = (); + type Args<'a> = (); fn read_options( reader: &mut R, endian: Endian, - _: Self::Args, + _: Self::Args<'_>, ) -> BinResult { let mut values = vec![]; @@ -54,13 +54,13 @@ impl BinRead for NullString { } impl BinWrite for NullString { - type Args = (); + type Args<'a> = (); fn write_options( &self, writer: &mut W, endian: Endian, - args: Self::Args, + args: Self::Args<'_>, ) -> BinResult<()> { self.0.write_options(writer, endian, args)?; 0u8.write_options(writer, endian, args)?; @@ -156,12 +156,12 @@ pub struct NullWideString( ); impl BinRead for NullWideString { - type Args = (); + type Args<'a> = (); fn read_options( reader: &mut R, endian: Endian, - _: Self::Args, + _: Self::Args<'_>, ) -> BinResult { let mut values = vec![]; @@ -176,13 +176,13 @@ impl BinRead for NullWideString { } impl BinWrite for NullWideString { - type Args = (); + type Args<'a> = (); fn write_options( &self, writer: &mut W, endian: Endian, - args: Self::Args, + args: Self::Args<'_>, ) -> BinResult<()> { self.0.write_options(writer, endian, args)?; 0u16.write_options(writer, endian, args)?; diff --git a/binrw/tests/after_parse_test.rs b/binrw/tests/after_parse_test.rs index 1c6c1190..3dee7e76 100644 --- a/binrw/tests/after_parse_test.rs +++ b/binrw/tests/after_parse_test.rs @@ -11,9 +11,12 @@ fn BinReaderExt_calls_after_parse() { #[test] fn try_calls_after_parse() { #[derive(BinRead)] - struct Try, Args: Default + 'static>(#[br(try)] Option
); + struct Try
(#[br(try)] Option
) + where + BR: BinRead, + for<'a> BR::Args<'a>: Default + 'static; - let test: Try, _> = Cursor::new([0x01, 0xFF]).read_be().unwrap(); + let test: Try> = Cursor::new([0x01, 0xFF]).read_be().unwrap(); assert_eq!(*test.0.unwrap(), 0xFF) } diff --git a/binrw/tests/derive/struct.rs b/binrw/tests/derive/struct.rs index 11b0498e..7d8fbd59 100644 --- a/binrw/tests/derive/struct.rs +++ b/binrw/tests/derive/struct.rs @@ -228,6 +228,51 @@ fn all_default_imports() { assert_eq!(result, Test { a: 1 }); } +#[test] +fn gat_list() { + #[derive(BinRead, Debug, PartialEq)] + #[br(little, import(borrowed: &u8))] + struct Test { + #[br(calc(*borrowed))] + a: u8, + } + + assert_eq!( + Test::read_args(&mut Cursor::new(b""), (&1_u8,)).unwrap(), + Test { a: 1 } + ); +} + +#[test] +fn gat_named() { + #[derive(BinRead, Debug, PartialEq)] + #[br(little, import { borrowed: &u8 })] + struct Test { + #[br(calc(*borrowed))] + a: u8, + } + + assert_eq!( + Test::read_args(&mut Cursor::new(b""), binrw::args! { borrowed: &1_u8 }).unwrap(), + Test { a: 1 } + ); +} + +#[test] +fn gat_raw() { + #[derive(BinRead, Debug, PartialEq)] + #[br(little, import_raw(borrowed: &u8))] + struct Test { + #[br(calc(*borrowed))] + a: u8, + } + + assert_eq!( + Test::read_args(&mut Cursor::new(b""), &1_u8).unwrap(), + Test { a: 1 } + ); +} + #[test] fn if_alternate() { #[derive(BinRead, Debug)] diff --git a/binrw/tests/derive/struct_generic.rs b/binrw/tests/derive/struct_generic.rs index e28f34be..5d887559 100644 --- a/binrw/tests/derive/struct_generic.rs +++ b/binrw/tests/derive/struct_generic.rs @@ -3,7 +3,7 @@ use binrw::{io::Cursor, BinRead}; #[test] fn derive_generic() { #[derive(BinRead)] - struct Test + Default> { + struct Test BinRead = ()> + Default> { a: [T; 3], } diff --git a/binrw/tests/derive/write/import.rs b/binrw/tests/derive/write/import.rs index 88945dc9..9c3b11f3 100644 --- a/binrw/tests/derive/write/import.rs +++ b/binrw/tests/derive/write/import.rs @@ -1,4 +1,4 @@ -use binrw::{binrw, BinWrite}; +use binrw::{binrw, io::Cursor, BinWrite}; #[test] fn correct_args_type_set() { @@ -6,13 +6,60 @@ fn correct_args_type_set() { #[bw(import { _x: u32, _y: u8 })] struct Test {} - let mut x = binrw::io::Cursor::new(Vec::new()); + let mut x = Cursor::new(Vec::new()); Test {} .write_le_args(&mut x, binrw::args! { _x: 3, _y: 2 }) .unwrap(); } +#[test] +fn gat_list() { + #[derive(BinWrite)] + #[bw(little, import(borrowed: &u8))] + struct Test { + #[bw(map = |a| *a + *borrowed)] + a: u8, + } + + let mut out = Cursor::new(Vec::new()); + Test { a: 0 }.write_args(&mut out, (&1_u8,)).unwrap(); + + assert_eq!(out.into_inner(), b"\x01"); +} + +#[test] +fn gat_named() { + #[derive(BinWrite)] + #[bw(little, import { borrowed: &u8 })] + struct Test { + #[bw(map = |a| *a + *borrowed)] + a: u8, + } + + let mut out = Cursor::new(Vec::new()); + Test { a: 0 } + .write_args(&mut out, binrw::args! { borrowed: &1_u8, }) + .unwrap(); + + assert_eq!(out.into_inner(), b"\x01"); +} + +#[test] +fn gat_raw() { + #[derive(BinWrite)] + #[bw(little, import_raw(borrowed: &u8))] + struct Test { + #[bw(map = |a| *a + *borrowed)] + a: u8, + } + + let mut out = Cursor::new(Vec::new()); + Test { a: 0 }.write_args(&mut out, &1_u8).unwrap(); + + assert_eq!(out.into_inner(), b"\x01"); +} + #[test] fn usable_args() { #[binrw] @@ -23,7 +70,7 @@ fn usable_args() { x_copy: u32, } - let mut x = binrw::io::Cursor::new(Vec::new()); + let mut x = Cursor::new(Vec::new()); Test {} .write_le_args(&mut x, binrw::args! { x: 3, _y: 2 }) diff --git a/binrw/tests/ui/args_vec_mistakes.stderr b/binrw/tests/ui/args_vec_mistakes.stderr index df05d066..4b51ebcb 100644 --- a/binrw/tests/ui/args_vec_mistakes.stderr +++ b/binrw/tests/ui/args_vec_mistakes.stderr @@ -82,5 +82,5 @@ error[E0277]: the trait bound `VecArgs<()>: Default` is not satisfied note: required by a bound in `binrw::BinRead::read` --> src/binread/mod.rs | - | Self::Args: Required, - | ^^^^^^^^ required by this bound in `binrw::BinRead::read` + | for<'a> Self::Args<'a>: Required, + | ^^^^^^^^ required by this bound in `binrw::BinRead::read` diff --git a/binrw_derive/Cargo.toml b/binrw_derive/Cargo.toml index 8e269479..d83127e2 100644 --- a/binrw_derive/Cargo.toml +++ b/binrw_derive/Cargo.toml @@ -21,11 +21,11 @@ either = "1.8" owo-colors = { version = "3", optional = true } proc-macro2 = { version = "1", features = ["span-locations"] } quote = "1" -syn = { version = "1", features = ["extra-traits", "full"] } +syn = { version = "1", features = ["extra-traits", "fold", "full", "visit"] } [dev-dependencies] runtime-macros-derive = "0.4.0" [features] default = [] -verbose-backtrace = ["owo-colors", "syn/visit"] +verbose-backtrace = ["owo-colors"] diff --git a/binrw_derive/src/binrw/codegen/mod.rs b/binrw_derive/src/binrw/codegen/mod.rs index 4e2c168c..e612d0d2 100644 --- a/binrw_derive/src/binrw/codegen/mod.rs +++ b/binrw_derive/src/binrw/codegen/mod.rs @@ -13,8 +13,9 @@ use crate::{ use proc_macro2::{Span, TokenStream}; use quote::{quote, quote_spanned, ToTokens}; use sanitization::{ - ARGS, ARGS_MACRO, ASSERT, ASSERT_ERROR_FN, BINREAD_TRAIT, BINWRITE_TRAIT, BIN_ERROR, - BIN_RESULT, ENDIAN_ENUM, OPT, POS, READER, READ_TRAIT, SEEK_TRAIT, TEMP, WRITER, WRITE_TRAIT, + ARGS, ARGS_LIFETIME, ARGS_MACRO, ASSERT, ASSERT_ERROR_FN, BINREAD_TRAIT, BINWRITE_TRAIT, + BIN_ERROR, BIN_RESULT, ENDIAN_ENUM, OPT, POS, READER, READ_TRAIT, SEEK_TRAIT, TEMP, WRITER, + WRITE_TRAIT, }; use syn::{spanned::Spanned, DeriveInput, Ident, Type}; @@ -54,14 +55,80 @@ fn generate_imports( ty_vis: &syn::Visibility, is_write: bool, ) -> (TokenStream, Option) { + use syn::fold::Fold; + + fn has_elided_lifetime(ty: &syn::Type) -> bool { + use syn::visit::Visit; + struct Finder(bool); + impl Visit<'_> for Finder { + fn visit_lifetime(&mut self, i: &syn::Lifetime) { + self.0 |= i.ident == "_"; + } + + fn visit_type_reference(&mut self, i: &syn::TypeReference) { + self.0 |= i.lifetime.is_none(); + } + } + let mut finder = Finder(false); + finder.visit_type(ty); + finder.0 + } + + struct ExpandLifetimes; + impl Fold for ExpandLifetimes { + fn fold_lifetime(&mut self, mut i: syn::Lifetime) -> syn::Lifetime { + if i.ident == "_" { + i.ident = syn::Ident::new(ARGS_LIFETIME, i.ident.span()); + } + i + } + + fn fold_type_reference(&mut self, mut i: syn::TypeReference) -> syn::TypeReference { + if i.lifetime.is_none() { + i.lifetime = Some(get_args_lifetime(i.and_token.span())); + } + i + } + } + match imports { Imports::None => (quote! { () }, None), - Imports::List(_, types) => (quote! { (#(#types,)*) }, None), - Imports::Raw(_, ty) => (ty.to_token_stream(), None), + Imports::List(_, types) => { + let types = types.iter().map(|ty| ExpandLifetimes.fold_type(ty.clone())); + (quote! { (#(#types,)*) }, None) + } + Imports::Raw(_, ty) => ( + ExpandLifetimes + .fold_type(ty.as_ref().clone()) + .into_token_stream(), + None, + ), Imports::Named(args) => { let name = arg_type_name(type_name, is_write); - let defs = derive_from_imports(type_name, is_write, &name, ty_vis, args.iter()); - (name.into_token_stream(), Some(defs)) + let lifetime = args + .iter() + .any(|arg| has_elided_lifetime(&arg.ty)) + .then(|| get_args_lifetime(type_name.span())); + let defs = derive_from_imports( + type_name, + is_write, + &name, + ty_vis, + lifetime.clone(), + args.iter().map(|arg| { + let mut arg = arg.clone(); + arg.ty = ExpandLifetimes.fold_type(arg.ty); + arg + }), + ); + ( + if let Some(lifetime) = lifetime { + quote_spanned! { type_name.span()=> #name<#lifetime> } + } else { + name.into_token_stream() + }, + Some(defs), + ) } } } @@ -79,7 +146,7 @@ fn generate_trait_impl( &self, #WRITER: &mut W, #OPT: #ENDIAN_ENUM, - #ARGS: Self::Args + #ARGS: Self::Args<'_> ) -> #BIN_RESULT<()> }, ) @@ -88,7 +155,7 @@ fn generate_trait_impl( BINREAD_TRAIT, quote! { fn read_options - (#READER: &mut R, #OPT: #ENDIAN_ENUM, #ARGS: Self::Args) + (#READER: &mut R, #OPT: #ENDIAN_ENUM, #ARGS: Self::Args<'_>) -> #BIN_RESULT }, ) @@ -112,12 +179,13 @@ fn generate_trait_impl( let name = &derive_input.ident; let (impl_generics, ty_generics, where_clause) = derive_input.generics.split_for_impl(); + let args_lifetime = get_args_lifetime(Span::call_site()); quote! { #[automatically_derived] #[allow(non_snake_case)] #[allow(clippy::redundant_closure_call)] impl #impl_generics #trait_name for #name #ty_generics #where_clause { - type Args = #arg_type; + type Args<#args_lifetime> = #arg_type; #fn_sig { #fn_impl @@ -126,6 +194,10 @@ fn generate_trait_impl( } } +fn get_args_lifetime(span: proc_macro2::Span) -> syn::Lifetime { + syn::Lifetime::new(&format!("'{}", ARGS_LIFETIME), span) +} + fn get_assertions(assertions: &[Assert]) -> impl Iterator + '_ { assertions.iter().map( |Assert { diff --git a/binrw_derive/src/binrw/codegen/read_options/struct.rs b/binrw_derive/src/binrw/codegen/read_options/struct.rs index daa7ffa3..85f241a0 100644 --- a/binrw_derive/src/binrw/codegen/read_options/struct.rs +++ b/binrw_derive/src/binrw/codegen/read_options/struct.rs @@ -409,7 +409,7 @@ impl<'field> FieldGenerator<'field> { } Map::None => { quote_spanned! {ty.span()=> - let #args_var: <#ty as #BINREAD_TRAIT>::Args = #args; + let #args_var: <#ty as #BINREAD_TRAIT>::Args<'_> = #args; } } } diff --git a/binrw_derive/src/binrw/codegen/sanitization.rs b/binrw_derive/src/binrw/codegen/sanitization.rs index 97fcd167..88b7c9dc 100644 --- a/binrw_derive/src/binrw/codegen/sanitization.rs +++ b/binrw_derive/src/binrw/codegen/sanitization.rs @@ -20,6 +20,8 @@ macro_rules! from_write_trait { }; } +pub(crate) const ARGS_LIFETIME: &str = "__binrw_generated_args_lifetime"; + ident_str! { pub(crate) BINREAD_TRAIT = from_read_trait!(); pub(crate) BINWRITE_TRAIT = from_write_trait!(); diff --git a/binrw_derive/src/binrw/codegen/write_options/struct_field.rs b/binrw_derive/src/binrw/codegen/write_options/struct_field.rs index ff839058..cfc5aa41 100644 --- a/binrw_derive/src/binrw/codegen/write_options/struct_field.rs +++ b/binrw_derive/src/binrw/codegen/write_options/struct_field.rs @@ -231,7 +231,7 @@ impl<'a> StructFieldGenerator<'a> { Map::None => { let ty = &self.field.ty; quote! { - let #args: <#ty as #BINWRITE_TRAIT>::Args = #args_val; + let #args: <#ty as #BINWRITE_TRAIT>::Args<'_> = #args_val; #out } } diff --git a/binrw_derive/src/named_args/codegen.rs b/binrw_derive/src/named_args/codegen.rs index d0bc7365..237aad8e 100644 --- a/binrw_derive/src/named_args/codegen.rs +++ b/binrw_derive/src/named_args/codegen.rs @@ -422,19 +422,16 @@ impl BuilderField { } } -impl From<&IdentTypeMaybeDefault> for BuilderField { - fn from(import: &IdentTypeMaybeDefault) -> Self { - let name = import.ident.clone(); - let ty = import.ty.clone(); +impl From for BuilderField { + fn from(import: IdentTypeMaybeDefault) -> Self { + let name = import.ident; + let ty = import.ty; // if no default is provided, mark as required let kind = import .default - .as_ref() .map_or(BuilderFieldKind::Required, |default| { - BuilderFieldKind::Optional { - default: default.clone(), - } + BuilderFieldKind::Optional { default } }); BuilderField { name, ty, kind } diff --git a/binrw_derive/src/named_args/mod.rs b/binrw_derive/src/named_args/mod.rs index 542eac7b..cfc22340 100644 --- a/binrw_derive/src/named_args/mod.rs +++ b/binrw_derive/src/named_args/mod.rs @@ -18,12 +18,13 @@ pub(crate) fn arg_type_name(ty_name: &Ident, is_write: bool) -> Ident { } } -pub(crate) fn derive_from_imports<'a>( +pub(crate) fn derive_from_imports( ty_name: &Ident, is_write: bool, result_name: &Ident, vis: &Visibility, - args: impl Iterator, + lifetime: Option, + args: impl Iterator, ) -> TokenStream { let builder_name = &if is_write { format_ident!("{}BinWriteArgBuilder", ty_name, span = Span::mixed_site()) @@ -37,7 +38,10 @@ pub(crate) fn derive_from_imports<'a>( builder_name, result_name, fields: &args.map(Into::into).collect::>(), - generics: &[], + generics: lifetime + .map(|lifetime| [syn::GenericParam::Lifetime(syn::LifetimeDef::new(lifetime))]) + .as_ref() + .map_or(&[], |generics| generics.as_slice()), vis, } .generate(true)