From bdd9ee3cc7f49008fd5d0ea11c16d681910d291e Mon Sep 17 00:00:00 2001 From: Jakub Wieczorek Date: Tue, 16 Sep 2014 20:11:16 +0200 Subject: [PATCH] Run cleanup for base struct in functional struct update expressions Fixes #17302. --- src/librustc/middle/trans/expr.rs | 12 +++++------ src/test/run-pass/issue-17302.rs | 34 +++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 6 deletions(-) create mode 100644 src/test/run-pass/issue-17302.rs diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs index af57d49d9d8..77712570185 100644 --- a/src/librustc/middle/trans/expr.rs +++ b/src/librustc/middle/trans/expr.rs @@ -1380,7 +1380,11 @@ pub fn trans_adt<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, assert_eq!(discr, 0); match ty::expr_kind(bcx.tcx(), &*base.expr) { - ty::LvalueExpr => { + ty::RvalueDpsExpr | ty::RvalueDatumExpr if !ty::type_needs_drop(bcx.tcx(), ty) => { + bcx = trans_into(bcx, &*base.expr, SaveIn(addr)); + }, + ty::RvalueStmtExpr => bcx.tcx().sess.bug("unexpected expr kind for struct base expr"), + _ => { let base_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, &*base.expr, "base")); for &(i, t) in base.fields.iter() { let datum = base_datum.get_element( @@ -1389,11 +1393,7 @@ pub fn trans_adt<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, let dest = adt::trans_field_ptr(bcx, &*repr, addr, discr, i); bcx = datum.store_to(bcx, dest); } - }, - ty::RvalueDpsExpr | ty::RvalueDatumExpr => { - bcx = trans_into(bcx, &*base.expr, SaveIn(addr)); - }, - ty::RvalueStmtExpr => bcx.tcx().sess.bug("unexpected expr kind for struct base expr") + } } } diff --git a/src/test/run-pass/issue-17302.rs b/src/test/run-pass/issue-17302.rs new file mode 100644 index 00000000000..50583c7d127 --- /dev/null +++ b/src/test/run-pass/issue-17302.rs @@ -0,0 +1,34 @@ +// Copyright 2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +static mut DROPPED: [bool, ..2] = [false, false]; + +struct A(uint); +struct Foo { _a: A, _b: int } + +impl Drop for A { + fn drop(&mut self) { + let A(i) = *self; + unsafe { DROPPED[i] = true; } + } +} + +fn main() { + { + Foo { + _a: A(0), + ..Foo { _a: A(1), _b: 2 } + }; + } + unsafe { + assert!(DROPPED[0]); + assert!(DROPPED[1]); + } +}