提交 d9b332bd 编写于 作者: V Vadim Petrochenkov

Translate union constants

Fix alignment for packed unions
Add some missing privacy test
Get rid of `unimplemented_unions` macro
上级 2dc2fc5f
......@@ -258,8 +258,7 @@ pub fn const_expr_to_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
format!("floating point constants cannot be used in patterns"));
}
ty::TyEnum(adt_def, _) |
ty::TyStruct(adt_def, _) |
ty::TyUnion(adt_def, _) => {
ty::TyStruct(adt_def, _) => {
if !tcx.has_attr(adt_def.did, "structural_match") {
tcx.sess.add_lint(
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>,
tcx.item_path_str(adt_def.did)));
}
}
ty::TyUnion(..) => {
// Matching on union fields is unsafe, we can't hide it in constants
tcx.sess.span_err(span, "cannot use unions in constant patterns");
}
_ => { }
}
let pat = match expr.node {
......
......@@ -385,8 +385,9 @@ fn item_is_accessible(&self, did: DefId) -> bool {
fn check_field(&mut self, span: Span, def: ty::AdtDef<'tcx>, field: ty::FieldDef<'tcx>) {
if def.adt_kind() != ty::AdtKind::Enum &&
!field.vis.is_accessible_from(self.curitem, &self.tcx.map) {
struct_span_err!(self.tcx.sess, span, E0451, "field `{}` of struct `{}` is private",
field.name, self.tcx.item_path_str(def.did))
let kind_descr = if def.adt_kind() == ty::AdtKind::Union { "union" } else { "struct" };
struct_span_err!(self.tcx.sess, span, E0451, "field `{}` of {} `{}` is private",
field.name, kind_descr, self.tcx.item_path_str(def.did))
.span_label(span, &format!("field `{}` is private", field.name))
.emit();
}
......
......@@ -516,7 +516,7 @@ fn mk_union<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
Union {
min_size: min_size,
align: align,
align: if packed { 1 } else { align },
packed: packed,
fields: tys.to_vec(),
}
......@@ -1176,8 +1176,10 @@ pub fn trans_const<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, r: &Repr<'tcx>, discr
contents.extend_from_slice(&[padding(ccx, max_sz - case.size)]);
C_struct(ccx, &contents[..], false)
}
UntaggedUnion(..) => {
unimplemented_unions!();
UntaggedUnion(ref un) => {
assert_eq!(discr, Disr(0));
let contents = build_const_union(ccx, un, vals[0]);
C_struct(ccx, &contents, un.packed)
}
Univariant(ref st) => {
assert_eq!(discr, Disr(0));
......@@ -1272,6 +1274,21 @@ fn build_const_struct<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
cfields
}
fn build_const_union<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
un: &Union<'tcx>,
field_val: ValueRef)
-> Vec<ValueRef> {
let mut cfields = vec![field_val];
let offset = machine::llsize_of_alloc(ccx, val_ty(field_val));
let size = roundup(un.min_size, un.align);
if offset != size {
cfields.push(padding(ccx, size - offset));
}
cfields
}
fn padding(ccx: &CrateContext, size: u64) -> ValueRef {
C_undef(Type::array(&Type::i8(ccx), size))
}
......
......@@ -786,7 +786,7 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
usage_site_span).finalize(cx)
}
ty::TyUnion(..) => {
unimplemented_unions!();
unimplemented!();
}
ty::TyTuple(ref elements) => {
prepare_tuple_metadata(cx,
......@@ -1302,9 +1302,6 @@ fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>)
]
}
}
adt::UntaggedUnion(..) => {
unimplemented_unions!();
}
adt::RawNullablePointer { nndiscr: non_null_variant_index, nnty, .. } => {
// As far as debuginfo is concerned, the pointer this enum
// represents is still wrapped in a struct. This is to make the
......@@ -1421,7 +1418,9 @@ fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>)
}
]
},
adt::CEnum(..) => span_bug!(self.span, "This should be unreachable.")
adt::CEnum(..) | adt::UntaggedUnion(..) => {
span_bug!(self.span, "This should be unreachable.")
}
}
}
}
......
......@@ -107,13 +107,6 @@
})
}
#[macro_export]
macro_rules! unimplemented_unions {
() => ({
panic!("unions are not fully implemented");
})
}
#[macro_export]
macro_rules! register_diagnostics {
($($code:tt),*) => (
......
......@@ -959,7 +959,7 @@ fn visit_item(&mut self, i: &ast::Item) {
ast::ItemKind::Union(..) => {
gate_feature_post!(&self, untagged_unions,
i.span,
"unions are unstable and not fully implemented");
"unions are unstable and possibly buggy");
}
ast::ItemKind::DefaultImpl(..) => {
......
// Copyright 2016 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.
#![feature(untagged_unions)]
union U {
a: usize,
b: usize,
}
const C: U = U { a: 10 };
fn main() {
unsafe {
let a: [u8; C.a]; // OK
let b: [u8; C.b]; //~ ERROR constant evaluation error
//~^ NOTE nonexistent struct field
}
}
// Copyright 2016 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.
#![feature(untagged_unions)]
union U {
a: usize,
b: usize,
}
const C: U = U { a: 10 };
fn main() {
match C {
C => {} //~ ERROR cannot use unions in constant patterns
_ => {}
}
}
// Copyright 2016 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.
#![feature(untagged_unions)]
mod m {
pub union U {
a: u8
}
}
fn main() {
let u = m::U { a: 0 }; //~ ERROR field `a` of union `m::U` is private
}
// Copyright 2016 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.
#![feature(untagged_unions)]
union U {
a: u64,
b: u64,
}
const C: U = U { b: 10 };
fn main() {
unsafe {
let a = C.a;
let b = C.b;
assert_eq!(a, 10);
assert_eq!(b, 10);
}
}
// Copyright 2016 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.
#![feature(untagged_unions)]
use std::mem::{size_of, size_of_val, align_of, align_of_val};
struct S {
a: u16,
b: [u8; 3],
}
#[repr(packed)]
struct Sp {
a: u16,
b: [u8; 3],
}
union U {
a: u16,
b: [u8; 3],
}
#[repr(packed)]
union Up {
a: u16,
b: [u8; 3],
}
const CS: S = S { a: 0, b: [0, 0, 0] };
const CSP: Sp = Sp { a: 0, b: [0, 0, 0] };
const CU: U = U { b: [0, 0, 0] };
const CUP: Up = Up { b: [0, 0, 0] };
fn main() {
let s = S { a: 0, b: [0, 0, 0] };
assert_eq!(size_of::<S>(), 6);
assert_eq!(size_of_val(&s), 6);
assert_eq!(size_of_val(&CS), 6);
assert_eq!(align_of::<S>(), 2);
assert_eq!(align_of_val(&s), 2);
assert_eq!(align_of_val(&CS), 2);
let sp = Sp { a: 0, b: [0, 0, 0] };
assert_eq!(size_of::<Sp>(), 5);
assert_eq!(size_of_val(&sp), 5);
assert_eq!(size_of_val(&CSP), 5);
assert_eq!(align_of::<Sp>(), 1);
assert_eq!(align_of_val(&sp), 1);
assert_eq!(align_of_val(&CSP), 1);
let u = U { b: [0, 0, 0] };
assert_eq!(size_of::<U>(), 4);
assert_eq!(size_of_val(&u), 4);
assert_eq!(size_of_val(&CU), 4);
assert_eq!(align_of::<U>(), 2);
assert_eq!(align_of_val(&u), 2);
assert_eq!(align_of_val(&CU), 2);
let up = Up { b: [0, 0, 0] };
assert_eq!(size_of::<Up>(), 3);
assert_eq!(size_of_val(&up), 3);
assert_eq!(size_of_val(&CUP), 3);
assert_eq!(align_of::<Up>(), 1);
assert_eq!(align_of_val(&up), 1);
assert_eq!(align_of_val(&CUP), 1);
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册