// 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 { 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 { 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(){ }