mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-18 18:53:04 +00:00
partially fix immediate rvalues
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
This commit is contained in:
parent
6c08cc2db4
commit
34ae5d70ac
@ -1917,7 +1917,7 @@ fn trans_match_inner(scope_cx: @mut Block,
|
||||
Infallible
|
||||
}
|
||||
};
|
||||
let lldiscr = discr_datum.to_zeroable_ref_llval(bcx);
|
||||
let lldiscr = discr_datum.to_ref_llval(bcx);
|
||||
compile_submatch(bcx, matches, [lldiscr], chk);
|
||||
|
||||
let mut arm_cxs = ~[];
|
||||
@ -1996,7 +1996,7 @@ pub fn store_local(bcx: @mut Block,
|
||||
if bcx.sess().asm_comments() {
|
||||
add_comment(bcx, "creating zeroable ref llval");
|
||||
}
|
||||
let llptr = init_datum.to_zeroable_ref_llval(bcx);
|
||||
let llptr = init_datum.to_ref_llval(bcx);
|
||||
return bind_irrefutable_pat(bcx, pat, llptr, BindLocal);
|
||||
}
|
||||
}
|
||||
|
@ -473,38 +473,25 @@ impl Datum {
|
||||
C_null(type_of::type_of(bcx.ccx(), self.ty).ptr_to())
|
||||
} else {
|
||||
let slot = alloc_ty(bcx, self.ty, "");
|
||||
// The store created here can be modified through a reference, for example:
|
||||
//
|
||||
// // free the old allocation, and change the pointer to a new allocation
|
||||
// fn foo(x: &mut ~u8) {
|
||||
// *x = ~5;
|
||||
// }
|
||||
//
|
||||
// foo(&mut ~5);
|
||||
Store(bcx, self.val, slot);
|
||||
// The old cleanup needs to be cancelled, in order for the destructor to observe
|
||||
// any changes made through the reference.
|
||||
self.cancel_clean(bcx);
|
||||
add_clean_temp_mem(bcx, slot, self.ty);
|
||||
slot
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_zeroable_ref_llval(&self, bcx: @mut Block) -> ValueRef {
|
||||
/*!
|
||||
* Returns a by-ref llvalue that can be zeroed in order to
|
||||
* cancel cleanup. This is a kind of hokey bridge used
|
||||
* to adapt to the match code. Please don't use it for new code.
|
||||
*/
|
||||
|
||||
match self.mode {
|
||||
// All by-ref datums are zeroable, even if we *could* just
|
||||
// cancel the cleanup.
|
||||
ByRef(_) => self.val,
|
||||
|
||||
// By value datums can't be zeroed (where would you store
|
||||
// the zero?) so we have to spill them. Add a temp cleanup
|
||||
// for this spilled value and cancel the cleanup on this
|
||||
// current value.
|
||||
ByValue => {
|
||||
let slot = self.to_ref_llval(bcx);
|
||||
self.cancel_clean(bcx);
|
||||
add_clean_temp_mem(bcx, slot, self.ty);
|
||||
slot
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn appropriate_mode(&self, ccx: &mut CrateContext) -> DatumMode {
|
||||
/*! See the `appropriate_mode()` function */
|
||||
|
||||
|
17
src/test/run-pass/cancel-clean-via-immediate-rvalue-ref.rs
Normal file
17
src/test/run-pass/cancel-clean-via-immediate-rvalue-ref.rs
Normal file
@ -0,0 +1,17 @@
|
||||
// Copyright 2013 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.
|
||||
|
||||
fn foo(x: &mut ~u8) {
|
||||
*x = ~5;
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
foo(&mut ~4);
|
||||
}
|
Loading…
Reference in New Issue
Block a user