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,
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 {
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();
}
Union {
min_size: min_size,
- align: align,
+ align: if packed { 1 } else { align },
packed: packed,
fields: tys.to_vec(),
}
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));
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))
}
usage_site_span).finalize(cx)
}
ty::TyUnion(..) => {
- unimplemented_unions!();
+ unimplemented!();
}
ty::TyTuple(ref elements) => {
prepare_tuple_metadata(cx,
]
}
}
- 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
}
]
},
- adt::CEnum(..) => span_bug!(self.span, "This should be unreachable.")
+ adt::CEnum(..) | adt::UntaggedUnion(..) => {
+ span_bug!(self.span, "This should be unreachable.")
+ }
}
}
}
})
}
-#[macro_export]
-macro_rules! unimplemented_unions {
- () => ({
- panic!("unions are not fully implemented");
- })
-}
-
#[macro_export]
macro_rules! register_diagnostics {
($($code:tt),*) => (
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(..) => {
--- /dev/null
+// 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
+ }
+}
--- /dev/null
+// 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
+ _ => {}
+ }
+}
--- /dev/null
+// 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
+}
--- /dev/null
+// 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);
+ }
+}
--- /dev/null
+// 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);
+}