diff options
| author | Ariel Ben-Yehuda <ariel.byd@gmail.com> | 2017-10-02 15:15:23 +0200 |
|---|---|---|
| committer | Ariel Ben-Yehuda <arielb1@mail.tau.ac.il> | 2017-11-26 16:12:43 +0200 |
| commit | dee8a71cd5221536c319ca8c14108e93521092f5 (patch) | |
| tree | 61b09dc7938e27204cd5f6c05bda56cce7e9f356 /src/test | |
| parent | 1a2d443f55ce05fa96f309b94ceabf4813f06045 (diff) | |
| download | rust-dee8a71cd5221536c319ca8c14108e93521092f5.tar.gz rust-dee8a71cd5221536c319ca8c14108e93521092f5.zip | |
fix #[derive] implementation for repr(packed) structs
Fix the derive implementation for repr(packed) structs to move the
fields out instead of calling functions on references to each subfield.
That's it, `#[derive(PartialEq)]` on a packed struct now does:
```Rust
fn eq(&self, other: &Self) {
let field_0 = self.0;
let other_field_0 = other.0;
&field_0 == &other_field_0
}
```
Instead of
```Rust
fn eq(&self, other: &Self) {
let ref field_0 = self.0;
let ref other_field_0 = other.0;
&*field_0 == &*other_field_0
}
```
Taking (unaligned) references to each subfield is undefined, unsound and
is an error with MIR effectck, so it had to be prevented. This causes
a borrowck error when a `repr(packed)` struct has a non-Copy field (and
therefore is a [breaking-change]), but I don't see a sound way to avoid
that error.
Diffstat (limited to 'src/test')
| -rw-r--r-- | src/test/compile-fail/deriving-with-repr-packed-not-copy.rs | 28 | ||||
| -rw-r--r-- | src/test/run-pass/deriving-with-repr-packed.rs | 45 |
2 files changed, 73 insertions, 0 deletions
diff --git a/src/test/compile-fail/deriving-with-repr-packed-not-copy.rs b/src/test/compile-fail/deriving-with-repr-packed-not-copy.rs new file mode 100644 index 00000000000..5ab916b91fa --- /dev/null +++ b/src/test/compile-fail/deriving-with-repr-packed-not-copy.rs @@ -0,0 +1,28 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// check that derive on a packed struct with non-Copy fields +// correctly. This can't be made to work perfectly because +// we can't just use the field from the struct as it might +// not be aligned. + +#[derive(PartialEq)] +struct Y(usize); + +#[derive(PartialEq)] +//~^ ERROR cannot move out of borrowed +//~| ERROR cannot move out of borrowed +//~| ERROR cannot move out of borrowed +//~| ERROR cannot move out of borrowed +#[repr(packed)] +struct X(Y); + +fn main() { +} diff --git a/src/test/run-pass/deriving-with-repr-packed.rs b/src/test/run-pass/deriving-with-repr-packed.rs new file mode 100644 index 00000000000..fcc31b462f8 --- /dev/null +++ b/src/test/run-pass/deriving-with-repr-packed.rs @@ -0,0 +1,45 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// check that derive on a packed struct does not call field +// methods with a misaligned field. + +use std::mem; + +#[derive(Copy, Clone)] +struct Aligned(usize); + +#[inline(never)] +fn check_align(ptr: *const Aligned) { + assert_eq!(ptr as usize % mem::align_of::<Aligned>(), + 0); +} + +impl PartialEq for Aligned { + fn eq(&self, other: &Self) -> bool { + check_align(self); + check_align(other); + self.0 == other.0 + } +} + +#[repr(packed)] +#[derive(PartialEq)] +struct Packed(Aligned, Aligned); + +#[derive(PartialEq)] +#[repr(C)] +struct Dealigned<T>(u8, T); + +fn main() { + let d1 = Dealigned(0, Packed(Aligned(1), Aligned(2))); + let ck = d1 == d1; + assert!(ck); +} |
