diff --git a/src/librustc/cfg/construct.rs b/src/librustc/cfg/construct.rs index 118125a19ddef..d8cf147e3ee4b 100644 --- a/src/librustc/cfg/construct.rs +++ b/src/librustc/cfg/construct.rs @@ -582,19 +582,16 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { scope_cf_kind: ScopeCfKind) -> (region::Scope, CFGIndex) { match destination.target_id { - hir::ScopeTarget::Block(block_expr_id) => { + Ok(loop_id) => { for b in &self.breakable_block_scopes { - if b.block_expr_id == self.tcx.hir.node_to_hir_id(block_expr_id).local_id { - let scope_id = self.tcx.hir.node_to_hir_id(block_expr_id).local_id; + if b.block_expr_id == self.tcx.hir.node_to_hir_id(loop_id).local_id { + let scope_id = self.tcx.hir.node_to_hir_id(loop_id).local_id; return (region::Scope::Node(scope_id), match scope_cf_kind { ScopeCfKind::Break => b.break_index, ScopeCfKind::Continue => bug!("can't continue to block"), }); } } - span_bug!(expr.span, "no block expr for id {}", block_expr_id); - } - hir::ScopeTarget::Loop(hir::LoopIdResult::Ok(loop_id)) => { for l in &self.loop_scopes { if l.loop_id == self.tcx.hir.node_to_hir_id(loop_id).local_id { let scope_id = self.tcx.hir.node_to_hir_id(loop_id).local_id; @@ -604,10 +601,9 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { }); } } - span_bug!(expr.span, "no loop scope for id {}", loop_id); + span_bug!(expr.span, "no scope for id {}", loop_id); } - hir::ScopeTarget::Loop(hir::LoopIdResult::Err(err)) => - span_bug!(expr.span, "loop scope error: {}", err), + Err(err) => span_bug!(expr.span, "scope error: {}", err), } } } diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index 3e5dcee113a4e..1fb496cca629e 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -1039,10 +1039,8 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { if let Some(ref label) = destination.label { visitor.visit_label(label); match destination.target_id { - ScopeTarget::Block(node_id) | - ScopeTarget::Loop(LoopIdResult::Ok(node_id)) => - visitor.visit_def_mention(Def::Label(node_id)), - ScopeTarget::Loop(LoopIdResult::Err(_)) => {}, + Ok(node_id) => visitor.visit_def_mention(Def::Label(node_id)), + Err(_) => {}, }; } walk_list!(visitor, visit_expr, opt_expr); @@ -1051,10 +1049,8 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { if let Some(ref label) = destination.label { visitor.visit_label(label); match destination.target_id { - ScopeTarget::Block(_) => bug!("can't `continue` to a non-loop block"), - ScopeTarget::Loop(LoopIdResult::Ok(node_id)) => - visitor.visit_def_mention(Def::Label(node_id)), - ScopeTarget::Loop(LoopIdResult::Err(_)) => {}, + Ok(node_id) => visitor.visit_def_mention(Def::Label(node_id)), + Err(_) => {}, }; } } diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 51f0c1d7047c9..d5d3746bc184f 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -928,29 +928,27 @@ impl<'a> LoweringContext<'a> { fn lower_loop_destination(&mut self, destination: Option<(NodeId, Label)>) -> hir::Destination { match destination { Some((id, label)) => { - let target = if let Def::Label(loop_id) = self.expect_full_def(id) { - hir::LoopIdResult::Ok(self.lower_node_id(loop_id).node_id) + let target_id = if let Def::Label(loop_id) = self.expect_full_def(id) { + Ok(self.lower_node_id(loop_id).node_id) } else { - hir::LoopIdResult::Err(hir::LoopIdError::UnresolvedLabel) + Err(hir::LoopIdError::UnresolvedLabel) }; hir::Destination { label: self.lower_label(Some(label)), - target_id: hir::ScopeTarget::Loop(target), + target_id, } } None => { - let loop_id = self.loop_scopes + let target_id = self.loop_scopes .last() - .map(|innermost_loop_id| *innermost_loop_id); + .map(|innermost_loop_id| *innermost_loop_id) + .map(|id| Ok(self.lower_node_id(id).node_id)) + .unwrap_or(Err(hir::LoopIdError::OutsideLoopScope)) + .into(); hir::Destination { label: None, - target_id: hir::ScopeTarget::Loop( - loop_id - .map(|id| Ok(self.lower_node_id(id).node_id)) - .unwrap_or(Err(hir::LoopIdError::OutsideLoopScope)) - .into(), - ), + target_id, } } } @@ -3193,9 +3191,7 @@ impl<'a> LoweringContext<'a> { let destination = if self.is_in_loop_condition && opt_label.is_none() { hir::Destination { label: None, - target_id: hir::ScopeTarget::Loop( - Err(hir::LoopIdError::UnlabeledCfInWhileCondition).into(), - ), + target_id: Err(hir::LoopIdError::UnlabeledCfInWhileCondition).into(), } } else { self.lower_loop_destination(opt_label.map(|label| (e.id, label))) @@ -3209,9 +3205,7 @@ impl<'a> LoweringContext<'a> { hir::ExprAgain(if self.is_in_loop_condition && opt_label.is_none() { hir::Destination { label: None, - target_id: hir::ScopeTarget::Loop( - Err(hir::LoopIdError::UnlabeledCfInWhileCondition).into(), - ), + target_id: Err(hir::LoopIdError::UnlabeledCfInWhileCondition).into(), } } else { self.lower_loop_destination(opt_label.map(|label| (e.id, label))) @@ -3604,7 +3598,7 @@ impl<'a> LoweringContext<'a> { hir::ExprBreak( hir::Destination { label: None, - target_id: hir::ScopeTarget::Block(catch_node), + target_id: Ok(catch_node), }, Some(from_err_expr), ), diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 33076267dbc9d..3f49e0bfd1983 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -1502,46 +1502,6 @@ impl fmt::Display for LoopIdError { } } -// FIXME(cramertj) this should use `Result` once master compiles w/ a vesion of Rust where -// `Result` implements `Encodable`/`Decodable` -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] -pub enum LoopIdResult { - Ok(NodeId), - Err(LoopIdError), -} -impl Into> for LoopIdResult { - fn into(self) -> Result { - match self { - LoopIdResult::Ok(ok) => Ok(ok), - LoopIdResult::Err(err) => Err(err), - } - } -} -impl From> for LoopIdResult { - fn from(res: Result) -> Self { - match res { - Ok(ok) => LoopIdResult::Ok(ok), - Err(err) => LoopIdResult::Err(err), - } - } -} - -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] -pub enum ScopeTarget { - Block(NodeId), - Loop(LoopIdResult), -} - -impl ScopeTarget { - pub fn opt_id(self) -> Option { - match self { - ScopeTarget::Block(node_id) | - ScopeTarget::Loop(LoopIdResult::Ok(node_id)) => Some(node_id), - ScopeTarget::Loop(LoopIdResult::Err(_)) => None, - } - } -} - #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] pub struct Destination { // This is `Some(_)` iff there is an explicit user-specified `label @@ -1549,7 +1509,7 @@ pub struct Destination { // These errors are caught and then reported during the diagnostics pass in // librustc_passes/loops.rs - pub target_id: ScopeTarget, + pub target_id: Result, } #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index 4a001802eacb4..6edf1b35bdd73 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -656,22 +656,12 @@ impl_stable_hash_for!(struct hir::Destination { impl_stable_hash_for_spanned!(ast::Ident); -impl_stable_hash_for!(enum hir::LoopIdResult { - Ok(node_id), - Err(loop_id_error) -}); - impl_stable_hash_for!(enum hir::LoopIdError { OutsideLoopScope, UnlabeledCfInWhileCondition, UnresolvedLabel }); -impl_stable_hash_for!(enum hir::ScopeTarget { - Block(node_id), - Loop(loop_id_result) -}); - impl<'a> HashStable> for ast::Ident { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index acdd5e6acad04..2b1663bed2f40 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -571,9 +571,6 @@ struct Liveness<'a, 'tcx: 'a> { // it probably doesn't now) break_ln: NodeMap, cont_ln: NodeMap, - - // mappings from node ID to LiveNode for "breakable" blocks-- currently only `catch {...}` - breakable_block_ln: NodeMap, } impl<'a, 'tcx> Liveness<'a, 'tcx> { @@ -601,7 +598,6 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { users: vec![invalid_users(); num_live_nodes * num_vars], break_ln: NodeMap(), cont_ln: NodeMap(), - breakable_block_ln: NodeMap(), } } @@ -870,7 +866,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { fn propagate_through_block(&mut self, blk: &hir::Block, succ: LiveNode) -> LiveNode { if blk.targeted_by_break { - self.breakable_block_ln.insert(blk.id, succ); + self.break_ln.insert(blk.id, succ); } let succ = self.propagate_through_opt_expr(blk.expr.as_ref().map(|e| &**e), succ); blk.stmts.iter().rev().fold(succ, |succ, stmt| { @@ -1055,12 +1051,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { hir::ExprBreak(label, ref opt_expr) => { // Find which label this break jumps to let target = match label.target_id { - hir::ScopeTarget::Block(node_id) => - self.breakable_block_ln.get(&node_id), - hir::ScopeTarget::Loop(hir::LoopIdResult::Ok(node_id)) => - self.break_ln.get(&node_id), - hir::ScopeTarget::Loop(hir::LoopIdResult::Err(err)) => - span_bug!(expr.span, "loop scope error: {}", err), + Ok(node_id) => self.break_ln.get(&node_id), + Err(err) => span_bug!(expr.span, "loop scope error: {}", err), }.map(|x| *x); // Now that we know the label we're going to, @@ -1075,10 +1067,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { hir::ExprAgain(label) => { // Find which label this expr continues to let sc = match label.target_id { - hir::ScopeTarget::Block(_) => bug!("can't `continue` to a non-loop block"), - hir::ScopeTarget::Loop(hir::LoopIdResult::Ok(node_id)) => node_id, - hir::ScopeTarget::Loop(hir::LoopIdResult::Err(err)) => - span_bug!(expr.span, "loop scope error: {}", err), + Ok(node_id) => node_id, + Err(err) => span_bug!(expr.span, "loop scope error: {}", err), }; // Now that we know the label we're going to, diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index e3ff67703bd4e..3e432d84c699d 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -536,23 +536,19 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, hir::ExprRet(ref v) => ExprKind::Return { value: v.to_ref() }, hir::ExprBreak(dest, ref value) => { match dest.target_id { - hir::ScopeTarget::Block(target_id) | - hir::ScopeTarget::Loop(hir::LoopIdResult::Ok(target_id)) => ExprKind::Break { + Ok(target_id) => ExprKind::Break { label: region::Scope::Node(cx.tcx.hir.node_to_hir_id(target_id).local_id), value: value.to_ref(), }, - hir::ScopeTarget::Loop(hir::LoopIdResult::Err(err)) => - bug!("invalid loop id for break: {}", err) + Err(err) => bug!("invalid loop id for break: {}", err) } } hir::ExprAgain(dest) => { match dest.target_id { - hir::ScopeTarget::Block(_) => bug!("cannot continue to blocks"), - hir::ScopeTarget::Loop(hir::LoopIdResult::Ok(loop_id)) => ExprKind::Continue { + Ok(loop_id) => ExprKind::Continue { label: region::Scope::Node(cx.tcx.hir.node_to_hir_id(loop_id).local_id), }, - hir::ScopeTarget::Loop(hir::LoopIdResult::Err(err)) => - bug!("invalid loop id for continue: {}", err) + Err(err) => bug!("invalid loop id for continue: {}", err) } } hir::ExprMatch(ref discr, ref arms, _) => { diff --git a/src/librustc_passes/loops.rs b/src/librustc_passes/loops.rs index 008c71cc9ce3d..81299f4ba9f66 100644 --- a/src/librustc_passes/loops.rs +++ b/src/librustc_passes/loops.rs @@ -85,20 +85,21 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> { self.with_context(Closure, |v| v.visit_nested_body(b)); } hir::ExprBreak(label, ref opt_expr) => { - let loop_id = match label.target_id { - hir::ScopeTarget::Block(_) => return, - hir::ScopeTarget::Loop(loop_res) => { - match loop_res.into() { - Ok(loop_id) => loop_id, - Err(hir::LoopIdError::OutsideLoopScope) => ast::DUMMY_NODE_ID, - Err(hir::LoopIdError::UnlabeledCfInWhileCondition) => { - self.emit_unlabled_cf_in_while_condition(e.span, "break"); - ast::DUMMY_NODE_ID - }, - Err(hir::LoopIdError::UnresolvedLabel) => ast::DUMMY_NODE_ID, - } - } + let loop_id = match label.target_id.into() { + Ok(loop_id) => loop_id, + Err(hir::LoopIdError::OutsideLoopScope) => ast::DUMMY_NODE_ID, + Err(hir::LoopIdError::UnlabeledCfInWhileCondition) => { + self.emit_unlabled_cf_in_while_condition(e.span, "break"); + ast::DUMMY_NODE_ID + }, + Err(hir::LoopIdError::UnresolvedLabel) => ast::DUMMY_NODE_ID, }; + if loop_id != ast::DUMMY_NODE_ID { + match self.hir_map.find(loop_id).unwrap() { + hir::map::NodeBlock(_) => return, + _=> (), + } + } if opt_expr.is_some() { let loop_kind = if loop_id == ast::DUMMY_NODE_ID { @@ -132,9 +133,7 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> { self.require_loop("break", e.span); } hir::ExprAgain(label) => { - if let hir::ScopeTarget::Loop( - hir::LoopIdResult::Err( - hir::LoopIdError::UnlabeledCfInWhileCondition)) = label.target_id { + if let Err(hir::LoopIdError::UnlabeledCfInWhileCondition) = label.target_id { self.emit_unlabled_cf_in_while_condition(e.span, "continue"); } self.require_loop("continue", e.span) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index b4a7de7b8443c..58502bef9353f 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3723,7 +3723,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { tcx.mk_nil() } hir::ExprBreak(destination, ref expr_opt) => { - if let Some(target_id) = destination.target_id.opt_id() { + if let Ok(target_id) = destination.target_id { let (e_ty, cause); if let Some(ref e) = *expr_opt { // If this is a break with a value, we need to type-check