Skip to content

Commit d9b332b

Browse files
committed
Translate union constants
Fix alignment for packed unions Add some missing privacy test Get rid of `unimplemented_unions` macro
1 parent 2dc2fc5 commit d9b332b

File tree

11 files changed

+206
-20
lines changed

11 files changed

+206
-20
lines changed

src/librustc_const_eval/eval.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -258,8 +258,7 @@ pub fn const_expr_to_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
258258
format!("floating point constants cannot be used in patterns"));
259259
}
260260
ty::TyEnum(adt_def, _) |
261-
ty::TyStruct(adt_def, _) |
262-
ty::TyUnion(adt_def, _) => {
261+
ty::TyStruct(adt_def, _) => {
263262
if !tcx.has_attr(adt_def.did, "structural_match") {
264263
tcx.sess.add_lint(
265264
lint::builtin::ILLEGAL_STRUCT_OR_ENUM_CONSTANT_PATTERN,
@@ -272,6 +271,10 @@ pub fn const_expr_to_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
272271
tcx.item_path_str(adt_def.did)));
273272
}
274273
}
274+
ty::TyUnion(..) => {
275+
// Matching on union fields is unsafe, we can't hide it in constants
276+
tcx.sess.span_err(span, "cannot use unions in constant patterns");
277+
}
275278
_ => { }
276279
}
277280
let pat = match expr.node {

src/librustc_privacy/lib.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -385,8 +385,9 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
385385
fn check_field(&mut self, span: Span, def: ty::AdtDef<'tcx>, field: ty::FieldDef<'tcx>) {
386386
if def.adt_kind() != ty::AdtKind::Enum &&
387387
!field.vis.is_accessible_from(self.curitem, &self.tcx.map) {
388-
struct_span_err!(self.tcx.sess, span, E0451, "field `{}` of struct `{}` is private",
389-
field.name, self.tcx.item_path_str(def.did))
388+
let kind_descr = if def.adt_kind() == ty::AdtKind::Union { "union" } else { "struct" };
389+
struct_span_err!(self.tcx.sess, span, E0451, "field `{}` of {} `{}` is private",
390+
field.name, kind_descr, self.tcx.item_path_str(def.did))
390391
.span_label(span, &format!("field `{}` is private", field.name))
391392
.emit();
392393
}

src/librustc_trans/adt.rs

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -516,7 +516,7 @@ fn mk_union<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
516516

517517
Union {
518518
min_size: min_size,
519-
align: align,
519+
align: if packed { 1 } else { align },
520520
packed: packed,
521521
fields: tys.to_vec(),
522522
}
@@ -1176,8 +1176,10 @@ pub fn trans_const<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, r: &Repr<'tcx>, discr
11761176
contents.extend_from_slice(&[padding(ccx, max_sz - case.size)]);
11771177
C_struct(ccx, &contents[..], false)
11781178
}
1179-
UntaggedUnion(..) => {
1180-
unimplemented_unions!();
1179+
UntaggedUnion(ref un) => {
1180+
assert_eq!(discr, Disr(0));
1181+
let contents = build_const_union(ccx, un, vals[0]);
1182+
C_struct(ccx, &contents, un.packed)
11811183
}
11821184
Univariant(ref st) => {
11831185
assert_eq!(discr, Disr(0));
@@ -1272,6 +1274,21 @@ fn build_const_struct<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
12721274
cfields
12731275
}
12741276

1277+
fn build_const_union<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
1278+
un: &Union<'tcx>,
1279+
field_val: ValueRef)
1280+
-> Vec<ValueRef> {
1281+
let mut cfields = vec![field_val];
1282+
1283+
let offset = machine::llsize_of_alloc(ccx, val_ty(field_val));
1284+
let size = roundup(un.min_size, un.align);
1285+
if offset != size {
1286+
cfields.push(padding(ccx, size - offset));
1287+
}
1288+
1289+
cfields
1290+
}
1291+
12751292
fn padding(ccx: &CrateContext, size: u64) -> ValueRef {
12761293
C_undef(Type::array(&Type::i8(ccx), size))
12771294
}

src/librustc_trans/debuginfo/metadata.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -786,7 +786,7 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
786786
usage_site_span).finalize(cx)
787787
}
788788
ty::TyUnion(..) => {
789-
unimplemented_unions!();
789+
unimplemented!();
790790
}
791791
ty::TyTuple(ref elements) => {
792792
prepare_tuple_metadata(cx,
@@ -1302,9 +1302,6 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> {
13021302
]
13031303
}
13041304
}
1305-
adt::UntaggedUnion(..) => {
1306-
unimplemented_unions!();
1307-
}
13081305
adt::RawNullablePointer { nndiscr: non_null_variant_index, nnty, .. } => {
13091306
// As far as debuginfo is concerned, the pointer this enum
13101307
// represents is still wrapped in a struct. This is to make the
@@ -1421,7 +1418,9 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> {
14211418
}
14221419
]
14231420
},
1424-
adt::CEnum(..) => span_bug!(self.span, "This should be unreachable.")
1421+
adt::CEnum(..) | adt::UntaggedUnion(..) => {
1422+
span_bug!(self.span, "This should be unreachable.")
1423+
}
14251424
}
14261425
}
14271426
}

src/libsyntax/diagnostics/macros.rs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -107,13 +107,6 @@ macro_rules! help {
107107
})
108108
}
109109

110-
#[macro_export]
111-
macro_rules! unimplemented_unions {
112-
() => ({
113-
panic!("unions are not fully implemented");
114-
})
115-
}
116-
117110
#[macro_export]
118111
macro_rules! register_diagnostics {
119112
($($code:tt),*) => (

src/libsyntax/feature_gate.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -959,7 +959,7 @@ impl<'a> Visitor for PostExpansionVisitor<'a> {
959959
ast::ItemKind::Union(..) => {
960960
gate_feature_post!(&self, untagged_unions,
961961
i.span,
962-
"unions are unstable and not fully implemented");
962+
"unions are unstable and possibly buggy");
963963
}
964964

965965
ast::ItemKind::DefaultImpl(..) => {
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(untagged_unions)]
12+
13+
union U {
14+
a: usize,
15+
b: usize,
16+
}
17+
18+
const C: U = U { a: 10 };
19+
20+
fn main() {
21+
unsafe {
22+
let a: [u8; C.a]; // OK
23+
let b: [u8; C.b]; //~ ERROR constant evaluation error
24+
//~^ NOTE nonexistent struct field
25+
}
26+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(untagged_unions)]
12+
13+
union U {
14+
a: usize,
15+
b: usize,
16+
}
17+
18+
const C: U = U { a: 10 };
19+
20+
fn main() {
21+
match C {
22+
C => {} //~ ERROR cannot use unions in constant patterns
23+
_ => {}
24+
}
25+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(untagged_unions)]
12+
13+
mod m {
14+
pub union U {
15+
a: u8
16+
}
17+
}
18+
19+
fn main() {
20+
let u = m::U { a: 0 }; //~ ERROR field `a` of union `m::U` is private
21+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(untagged_unions)]
12+
13+
union U {
14+
a: u64,
15+
b: u64,
16+
}
17+
18+
const C: U = U { b: 10 };
19+
20+
fn main() {
21+
unsafe {
22+
let a = C.a;
23+
let b = C.b;
24+
assert_eq!(a, 10);
25+
assert_eq!(b, 10);
26+
}
27+
}

src/test/run-pass/union-packed.rs

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(untagged_unions)]
12+
13+
use std::mem::{size_of, size_of_val, align_of, align_of_val};
14+
15+
struct S {
16+
a: u16,
17+
b: [u8; 3],
18+
}
19+
20+
#[repr(packed)]
21+
struct Sp {
22+
a: u16,
23+
b: [u8; 3],
24+
}
25+
26+
union U {
27+
a: u16,
28+
b: [u8; 3],
29+
}
30+
31+
#[repr(packed)]
32+
union Up {
33+
a: u16,
34+
b: [u8; 3],
35+
}
36+
37+
const CS: S = S { a: 0, b: [0, 0, 0] };
38+
const CSP: Sp = Sp { a: 0, b: [0, 0, 0] };
39+
const CU: U = U { b: [0, 0, 0] };
40+
const CUP: Up = Up { b: [0, 0, 0] };
41+
42+
fn main() {
43+
let s = S { a: 0, b: [0, 0, 0] };
44+
assert_eq!(size_of::<S>(), 6);
45+
assert_eq!(size_of_val(&s), 6);
46+
assert_eq!(size_of_val(&CS), 6);
47+
assert_eq!(align_of::<S>(), 2);
48+
assert_eq!(align_of_val(&s), 2);
49+
assert_eq!(align_of_val(&CS), 2);
50+
51+
let sp = Sp { a: 0, b: [0, 0, 0] };
52+
assert_eq!(size_of::<Sp>(), 5);
53+
assert_eq!(size_of_val(&sp), 5);
54+
assert_eq!(size_of_val(&CSP), 5);
55+
assert_eq!(align_of::<Sp>(), 1);
56+
assert_eq!(align_of_val(&sp), 1);
57+
assert_eq!(align_of_val(&CSP), 1);
58+
59+
let u = U { b: [0, 0, 0] };
60+
assert_eq!(size_of::<U>(), 4);
61+
assert_eq!(size_of_val(&u), 4);
62+
assert_eq!(size_of_val(&CU), 4);
63+
assert_eq!(align_of::<U>(), 2);
64+
assert_eq!(align_of_val(&u), 2);
65+
assert_eq!(align_of_val(&CU), 2);
66+
67+
let up = Up { b: [0, 0, 0] };
68+
assert_eq!(size_of::<Up>(), 3);
69+
assert_eq!(size_of_val(&up), 3);
70+
assert_eq!(size_of_val(&CUP), 3);
71+
assert_eq!(align_of::<Up>(), 1);
72+
assert_eq!(align_of_val(&up), 1);
73+
assert_eq!(align_of_val(&CUP), 1);
74+
}

0 commit comments

Comments
 (0)