mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 23:04:33 +00:00
4b3ece475d
Derive expansions for packed structs cause move errors because they prefer copying over borrowing since borrowing the fields of a packed struct can result in unaligned access and therefore undefined behaviour. This underlying cause of the errors, however, is not apparent to the user. We add a diagnostic note here to remedy that.
97 lines
3.5 KiB
Rust
97 lines
3.5 KiB
Rust
// 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(){
|
|
}
|