-
Notifications
You must be signed in to change notification settings - Fork 59
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
Cast to a DST pointer? #288
Comments
Oh interesting, I did not realize that we even allow DST raw pointer casts that change the type. I would strongly assume that this affects only the type, and leaves the value unchanged. But I don't think we fully document what the wide pointer metadata of types like |
Yeah, it'd be great if there were some specified way to construct a DST raw pointer. Speaking for myself, it would allow us to support DSTs in zerocopy. |
I think the plan is for that to happen via rust-lang/rust#81513 |
I agree that I don't think it's explicitly documented, but I recall it at least being mentioned in one place that compound DSTs have the same metadata as their tail DST member. I hope it's not just the stdlib source that I recall this from, though... This is also implicitly reinforced by the error: when you mismatch fat pointer types, you get the error
which (for better or for worse) implies that the fat pointers match when the error is not emitted (i.e. when the DSTs have the same terminal tail DST kind). The fact that this works is used extensively by the ecosystem at this point, at least by rowan (in rust-analyzer), triomphe, and bitvec. |
The `FileInfo`, `FileSystemInfo`, and `FileSystemVolumeLabel` structs are all DSTs because they end with a `Char16` slice containing a name. A wide pointer (or reference) to such a struct contains two parts: the base memory address, and the number of elements in the slice. Previously there was no officially-documented way to create such a wide pointer, so uefi-rs used a trick that is used [elsewhere in the Rust ecosystem][1]: create a slice matching the type and length of the slice at the end of the struct, but passing in the desired base pointer instead. Then the slice type is cast to match the desired struct type. There is now a standard (albeit currently unstable) API for performing this construction added by [RFC 2580][2]. This requires enabling the `ptr_metadata` feature. The runtime result should be the same, but without relying on undocumented Rust internals. [1]: rust-lang/unsafe-code-guidelines#288 (comment) [2]: https://rust-lang.github.io/rfcs/2580-ptr-meta.html
The `FileInfo`, `FileSystemInfo`, and `FileSystemVolumeLabel` structs are all DSTs because they end with a `Char16` slice containing a name. A wide pointer (or reference) to such a struct contains two parts: the base memory address, and the number of elements in the slice. Previously there was no officially-documented way to create such a wide pointer, so uefi-rs used a trick that is used [elsewhere in the Rust ecosystem][1]: create a slice matching the type and length of the slice at the end of the struct, but passing in the desired base pointer instead. Then the slice type is cast to match the desired struct type. There is now a standard (albeit currently unstable) API for performing this construction added by [RFC 2580][2]. This requires enabling the `ptr_metadata` feature. The runtime result should be the same, but without relying on undocumented Rust internals. [1]: rust-lang/unsafe-code-guidelines#288 (comment) [2]: https://rust-lang.github.io/rfcs/2580-ptr-meta.html
This encodes the behavior agreed upon in rust-lang/unsafe-code-guidelines#288.
I've submitted rust-lang/reference#1417 to document this behavior. |
Just ran across another instance of this being relied upon in the ecosystem. |
Those are two slice types, that's IMO much less subtle than when structs with slice tail are involved. |
Agreed; my point is just that it's an example of relying on behavior which is technically not guaranteed, but would be with rust-lang/reference#1417. |
This encodes the behavior agreed upon in rust-lang/unsafe-code-guidelines#288.
This question is inspired by the slice_dst crate (cc @CAD97)
Is it valid, given a
#[repr(C)]
struct with a trailing slice field, to cast a slice fat pointer to a fat pointer to that struct? If so, is it guaranteed that the slice length will be retained as expected? Concretely:The text was updated successfully, but these errors were encountered: