diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:19:50 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:19:50 +0000 |
commit | 2e00214b3efbdfeefaa0fe9e8b8fd519de7adc35 (patch) | |
tree | d325add32978dbdc1db975a438b3a77d571b1ab8 /compiler/rustc_error_codes/src/error_codes/E0793.md | |
parent | Releasing progress-linux version 1.68.2+dfsg1-1~progress7.99u1. (diff) | |
download | rustc-2e00214b3efbdfeefaa0fe9e8b8fd519de7adc35.tar.xz rustc-2e00214b3efbdfeefaa0fe9e8b8fd519de7adc35.zip |
Merging upstream version 1.69.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_error_codes/src/error_codes/E0793.md')
-rw-r--r-- | compiler/rustc_error_codes/src/error_codes/E0793.md | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/compiler/rustc_error_codes/src/error_codes/E0793.md b/compiler/rustc_error_codes/src/error_codes/E0793.md new file mode 100644 index 000000000..b2e51e24e --- /dev/null +++ b/compiler/rustc_error_codes/src/error_codes/E0793.md @@ -0,0 +1,64 @@ +An unaligned references to a field of a [packed] struct got created. + +Erroneous code example: + +```compile_fail,E0793 +#[repr(packed)] +pub struct Foo { + field1: u64, + field2: u8, +} + +unsafe { + let foo = Foo { field1: 0, field2: 0 }; + // Accessing the field directly is fine. + let val = foo.field1; + // A reference to a packed field causes a error. + let val = &foo.field1; // ERROR + // An implicit `&` is added in format strings, causing the same error. + println!("{}", foo.field1); // ERROR +} +``` + +Creating a reference to an insufficiently aligned packed field is +[undefined behavior] and therefore disallowed. Using an `unsafe` block does not +change anything about this. Instead, the code should do a copy of the data in +the packed field or use raw pointers and unaligned accesses. + +``` +#[repr(packed)] +pub struct Foo { + field1: u64, + field2: u8, +} + +unsafe { + let foo = Foo { field1: 0, field2: 0 }; + + // Instead of a reference, we can create a raw pointer... + let ptr = std::ptr::addr_of!(foo.field1); + // ... and then (crucially!) access it in an explicitly unaligned way. + let val = unsafe { ptr.read_unaligned() }; + // This would *NOT* be correct: + // let val = unsafe { *ptr }; // Undefined Behavior due to unaligned load! + + // For formatting, we can create a copy to avoid the direct reference. + let copy = foo.field1; + println!("{}", copy); + // Creating a copy can be written in a single line with curly braces. + // (This is equivalent to the two lines above.) + println!("{}", { foo.field1 }); +} +``` + +### Additional information + +Note that this error is specifically about *references* to packed fields. +Direct by-value access of those fields is fine, since then the compiler has +enough information to generate the correct kind of access. + +See [issue #82523] for more information. + +[packed]: https://doc.rust-lang.org/reference/type-layout.html#the-alignment-modifiers +[undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html +[issue #82523]: https://github.com/rust-lang/rust/issues/82523 |