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 .
This commit is contained in:
Valentin 2023-09-05 21:41:44 +02:00 committed by GitHub
parent f047fb6aeb
commit 3c1a0d9b35
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -378,12 +378,31 @@ impl Derivable for Contiguous {
let min_lit = LitInt::new(&format!("{}", min), input.span()); let min_lit = LitInt::new(&format!("{}", min), input.span());
let max_lit = LitInt::new(&format!("{}", max), 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(( Ok((
quote!(), quote!(),
quote! { quote! {
type Int = #integer_ty; type Int = #integer_ty;
const MIN_VALUE: #integer_ty = #min_lit; const MIN_VALUE: #integer_ty = #min_lit;
const MAX_VALUE: #integer_ty = #max_lit; const MAX_VALUE: #integer_ty = #max_lit;
#[inline]
fn from_integer(value: Self::Int) -> Option<Self> {
#[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
}
}, },
)) ))
} }