Change:
Was trying to find another bug, found this bug! That code will fail with
I'll take it
Different testcases: EDIT: Found more testcases
Interesting. I'm looking into it. Not sure what is causing this, though.
Another testcase: (The and are both necessary.)
Even simpler example: Debug Log EDIT: Making the block return doesn't raise this issue.
My final testcase:
Could this be related to the no-argument version of lambda block expressions that were used in syntax? Looking in , there's a comment to this form of lambda expressions used with . As far as why doesn't raise the issue, maybe that's parsed as a block expression instead?
I don't see how it could be related. The error here has to do with a (or just zero-sized? I'm not sure) result of a block being stored somewhere. I'm not even sure the assert needs to be that strict.
Yet another test case to consider:
thanks! I'll get back to debug this in a bit

Discussion:
// emitting should be enabled. debuginfo::start_emitting_source_locations(&fcx); <ins> let dest = match fcx.llretptr.get() { Some(e) => {expr::SaveIn(e)} None => { assert!(type_is_zero_size(bcx.ccx(), block_ty)) expr::Ignore } }; </ins> // 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). <del> 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); } </del> <ins> bcx = controlflow::trans_block(bcx, body, dest); </ins> match fcx.llreturn.get() { Some(_) => {

pub fn trans_block<'a>(bcx: &'a Block<'a>, b: &ast::Block, <del> dest: expr::Dest) </del> <ins> mut dest: expr::Dest) </ins> -> &'a Block<'a> { let _icx = push_ctxt("trans_block"); let fcx = bcx.fcx;

for s in b.stmts.iter() { bcx = trans_stmt(bcx, *s); } <ins> 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; } } </ins> match b.expr { Some(e) => { bcx = expr::trans_into(bcx, e, dest);

<ins> // 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 <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. // 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()>, _: 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); } </ins>