4 ms·
Woot woot, transmute is const now
by nynx 5y ago
Woot woot, transmute is const now
- orra 5y agoCurious what the applications are. Collections? Would you write a lot of "unsafe" const code, given the chance?
- luizfelberti 5y agoI will shamefully admit to using transmute in very sinful ways, such as having enums that are repr(u16) or something like that at multiple numeric ranges such as: #[repr(u16)] enum Foo { A = 0, B } #[repr(u16)] enum Bar { A = 3200, B } struct FooOrBar(u16); And then proceeding to violate all of the unwritten rules of Rust by wrangling casts across these types like a goddamn wizard I'm not proud of this...
- lilyball 5y agoThis sounds like a great example of where you might want a union (https://doc.rust-lang.org/1.56.0/reference/items/unions.html https://doc.rust-lang.org/1.56.0/reference/items/unions.html)
- luizfelberti 5y agoOoh I forgot the language had those! I still feel like this trick has it's place though, as an example take a look at where I stole this trick from, by matklad [0] and tell me what you think :) [0] https://github.com/rust-analyzer/rowan/blob/d2c7843858da9d9e378de790bd14487c848f6f2e/examples/s_expressions.rs#L51 https://github.com/rust-analyzer/rowan/blob/d2c7843858da9d9e...
- lilyball 5y agoI think that this code is acceptable as long as you're careful. And I wish Rust had a `#[derive(TryFrom)]` sort of thing for deriving conversions from the declared primitive type to the enum.
- brink 5y agoIt's useful for handling data that came from outside Rust. If you have a byte array that you've received over a network connection that represents an array of floats, or you need to convert a 32bit RGBA pixel buffer that you got from some clang ffi binding to a byte pixel buffer without having to split/copy to a new vector.
- nynx 5y agoI can't think of an example now, but it has come up before when working on collections and other things.
- steveklabnik 5y agoOne thing that's come up a couple times are... well, what transmute is, that is, two types that have the same representation, and you want to cast between them. For example, the "try Rust out in the Linux kernel" code has a function that turns a byte slice into a &Cstr via a transmute. Those kinds of conversions can be useful inside of const fns.
- ishanjain28 5y agoHi Steve, I came across this post which presents an example using rust's transmute and it's incorrect behavior when the alignment is different. https://andrewkelley.me/post/unsafe-zig-safer-than-unsafe-rust.html https://andrewkelley.me/post/unsafe-zig-safer-than-unsafe-ru... Is this issue still present? I tried to figure it out the other day using latest rust's nightly but the llvm ir output has so much going on that I didn't _really_ understand what was going on
- MaulingMonkey 5y agoPer transmute's docs @ https://doc.rust-lang.org/std/mem/fn.transmute.html https://doc.rust-lang.org/std/mem/fn.transmute.html: > Because transmute is a by-value operation, alignment of the transmuted values themselves is not a concern. As with any other function, the compiler already ensures both T and U are properly aligned. However, when transmuting values that point elsewhere (such as pointers, references, boxes…), the caller has to ensure proper alignment of the pointed-to values. The post you've linked transmutes a reference, and as the caller fails to explicitly ensure proper alignment, it explicitly risks invoking undefined behavior - I would consider the code buggy. The easiest way to prove it's broken would be to create an reference that's more likely to be unaligned (&array[1] instead of &array[0]?) and run the code on a less misalignment-tolerant platform (ARM?). Here are some 100% sound alternatives using bytemuck (no unsafe required!) and core::ptr::{read,write}_unaligned (unsafe required): https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=bc30cc223eb8a454ca78338cfbee0a7a https://play.rust-lang.org/?version=stable&mode=debug&editio...
- steveklabnik 5y agoI am unsure about the specific details about IR that's emitted (though at first glance it seems we do emit the alignment attribute now, I think?), but transmute is, as the documentation says, "incredibly" unsafe: > Because transmute is a by-value operation, alignment of the transmuted values themselves is not a concern. As with any other function, the compiler already ensures both T and U are properly aligned. However, when transmuting values that point elsewhere (such as pointers, references, boxes…), the caller has to ensure proper alignment of the pointed-to values. This code is doing the latter incorrectly, and therefore invokes UB, as far as I can tell. To be honest, I don't use transmute very often and so I don't have every single last corner case about it memorized. It's not so much an "issue" as it is "Here's an API that's extremely sharp in Rust, and a similar, but less sharp API in Zig."
- kzrdude 5y agoHappy that the const subset of the language grows