diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index cef1be5cee232..131972a920899 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -2025,5 +2025,4 @@ register_diagnostics! { E0490, // a value of type `..` is borrowed for too long E0495, // cannot infer an appropriate lifetime due to conflicting requirements E0566, // conflicting representation hints - E0587, // conflicting packed and align representation hints } diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs index e4b1cdabb0466..946cbb7960b67 100644 --- a/src/librustc/hir/check_attr.rs +++ b/src/librustc/hir/check_attr.rs @@ -76,8 +76,6 @@ impl<'a> CheckAttrVisitor<'a> { }; let mut conflicting_reprs = 0; - let mut found_packed = false; - let mut found_align = false; for word in words { @@ -106,7 +104,6 @@ impl<'a> CheckAttrVisitor<'a> { ("attribute should be applied to struct or union", "a struct or union") } else { - found_packed = true; continue } } @@ -120,7 +117,6 @@ impl<'a> CheckAttrVisitor<'a> { } } "align" => { - found_align = true; if target != Target::Struct && target != Target::Union { ("attribute should be applied to struct or union", @@ -150,10 +146,6 @@ impl<'a> CheckAttrVisitor<'a> { span_warn!(self.sess, attr.span, E0566, "conflicting representation hints"); } - if found_align && found_packed { - struct_span_err!(self.sess, attr.span, E0587, - "conflicting packed and align representation hints").emit(); - } } } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index af11cacb247b6..74d46c1525caf 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1063,11 +1063,7 @@ fn check_struct<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, check_simd(tcx, span, def_id); } - // if struct is packed and not aligned, check fields for alignment. - // Checks for combining packed and align attrs on single struct are done elsewhere. - if tcx.adt_def(def_id).repr.packed() && tcx.adt_def(def_id).repr.align == 0 { - check_packed(tcx, span, def_id); - } + check_packed(tcx, span, def_id); } fn check_union<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, @@ -1077,6 +1073,8 @@ fn check_union<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let def = tcx.adt_def(def_id); def.destructor(tcx); // force the destructor to be evaluated check_representable(tcx, span, def_id); + + check_packed(tcx, span, def_id); } pub fn check_item_type<'a,'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &'tcx hir::Item) { @@ -1478,9 +1476,15 @@ pub fn check_simd<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, sp: Span, def_id: DefId } fn check_packed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, sp: Span, def_id: DefId) { - if check_packed_inner(tcx, def_id, &mut Vec::new()) { - struct_span_err!(tcx.sess, sp, E0588, - "packed struct cannot transitively contain a `[repr(align)]` struct").emit(); + if tcx.adt_def(def_id).repr.packed() { + if tcx.adt_def(def_id).repr.align > 0 { + struct_span_err!(tcx.sess, sp, E0587, + "type has conflicting packed and align representation hints").emit(); + } + else if check_packed_inner(tcx, def_id, &mut Vec::new()) { + struct_span_err!(tcx.sess, sp, E0588, + "packed type cannot transitively contain a `[repr(align)]` type").emit(); + } } } @@ -1493,7 +1497,7 @@ fn check_packed_inner<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, return false; } match t.sty { - ty::TyAdt(def, substs) if def.is_struct() => { + ty::TyAdt(def, substs) if def.is_struct() || def.is_union() => { if tcx.adt_def(def.did).repr.align > 0 { return true; } diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 1e26a734e7640..60f32408abba1 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -4663,6 +4663,7 @@ register_diagnostics! { // but `{}` was found in the type `{}` E0567, // auto traits can not have type parameters E0568, // auto-traits can not have predicates, + E0587, // struct has conflicting packed and align representation hints E0588, // packed struct cannot transitively contain a `[repr(align)]` struct E0592, // duplicate definitions with name `{}` // E0613, // Removed (merged with E0609) diff --git a/src/test/compile-fail/conflicting-repr-hints.rs b/src/test/compile-fail/conflicting-repr-hints.rs index 01fa3ffbaa6ae..12ac8fb57b1f8 100644 --- a/src/test/compile-fail/conflicting-repr-hints.rs +++ b/src/test/compile-fail/conflicting-repr-hints.rs @@ -27,7 +27,32 @@ enum D { D } #[repr(C, packed)] struct E(i32); -#[repr(packed, align(8))] //~ ERROR conflicting packed and align representation hints -struct F(i32); +#[repr(packed, align(8))] +struct F(i32); //~ ERROR type has conflicting packed and align representation hints + +#[repr(packed)] +#[repr(align(8))] +struct G(i32); //~ ERROR type has conflicting packed and align representation hints + +#[repr(align(8))] +#[repr(packed)] +struct H(i32); //~ ERROR type has conflicting packed and align representation hints + +#[repr(packed, align(8))] +union X { //~ ERROR type has conflicting packed and align representation hints + i: i32 +} + +#[repr(packed)] +#[repr(align(8))] +union Y { //~ ERROR type has conflicting packed and align representation hints + i: i32 +} + +#[repr(align(8))] +#[repr(packed)] +union Z { //~ ERROR type has conflicting packed and align representation hints + i: i32 +} fn main() {} diff --git a/src/test/compile-fail/repr-packed-contains-align.rs b/src/test/compile-fail/repr-packed-contains-align.rs index c584dcf3e5993..78d43064ea3d2 100644 --- a/src/test/compile-fail/repr-packed-contains-align.rs +++ b/src/test/compile-fail/repr-packed-contains-align.rs @@ -9,17 +9,53 @@ // except according to those terms. #![feature(attr_literals)] #![feature(repr_align)] +#![feature(untagged_unions)] #![allow(dead_code)] #[repr(align(16))] -struct A(i32); +struct SA(i32); -struct B(A); +struct SB(SA); + +#[repr(align(16))] +union UA { + i: i32 +} + +union UB { + a: UA +} + +#[repr(packed)] +struct SC(SA); //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type + +#[repr(packed)] +struct SD(SB); //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type + +#[repr(packed)] +struct SE(UA); //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type + +#[repr(packed)] +struct SF(UB); //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type + +#[repr(packed)] +union UC { //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type + a: UA +} + +#[repr(packed)] +union UD { //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type + n: UB +} #[repr(packed)] -struct C(A); //~ ERROR: packed struct cannot transitively contain a `[repr(align)]` struct +union UE { //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type + a: SA +} #[repr(packed)] -struct D(B); //~ ERROR: packed struct cannot transitively contain a `[repr(align)]` struct +union UF { //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type + n: SB +} fn main() {}