-
Notifications
You must be signed in to change notification settings - Fork 12.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Auto merge of #117511 - gurry:117406-err-packed-structs, r=compiler-e…
…rrors Emit explanatory note for move errors in packed struct derives Derive expansions for packed structs with non-`Copy` fields cause move errors because they prefer copying over borrowing since borrowing the fields of a packed struct can result in unaligned access. This underlying cause of the errors, however, is not apparent to the user. This PR adds a diagnostic note to make it clear to the user (the new note is on the second last line): ``` tests/ui/derives/deriving-with-repr-packed-move-errors.rs:13:16 | 12 | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)] | ----- in this derive macro expansion 13 | struct StructA(String); | ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait | = note: `#[derive(Debug)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) ``` Fixes #117406 Partially addresses #110777
- Loading branch information
Showing
4 changed files
with
290 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
// Check that deriving builtin traits for a packed struct with | ||
// non-Copy fields emits move errors along with an additional | ||
// diagnostic note explaining the reason | ||
// See issue #117406 | ||
|
||
use std::fmt::{Debug, Formatter, Result}; | ||
use std::cmp::Ordering; | ||
|
||
// Packed + derives: additional diagnostic should be emitted | ||
// for each of Debug, PartialEq and PartialOrd | ||
#[repr(packed)] | ||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)] | ||
struct StructA(String); | ||
//~^ ERROR: cannot move out of `self` which is behind a shared reference | ||
//~| ERROR: cannot move out of `self` which is behind a shared reference | ||
//~| ERROR: cannot move out of `other` which is behind a shared reference | ||
//~| ERROR: cannot move out of `self` which is behind a shared reference | ||
//~| ERROR: cannot move out of `other` which is behind a shared reference | ||
//~| ERROR: cannot move out of `self` which is behind a shared reference | ||
//~| ERROR: cannot move out of `other` which is behind a shared reference | ||
//~| ERROR: cannot move out of `self` which is behind a shared reference | ||
//~| ERROR: cannot move out of `self` which is behind a shared reference | ||
|
||
|
||
// Unrelated impl: additinal diagnostic should NOT be emitted | ||
impl StructA { | ||
fn fmt(&self) -> String { | ||
self.0 //~ ERROR: cannot move out of `self` which is behind a shared reference | ||
} | ||
} | ||
|
||
// Packed + manual impls: additional diagnostic should NOT be emitted | ||
#[repr(packed)] | ||
struct StructB(String); | ||
|
||
impl Debug for StructB { | ||
fn fmt(&self, f: &mut Formatter) -> Result { | ||
let x = &{ self.0 }; //~ ERROR: cannot move out of `self` which is behind a shared reference | ||
write!(f, "{}", x) | ||
} | ||
} | ||
|
||
impl PartialEq for StructB { | ||
fn eq(&self, other: &StructB) -> bool { | ||
({ self.0 }) == ({ other.0 }) | ||
//~^ ERROR: cannot move out of `self` which is behind a shared reference | ||
//~| ERROR: cannot move out of `other` which is behind a shared reference | ||
} | ||
} | ||
|
||
impl PartialOrd for StructB { | ||
fn partial_cmp(&self, other: &StructB) -> Option<Ordering> { | ||
PartialOrd::partial_cmp(&{ self.0 }, &{ other.0 }) | ||
//~^ ERROR: cannot move out of `self` which is behind a shared reference | ||
//~| ERROR: cannot move out of `other` which is behind a shared reference | ||
} | ||
} | ||
|
||
// NOT packed + derives: additinal diagnostic should NOT be emitted | ||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)] | ||
struct StructC(String); | ||
|
||
// NOT packed + manual impls: additinal dignostic should NOT be emitted | ||
struct StructD(String); | ||
|
||
impl Debug for StructD { | ||
fn fmt(&self, f: &mut Formatter) -> Result { | ||
let x = &{ self.0 }; //~ ERROR: cannot move out of `self` which is behind a shared reference | ||
write!(f, "{}", x) | ||
} | ||
} | ||
|
||
impl PartialEq for StructD { | ||
fn eq(&self, other: &StructD) -> bool { | ||
({ self.0 }) == ({ other.0 }) | ||
//~^ ERROR: cannot move out of `self` which is behind a shared reference | ||
//~| ERROR: cannot move out of `other` which is behind a shared reference | ||
} | ||
} | ||
|
||
impl PartialOrd for StructD { | ||
fn partial_cmp(&self, other: &StructD) -> Option<Ordering> { | ||
PartialOrd::partial_cmp(&{ self.0 }, &{ other.0 }) | ||
//~^ ERROR: cannot move out of `self` which is behind a shared reference | ||
//~| ERROR: cannot move out of `other` which is behind a shared reference | ||
} | ||
} | ||
|
||
// Packed + derives but the move is outside of a derive | ||
// expansion: additinal diagnostic should NOT be emitted | ||
fn func(arg: &StructA) -> String { | ||
arg.0 //~ ERROR: cannot move out of `arg` which is behind a shared reference | ||
} | ||
|
||
fn main(){ | ||
} |
174 changes: 174 additions & 0 deletions
174
tests/ui/derives/deriving-with-repr-packed-move-errors.stderr
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,174 @@ | ||
error[E0507]: cannot move out of `self` which is behind a shared reference | ||
--> $DIR/deriving-with-repr-packed-move-errors.rs:13:16 | ||
| | ||
LL | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)] | ||
| ----- in this derive macro expansion | ||
LL | struct StructA(String); | ||
| ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait | ||
| | ||
= note: `#[derive(Debug)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour | ||
= note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) | ||
|
||
error[E0507]: cannot move out of `self` which is behind a shared reference | ||
--> $DIR/deriving-with-repr-packed-move-errors.rs:13:16 | ||
| | ||
LL | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)] | ||
| --------- in this derive macro expansion | ||
LL | struct StructA(String); | ||
| ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait | ||
| | ||
= note: `#[derive(PartialEq)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour | ||
= note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) | ||
|
||
error[E0507]: cannot move out of `other` which is behind a shared reference | ||
--> $DIR/deriving-with-repr-packed-move-errors.rs:13:16 | ||
| | ||
LL | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)] | ||
| --------- in this derive macro expansion | ||
LL | struct StructA(String); | ||
| ^^^^^^ move occurs because `other.0` has type `String`, which does not implement the `Copy` trait | ||
| | ||
= note: `#[derive(PartialEq)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour | ||
= note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) | ||
|
||
error[E0507]: cannot move out of `self` which is behind a shared reference | ||
--> $DIR/deriving-with-repr-packed-move-errors.rs:13:16 | ||
| | ||
LL | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)] | ||
| ---------- in this derive macro expansion | ||
LL | struct StructA(String); | ||
| ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait | ||
| | ||
= note: `#[derive(PartialOrd)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour | ||
= note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) | ||
|
||
error[E0507]: cannot move out of `other` which is behind a shared reference | ||
--> $DIR/deriving-with-repr-packed-move-errors.rs:13:16 | ||
| | ||
LL | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)] | ||
| ---------- in this derive macro expansion | ||
LL | struct StructA(String); | ||
| ^^^^^^ move occurs because `other.0` has type `String`, which does not implement the `Copy` trait | ||
| | ||
= note: `#[derive(PartialOrd)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour | ||
= note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) | ||
|
||
error[E0507]: cannot move out of `self` which is behind a shared reference | ||
--> $DIR/deriving-with-repr-packed-move-errors.rs:13:16 | ||
| | ||
LL | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)] | ||
| --- in this derive macro expansion | ||
LL | struct StructA(String); | ||
| ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait | ||
| | ||
= note: `#[derive(Ord)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour | ||
= note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) | ||
|
||
error[E0507]: cannot move out of `other` which is behind a shared reference | ||
--> $DIR/deriving-with-repr-packed-move-errors.rs:13:16 | ||
| | ||
LL | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)] | ||
| --- in this derive macro expansion | ||
LL | struct StructA(String); | ||
| ^^^^^^ move occurs because `other.0` has type `String`, which does not implement the `Copy` trait | ||
| | ||
= note: `#[derive(Ord)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour | ||
= note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) | ||
|
||
error[E0507]: cannot move out of `self` which is behind a shared reference | ||
--> $DIR/deriving-with-repr-packed-move-errors.rs:13:16 | ||
| | ||
LL | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)] | ||
| ---- in this derive macro expansion | ||
LL | struct StructA(String); | ||
| ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait | ||
| | ||
= note: `#[derive(Hash)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour | ||
= note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info) | ||
|
||
error[E0507]: cannot move out of `self` which is behind a shared reference | ||
--> $DIR/deriving-with-repr-packed-move-errors.rs:13:16 | ||
| | ||
LL | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)] | ||
| ----- in this derive macro expansion | ||
LL | struct StructA(String); | ||
| ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait | ||
| | ||
= note: `#[derive(Clone)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour | ||
= note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) | ||
|
||
error[E0507]: cannot move out of `self` which is behind a shared reference | ||
--> $DIR/deriving-with-repr-packed-move-errors.rs:28:9 | ||
| | ||
LL | self.0 | ||
| ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait | ||
|
||
error[E0507]: cannot move out of `self` which is behind a shared reference | ||
--> $DIR/deriving-with-repr-packed-move-errors.rs:38:20 | ||
| | ||
LL | let x = &{ self.0 }; | ||
| ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait | ||
|
||
error[E0507]: cannot move out of `self` which is behind a shared reference | ||
--> $DIR/deriving-with-repr-packed-move-errors.rs:45:12 | ||
| | ||
LL | ({ self.0 }) == ({ other.0 }) | ||
| ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait | ||
|
||
error[E0507]: cannot move out of `other` which is behind a shared reference | ||
--> $DIR/deriving-with-repr-packed-move-errors.rs:45:28 | ||
| | ||
LL | ({ self.0 }) == ({ other.0 }) | ||
| ^^^^^^^ move occurs because `other.0` has type `String`, which does not implement the `Copy` trait | ||
|
||
error[E0507]: cannot move out of `self` which is behind a shared reference | ||
--> $DIR/deriving-with-repr-packed-move-errors.rs:53:36 | ||
| | ||
LL | PartialOrd::partial_cmp(&{ self.0 }, &{ other.0 }) | ||
| ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait | ||
|
||
error[E0507]: cannot move out of `other` which is behind a shared reference | ||
--> $DIR/deriving-with-repr-packed-move-errors.rs:53:49 | ||
| | ||
LL | PartialOrd::partial_cmp(&{ self.0 }, &{ other.0 }) | ||
| ^^^^^^^ move occurs because `other.0` has type `String`, which does not implement the `Copy` trait | ||
|
||
error[E0507]: cannot move out of `self` which is behind a shared reference | ||
--> $DIR/deriving-with-repr-packed-move-errors.rs:68:20 | ||
| | ||
LL | let x = &{ self.0 }; | ||
| ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait | ||
|
||
error[E0507]: cannot move out of `self` which is behind a shared reference | ||
--> $DIR/deriving-with-repr-packed-move-errors.rs:75:12 | ||
| | ||
LL | ({ self.0 }) == ({ other.0 }) | ||
| ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait | ||
|
||
error[E0507]: cannot move out of `other` which is behind a shared reference | ||
--> $DIR/deriving-with-repr-packed-move-errors.rs:75:28 | ||
| | ||
LL | ({ self.0 }) == ({ other.0 }) | ||
| ^^^^^^^ move occurs because `other.0` has type `String`, which does not implement the `Copy` trait | ||
|
||
error[E0507]: cannot move out of `self` which is behind a shared reference | ||
--> $DIR/deriving-with-repr-packed-move-errors.rs:83:36 | ||
| | ||
LL | PartialOrd::partial_cmp(&{ self.0 }, &{ other.0 }) | ||
| ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait | ||
|
||
error[E0507]: cannot move out of `other` which is behind a shared reference | ||
--> $DIR/deriving-with-repr-packed-move-errors.rs:83:49 | ||
| | ||
LL | PartialOrd::partial_cmp(&{ self.0 }, &{ other.0 }) | ||
| ^^^^^^^ move occurs because `other.0` has type `String`, which does not implement the `Copy` trait | ||
|
||
error[E0507]: cannot move out of `arg` which is behind a shared reference | ||
--> $DIR/deriving-with-repr-packed-move-errors.rs:92:5 | ||
| | ||
LL | arg.0 | ||
| ^^^^^ move occurs because `arg.0` has type `String`, which does not implement the `Copy` trait | ||
|
||
error: aborting due to 21 previous errors | ||
|
||
For more information about this error, try `rustc --explain E0507`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters