summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_error_codes/src/error_codes/E0793.md
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_error_codes/src/error_codes/E0793.md')
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0793.md64
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