pub struct Entry_Key([u8; 40]);
impl Entry_Key {
pub fn data(&self) -> &[u8; 32] {
&self.0[8..40]}
I feel like I am missing something very fundamental. To me [8 .. 40] is obviously 32 entries. So why is it not a &[u8; 32]
?
Aside: #2 since "title has already been used here"
chrefr
March 11, 2022, 3:09am
2
The compiler doesn't analyze the size. It could have been anything. You can do:
pub fn data(&self) -> &[u8; 32] { self.0[8..40].try_into().unwrap() } // Cannot fail
The optimizer is likely to remove the check.
5 Likes
Godbolt confirms that the check is indeed optimized away in release mode
1 Like
Also, indexing an array defers to indexing a slice, which uses this implementation that returns another slice.
You would need const
generics that could do math and monomorphized independently for every combination of usize
s to support it (at least naively/without more magic).
1 Like
Why does
fn test_00() {
let mut x = [0_u8; 20];
let y: &mut [u8; 10] = x[0..10].try_into().unwrap();}
not compile? Here I want a mut ref instead of a ref.
chrefr
March 11, 2022, 5:18am
8
Inference problem. Be more specific:
let y: &mut [u8; 10] = (&mut x[0..10]).try_into().unwrap();
The problem is that the compiler is picking the implementation that returns a shared reference and then complains.
6 Likes
Because you're conflating value-level thinking and type-level thinking.
To the type system, 8..40
is just a Range<usize>
, so it has no idea how long it is. And thus the type you get out is a slice, not an array.
You'll see this in lots of places in Rust. For example, this doesn't compile :
let x;
if true {
x = 4;
}
dbg!(x);
Because it doesn't look at the value true
, just the type bool.
7 Likes
scottmcm:
Because you're conflating value-level thinking and type-level thinking.
To the type system, 8..40
is just a Range<usize>
, so it has no idea how long it is. And thus the type you get out is a slice, not an array.
I am not sure if we are discussing the same thing, but I definitely am misunderstanding something here. Is the issue: there are lots of types:
[u8; 1], [u8; 2], [u8; 3], ..., [u8; N] for arbitrarily large N
and a separate type [u8]
and here, I am confusing a [u8]
of length 32 with a [u8; 32]
?
Yes, that's basically the case. In particular, there's only one type that represents 𝓍..𝓎, regardless of the values of 𝓍 and 𝓎: Range<usize>
.
Because this doesn't contain any type-level length information, the index operation can't return a type with an embedded length, such as [u8;0]
, [u8;1]
, [u8;2]
, etc. Instead, it uses [u8]
which requires the length to be checked at runtime (or at least inside the optimizer).
1 Like
system
Closed
June 9, 2022, 11:49am
12
This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.