mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-14 16:03:17 +00:00
Translate union constants
Fix alignment for packed unions Add some missing privacy test Get rid of `unimplemented_unions` macro
This commit is contained in:
parent
2dc2fc5fc5
commit
d9b332bd69
@ -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 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
|
||||
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 @@ impl<'tcx> EnumMemberDescriptionFactory<'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 @@ impl<'tcx> EnumMemberDescriptionFactory<'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_rules! help {
|
||||
})
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! unimplemented_unions {
|
||||
() => ({
|
||||
panic!("unions are not fully implemented");
|
||||
})
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! register_diagnostics {
|
||||
($($code:tt),*) => (
|
||||
|
@ -959,7 +959,7 @@ impl<'a> Visitor for PostExpansionVisitor<'a> {
|
||||
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(..) => {
|
||||
|
26
src/test/compile-fail/union-const-eval.rs
Normal file
26
src/test/compile-fail/union-const-eval.rs
Normal file
@ -0,0 +1,26 @@
|
||||
// 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
|
||||
}
|
||||
}
|
25
src/test/compile-fail/union-const-pat.rs
Normal file
25
src/test/compile-fail/union-const-pat.rs
Normal file
@ -0,0 +1,25 @@
|
||||
// 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
|
||||
_ => {}
|
||||
}
|
||||
}
|
21
src/test/compile-fail/union-field-privacy.rs
Normal file
21
src/test/compile-fail/union-field-privacy.rs
Normal file
@ -0,0 +1,21 @@
|
||||
// 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
|
||||
}
|
27
src/test/run-pass/union-const-trans.rs
Normal file
27
src/test/run-pass/union-const-trans.rs
Normal file
@ -0,0 +1,27 @@
|
||||
// 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);
|
||||
}
|
||||
}
|
74
src/test/run-pass/union-packed.rs
Normal file
74
src/test/run-pass/union-packed.rs
Normal file
@ -0,0 +1,74 @@
|
||||
// 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);
|
||||
}
|
Loading…
Reference in New Issue
Block a user