Skip to content

Commit 3fd0e3a

Browse files
committed
auto merge of #9902 : thestinger/rust/immediate, r=nikomatsakis
The code generation previously assumed a reference could not alter the value in a way the destructor would notice. This is an incorrect assumption for `&mut`, and is also incorrect for an `&` pointer to a non-`Freeze` type. Closes #7972
2 parents d773a02 + 34ae5d7 commit 3fd0e3a

File tree

3 files changed

+31
-27
lines changed

3 files changed

+31
-27
lines changed

src/librustc/middle/trans/_match.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1917,7 +1917,7 @@ fn trans_match_inner(scope_cx: @mut Block,
19171917
Infallible
19181918
}
19191919
};
1920-
let lldiscr = discr_datum.to_zeroable_ref_llval(bcx);
1920+
let lldiscr = discr_datum.to_ref_llval(bcx);
19211921
compile_submatch(bcx, matches, [lldiscr], chk);
19221922

19231923
let mut arm_cxs = ~[];
@@ -1996,7 +1996,7 @@ pub fn store_local(bcx: @mut Block,
19961996
if bcx.sess().asm_comments() {
19971997
add_comment(bcx, "creating zeroable ref llval");
19981998
}
1999-
let llptr = init_datum.to_zeroable_ref_llval(bcx);
1999+
let llptr = init_datum.to_ref_llval(bcx);
20002000
return bind_irrefutable_pat(bcx, pat, llptr, BindLocal);
20012001
}
20022002
}

src/librustc/middle/trans/datum.rs

+12-25
Original file line numberDiff line numberDiff line change
@@ -473,38 +473,25 @@ impl Datum {
473473
C_null(type_of::type_of(bcx.ccx(), self.ty).ptr_to())
474474
} else {
475475
let slot = alloc_ty(bcx, self.ty, "");
476+
// The store created here can be modified through a reference, for example:
477+
//
478+
// // free the old allocation, and change the pointer to a new allocation
479+
// fn foo(x: &mut ~u8) {
480+
// *x = ~5;
481+
// }
482+
//
483+
// foo(&mut ~5);
476484
Store(bcx, self.val, slot);
485+
// The old cleanup needs to be cancelled, in order for the destructor to observe
486+
// any changes made through the reference.
487+
self.cancel_clean(bcx);
488+
add_clean_temp_mem(bcx, slot, self.ty);
477489
slot
478490
}
479491
}
480492
}
481493
}
482494

483-
pub fn to_zeroable_ref_llval(&self, bcx: @mut Block) -> ValueRef {
484-
/*!
485-
* Returns a by-ref llvalue that can be zeroed in order to
486-
* cancel cleanup. This is a kind of hokey bridge used
487-
* to adapt to the match code. Please don't use it for new code.
488-
*/
489-
490-
match self.mode {
491-
// All by-ref datums are zeroable, even if we *could* just
492-
// cancel the cleanup.
493-
ByRef(_) => self.val,
494-
495-
// By value datums can't be zeroed (where would you store
496-
// the zero?) so we have to spill them. Add a temp cleanup
497-
// for this spilled value and cancel the cleanup on this
498-
// current value.
499-
ByValue => {
500-
let slot = self.to_ref_llval(bcx);
501-
self.cancel_clean(bcx);
502-
add_clean_temp_mem(bcx, slot, self.ty);
503-
slot
504-
}
505-
}
506-
}
507-
508495
pub fn appropriate_mode(&self, ccx: &mut CrateContext) -> DatumMode {
509496
/*! See the `appropriate_mode()` function */
510497

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright 2013 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+
fn foo(x: &mut ~u8) {
12+
*x = ~5;
13+
}
14+
15+
pub fn main() {
16+
foo(&mut ~4);
17+
}

0 commit comments

Comments
 (0)