Skip to content

Commit 52a3309

Browse files
committed
Auto merge of #43443 - bitshifter:issue-43317, r=nikomatsakis
Improve checking of conflicting packed and align representation hints on structs and unions. Fixes #43317 and improves #33626.
2 parents 5cc1baa + 5cccd6a commit 52a3309

File tree

6 files changed

+81
-24
lines changed

6 files changed

+81
-24
lines changed

src/librustc/diagnostics.rs

-1
Original file line numberDiff line numberDiff line change
@@ -2025,5 +2025,4 @@ register_diagnostics! {
20252025
E0490, // a value of type `..` is borrowed for too long
20262026
E0495, // cannot infer an appropriate lifetime due to conflicting requirements
20272027
E0566, // conflicting representation hints
2028-
E0587, // conflicting packed and align representation hints
20292028
}

src/librustc/hir/check_attr.rs

-8
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,6 @@ impl<'a> CheckAttrVisitor<'a> {
7676
};
7777

7878
let mut conflicting_reprs = 0;
79-
let mut found_packed = false;
80-
let mut found_align = false;
8179

8280
for word in words {
8381

@@ -106,7 +104,6 @@ impl<'a> CheckAttrVisitor<'a> {
106104
("attribute should be applied to struct or union",
107105
"a struct or union")
108106
} else {
109-
found_packed = true;
110107
continue
111108
}
112109
}
@@ -120,7 +117,6 @@ impl<'a> CheckAttrVisitor<'a> {
120117
}
121118
}
122119
"align" => {
123-
found_align = true;
124120
if target != Target::Struct &&
125121
target != Target::Union {
126122
("attribute should be applied to struct or union",
@@ -150,10 +146,6 @@ impl<'a> CheckAttrVisitor<'a> {
150146
span_warn!(self.sess, attr.span, E0566,
151147
"conflicting representation hints");
152148
}
153-
if found_align && found_packed {
154-
struct_span_err!(self.sess, attr.span, E0587,
155-
"conflicting packed and align representation hints").emit();
156-
}
157149
}
158150
}
159151

src/librustc_typeck/check/mod.rs

+13-9
Original file line numberDiff line numberDiff line change
@@ -1063,11 +1063,7 @@ fn check_struct<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
10631063
check_simd(tcx, span, def_id);
10641064
}
10651065

1066-
// if struct is packed and not aligned, check fields for alignment.
1067-
// Checks for combining packed and align attrs on single struct are done elsewhere.
1068-
if tcx.adt_def(def_id).repr.packed() && tcx.adt_def(def_id).repr.align == 0 {
1069-
check_packed(tcx, span, def_id);
1070-
}
1066+
check_packed(tcx, span, def_id);
10711067
}
10721068

10731069
fn check_union<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
@@ -1077,6 +1073,8 @@ fn check_union<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
10771073
let def = tcx.adt_def(def_id);
10781074
def.destructor(tcx); // force the destructor to be evaluated
10791075
check_representable(tcx, span, def_id);
1076+
1077+
check_packed(tcx, span, def_id);
10801078
}
10811079

10821080
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
14781476
}
14791477

14801478
fn check_packed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, sp: Span, def_id: DefId) {
1481-
if check_packed_inner(tcx, def_id, &mut Vec::new()) {
1482-
struct_span_err!(tcx.sess, sp, E0588,
1483-
"packed struct cannot transitively contain a `[repr(align)]` struct").emit();
1479+
if tcx.adt_def(def_id).repr.packed() {
1480+
if tcx.adt_def(def_id).repr.align > 0 {
1481+
struct_span_err!(tcx.sess, sp, E0587,
1482+
"type has conflicting packed and align representation hints").emit();
1483+
}
1484+
else if check_packed_inner(tcx, def_id, &mut Vec::new()) {
1485+
struct_span_err!(tcx.sess, sp, E0588,
1486+
"packed type cannot transitively contain a `[repr(align)]` type").emit();
1487+
}
14841488
}
14851489
}
14861490

@@ -1493,7 +1497,7 @@ fn check_packed_inner<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
14931497
return false;
14941498
}
14951499
match t.sty {
1496-
ty::TyAdt(def, substs) if def.is_struct() => {
1500+
ty::TyAdt(def, substs) if def.is_struct() || def.is_union() => {
14971501
if tcx.adt_def(def.did).repr.align > 0 {
14981502
return true;
14991503
}

src/librustc_typeck/diagnostics.rs

+1
Original file line numberDiff line numberDiff line change
@@ -4663,6 +4663,7 @@ register_diagnostics! {
46634663
// but `{}` was found in the type `{}`
46644664
E0567, // auto traits can not have type parameters
46654665
E0568, // auto-traits can not have predicates,
4666+
E0587, // struct has conflicting packed and align representation hints
46664667
E0588, // packed struct cannot transitively contain a `[repr(align)]` struct
46674668
E0592, // duplicate definitions with name `{}`
46684669
// E0613, // Removed (merged with E0609)

src/test/compile-fail/conflicting-repr-hints.rs

+27-2
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,32 @@ enum D { D }
2727
#[repr(C, packed)]
2828
struct E(i32);
2929

30-
#[repr(packed, align(8))] //~ ERROR conflicting packed and align representation hints
31-
struct F(i32);
30+
#[repr(packed, align(8))]
31+
struct F(i32); //~ ERROR type has conflicting packed and align representation hints
32+
33+
#[repr(packed)]
34+
#[repr(align(8))]
35+
struct G(i32); //~ ERROR type has conflicting packed and align representation hints
36+
37+
#[repr(align(8))]
38+
#[repr(packed)]
39+
struct H(i32); //~ ERROR type has conflicting packed and align representation hints
40+
41+
#[repr(packed, align(8))]
42+
union X { //~ ERROR type has conflicting packed and align representation hints
43+
i: i32
44+
}
45+
46+
#[repr(packed)]
47+
#[repr(align(8))]
48+
union Y { //~ ERROR type has conflicting packed and align representation hints
49+
i: i32
50+
}
51+
52+
#[repr(align(8))]
53+
#[repr(packed)]
54+
union Z { //~ ERROR type has conflicting packed and align representation hints
55+
i: i32
56+
}
3257

3358
fn main() {}

src/test/compile-fail/repr-packed-contains-align.rs

+40-4
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,53 @@
99
// except according to those terms.
1010
#![feature(attr_literals)]
1111
#![feature(repr_align)]
12+
#![feature(untagged_unions)]
1213
#![allow(dead_code)]
1314

1415
#[repr(align(16))]
15-
struct A(i32);
16+
struct SA(i32);
1617

17-
struct B(A);
18+
struct SB(SA);
19+
20+
#[repr(align(16))]
21+
union UA {
22+
i: i32
23+
}
24+
25+
union UB {
26+
a: UA
27+
}
28+
29+
#[repr(packed)]
30+
struct SC(SA); //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type
31+
32+
#[repr(packed)]
33+
struct SD(SB); //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type
34+
35+
#[repr(packed)]
36+
struct SE(UA); //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type
37+
38+
#[repr(packed)]
39+
struct SF(UB); //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type
40+
41+
#[repr(packed)]
42+
union UC { //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type
43+
a: UA
44+
}
45+
46+
#[repr(packed)]
47+
union UD { //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type
48+
n: UB
49+
}
1850

1951
#[repr(packed)]
20-
struct C(A); //~ ERROR: packed struct cannot transitively contain a `[repr(align)]` struct
52+
union UE { //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type
53+
a: SA
54+
}
2155

2256
#[repr(packed)]
23-
struct D(B); //~ ERROR: packed struct cannot transitively contain a `[repr(align)]` struct
57+
union UF { //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type
58+
n: SB
59+
}
2460

2561
fn main() {}

0 commit comments

Comments
 (0)