Skip to content

Commit 342321d

Browse files
committedJul 5, 2014
auto merge of #15442 : luqmana/rust/odp, r=pnkfelix
Inadvertently changed the order in which destructors ran in certain cases with #15076. Fixes #15438.
2 parents e0d3cf6 + 1af8663 commit 342321d

File tree

3 files changed

+116
-8
lines changed

3 files changed

+116
-8
lines changed
 

‎src/librustc/middle/trans/_match.rs

+11-5
Original file line numberDiff line numberDiff line change
@@ -947,8 +947,8 @@ fn compare_values<'a>(
947947
}
948948
}
949949

950-
fn insert_lllocals<'a>(mut bcx: &'a Block<'a>,
951-
bindings_map: &BindingsMap)
950+
fn insert_lllocals<'a>(mut bcx: &'a Block<'a>, bindings_map: &BindingsMap,
951+
cs: Option<cleanup::ScopeId>)
952952
-> &'a Block<'a> {
953953
/*!
954954
* For each binding in `data.bindings_map`, adds an appropriate entry into
@@ -975,6 +975,10 @@ fn insert_lllocals<'a>(mut bcx: &'a Block<'a>,
975975
};
976976

977977
let datum = Datum::new(llval, binding_info.ty, Lvalue);
978+
match cs {
979+
Some(cs) => bcx.fcx.schedule_drop_and_zero_mem(cs, llval, binding_info.ty),
980+
_ => {}
981+
}
978982

979983
debug!("binding {:?} to {}",
980984
binding_info.id,
@@ -1006,7 +1010,7 @@ fn compile_guard<'a, 'b>(
10061010
vec_map_to_str(vals, |v| bcx.val_to_str(*v)));
10071011
let _indenter = indenter();
10081012

1009-
let mut bcx = insert_lllocals(bcx, &data.bindings_map);
1013+
let mut bcx = insert_lllocals(bcx, &data.bindings_map, None);
10101014

10111015
let val = unpack_datum!(bcx, expr::trans(bcx, guard_expr));
10121016
let val = val.to_llbool(bcx);
@@ -1460,9 +1464,11 @@ fn trans_match_inner<'a>(scope_cx: &'a Block<'a>,
14601464
for arm_data in arm_datas.iter() {
14611465
let mut bcx = arm_data.bodycx;
14621466

1463-
// insert bindings into the lllocals map
1464-
bcx = insert_lllocals(bcx, &arm_data.bindings_map);
1467+
// insert bindings into the lllocals map and add cleanups
1468+
let cs = fcx.push_custom_cleanup_scope();
1469+
bcx = insert_lllocals(bcx, &arm_data.bindings_map, Some(cleanup::CustomScope(cs)));
14651470
bcx = expr::trans_into(bcx, &*arm_data.arm.body, dest);
1471+
bcx = fcx.pop_and_trans_custom_cleanup_scope(bcx, cs);
14661472
arm_cxs.push(bcx);
14671473
}
14681474

‎src/librustc/middle/trans/cleanup.rs

+41-3
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,8 @@ impl<'a> CleanupMethods<'a> for FunctionContext<'a> {
240240
is_immediate: false,
241241
on_unwind: ty::type_needs_unwind_cleanup(self.ccx.tcx(), ty),
242242
val: val,
243-
ty: ty
243+
ty: ty,
244+
zero: false
244245
};
245246

246247
debug!("schedule_drop_mem({:?}, val={}, ty={})",
@@ -251,6 +252,33 @@ impl<'a> CleanupMethods<'a> for FunctionContext<'a> {
251252
self.schedule_clean(cleanup_scope, drop as Box<Cleanup>);
252253
}
253254

255+
fn schedule_drop_and_zero_mem(&self,
256+
cleanup_scope: ScopeId,
257+
val: ValueRef,
258+
ty: ty::t) {
259+
/*!
260+
* Schedules a (deep) drop and zero-ing of `val`, which is a pointer
261+
* to an instance of `ty`
262+
*/
263+
264+
if !ty::type_needs_drop(self.ccx.tcx(), ty) { return; }
265+
let drop = box DropValue {
266+
is_immediate: false,
267+
on_unwind: ty::type_needs_unwind_cleanup(self.ccx.tcx(), ty),
268+
val: val,
269+
ty: ty,
270+
zero: true
271+
};
272+
273+
debug!("schedule_drop_and_zero_mem({:?}, val={}, ty={}, zero={})",
274+
cleanup_scope,
275+
self.ccx.tn.val_to_str(val),
276+
ty.repr(self.ccx.tcx()),
277+
true);
278+
279+
self.schedule_clean(cleanup_scope, drop as Box<Cleanup>);
280+
}
281+
254282
fn schedule_drop_immediate(&self,
255283
cleanup_scope: ScopeId,
256284
val: ValueRef,
@@ -264,7 +292,8 @@ impl<'a> CleanupMethods<'a> for FunctionContext<'a> {
264292
is_immediate: true,
265293
on_unwind: ty::type_needs_unwind_cleanup(self.ccx.tcx(), ty),
266294
val: val,
267-
ty: ty
295+
ty: ty,
296+
zero: false
268297
};
269298

270299
debug!("schedule_drop_immediate({:?}, val={}, ty={})",
@@ -824,6 +853,7 @@ pub struct DropValue {
824853
on_unwind: bool,
825854
val: ValueRef,
826855
ty: ty::t,
856+
zero: bool
827857
}
828858

829859
impl Cleanup for DropValue {
@@ -832,11 +862,15 @@ impl Cleanup for DropValue {
832862
}
833863

834864
fn trans<'a>(&self, bcx: &'a Block<'a>) -> &'a Block<'a> {
835-
if self.is_immediate {
865+
let bcx = if self.is_immediate {
836866
glue::drop_ty_immediate(bcx, self.val, self.ty)
837867
} else {
838868
glue::drop_ty(bcx, self.val, self.ty)
869+
};
870+
if self.zero {
871+
base::zero_mem(bcx, self.val, self.ty);
839872
}
873+
bcx
840874
}
841875
}
842876

@@ -927,6 +961,10 @@ pub trait CleanupMethods<'a> {
927961
cleanup_scope: ScopeId,
928962
val: ValueRef,
929963
ty: ty::t);
964+
fn schedule_drop_and_zero_mem(&self,
965+
cleanup_scope: ScopeId,
966+
val: ValueRef,
967+
ty: ty::t);
930968
fn schedule_drop_immediate(&self,
931969
cleanup_scope: ScopeId,
932970
val: ValueRef,
+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// Copyright 2014 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+
12+
// Test to make sure the destructors run in the right order.
13+
// Each destructor sets it's tag in the corresponding entry
14+
// in ORDER matching up to when it ran.
15+
// Correct order is: matched, inner, outer
16+
17+
static mut ORDER: [uint, ..3] = [0, 0, 0];
18+
static mut INDEX: uint = 0;
19+
20+
struct A;
21+
impl Drop for A {
22+
fn drop(&mut self) {
23+
unsafe {
24+
ORDER[INDEX] = 1;
25+
INDEX = INDEX + 1;
26+
}
27+
}
28+
}
29+
30+
struct B;
31+
impl Drop for B {
32+
fn drop(&mut self) {
33+
unsafe {
34+
ORDER[INDEX] = 2;
35+
INDEX = INDEX + 1;
36+
}
37+
}
38+
}
39+
40+
struct C;
41+
impl Drop for C {
42+
fn drop(&mut self) {
43+
unsafe {
44+
ORDER[INDEX] = 3;
45+
INDEX = INDEX + 1;
46+
}
47+
}
48+
}
49+
50+
fn main() {
51+
{
52+
let matched = A;
53+
let _outer = C;
54+
{
55+
match matched {
56+
_s => {}
57+
}
58+
let _inner = B;
59+
}
60+
}
61+
unsafe {
62+
assert_eq!(&[1, 2, 3], ORDER.as_slice());
63+
}
64+
}

0 commit comments

Comments
 (0)