mirror of
https://github.com/rust-lang/rust.git
synced 2024-10-31 14:31:55 +00:00
Address comments and add requested tests
This commit is contained in:
parent
e67c2282af
commit
93067ca089
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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(..) => {
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
30
src/test/compile-fail/privacy/union-field-privacy-1.rs
Normal file
30
src/test/compile-fail/privacy/union-field-privacy-1.rs
Normal file
@ -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
|
||||
}
|
28
src/test/compile-fail/privacy/union-field-privacy-2.rs
Normal file
28
src/test/compile-fail/privacy/union-field-privacy-2.rs
Normal file
@ -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
|
||||
}
|
26
src/test/compile-fail/union/union-copy.rs
Normal file
26
src/test/compile-fail/union/union-copy.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: 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() {}
|
15
src/test/compile-fail/union/union-feature-gate.rs
Normal file
15
src/test/compile-fail/union/union-feature-gate.rs
Normal file
@ -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() {}
|
@ -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
|
||||
}
|
24
src/test/compile-fail/union/union-generic.rs
Normal file
24
src/test/compile-fail/union/union-generic.rs
Normal file
@ -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
|
||||
}
|
29
src/test/compile-fail/union/union-repr-c.rs
Normal file
29
src/test/compile-fail/union/union-repr-c.rs
Normal file
@ -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() {}
|
29
src/test/compile-fail/union/union-suggest-field.rs
Normal file
29
src/test/compile-fail/union/union-suggest-field.rs
Normal file
@ -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?
|
||||
}
|
@ -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
|
||||
}
|
@ -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() {}
|
@ -10,7 +10,11 @@
|
||||
|
||||
#![feature(untagged_unions)]
|
||||
|
||||
fn union() {}
|
||||
|
||||
fn main() {
|
||||
union();
|
||||
|
||||
let union = 10;
|
||||
|
||||
union;
|
47
src/test/run-pass/union/union-c-interop.rs
Normal file
47
src/test/run-pass/union/union-c-interop.rs
Normal file
@ -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);
|
||||
}
|
||||
}
|
43
src/test/run-pass/union/union-generic.rs
Normal file
43
src/test/run-pass/union/union-generic.rs
Normal file
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
33
src/test/run-pass/union/union-macro.rs
Normal file
33
src/test/run-pass/union/union-macro.rs
Normal file
@ -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 };
|
||||
}
|
80
src/test/run-pass/union/union-overwrite.rs
Normal file
80
src/test/run-pass/union/union-overwrite.rs
Normal file
@ -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();
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
27
src/test/run-pass/union/union-trait-impl.rs
Normal file
27
src/test/run-pass/union/union-trait-impl.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)]
|
||||
|
||||
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");
|
||||
}
|
42
src/test/run-pass/union/union-with-drop-fields-lint.rs
Normal file
42
src/test/run-pass/union/union-with-drop-fields-lint.rs
Normal file
@ -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() {}
|
Loading…
Reference in New Issue
Block a user