diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 485daf3d387fc..90e3c19a07ee8 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -1510,16 +1510,19 @@ pub fn trans_closure<'a>(ccx: @CrateContext, // emitting should be enabled. debuginfo::start_emitting_source_locations(&fcx); + let dest = match fcx.llretptr.get() { + Some(e) => {expr::SaveIn(e)} + None => { + assert!(type_is_zero_size(bcx.ccx(), block_ty)) + expr::Ignore + } + }; + // This call to trans_block is the place where we bridge between // translation calls that don't have a return value (trans_crate, // trans_mod, trans_item, et cetera) and those that do // (trans_block, trans_expr, et cetera). - if body.expr.is_none() || type_is_zero_size(bcx.ccx(), block_ty) { - bcx = controlflow::trans_block(bcx, body, expr::Ignore); - } else { - let dest = expr::SaveIn(fcx.llretptr.get().unwrap()); - bcx = controlflow::trans_block(bcx, body, dest); - } + bcx = controlflow::trans_block(bcx, body, dest); match fcx.llreturn.get() { Some(_) => { diff --git a/src/librustc/middle/trans/controlflow.rs b/src/librustc/middle/trans/controlflow.rs index d361c36fbdacd..c867dc390f6a6 100644 --- a/src/librustc/middle/trans/controlflow.rs +++ b/src/librustc/middle/trans/controlflow.rs @@ -74,7 +74,7 @@ pub fn trans_stmt<'a>(cx: &'a Block<'a>, pub fn trans_block<'a>(bcx: &'a Block<'a>, b: &ast::Block, - dest: expr::Dest) + mut dest: expr::Dest) -> &'a Block<'a> { let _icx = push_ctxt("trans_block"); let fcx = bcx.fcx; @@ -85,6 +85,14 @@ pub fn trans_block<'a>(bcx: &'a Block<'a>, for s in b.stmts.iter() { bcx = trans_stmt(bcx, *s); } + + if dest != expr::Ignore { + let block_ty = node_id_type(bcx, b.id); + if b.expr.is_none() || type_is_zero_size(bcx.ccx(), block_ty) { + dest = expr::Ignore; + } + } + match b.expr { Some(e) => { bcx = expr::trans_into(bcx, e, dest); diff --git a/src/test/run-pass/issue-11709.rs b/src/test/run-pass/issue-11709.rs new file mode 100644 index 0000000000000..6bddfd7d1a9ff --- /dev/null +++ b/src/test/run-pass/issue-11709.rs @@ -0,0 +1,47 @@ +// Copyright 2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// xfail-pretty + +// Don't fail on blocks without results +// There are several tests in this run-pass that raised +// when this bug was oppened. The cases where the compiler +// failed before the fix have a comment. + +struct S {x:()} + + +fn test(slot: &mut Option proc()>, _: proc()) -> () { + let a = slot.take(); + let _a = match a { + // `{let .. a(); }` would break + Some(a) => { let _a = a(); }, + None => (), + }; +} + +fn not(b: bool) -> bool { + if b { + !b + } else { + // `fail!(...)` would break + fail!("Break the compiler"); + } +} + +pub fn main() { + // {} would break + let _r = {}; + let mut slot = None; + // `{ test(...); }` would break + let _s : S = S{ x: { test(&mut slot, proc() {}); } }; + + let _b = not(true); +}