From b8b898093cf2b37dfe5c192cbd7f1004073fde0e Mon Sep 17 00:00:00 2001 From: Scott Olson Date: Thu, 9 Feb 2017 03:09:36 -0800 Subject: [PATCH 1/2] Avoid unsafe unaligned loads in test. --- src/test/run-pass/mir_adt_construction.rs | 33 ++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/src/test/run-pass/mir_adt_construction.rs b/src/test/run-pass/mir_adt_construction.rs index 6b47721ab4b32..c54cbe7bd6f45 100644 --- a/src/test/run-pass/mir_adt_construction.rs +++ b/src/test/run-pass/mir_adt_construction.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::fmt; + #[repr(C)] enum CEnum { Hello = 30, @@ -24,7 +26,6 @@ fn test1(c: CEnum) -> i32 { } #[repr(packed)] -#[derive(PartialEq, Debug)] struct Pakd { a: u64, b: u32, @@ -33,6 +34,36 @@ struct Pakd { e: () } +// It is unsafe to use #[derive(Debug)] on a packed struct because the code generated by the derive +// macro takes references to the fields instead of accessing them directly. +impl fmt::Debug for Pakd { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + // It's important that we load the fields into locals by-value here. This will do safe + // unaligned loads into the locals, then pass references to the properly-aligned locals to + // the formatting code. + let Pakd { a, b, c, d, e } = *self; + f.debug_struct("Pakd") + .field("a", &a) + .field("b", &b) + .field("c", &c) + .field("d", &d) + .field("e", &e) + .finish() + } +} + +// It is unsafe to use #[derive(PartialEq)] on a packed struct because the code generated by the +// derive macro takes references to the fields instead of accessing them directly. +impl PartialEq for Pakd { + fn eq(&self, other: &Pakd) -> bool { + self.a == other.a && + self.b == other.b && + self.c == other.c && + self.d == other.d && + self.e == other.e + } +} + impl Drop for Pakd { fn drop(&mut self) {} } From 2589f4a7511ab04a3325b0372cd2ae174940c6c8 Mon Sep 17 00:00:00 2001 From: Scott Olson Date: Thu, 9 Feb 2017 03:10:33 -0800 Subject: [PATCH 2/2] Fix indentation in test. --- src/test/run-pass/mir_adt_construction.rs | 28 +++++++++++------------ 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/test/run-pass/mir_adt_construction.rs b/src/test/run-pass/mir_adt_construction.rs index c54cbe7bd6f45..eb96d94efec93 100644 --- a/src/test/run-pass/mir_adt_construction.rs +++ b/src/test/run-pass/mir_adt_construction.rs @@ -17,12 +17,12 @@ enum CEnum { } fn test1(c: CEnum) -> i32 { - let c2 = CEnum::Hello; - match (c, c2) { - (CEnum::Hello, CEnum::Hello) => 42, - (CEnum::World, CEnum::Hello) => 0, - _ => 1 - } + let c2 = CEnum::Hello; + match (c, c2) { + (CEnum::Hello, CEnum::Hello) => 42, + (CEnum::World, CEnum::Hello) => 0, + _ => 1 + } } #[repr(packed)] @@ -90,12 +90,12 @@ fn test5(x: fn(u32) -> Option) -> (Option, Option) { } fn main() { - assert_eq!(test1(CEnum::Hello), 42); - assert_eq!(test1(CEnum::World), 0); - assert_eq!(test2(), Pakd { a: 42, b: 42, c: 42, d: 42, e: () }); - assert_eq!(test3(), TupleLike(42, 42)); - let t4 = test4(TupleLike); - assert_eq!(t4.0, t4.1); - let t5 = test5(Some); - assert_eq!(t5.0, t5.1); + assert_eq!(test1(CEnum::Hello), 42); + assert_eq!(test1(CEnum::World), 0); + assert_eq!(test2(), Pakd { a: 42, b: 42, c: 42, d: 42, e: () }); + assert_eq!(test3(), TupleLike(42, 42)); + let t4 = test4(TupleLike); + assert_eq!(t4.0, t4.1); + let t5 = test5(Some); + assert_eq!(t5.0, t5.1); }