From 3c1a0d9b35c3596b58fe5f8bbb994e14201fd915 Mon Sep 17 00:00:00 2001 From: Valentin Date: Tue, 5 Sep 2023 21:41:44 +0200 Subject: [PATCH] Improve assembly of Contiguous derive (#200) `from_integer` and `into_integer` are usually provided by the trait's default implementation. We override this implementation because it goes through `transmute_copy`, which can lead to inefficient assembly as seen in https://github.com/Lokathor/bytemuck/issues/175 . --- derive/src/traits.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/derive/src/traits.rs b/derive/src/traits.rs index da51275..f513356 100644 --- a/derive/src/traits.rs +++ b/derive/src/traits.rs @@ -378,12 +378,31 @@ impl Derivable for Contiguous { let min_lit = LitInt::new(&format!("{}", min), input.span()); let max_lit = LitInt::new(&format!("{}", max), input.span()); + // `from_integer` and `into_integer` are usually provided by the trait's default implementation. + // We override this implementation because it goes through `transmute_copy`, which can lead to + // inefficient assembly as seen in https://github.com/Lokathor/bytemuck/issues/175 . + Ok(( quote!(), quote! { type Int = #integer_ty; const MIN_VALUE: #integer_ty = #min_lit; const MAX_VALUE: #integer_ty = #max_lit; + + #[inline] + fn from_integer(value: Self::Int) -> Option { + #[allow(clippy::manual_range_contains)] + if Self::MIN_VALUE <= value && value <= Self::MAX_VALUE { + Some(unsafe { ::core::mem::transmute(value) }) + } else { + None + } + } + + #[inline] + fn into_integer(self) -> Self::Int { + self as #integer_ty + } }, )) }