diff options
| author | bors <bors@rust-lang.org> | 2017-04-14 16:28:14 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2017-04-14 16:28:14 +0000 |
| commit | ba377982a3fde98a3cac02493c16dc623b02a421 (patch) | |
| tree | 4ec1531021869ff497c0ef77158b3acac6b645a6 | |
| parent | 5637ed756632ded9e458b82a23cc1dddbb57c51f (diff) | |
| parent | ad58d37c56c4121182b37fb9062c681d3d314c22 (diff) | |
| download | rust-ba377982a3fde98a3cac02493c16dc623b02a421.tar.gz rust-ba377982a3fde98a3cac02493c16dc623b02a421.zip | |
Auto merge of #41153 - petrochenkov:umove, r=pnkfelix
Fix move checking for nested union fields Fixes https://github.com/rust-lang/rust/issues/41126 r? @arielb1
| -rw-r--r-- | src/librustc_borrowck/borrowck/move_data.rs | 30 | ||||
| -rw-r--r-- | src/test/compile-fail/union/union-borrow-move-parent-sibling.rs | 57 |
2 files changed, 72 insertions, 15 deletions
diff --git a/src/librustc_borrowck/borrowck/move_data.rs b/src/librustc_borrowck/borrowck/move_data.rs index 2047a58f8ed..5012969eef9 100644 --- a/src/librustc_borrowck/borrowck/move_data.rs +++ b/src/librustc_borrowck/borrowck/move_data.rs @@ -362,31 +362,31 @@ impl<'a, 'tcx> MoveData<'tcx> { /// Adds a new move entry for a move of `lp` that occurs at location `id` with kind `kind`. pub fn add_move(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, - lp: Rc<LoanPath<'tcx>>, + orig_lp: Rc<LoanPath<'tcx>>, id: ast::NodeId, kind: MoveKind) { - // Moving one union field automatically moves all its fields. - if let LpExtend(ref base_lp, mutbl, LpInterior(opt_variant_id, interior)) = lp.kind { - if let ty::TyAdt(adt_def, _) = base_lp.ty.sty { + // Moving one union field automatically moves all its fields. Also move siblings of + // all parent union fields, moves do not propagate upwards automatically. + let mut lp = orig_lp.clone(); + while let LpExtend(ref base_lp, mutbl, lp_elem) = lp.clone().kind { + if let (&ty::TyAdt(adt_def, _), LpInterior(opt_variant_id, interior)) + = (&base_lp.ty.sty, lp_elem) { if adt_def.is_union() { for field in &adt_def.struct_variant().fields { let field = InteriorKind::InteriorField(mc::NamedField(field.name)); - let field_ty = if field == interior { - lp.ty - } else { - tcx.types.err // Doesn't matter - }; - let sibling_lp_kind = LpExtend(base_lp.clone(), mutbl, - LpInterior(opt_variant_id, field)); - let sibling_lp = Rc::new(LoanPath::new(sibling_lp_kind, field_ty)); - self.add_move_helper(tcx, sibling_lp, id, kind); + if field != interior { + let sibling_lp_kind = + LpExtend(base_lp.clone(), mutbl, LpInterior(opt_variant_id, field)); + let sibling_lp = Rc::new(LoanPath::new(sibling_lp_kind, tcx.types.err)); + self.add_move_helper(tcx, sibling_lp, id, kind); + } } - return; } } + lp = base_lp.clone(); } - self.add_move_helper(tcx, lp.clone(), id, kind); + self.add_move_helper(tcx, orig_lp.clone(), id, kind); } fn add_move_helper(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, diff --git a/src/test/compile-fail/union/union-borrow-move-parent-sibling.rs b/src/test/compile-fail/union/union-borrow-move-parent-sibling.rs new file mode 100644 index 00000000000..5f504feabb2 --- /dev/null +++ b/src/test/compile-fail/union/union-borrow-move-parent-sibling.rs @@ -0,0 +1,57 @@ +// Copyright 2017 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)] + +#[allow(unions_with_drop_fields)] +union U { + x: ((Vec<u8>, Vec<u8>), Vec<u8>), + y: Box<Vec<u8>>, +} + +unsafe fn parent_sibling_borrow() { + let mut u = U { x: ((Vec::new(), Vec::new()), Vec::new()) }; + let a = &mut u.x.0; + let a = &u.y; //~ ERROR cannot borrow `u.y` +} + +unsafe fn parent_sibling_move() { + let u = U { x: ((Vec::new(), Vec::new()), Vec::new()) }; + let a = u.x.0; + let a = u.y; //~ ERROR use of moved value: `u.y` +} + +unsafe fn grandparent_sibling_borrow() { + let mut u = U { x: ((Vec::new(), Vec::new()), Vec::new()) }; + let a = &mut (u.x.0).0; + let a = &u.y; //~ ERROR cannot borrow `u.y` +} + +unsafe fn grandparent_sibling_move() { + let u = U { x: ((Vec::new(), Vec::new()), Vec::new()) }; + let a = (u.x.0).0; + let a = u.y; //~ ERROR use of moved value: `u.y` +} + +unsafe fn deref_sibling_borrow() { + let mut u = U { y: Box::default() }; + let a = &mut *u.y; + let a = &u.x; //~ ERROR cannot borrow `u` (via `u.x`) +} + +unsafe fn deref_sibling_move() { + let u = U { x: ((Vec::new(), Vec::new()), Vec::new()) }; + let a = *u.y; + let a = u.x; //~ ERROR use of moved value: `u.x` +} + + +fn main() {} |
