diff options
| author | kennytm <kennytm@gmail.com> | 2018-11-24 01:31:52 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-11-24 01:31:52 +0800 |
| commit | 419a101d9c8a323ccc984141b3bd5c4cbe5a5673 (patch) | |
| tree | 4bb2b62b49e7a438fd269d576042e6d43f680a13 | |
| parent | 12f6a42f610f0d4cd72886848d91f00e98d40590 (diff) | |
| parent | bcf82efe081dd12e4b6708241f5a1d165d103cae (diff) | |
| download | rust-419a101d9c8a323ccc984141b3bd5c4cbe5a5673.tar.gz rust-419a101d9c8a323ccc984141b3bd5c4cbe5a5673.zip | |
Rollup merge of #56022 - RalfJung:validate-before-jump, r=oli-obk
When popping in CTFE, perform validation before jumping to next statement to have a better span for the error Currently, when validating the return value fails, the span points at the next statement after the call. That does not make much sense. r? @oli-obk
| -rw-r--r-- | src/librustc_mir/interpret/eval_context.rs | 21 |
1 files changed, 14 insertions, 7 deletions
diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 936b476df39..2eb5f7c853f 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -504,15 +504,14 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc let frame = self.stack.pop().expect( "tried to pop a stack frame, but there were none", ); + // Abort early if we do not want to clean up: We also avoid validation in that case, + // because this is CTFE and the final value will be thoroughly validated anyway. match frame.return_to_block { - StackPopCleanup::Goto(block) => { - self.goto_block(block)?; - } + StackPopCleanup::Goto(_) => {}, StackPopCleanup::None { cleanup } => { if !cleanup { - // Leak the locals. Also skip validation, this is only used by - // static/const computation which does its own (stronger) final - // validation. + assert!(self.stack.is_empty(), "only the topmost frame should ever be leaked"); + // Leak the locals, skip validation. return Ok(()); } } @@ -521,7 +520,8 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc for local in frame.locals { self.deallocate_local(local)?; } - // Validate the return value. + // Validate the return value. Do this after deallocating so that we catch dangling + // references. if let Some(return_place) = frame.return_place { if M::enforce_validity(self) { // Data got changed, better make sure it matches the type! @@ -542,6 +542,13 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc // Uh, that shouldn't happen... the function did not intend to return return err!(Unreachable); } + // Jump to new block -- *after* validation so that the spans make more sense. + match frame.return_to_block { + StackPopCleanup::Goto(block) => { + self.goto_block(block)?; + } + StackPopCleanup::None { .. } => {} + } if self.stack.len() > 1 { // FIXME should be "> 0", printing topmost frame crashes rustc... debug!("CONTINUING({}) {}", self.cur_frame(), self.frame().instance); |
