Skip to content

Commit 93067ca

Browse files
committed
Address comments and add requested tests
1 parent e67c228 commit 93067ca

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+582
-61
lines changed

src/librustc/middle/expr_use_visitor.rs

+20-23
Original file line numberDiff line numberDiff line change
@@ -671,31 +671,28 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
671671

672672
// Select just those fields of the `with`
673673
// expression that will actually be used
674-
match with_cmt.ty.sty {
675-
ty::TyStruct(def, substs) => {
676-
// Consume those fields of the with expression that are needed.
677-
for with_field in &def.struct_variant().fields {
678-
if !contains_field_named(with_field, fields) {
679-
let cmt_field = self.mc.cat_field(
680-
&*with_expr,
681-
with_cmt.clone(),
682-
with_field.name,
683-
with_field.ty(self.tcx(), substs)
684-
);
685-
self.delegate_consume(with_expr.id, with_expr.span, cmt_field);
686-
}
674+
if let ty::TyStruct(def, substs) = with_cmt.ty.sty {
675+
// Consume those fields of the with expression that are needed.
676+
for with_field in &def.struct_variant().fields {
677+
if !contains_field_named(with_field, fields) {
678+
let cmt_field = self.mc.cat_field(
679+
&*with_expr,
680+
with_cmt.clone(),
681+
with_field.name,
682+
with_field.ty(self.tcx(), substs)
683+
);
684+
self.delegate_consume(with_expr.id, with_expr.span, cmt_field);
687685
}
688686
}
689-
_ => {
690-
// the base expression should always evaluate to a
691-
// struct; however, when EUV is run during typeck, it
692-
// may not. This will generate an error earlier in typeck,
693-
// so we can just ignore it.
694-
if !self.tcx().sess.has_errors() {
695-
span_bug!(
696-
with_expr.span,
697-
"with expression doesn't evaluate to a struct");
698-
}
687+
} else {
688+
// the base expression should always evaluate to a
689+
// struct; however, when EUV is run during typeck, it
690+
// may not. This will generate an error earlier in typeck,
691+
// so we can just ignore it.
692+
if !self.tcx().sess.has_errors() {
693+
span_bug!(
694+
with_expr.span,
695+
"with expression doesn't evaluate to a struct");
699696
}
700697
}
701698

src/librustc/ty/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1423,7 +1423,7 @@ bitflags! {
14231423
const IS_PHANTOM_DATA = 1 << 3,
14241424
const IS_SIMD = 1 << 4,
14251425
const IS_FUNDAMENTAL = 1 << 5,
1426-
const IS_UNION = 1 << 7,
1426+
const IS_UNION = 1 << 6,
14271427
}
14281428
}
14291429

src/librustc_borrowck/borrowck/gather_loans/restrictions.rs

+1
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ impl<'a, 'tcx> RestrictionsContext<'a, 'tcx> {
102102
let interior = interior.cleaned();
103103
let base_ty = cmt_base.ty;
104104
let result = self.restrict(cmt_base);
105+
// Borrowing one union field automatically borrows all its fields.
105106
if let ty::TyUnion(ref adt_def, _) = base_ty.sty {
106107
match result {
107108
RestrictionResult::Safe => RestrictionResult::Safe,

src/librustc_borrowck/borrowck/move_data.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -442,12 +442,12 @@ impl<'a, 'tcx> MoveData<'tcx> {
442442
self.add_assignment_helper(tcx, lp.clone(), assign_id, span, assignee_id, mode);
443443
}
444444

445-
pub fn add_assignment_helper(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
446-
lp: Rc<LoanPath<'tcx>>,
447-
assign_id: ast::NodeId,
448-
span: Span,
449-
assignee_id: ast::NodeId,
450-
mode: euv::MutateMode) {
445+
fn add_assignment_helper(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
446+
lp: Rc<LoanPath<'tcx>>,
447+
assign_id: ast::NodeId,
448+
span: Span,
449+
assignee_id: ast::NodeId,
450+
mode: euv::MutateMode) {
451451
debug!("add_assignment(lp={:?}, assign_id={}, assignee_id={}",
452452
lp, assign_id, assignee_id);
453453

src/librustc_privacy/lib.rs

+14-9
Original file line numberDiff line numberDiff line change
@@ -429,19 +429,24 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
429429
let method = self.tcx.tables.borrow().method_map[&method_call];
430430
self.check_method(expr.span, method.def_id);
431431
}
432-
hir::ExprStruct(_, ref fields, _) => {
432+
hir::ExprStruct(_, ref expr_fields, _) => {
433433
let adt = self.tcx.expr_ty(expr).ty_adt_def().unwrap();
434434
let variant = adt.variant_of_def(self.tcx.expect_def(expr.id));
435435
// RFC 736: ensure all unmentioned fields are visible.
436436
// Rather than computing the set of unmentioned fields
437-
// (i.e. `all_fields - fields`), just check them all.
438-
for field in variant.fields.iter() {
439-
let span = if let Some(f) = fields.iter().find(|f| f.name.node == field.name) {
440-
f.span
441-
} else {
442-
expr.span
443-
};
444-
self.check_field(span, adt, field);
437+
// (i.e. `all_fields - fields`), just check them all,
438+
// unless the ADT is a union, then unmentioned fields
439+
// are not checked.
440+
if adt.adt_kind() == ty::AdtKind::Union {
441+
for expr_field in expr_fields {
442+
self.check_field(expr.span, adt, variant.field_named(expr_field.name.node));
443+
}
444+
} else {
445+
for field in &variant.fields {
446+
let expr_field = expr_fields.iter().find(|f| f.name.node == field.name);
447+
let span = if let Some(f) = expr_field { f.span } else { expr.span };
448+
self.check_field(span, adt, field);
449+
}
445450
}
446451
}
447452
hir::ExprPath(..) => {

src/librustc_trans/glue.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -265,13 +265,13 @@ pub fn implement_drop_glue<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
265265
fcx.finish(bcx, DebugLoc::None);
266266
}
267267

268-
fn trans_struct_drop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
268+
fn trans_custom_dtor<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
269269
t: Ty<'tcx>,
270270
v0: ValueRef,
271271
shallow_drop: bool)
272272
-> Block<'blk, 'tcx>
273273
{
274-
debug!("trans_struct_drop t: {}", t);
274+
debug!("trans_custom_dtor t: {}", t);
275275
let tcx = bcx.tcx();
276276
let mut bcx = bcx;
277277

@@ -489,11 +489,11 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, g: DropGlueK
489489
}
490490
ty::TyStruct(def, _) | ty::TyEnum(def, _)
491491
if def.dtor_kind().is_present() && !skip_dtor => {
492-
trans_struct_drop(bcx, t, v0, false)
492+
trans_custom_dtor(bcx, t, v0, false)
493493
}
494494
ty::TyUnion(def, _) => {
495495
if def.dtor_kind().is_present() && !skip_dtor {
496-
trans_struct_drop(bcx, t, v0, true)
496+
trans_custom_dtor(bcx, t, v0, true)
497497
} else {
498498
bcx
499499
}

src/librustc_typeck/check/_match.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -718,12 +718,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
718718

719719
// Report an error if incorrect number of the fields were specified.
720720
if kind_name == "union" {
721-
if fields.len() > 1 {
722-
tcx.sess.span_err(span, "union patterns can have at most one field");
721+
if fields.len() != 1 {
722+
tcx.sess.span_err(span, "union patterns should have exactly one field");
723723
}
724-
if fields.is_empty() && !etc {
725-
tcx.sess.span_err(span, "union patterns without `..` \
726-
should have at least one field");
724+
if etc {
725+
tcx.sess.span_err(span, "`..` cannot be used in union patterns");
727726
}
728727
} else if !etc {
729728
for field in variant.fields

src/rt/rust_test_helpers.c

+21
Original file line numberDiff line numberDiff line change
@@ -247,3 +247,24 @@ double rust_interesting_average(uint64_t n, ...) {
247247
int32_t rust_int8_to_int32(int8_t x) {
248248
return (int32_t)x;
249249
}
250+
251+
typedef union LARGE_INTEGER {
252+
struct {
253+
uint32_t LowPart;
254+
uint32_t HighPart;
255+
};
256+
struct {
257+
uint32_t LowPart;
258+
uint32_t HighPart;
259+
} u;
260+
uint64_t QuadPart;
261+
} LARGE_INTEGER;
262+
263+
LARGE_INTEGER increment_all_parts(LARGE_INTEGER li) {
264+
li.LowPart += 1;
265+
li.HighPart += 1;
266+
li.u.LowPart += 1;
267+
li.u.HighPart += 1;
268+
li.QuadPart += 1;
269+
return li;
270+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(pub_restricted)]
12+
#![feature(untagged_unions)]
13+
14+
mod m {
15+
pub union U {
16+
pub a: u8,
17+
pub(super) b: u8,
18+
c: u8,
19+
}
20+
}
21+
22+
fn main() {
23+
let u = m::U { a: 0 }; // OK
24+
let u = m::U { b: 0 }; // OK
25+
let u = m::U { c: 0 }; //~ ERROR field `c` of union `m::U` is private
26+
27+
let m::U { a } = u; // OK
28+
let m::U { b } = u; // OK
29+
let m::U { c } = u; //~ ERROR field `c` of union `m::U` is private
30+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(pub_restricted)]
12+
#![feature(untagged_unions)]
13+
14+
mod m {
15+
pub union U {
16+
pub a: u8,
17+
pub(super) b: u8,
18+
c: u8,
19+
}
20+
}
21+
22+
fn main() {
23+
let u = m::U { a: 10 };
24+
25+
let a = u.a; // OK
26+
let b = u.b; // OK
27+
let c = u.c; //~ ERROR field `c` of struct `m::U` is private
28+
}
+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(untagged_unions)]
12+
13+
union U {
14+
a: u8
15+
}
16+
17+
union W {
18+
a: String
19+
}
20+
21+
impl Clone for U { fn clone(&self) { panic!(); } }
22+
impl Clone for W { fn clone(&self) { panic!(); } }
23+
impl Copy for U {} // OK
24+
impl Copy for W {} //~ ERROR the trait `Copy` may not be implemented for this type
25+
26+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
union U { //~ ERROR unions are unstable and possibly buggy
12+
a: u8,
13+
}
14+
15+
fn main() {}

src/test/compile-fail/union-fields.rs renamed to src/test/compile-fail/union/union-fields.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,12 @@ fn main() {
2424
let u = U { ..u }; //~ ERROR union expressions should have exactly one field
2525
//~^ ERROR functional record update syntax requires a struct
2626

27-
let U {} = u; //~ ERROR union patterns without `..` should have at least one field
27+
let U {} = u; //~ ERROR union patterns should have exactly one field
2828
let U { a } = u; // OK
29-
let U { a, b } = u; //~ ERROR union patterns can have at most one field
30-
let U { a, b, c } = u; //~ ERROR union patterns can have at most one field
29+
let U { a, b } = u; //~ ERROR union patterns should have exactly one field
30+
let U { a, b, c } = u; //~ ERROR union patterns should have exactly one field
3131
//~^ ERROR union `U` does not have a field named `c`
32-
let U { .. } = u; // OK
33-
let U { a, .. } = u; // OK
32+
let U { .. } = u; //~ ERROR union patterns should have exactly one field
33+
//~^ ERROR `..` cannot be used in union patterns
34+
let U { a, .. } = u; //~ ERROR `..` cannot be used in union patterns
3435
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(untagged_unions)]
12+
13+
use std::rc::Rc;
14+
15+
union U<T: Copy> {
16+
a: T
17+
}
18+
19+
fn main() {
20+
let u = U { a: Rc::new(0u32) };
21+
//~^ ERROR the trait bound `std::rc::Rc<u32>: std::marker::Copy` is not satisfied
22+
let u = U::<Rc<u32>> { a: Default::default() };
23+
//~^ ERROR the trait bound `std::rc::Rc<u32>: std::marker::Copy` is not satisfied
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(untagged_unions)]
12+
#![allow(unused)]
13+
#![deny(improper_ctypes)]
14+
15+
#[repr(C)]
16+
union U {
17+
a: u8,
18+
}
19+
20+
union W {
21+
a: u8,
22+
}
23+
24+
extern "C" {
25+
static FOREIGN1: U; // OK
26+
static FOREIGN2: W; //~ ERROR found union without foreign-function-safe representation
27+
}
28+
29+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(untagged_unions)]
12+
13+
union U {
14+
principal: u8,
15+
}
16+
17+
impl U {
18+
fn calculate(&self) {}
19+
}
20+
21+
fn main() {
22+
let u = U { principle: 0 }; //~ ERROR union `U` has no field named `principle`
23+
//~^ HELP did you mean `principal`?
24+
let w = u.principial; //~ ERROR attempted access of field `principial` on type `U`
25+
//~^ HELP did you mean `principal`?
26+
27+
let y = u.calculate; //~ ERROR attempted to take value of method `calculate` on type `U`
28+
//~^ HELP maybe a `()` to call it is missing?
29+
}

0 commit comments

Comments
 (0)