diff options
| author | Vadim Petrochenkov <vadim.petrochenkov@gmail.com> | 2016-08-26 19:23:42 +0300 |
|---|---|---|
| committer | Vadim Petrochenkov <vadim.petrochenkov@gmail.com> | 2016-09-03 13:39:35 +0300 |
| commit | 93067ca089ea570e4e2bdfc456958c81a4d1e092 (patch) | |
| tree | dcc0960db713f309dc92dd2fa23bfb596b9b9e8a /src | |
| parent | e67c2282afa3c527da49618b928280564e92868f (diff) | |
| download | rust-93067ca089ea570e4e2bdfc456958c81a4d1e092.tar.gz rust-93067ca089ea570e4e2bdfc456958c81a4d1e092.zip | |
Address comments and add requested tests
Diffstat (limited to 'src')
47 files changed, 582 insertions, 61 deletions
diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index a6835802f1c..541aeeb7d8d 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -671,31 +671,28 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { // Select just those fields of the `with` // expression that will actually be used - match with_cmt.ty.sty { - ty::TyStruct(def, substs) => { - // Consume those fields of the with expression that are needed. - for with_field in &def.struct_variant().fields { - if !contains_field_named(with_field, fields) { - let cmt_field = self.mc.cat_field( - &*with_expr, - with_cmt.clone(), - with_field.name, - with_field.ty(self.tcx(), substs) - ); - self.delegate_consume(with_expr.id, with_expr.span, cmt_field); - } + if let ty::TyStruct(def, substs) = with_cmt.ty.sty { + // Consume those fields of the with expression that are needed. + for with_field in &def.struct_variant().fields { + if !contains_field_named(with_field, fields) { + let cmt_field = self.mc.cat_field( + &*with_expr, + with_cmt.clone(), + with_field.name, + with_field.ty(self.tcx(), substs) + ); + self.delegate_consume(with_expr.id, with_expr.span, cmt_field); } } - _ => { - // the base expression should always evaluate to a - // struct; however, when EUV is run during typeck, it - // may not. This will generate an error earlier in typeck, - // so we can just ignore it. - if !self.tcx().sess.has_errors() { - span_bug!( - with_expr.span, - "with expression doesn't evaluate to a struct"); - } + } else { + // the base expression should always evaluate to a + // struct; however, when EUV is run during typeck, it + // may not. This will generate an error earlier in typeck, + // so we can just ignore it. + if !self.tcx().sess.has_errors() { + span_bug!( + with_expr.span, + "with expression doesn't evaluate to a struct"); } } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index ee2188e8e11..e88f72f2d84 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1423,7 +1423,7 @@ bitflags! { const IS_PHANTOM_DATA = 1 << 3, const IS_SIMD = 1 << 4, const IS_FUNDAMENTAL = 1 << 5, - const IS_UNION = 1 << 7, + const IS_UNION = 1 << 6, } } diff --git a/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs b/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs index 6193157fa7b..c08dc9330b8 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs @@ -102,6 +102,7 @@ impl<'a, 'tcx> RestrictionsContext<'a, 'tcx> { let interior = interior.cleaned(); let base_ty = cmt_base.ty; let result = self.restrict(cmt_base); + // Borrowing one union field automatically borrows all its fields. if let ty::TyUnion(ref adt_def, _) = base_ty.sty { match result { RestrictionResult::Safe => RestrictionResult::Safe, diff --git a/src/librustc_borrowck/borrowck/move_data.rs b/src/librustc_borrowck/borrowck/move_data.rs index b13291b8419..236a1a2835c 100644 --- a/src/librustc_borrowck/borrowck/move_data.rs +++ b/src/librustc_borrowck/borrowck/move_data.rs @@ -442,12 +442,12 @@ impl<'a, 'tcx> MoveData<'tcx> { self.add_assignment_helper(tcx, lp.clone(), assign_id, span, assignee_id, mode); } - pub fn add_assignment_helper(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, - lp: Rc<LoanPath<'tcx>>, - assign_id: ast::NodeId, - span: Span, - assignee_id: ast::NodeId, - mode: euv::MutateMode) { + fn add_assignment_helper(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, + lp: Rc<LoanPath<'tcx>>, + assign_id: ast::NodeId, + span: Span, + assignee_id: ast::NodeId, + mode: euv::MutateMode) { debug!("add_assignment(lp={:?}, assign_id={}, assignee_id={}", lp, assign_id, assignee_id); diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 6b291c69307..179863c16ff 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -429,19 +429,24 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> { let method = self.tcx.tables.borrow().method_map[&method_call]; self.check_method(expr.span, method.def_id); } - hir::ExprStruct(_, ref fields, _) => { + hir::ExprStruct(_, ref expr_fields, _) => { let adt = self.tcx.expr_ty(expr).ty_adt_def().unwrap(); let variant = adt.variant_of_def(self.tcx.expect_def(expr.id)); // RFC 736: ensure all unmentioned fields are visible. // Rather than computing the set of unmentioned fields - // (i.e. `all_fields - fields`), just check them all. - for field in variant.fields.iter() { - let span = if let Some(f) = fields.iter().find(|f| f.name.node == field.name) { - f.span - } else { - expr.span - }; - self.check_field(span, adt, field); + // (i.e. `all_fields - fields`), just check them all, + // unless the ADT is a union, then unmentioned fields + // are not checked. + if adt.adt_kind() == ty::AdtKind::Union { + for expr_field in expr_fields { + self.check_field(expr.span, adt, variant.field_named(expr_field.name.node)); + } + } else { + for field in &variant.fields { + let expr_field = expr_fields.iter().find(|f| f.name.node == field.name); + let span = if let Some(f) = expr_field { f.span } else { expr.span }; + self.check_field(span, adt, field); + } } } hir::ExprPath(..) => { diff --git a/src/librustc_trans/glue.rs b/src/librustc_trans/glue.rs index bb77db8fd69..34c92f334d0 100644 --- a/src/librustc_trans/glue.rs +++ b/src/librustc_trans/glue.rs @@ -265,13 +265,13 @@ pub fn implement_drop_glue<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fcx.finish(bcx, DebugLoc::None); } -fn trans_struct_drop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +fn trans_custom_dtor<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, t: Ty<'tcx>, v0: ValueRef, shallow_drop: bool) -> Block<'blk, 'tcx> { - debug!("trans_struct_drop t: {}", t); + debug!("trans_custom_dtor t: {}", t); let tcx = bcx.tcx(); let mut bcx = bcx; @@ -489,11 +489,11 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, g: DropGlueK } ty::TyStruct(def, _) | ty::TyEnum(def, _) if def.dtor_kind().is_present() && !skip_dtor => { - trans_struct_drop(bcx, t, v0, false) + trans_custom_dtor(bcx, t, v0, false) } ty::TyUnion(def, _) => { if def.dtor_kind().is_present() && !skip_dtor { - trans_struct_drop(bcx, t, v0, true) + trans_custom_dtor(bcx, t, v0, true) } else { bcx } diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 5c19fa2a66c..12fce4b928e 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -718,12 +718,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Report an error if incorrect number of the fields were specified. if kind_name == "union" { - if fields.len() > 1 { - tcx.sess.span_err(span, "union patterns can have at most one field"); + if fields.len() != 1 { + tcx.sess.span_err(span, "union patterns should have exactly one field"); } - if fields.is_empty() && !etc { - tcx.sess.span_err(span, "union patterns without `..` \ - should have at least one field"); + if etc { + tcx.sess.span_err(span, "`..` cannot be used in union patterns"); } } else if !etc { for field in variant.fields diff --git a/src/rt/rust_test_helpers.c b/src/rt/rust_test_helpers.c index d2ebdcca80c..7a04d377608 100644 --- a/src/rt/rust_test_helpers.c +++ b/src/rt/rust_test_helpers.c @@ -247,3 +247,24 @@ double rust_interesting_average(uint64_t n, ...) { int32_t rust_int8_to_int32(int8_t x) { return (int32_t)x; } + +typedef union LARGE_INTEGER { + struct { + uint32_t LowPart; + uint32_t HighPart; + }; + struct { + uint32_t LowPart; + uint32_t HighPart; + } u; + uint64_t QuadPart; +} LARGE_INTEGER; + +LARGE_INTEGER increment_all_parts(LARGE_INTEGER li) { + li.LowPart += 1; + li.HighPart += 1; + li.u.LowPart += 1; + li.u.HighPart += 1; + li.QuadPart += 1; + return li; +} diff --git a/src/test/compile-fail/union-borrow-nested.rs b/src/test/compile-fail/borrowck/borrowck-union-borrow-nested.rs index 19975d79b60..19975d79b60 100644 --- a/src/test/compile-fail/union-borrow-nested.rs +++ b/src/test/compile-fail/borrowck/borrowck-union-borrow-nested.rs diff --git a/src/test/compile-fail/union-borrow.rs b/src/test/compile-fail/borrowck/borrowck-union-borrow.rs index e8989a3c2d4..e8989a3c2d4 100644 --- a/src/test/compile-fail/union-borrow.rs +++ b/src/test/compile-fail/borrowck/borrowck-union-borrow.rs diff --git a/src/test/compile-fail/union-move-assign.rs b/src/test/compile-fail/borrowck/borrowck-union-move-assign.rs index d4d7bc6b0f7..d4d7bc6b0f7 100644 --- a/src/test/compile-fail/union-move-assign.rs +++ b/src/test/compile-fail/borrowck/borrowck-union-move-assign.rs diff --git a/src/test/compile-fail/union-move.rs b/src/test/compile-fail/borrowck/borrowck-union-move.rs index 5320244cf43..5320244cf43 100644 --- a/src/test/compile-fail/union-move.rs +++ b/src/test/compile-fail/borrowck/borrowck-union-move.rs diff --git a/src/test/compile-fail/union-uninitialized.rs b/src/test/compile-fail/borrowck/borrowck-union-uninitialized.rs index 36e062f8464..36e062f8464 100644 --- a/src/test/compile-fail/union-uninitialized.rs +++ b/src/test/compile-fail/borrowck/borrowck-union-uninitialized.rs diff --git a/src/test/compile-fail/privacy/union-field-privacy-1.rs b/src/test/compile-fail/privacy/union-field-privacy-1.rs new file mode 100644 index 00000000000..4924fabafb0 --- /dev/null +++ b/src/test/compile-fail/privacy/union-field-privacy-1.rs @@ -0,0 +1,30 @@ +// 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(pub_restricted)] +#![feature(untagged_unions)] + +mod m { + pub union U { + pub a: u8, + pub(super) b: u8, + c: u8, + } +} + +fn main() { + let u = m::U { a: 0 }; // OK + let u = m::U { b: 0 }; // OK + let u = m::U { c: 0 }; //~ ERROR field `c` of union `m::U` is private + + let m::U { a } = u; // OK + let m::U { b } = u; // OK + let m::U { c } = u; //~ ERROR field `c` of union `m::U` is private +} diff --git a/src/test/compile-fail/privacy/union-field-privacy-2.rs b/src/test/compile-fail/privacy/union-field-privacy-2.rs new file mode 100644 index 00000000000..7151538f412 --- /dev/null +++ b/src/test/compile-fail/privacy/union-field-privacy-2.rs @@ -0,0 +1,28 @@ +// 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(pub_restricted)] +#![feature(untagged_unions)] + +mod m { + pub union U { + pub a: u8, + pub(super) b: u8, + c: u8, + } +} + +fn main() { + let u = m::U { a: 10 }; + + let a = u.a; // OK + let b = u.b; // OK + let c = u.c; //~ ERROR field `c` of struct `m::U` is private +} diff --git a/src/test/compile-fail/union-const-eval.rs b/src/test/compile-fail/union/union-const-eval.rs index b2bf173c59c..b2bf173c59c 100644 --- a/src/test/compile-fail/union-const-eval.rs +++ b/src/test/compile-fail/union/union-const-eval.rs diff --git a/src/test/compile-fail/union-const-pat.rs b/src/test/compile-fail/union/union-const-pat.rs index 3d168980ed2..3d168980ed2 100644 --- a/src/test/compile-fail/union-const-pat.rs +++ b/src/test/compile-fail/union/union-const-pat.rs diff --git a/src/test/compile-fail/union/union-copy.rs b/src/test/compile-fail/union/union-copy.rs new file mode 100644 index 00000000000..6e08ae0074d --- /dev/null +++ b/src/test/compile-fail/union/union-copy.rs @@ -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: u8 +} + +union W { + a: String +} + +impl Clone for U { fn clone(&self) { panic!(); } } +impl Clone for W { fn clone(&self) { panic!(); } } +impl Copy for U {} // OK +impl Copy for W {} //~ ERROR the trait `Copy` may not be implemented for this type + +fn main() {} diff --git a/src/test/compile-fail/union-derive.rs b/src/test/compile-fail/union/union-derive.rs index 0f78e96f640..0f78e96f640 100644 --- a/src/test/compile-fail/union-derive.rs +++ b/src/test/compile-fail/union/union-derive.rs diff --git a/src/test/compile-fail/union-empty.rs b/src/test/compile-fail/union/union-empty.rs index ce5bbf60fee..ce5bbf60fee 100644 --- a/src/test/compile-fail/union-empty.rs +++ b/src/test/compile-fail/union/union-empty.rs diff --git a/src/test/compile-fail/union/union-feature-gate.rs b/src/test/compile-fail/union/union-feature-gate.rs new file mode 100644 index 00000000000..abfc4d90921 --- /dev/null +++ b/src/test/compile-fail/union/union-feature-gate.rs @@ -0,0 +1,15 @@ +// 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. + +union U { //~ ERROR unions are unstable and possibly buggy + a: u8, +} + +fn main() {} diff --git a/src/test/compile-fail/union-fields.rs b/src/test/compile-fail/union/union-fields.rs index 2bd1b8a7b32..a1721dda7de 100644 --- a/src/test/compile-fail/union-fields.rs +++ b/src/test/compile-fail/union/union-fields.rs @@ -24,11 +24,12 @@ fn main() { let u = U { ..u }; //~ ERROR union expressions should have exactly one field //~^ ERROR functional record update syntax requires a struct - let U {} = u; //~ ERROR union patterns without `..` should have at least one field + let U {} = u; //~ ERROR union patterns should have exactly one field let U { a } = u; // OK - let U { a, b } = u; //~ ERROR union patterns can have at most one field - let U { a, b, c } = u; //~ ERROR union patterns can have at most one field + let U { a, b } = u; //~ ERROR union patterns should have exactly one field + let U { a, b, c } = u; //~ ERROR union patterns should have exactly one field //~^ ERROR union `U` does not have a field named `c` - let U { .. } = u; // OK - let U { a, .. } = u; // OK + let U { .. } = u; //~ ERROR union patterns should have exactly one field + //~^ ERROR `..` cannot be used in union patterns + let U { a, .. } = u; //~ ERROR `..` cannot be used in union patterns } diff --git a/src/test/compile-fail/union/union-generic.rs b/src/test/compile-fail/union/union-generic.rs new file mode 100644 index 00000000000..e6586b0fb7f --- /dev/null +++ b/src/test/compile-fail/union/union-generic.rs @@ -0,0 +1,24 @@ +// 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::rc::Rc; + +union U<T: Copy> { + a: T +} + +fn main() { + let u = U { a: Rc::new(0u32) }; + //~^ ERROR the trait bound `std::rc::Rc<u32>: std::marker::Copy` is not satisfied + let u = U::<Rc<u32>> { a: Default::default() }; + //~^ ERROR the trait bound `std::rc::Rc<u32>: std::marker::Copy` is not satisfied +} diff --git a/src/test/compile-fail/union-nonrepresentable.rs b/src/test/compile-fail/union/union-nonrepresentable.rs index cb4683c2a0e..cb4683c2a0e 100644 --- a/src/test/compile-fail/union-nonrepresentable.rs +++ b/src/test/compile-fail/union/union-nonrepresentable.rs diff --git a/src/test/compile-fail/union/union-repr-c.rs b/src/test/compile-fail/union/union-repr-c.rs new file mode 100644 index 00000000000..d7dfb126c93 --- /dev/null +++ b/src/test/compile-fail/union/union-repr-c.rs @@ -0,0 +1,29 @@ +// 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)] +#![allow(unused)] +#![deny(improper_ctypes)] + +#[repr(C)] +union U { + a: u8, +} + +union W { + a: u8, +} + +extern "C" { + static FOREIGN1: U; // OK + static FOREIGN2: W; //~ ERROR found union without foreign-function-safe representation +} + +fn main() {} diff --git a/src/test/compile-fail/union/union-suggest-field.rs b/src/test/compile-fail/union/union-suggest-field.rs new file mode 100644 index 00000000000..b05e9b6e273 --- /dev/null +++ b/src/test/compile-fail/union/union-suggest-field.rs @@ -0,0 +1,29 @@ +// 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 { + principal: u8, +} + +impl U { + fn calculate(&self) {} +} + +fn main() { + let u = U { principle: 0 }; //~ ERROR union `U` has no field named `principle` + //~^ HELP did you mean `principal`? + let w = u.principial; //~ ERROR attempted access of field `principial` on type `U` + //~^ HELP did you mean `principal`? + + let y = u.calculate; //~ ERROR attempted to take value of method `calculate` on type `U` + //~^ HELP maybe a `()` to call it is missing? +} diff --git a/src/test/compile-fail/union-unsafe.rs b/src/test/compile-fail/union/union-unsafe.rs index 762ac5d8751..97e1ec2cba8 100644 --- a/src/test/compile-fail/union-unsafe.rs +++ b/src/test/compile-fail/union/union-unsafe.rs @@ -15,9 +15,10 @@ union U { } fn main() { - let u = U { a: 10 }; // OK + let mut u = U { a: 10 }; // OK let a = u.a; //~ ERROR access to union field requires unsafe function or block + u.a = 11; //~ ERROR access to union field requires unsafe function or block let U { a } = u; //~ ERROR matching on union field requires unsafe function or block - if let U { a: 11 } = u {} //~ ERROR matching on union field requires unsafe function or block - let U { .. } = u; // OK + if let U { a: 12 } = u {} //~ ERROR matching on union field requires unsafe function or block + // let U { .. } = u; // OK } diff --git a/src/test/compile-fail/union-unsized.rs b/src/test/compile-fail/union/union-unsized.rs index 381122406d7..a238eaf0525 100644 --- a/src/test/compile-fail/union-unsized.rs +++ b/src/test/compile-fail/union/union-unsized.rs @@ -12,6 +12,12 @@ union U { a: str, //~ ERROR the trait bound `str: std::marker::Sized` is not satisfied + b: u8, +} + +union W { + a: u8, + b: str, //~ ERROR the trait bound `str: std::marker::Sized` is not satisfied } fn main() {} diff --git a/src/test/compile-fail/union-with-drop-fields-lint.rs b/src/test/compile-fail/union/union-with-drop-fields-lint.rs index 87a72efbe08..87a72efbe08 100644 --- a/src/test/compile-fail/union-with-drop-fields-lint.rs +++ b/src/test/compile-fail/union/union-with-drop-fields-lint.rs diff --git a/src/test/run-pass/auxiliary/union.rs b/src/test/run-pass/union/auxiliary/union.rs index dc0ca7c81c0..dc0ca7c81c0 100644 --- a/src/test/run-pass/auxiliary/union.rs +++ b/src/test/run-pass/union/auxiliary/union.rs diff --git a/src/test/run-pass/union-backcomp.rs b/src/test/run-pass/union/union-backcomp.rs index c1210dd6212..9394b618ddf 100644 --- a/src/test/run-pass/union-backcomp.rs +++ b/src/test/run-pass/union/union-backcomp.rs @@ -10,7 +10,11 @@ #![feature(untagged_unions)] +fn union() {} + fn main() { + union(); + let union = 10; union; diff --git a/src/test/run-pass/union-basic.rs b/src/test/run-pass/union/union-basic.rs index 1651aa901b9..1651aa901b9 100644 --- a/src/test/run-pass/union-basic.rs +++ b/src/test/run-pass/union/union-basic.rs diff --git a/src/test/run-pass/union/union-c-interop.rs b/src/test/run-pass/union/union-c-interop.rs new file mode 100644 index 00000000000..a9f97620ebd --- /dev/null +++ b/src/test/run-pass/union/union-c-interop.rs @@ -0,0 +1,47 @@ +// 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)] + +#[derive(Copy)] +#[repr(C)] +struct LARGE_INTEGER_U { + LowPart: u32, + HighPart: u32, +} + +#[derive(Copy)] +#[repr(C)] +union LARGE_INTEGER { + __unnamed__: LARGE_INTEGER_U, + u: LARGE_INTEGER_U, + QuadPart: u64, +} + +impl Clone for LARGE_INTEGER_U { fn clone(&self) -> Self { *self } } +impl Clone for LARGE_INTEGER { fn clone(&self) -> Self { *self } } + +#[link(name = "rust_test_helpers")] +extern "C" { + fn increment_all_parts(_: LARGE_INTEGER) -> LARGE_INTEGER; +} + +fn main() { + unsafe { + let mut li = LARGE_INTEGER { QuadPart: 0 }; + let li_c = increment_all_parts(li); + li.__unnamed__.LowPart += 1; + li.__unnamed__.HighPart += 1; + li.u.LowPart += 1; + li.u.HighPart += 1; + li.QuadPart += 1; + assert_eq!(li.QuadPart, li_c.QuadPart); + } +} diff --git a/src/test/run-pass/union-const-trans.rs b/src/test/run-pass/union/union-const-trans.rs index bdae1a0eaf8..bdae1a0eaf8 100644 --- a/src/test/run-pass/union-const-trans.rs +++ b/src/test/run-pass/union/union-const-trans.rs diff --git a/src/test/run-pass/union-derive.rs b/src/test/run-pass/union/union-derive.rs index b71c23990a4..b71c23990a4 100644 --- a/src/test/run-pass/union-derive.rs +++ b/src/test/run-pass/union/union-derive.rs diff --git a/src/test/run-pass/union-drop-assign.rs b/src/test/run-pass/union/union-drop-assign.rs index 0da68e43f32..0da68e43f32 100644 --- a/src/test/run-pass/union-drop-assign.rs +++ b/src/test/run-pass/union/union-drop-assign.rs diff --git a/src/test/run-pass/union-drop.rs b/src/test/run-pass/union/union-drop.rs index 2ca68dc3b6e..2ca68dc3b6e 100644 --- a/src/test/run-pass/union-drop.rs +++ b/src/test/run-pass/union/union-drop.rs diff --git a/src/test/run-pass/union/union-generic.rs b/src/test/run-pass/union/union-generic.rs new file mode 100644 index 00000000000..9293805edbf --- /dev/null +++ b/src/test/run-pass/union/union-generic.rs @@ -0,0 +1,43 @@ +// 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 MaybeItem<T: Iterator> { + elem: T::Item, + none: (), +} + +union U<A, B> { + a: A, + b: B, +} + +unsafe fn union_transmute<A, B>(a: A) -> B { + U { a: a }.b +} + +fn main() { + unsafe { + let u = U::<String, Vec<u8>> { a: String::from("abcd") }; + + assert_eq!(u.b.len(), 4); + assert_eq!(u.b[0], b'a'); + + let b = union_transmute::<(u8, u8), u16>((1, 1)); + assert_eq!(b, (1 << 8) + 1); + + let v: Vec<u8> = vec![1, 2, 3]; + let mut i = v.iter(); + i.next(); + let mi = MaybeItem::<std::slice::Iter<_>> { elem: i.next().unwrap() }; + assert_eq!(*mi.elem, 2); + } +} diff --git a/src/test/compile-fail/union-field-privacy.rs b/src/test/run-pass/union/union-inherent-method.rs index d1f2bbbc3d0..adea27bd254 100644 --- a/src/test/compile-fail/union-field-privacy.rs +++ b/src/test/run-pass/union/union-inherent-method.rs @@ -10,12 +10,15 @@ #![feature(untagged_unions)] -mod m { - pub union U { - a: u8 - } +union U { + a: u8, +} + +impl U { + fn method(&self) -> u8 { unsafe { self.a } } } fn main() { - let u = m::U { a: 0 }; //~ ERROR field `a` of union `m::U` is private + let u = U { a: 10 }; + assert_eq!(u.method(), 10); } diff --git a/src/test/run-pass/union/union-macro.rs b/src/test/run-pass/union/union-macro.rs new file mode 100644 index 00000000000..a23fbc3be9e --- /dev/null +++ b/src/test/run-pass/union/union-macro.rs @@ -0,0 +1,33 @@ +// 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)] + +macro_rules! duplicate { + ($i: item) => { + mod m1 { + $i + } + mod m2 { + $i + } + } +} + +duplicate! { + pub union U { + pub a: u8 + } +} + +fn main() { + let u1 = m1::U { a: 0 }; + let u2 = m2::U { a: 0 }; +} diff --git a/src/test/run-pass/union/union-overwrite.rs b/src/test/run-pass/union/union-overwrite.rs new file mode 100644 index 00000000000..9389a6237bc --- /dev/null +++ b/src/test/run-pass/union/union-overwrite.rs @@ -0,0 +1,80 @@ +// 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)] + +#[repr(C)] +struct Pair<T, U>(T, U); +#[repr(C)] +struct Triple<T>(T, T, T); + +#[repr(C)] +union U<A, B> { + a: Pair<A, A>, + b: B, +} + +#[repr(C)] +union W<A, B> { + a: A, + b: B, +} + +#[cfg(target_endian = "little")] +unsafe fn check() { + let mut u = U::<u8, u16> { b: 0xDE_DE }; + u.a.0 = 0xBE; + assert_eq!(u.b, 0xDE_BE); + + let mut u = U::<u16, u32> { b: 0xDEAD_DEAD }; + u.a.0 = 0xBEEF; + assert_eq!(u.b, 0xDEAD_BEEF); + + let mut u = U::<u32, u64> { b: 0xDEADBEEF_DEADBEEF }; + u.a.0 = 0xBAADF00D; + assert_eq!(u.b, 0xDEADBEEF_BAADF00D); + + let mut w = W::<Pair<Triple<u8>, u8>, u32> { b: 0xDEAD_DEAD }; + w.a.0 = Triple(0, 0, 0); + assert_eq!(w.b, 0xDE00_0000); + + let mut w = W::<Pair<u8, Triple<u8>>, u32> { b: 0xDEAD_DEAD }; + w.a.1 = Triple(0, 0, 0); + assert_eq!(w.b, 0x0000_00AD); +} + +#[cfg(target_endian = "big")] +unsafe fn check() { + let mut u = U::<u8, u16> { b: 0xDE_DE }; + u.a.0 = 0xBE; + assert_eq!(u.b, 0xBE_DE); + + let mut u = U::<u16, u32> { b: 0xDEAD_DEAD }; + u.a.0 = 0xBEEF; + assert_eq!(u.b, 0xBEEF_DEAD); + + let mut u = U::<u32, u64> { b: 0xDEADBEEF_DEADBEEF }; + u.a.0 = 0xBAADF00D; + assert_eq!(u.b, 0xBAADF00D_DEADBEEF); + + let mut w = W::<Pair<Triple<u8>, u8>, u32> { b: 0xDEAD_DEAD }; + w.a.0 = Triple(0, 0, 0); + assert_eq!(w.b, 0x0000_00AD); + + let mut w = W::<Pair<u8, Triple<u8>>, u32> { b: 0xDEAD_DEAD }; + w.a.1 = Triple(0, 0, 0); + assert_eq!(w.b, 0xDE00_0000); +} + +fn main() { + unsafe { + check(); + } +} diff --git a/src/test/run-pass/union-packed.rs b/src/test/run-pass/union/union-packed.rs index b1650ae3a7c..6a61280823e 100644 --- a/src/test/run-pass/union-packed.rs +++ b/src/test/run-pass/union/union-packed.rs @@ -71,4 +71,34 @@ fn main() { assert_eq!(align_of::<Up>(), 1); assert_eq!(align_of_val(&up), 1); assert_eq!(align_of_val(&CUP), 1); + + hybrid::check_hybrid(); +} + +mod hybrid { + use std::mem::size_of; + + #[repr(packed)] + struct S1 { + a: u16, + b: u8, + } + + #[repr(packed)] + union U { + s: S1, + c: u16, + } + + #[repr(packed)] + struct S2 { + d: u8, + u: U, + } + + pub fn check_hybrid() { + assert_eq!(size_of::<S1>(), 3); + assert_eq!(size_of::<U>(), 3); + assert_eq!(size_of::<S2>(), 4); + } } diff --git a/src/test/run-pass/union-pat-refutability.rs b/src/test/run-pass/union/union-pat-refutability.rs index e6144f35f1d..e6144f35f1d 100644 --- a/src/test/run-pass/union-pat-refutability.rs +++ b/src/test/run-pass/union/union-pat-refutability.rs diff --git a/src/test/run-pass/union/union-trait-impl.rs b/src/test/run-pass/union/union-trait-impl.rs new file mode 100644 index 00000000000..a5a2be0133a --- /dev/null +++ b/src/test/run-pass/union/union-trait-impl.rs @@ -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)] + +use std::fmt; + +union U { + a: u8 +} + +impl fmt::Display for U { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + unsafe { write!(f, "Oh hai {}", self.a) } + } +} + +fn main() { + assert_eq!(U { a: 2 }.to_string(), "Oh hai 2"); +} diff --git a/src/test/run-pass/union-transmute.rs b/src/test/run-pass/union/union-transmute.rs index 4eb66268ab8..4eb66268ab8 100644 --- a/src/test/run-pass/union-transmute.rs +++ b/src/test/run-pass/union/union-transmute.rs diff --git a/src/test/run-pass/union/union-with-drop-fields-lint.rs b/src/test/run-pass/union/union-with-drop-fields-lint.rs new file mode 100644 index 00000000000..5a1424830d0 --- /dev/null +++ b/src/test/run-pass/union/union-with-drop-fields-lint.rs @@ -0,0 +1,42 @@ +// 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. + +// ignore-pretty + +#![feature(untagged_unions)] +#![allow(dead_code)] +#![allow(unions_with_drop_fields)] + +union U { + a: u8, // OK +} + +union W { + a: String, // OK + b: String, // OK +} + +struct S(String); + +// `S` doesn't implement `Drop` trait, but still has non-trivial destructor +union Y { + a: S, // OK +} + +// We don't know if `T` is trivially-destructable or not until trans +union J<T> { + a: T, // OK +} + +union H<T: Copy> { + a: T, // OK +} + +fn main() {} diff --git a/src/test/run-pass/union-xcrate.rs b/src/test/run-pass/union/union-xcrate.rs index 2a76c96ef25..2a76c96ef25 100644 --- a/src/test/run-pass/union-xcrate.rs +++ b/src/test/run-pass/union/union-xcrate.rs |
