Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unchecked versions of GenericArray::from_[mut_]slice #124

Open
eggyal opened this issue May 30, 2022 · 4 comments
Open

Unchecked versions of GenericArray::from_[mut_]slice #124

eggyal opened this issue May 30, 2022 · 4 comments

Comments

@eggyal
Copy link
Contributor

eggyal commented May 30, 2022

Minor point, but would it be possible to expose an unsafe version of these functions that doesn't perform any length-check?

@novacrazy
Copy link
Collaborator

Not exactly ergonomic, but you could do something like this in your own code where necessary:

use generic_array::{GenericArray, typenum::{U24, Unsigned}};

pub fn from_mut_slice(x: &mut [u8]) -> &mut GenericArray<u8, U24> {
    if x.len() != U24::USIZE {
        unsafe { std::hint::unreachable_unchecked() }
    }
    GenericArray::from_mut_slice(x)
}

@novacrazy
Copy link
Collaborator

Additional notes based on deleted comment:

If the goal is optimization, then the unreachable_unchecked tells the compiler there is no other option than to succeed and will remove the panic machinery.

Click here to open example
pub fn version_a(x: &mut [u8]) -> &mut GenericArray<u8, U24> {
    if x.len() != U24::USIZE {
        unsafe { std::hint::unreachable_unchecked() }
    }
    GenericArray::from_mut_slice(x)
}

pub fn version_b(x: &mut [u8]) -> &mut GenericArray<u8, U24> {
    GenericArray::from_mut_slice(x)
}

compiles down to

playground::version_a:
	movq	%rdi, %rax
	retq

playground::version_b:
	subq	$56, %rsp
	movq	%rsi, (%rsp)
	cmpq	$24, %rsi
	jne	.LBB4_1
	movq	%rdi, %rax
	addq	$56, %rsp
	retq

.LBB4_1:
	movq	$0, 8(%rsp)
	movq	%rsp, %rdi
	leaq	8(%rsp), %rsi
	callq	core::panicking::assert_failed
	ud2

If the goal is to just be unsafe for the sake of being unsafe, that's just asking for trouble.

@eggyal
Copy link
Contributor Author

eggyal commented May 31, 2022

Thank you, this does (unergonomically, as you say) compile down to what I need. However, it also relies on:

  1. GenericArray::from_mut_slice being inlined (its #[inline] attribute is only a hint, which the compiler can ignore); and

  2. an optimisation pass recognising that both tests (that in my fn and that in GenericArray::from_mut_slice) can thus be omitted.

I'm quite happy with this workaround if exposing _unchecked methods is unacceptable to this library. Feel free to close. Thanks again!

@novacrazy
Copy link
Collaborator

As of 1.0, unsafe { GenericArray::try_from_mut_slice(slice).unwrap_unchecked() } should be sufficient. Still relies on the optimizations, but I've marked everything involved with that as #[inline(always)].

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants