Skip to content

Commit fb3e871

Browse files
committed
Add some documentation
1 parent eee209d commit fb3e871

File tree

3 files changed

+38
-1
lines changed

3 files changed

+38
-1
lines changed

src/librustc_trans/trans/base.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1393,6 +1393,16 @@ fn build_cfg(tcx: &ty::ctxt, id: ast::NodeId) -> (ast::NodeId, Option<cfg::CFG>)
13931393
(blk.id, Some(cfg::CFG::new(tcx, &**blk)))
13941394
}
13951395

1396+
// Checks for the presence of "nested returns" in a function.
1397+
// Nested returns are when the inner expression of a return expression
1398+
// (the 'expr' in 'return expr') contains a return expression. Only cases
1399+
// where the outer return is actually reachable are considered. Implicit
1400+
// returns from the end of blocks are considered as well.
1401+
//
1402+
// This check is needed to handle the case where the inner expression is
1403+
// part of a larger expression that may have already partially-filled the
1404+
// return slot alloca. This can cause errors related to clean-up due to
1405+
// the clobbering of the existing value in the return slot.
13961406
fn has_nested_returns(tcx: &ty::ctxt, cfg: &cfg::CFG, blk_id: ast::NodeId) -> bool {
13971407
for n in cfg.graph.depth_traverse(cfg.entry) {
13981408
match tcx.map.find(n.id) {

src/librustc_trans/trans/controlflow.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,17 @@ pub fn trans_block<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
112112

113113
if dest != expr::Ignore {
114114
let block_ty = node_id_type(bcx, b.id);
115+
115116
if b.expr.is_none() || type_is_zero_size(bcx.ccx(), block_ty) {
116117
dest = expr::Ignore;
118+
} else if b.expr.is_some() {
119+
// If the block has an expression, but that expression isn't reachable,
120+
// don't save into the destination given, ignore it.
121+
if let Some(ref cfg) = bcx.fcx.cfg {
122+
if !cfg.node_is_reachable(b.expr.as_ref().unwrap().id) {
123+
dest = expr::Ignore;
124+
}
125+
}
117126
}
118127
}
119128

src/librustc_trans/trans/expr.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -928,7 +928,25 @@ fn trans_rvalue_stmt_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
928928
controlflow::trans_cont(bcx, expr.id, label_opt)
929929
}
930930
ast::ExprRet(ref ex) => {
931-
controlflow::trans_ret(bcx, ex.as_ref().map(|e| &**e))
931+
// Check to see if the return expression itself is reachable.
932+
// This can occur when the inner expression contains a return
933+
let reachable = if let Some(ref cfg) = bcx.fcx.cfg {
934+
cfg.node_is_reachable(expr.id)
935+
} else {
936+
true
937+
};
938+
939+
if reachable {
940+
controlflow::trans_ret(bcx, ex.as_ref().map(|e| &**e))
941+
} else {
942+
// If it's not reachable, just translate the inner expression
943+
// directly. This avoids having to manage a return slot when
944+
// it won't actually be used anyway.
945+
if let &Some(ref x) = ex {
946+
bcx = trans_into(bcx, &**x, Ignore);
947+
}
948+
bcx
949+
}
932950
}
933951
ast::ExprWhile(ref cond, ref body, _) => {
934952
controlflow::trans_while(bcx, expr.id, &**cond, &**body)

0 commit comments

Comments
 (0)