diff options
| author | Niko Matsakis <niko@alum.mit.edu> | 2013-05-29 18:33:30 -0400 |
|---|---|---|
| committer | Niko Matsakis <niko@alum.mit.edu> | 2013-05-30 15:20:36 -0400 |
| commit | 5209709e46ecfac2fd4db527952fe7ef96400801 (patch) | |
| tree | ae09745be3c75657f375c0a8d794cc23a878a8b1 /src | |
| parent | c492a2126fddb1b844ddee05a283a92329c6c041 (diff) | |
| download | rust-5209709e46ecfac2fd4db527952fe7ef96400801.tar.gz rust-5209709e46ecfac2fd4db527952fe7ef96400801.zip | |
Fix matching of rvalues with destructors
Fixes #4542.
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustc/middle/trans/_match.rs | 2 | ||||
| -rw-r--r-- | src/librustc/middle/trans/datum.rs | 25 | ||||
| -rw-r--r-- | src/test/run-pass/match-vec-rvalue.rs | 12 |
3 files changed, 38 insertions, 1 deletions
diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs index 6399fa5eedf..049e2162fe8 100644 --- a/src/librustc/middle/trans/_match.rs +++ b/src/librustc/middle/trans/_match.rs @@ -1701,7 +1701,7 @@ pub fn trans_match_inner(scope_cx: block, None } }; - let lldiscr = discr_datum.to_ref_llval(bcx); + let lldiscr = discr_datum.to_zeroable_ref_llval(bcx); compile_submatch(bcx, matches, [lldiscr], chk); let mut arm_cxs = ~[]; diff --git a/src/librustc/middle/trans/datum.rs b/src/librustc/middle/trans/datum.rs index 0f325c432f4..c0403083ce1 100644 --- a/src/librustc/middle/trans/datum.rs +++ b/src/librustc/middle/trans/datum.rs @@ -471,6 +471,31 @@ pub impl Datum { } } + fn to_zeroable_ref_llval(&self, bcx: 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 + } + } + } + fn appropriate_mode(&self) -> DatumMode { /*! See the `appropriate_mode()` function */ diff --git a/src/test/run-pass/match-vec-rvalue.rs b/src/test/run-pass/match-vec-rvalue.rs new file mode 100644 index 00000000000..5f68b0e9a69 --- /dev/null +++ b/src/test/run-pass/match-vec-rvalue.rs @@ -0,0 +1,12 @@ +// Tests that matching rvalues with drops does not crash. + +fn main() { + match ~[1, 2, 3] { + x => { + assert_eq!(x.len(), 3); + assert_eq!(x[0], 1); + assert_eq!(x[1], 2); + assert_eq!(x[2], 3); + } + } +} |
