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

Suggest {to,from}_ne_bytes when people use transmute between arrays and integers #136067

Open
scottmcm opened this issue Jan 25, 2025 · 5 comments
Assignees
Labels
A-diagnostics Area: Messages for errors, warnings, and lints T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@scottmcm
Copy link
Member

scottmcm commented Jan 25, 2025

Code

fn bytes_at_home_1(a: [u8; 4]) -> u32 {
    unsafe { std::mem::transmute(a) }
}

fn bytes_at_home_2(x: u32) -> [u8; 4] {
    unsafe { std::mem::transmute(x) }
}

Current output

(no warnings)

Desired output

Warning: use the safe alternative instead
|
|    unsafe { std::mem::transmute(a) }
|             ^^^^^^^^^^^^^^^^^^^ This can be done with `u32::from_ne_bytes(a)` instead
|
hint: there's also `from_le_bytes` and `from_ne_bytes` if you expect a particular byte order

Warning: use the safe alternative instead
|
|    unsafe { std::mem::transmute(x) }
|             ^^^^^^^^^^^^^^^^^^^ This can be done with `x.to_ne_bytes()` instead
|
hint: there's also `to_le_bytes` and `to_ne_bytes` if you expect a particular byte order

Rationale and extra context

I see people doing this a bunch, like it just came up in Discord.

It would be nice to point them to the safe alternative when possible.

Other cases

Rust Version

Playground nightly ⬇

Anything else?

https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=a89dfdaa49736b9d106b2099ca48ddd7

@scottmcm scottmcm added A-diagnostics Area: Messages for errors, warnings, and lints T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Jan 25, 2025
@kpreid
Copy link
Contributor

kpreid commented Jan 25, 2025

Some other byte-reinterpretations that could be linted against on the same premise, that don’t involve arrays:

  • iNNuNN
  • boolu8
  • charu32

@bend-n
Copy link
Contributor

bend-n commented Jan 26, 2025

@rustbot claim

@hanna-kruppe
Copy link
Contributor

FWIW, clippy already has a bunch of warn-by-default lints for transmutes that can be done with safe constructors or need extra checks to be sound (including some already mentioned in this thread, but also int<->float, &str <-> &[u8], NonZeroT <-> T). May be worth uplifting and expanding all of those if there’s appetite for this kind of lint in rustc.

@scottmcm
Copy link
Member Author

@hanna-kruppe To me, the thing that makes to_ne_bytes worth warning in rustc is that it removes unsafe code.

I'm definitely a fan of having clippy suggest better unsafe ways to do transmutes, but I don't know that it would necessarily meet the rustc bar if the replacement is still unsafe.

@hanna-kruppe
Copy link
Contributor

Sure, as long as there’s some consistent reason for what’s uplifted and what isn’t and we aren’t missing clippy existing lints just because nobody looked.

jhpratt added a commit to jhpratt/rust that referenced this issue Mar 27, 2025
Suggest {to,from}_ne_bytes for transmutations between arrays and integers, etc

implements rust-lang#136067

Rust has helper methods for many kinds of safe transmutes, for example integer<->bytes. This is a lint against using transmute for these cases.

```rs
fn bytes_at_home(x: [u8; 4]) -> u32 {
   transmute(x)
}

// other examples
transmute::<[u8; 2], u16>();
transmute::<[u8; 8], f64>();
transmute::<u32, [u8; 4]>();
transmute::<char, u32>();
transmute::<u32, char>();
```
It would be handy to suggest `u32::from_ne_bytes(x)`.
This is implemented for `[u8; _]` -> `{float int}`

This also implements the cases:
`fXX` <-> `uXX` = `{from_bits, to_bits}`
`uXX` -> `iXX` via `cast_unsigned` and `cast_signed`
{`char` -> `u32`, `bool` -> `n8`} via `from`
`u32` -> `char` via `from_u32_unchecked` (note: notes `from_u32().unwrap()`) (contested)
`u8` -> `bool` via `==` (debatable)
jhpratt added a commit to jhpratt/rust that referenced this issue Mar 27, 2025
Suggest {to,from}_ne_bytes for transmutations between arrays and integers, etc

implements rust-lang#136067

Rust has helper methods for many kinds of safe transmutes, for example integer<->bytes. This is a lint against using transmute for these cases.

```rs
fn bytes_at_home(x: [u8; 4]) -> u32 {
   transmute(x)
}

// other examples
transmute::<[u8; 2], u16>();
transmute::<[u8; 8], f64>();
transmute::<u32, [u8; 4]>();
transmute::<char, u32>();
transmute::<u32, char>();
```
It would be handy to suggest `u32::from_ne_bytes(x)`.
This is implemented for `[u8; _]` -> `{float int}`

This also implements the cases:
`fXX` <-> `uXX` = `{from_bits, to_bits}`
`uXX` -> `iXX` via `cast_unsigned` and `cast_signed`
{`char` -> `u32`, `bool` -> `n8`} via `from`
`u32` -> `char` via `from_u32_unchecked` (note: notes `from_u32().unwrap()`) (contested)
`u8` -> `bool` via `==` (debatable)
bors added a commit to rust-lang-ci/rust that referenced this issue Apr 11, 2025
Suggest {to,from}_ne_bytes for transmutations between arrays and integers, etc

implements rust-lang#136067

Rust has helper methods for many kinds of safe transmutes, for example integer<->bytes. This is a lint against using transmute for these cases.

```rs
fn bytes_at_home(x: [u8; 4]) -> u32 {
   transmute(x)
}

// other examples
transmute::<[u8; 2], u16>();
transmute::<[u8; 8], f64>();
transmute::<u32, [u8; 4]>();
transmute::<char, u32>();
transmute::<u32, char>();
```
It would be handy to suggest `u32::from_ne_bytes(x)`.
This is implemented for `[u8; _]` -> `{float int}`

This also implements the cases:
`fXX` <-> `uXX` = `{from_bits, to_bits}`
`uXX` -> `iXX` via `cast_unsigned` and `cast_signed`
{`char` -> `u32`, `bool` -> `n8`} via `from`
`u32` -> `char` via `from_u32_unchecked` (note: notes `from_u32().unwrap()`) (contested)
`u8` -> `bool` via `==` (debatable)

---
try-job: aarch64-gnu
try-job: test-various
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

4 participants