Rollup merge of #47502 - petrochenkov:label, r=eddyb
AST/HIR: Add a separate structure for labels
This commit is contained in:
commit
98b375483c
13 changed files with 203 additions and 202 deletions
|
@ -43,7 +43,6 @@
|
||||||
|
|
||||||
use syntax::abi::Abi;
|
use syntax::abi::Abi;
|
||||||
use syntax::ast::{NodeId, CRATE_NODE_ID, Name, Attribute};
|
use syntax::ast::{NodeId, CRATE_NODE_ID, Name, Attribute};
|
||||||
use syntax::codemap::Spanned;
|
|
||||||
use syntax_pos::Span;
|
use syntax_pos::Span;
|
||||||
use hir::*;
|
use hir::*;
|
||||||
use hir::def::Def;
|
use hir::def::Def;
|
||||||
|
@ -336,6 +335,9 @@ pub trait Visitor<'v> : Sized {
|
||||||
fn visit_variant(&mut self, v: &'v Variant, g: &'v Generics, item_id: NodeId) {
|
fn visit_variant(&mut self, v: &'v Variant, g: &'v Generics, item_id: NodeId) {
|
||||||
walk_variant(self, v, g, item_id)
|
walk_variant(self, v, g, item_id)
|
||||||
}
|
}
|
||||||
|
fn visit_label(&mut self, label: &'v Label) {
|
||||||
|
walk_label(self, label)
|
||||||
|
}
|
||||||
fn visit_lifetime(&mut self, lifetime: &'v Lifetime) {
|
fn visit_lifetime(&mut self, lifetime: &'v Lifetime) {
|
||||||
walk_lifetime(self, lifetime)
|
walk_lifetime(self, lifetime)
|
||||||
}
|
}
|
||||||
|
@ -370,18 +372,6 @@ pub trait Visitor<'v> : Sized {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn walk_opt_name<'v, V: Visitor<'v>>(visitor: &mut V, span: Span, opt_name: Option<Name>) {
|
|
||||||
if let Some(name) = opt_name {
|
|
||||||
visitor.visit_name(span, name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn walk_opt_sp_name<'v, V: Visitor<'v>>(visitor: &mut V, opt_sp_name: &Option<Spanned<Name>>) {
|
|
||||||
if let Some(ref sp_name) = *opt_sp_name {
|
|
||||||
visitor.visit_name(sp_name.span, sp_name.node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Walks the contents of a crate. See also `Crate::visit_all_items`.
|
/// Walks the contents of a crate. See also `Crate::visit_all_items`.
|
||||||
pub fn walk_crate<'v, V: Visitor<'v>>(visitor: &mut V, krate: &'v Crate) {
|
pub fn walk_crate<'v, V: Visitor<'v>>(visitor: &mut V, krate: &'v Crate) {
|
||||||
visitor.visit_mod(&krate.module, krate.span, CRATE_NODE_ID);
|
visitor.visit_mod(&krate.module, krate.span, CRATE_NODE_ID);
|
||||||
|
@ -420,6 +410,10 @@ pub fn walk_local<'v, V: Visitor<'v>>(visitor: &mut V, local: &'v Local) {
|
||||||
walk_list!(visitor, visit_ty, &local.ty);
|
walk_list!(visitor, visit_ty, &local.ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn walk_label<'v, V: Visitor<'v>>(visitor: &mut V, label: &'v Label) {
|
||||||
|
visitor.visit_name(label.span, label.name);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn walk_lifetime<'v, V: Visitor<'v>>(visitor: &mut V, lifetime: &'v Lifetime) {
|
pub fn walk_lifetime<'v, V: Visitor<'v>>(visitor: &mut V, lifetime: &'v Lifetime) {
|
||||||
visitor.visit_id(lifetime.id);
|
visitor.visit_id(lifetime.id);
|
||||||
match lifetime.name {
|
match lifetime.name {
|
||||||
|
@ -452,7 +446,9 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
|
||||||
match item.node {
|
match item.node {
|
||||||
ItemExternCrate(opt_name) => {
|
ItemExternCrate(opt_name) => {
|
||||||
visitor.visit_id(item.id);
|
visitor.visit_id(item.id);
|
||||||
walk_opt_name(visitor, item.span, opt_name)
|
if let Some(name) = opt_name {
|
||||||
|
visitor.visit_name(item.span, name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ItemUse(ref path, _) => {
|
ItemUse(ref path, _) => {
|
||||||
visitor.visit_id(item.id);
|
visitor.visit_id(item.id);
|
||||||
|
@ -993,14 +989,14 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
|
||||||
visitor.visit_expr(if_block);
|
visitor.visit_expr(if_block);
|
||||||
walk_list!(visitor, visit_expr, optional_else);
|
walk_list!(visitor, visit_expr, optional_else);
|
||||||
}
|
}
|
||||||
ExprWhile(ref subexpression, ref block, ref opt_sp_name) => {
|
ExprWhile(ref subexpression, ref block, ref opt_label) => {
|
||||||
|
walk_list!(visitor, visit_label, opt_label);
|
||||||
visitor.visit_expr(subexpression);
|
visitor.visit_expr(subexpression);
|
||||||
visitor.visit_block(block);
|
visitor.visit_block(block);
|
||||||
walk_opt_sp_name(visitor, opt_sp_name);
|
|
||||||
}
|
}
|
||||||
ExprLoop(ref block, ref opt_sp_name, _) => {
|
ExprLoop(ref block, ref opt_label, _) => {
|
||||||
|
walk_list!(visitor, visit_label, opt_label);
|
||||||
visitor.visit_block(block);
|
visitor.visit_block(block);
|
||||||
walk_opt_sp_name(visitor, opt_sp_name);
|
|
||||||
}
|
}
|
||||||
ExprMatch(ref subexpression, ref arms, _) => {
|
ExprMatch(ref subexpression, ref arms, _) => {
|
||||||
visitor.visit_expr(subexpression);
|
visitor.visit_expr(subexpression);
|
||||||
|
@ -1036,28 +1032,28 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
|
||||||
ExprPath(ref qpath) => {
|
ExprPath(ref qpath) => {
|
||||||
visitor.visit_qpath(qpath, expression.id, expression.span);
|
visitor.visit_qpath(qpath, expression.id, expression.span);
|
||||||
}
|
}
|
||||||
ExprBreak(label, ref opt_expr) => {
|
ExprBreak(ref destination, ref opt_expr) => {
|
||||||
label.ident.map(|ident| {
|
if let Some(ref label) = destination.label {
|
||||||
match label.target_id {
|
visitor.visit_label(label);
|
||||||
|
match destination.target_id {
|
||||||
ScopeTarget::Block(node_id) |
|
ScopeTarget::Block(node_id) |
|
||||||
ScopeTarget::Loop(LoopIdResult::Ok(node_id)) =>
|
ScopeTarget::Loop(LoopIdResult::Ok(node_id)) =>
|
||||||
visitor.visit_def_mention(Def::Label(node_id)),
|
visitor.visit_def_mention(Def::Label(node_id)),
|
||||||
ScopeTarget::Loop(LoopIdResult::Err(_)) => {},
|
ScopeTarget::Loop(LoopIdResult::Err(_)) => {},
|
||||||
};
|
};
|
||||||
visitor.visit_name(ident.span, ident.node.name);
|
}
|
||||||
});
|
|
||||||
walk_list!(visitor, visit_expr, opt_expr);
|
walk_list!(visitor, visit_expr, opt_expr);
|
||||||
}
|
}
|
||||||
ExprAgain(label) => {
|
ExprAgain(ref destination) => {
|
||||||
label.ident.map(|ident| {
|
if let Some(ref label) = destination.label {
|
||||||
match label.target_id {
|
visitor.visit_label(label);
|
||||||
|
match destination.target_id {
|
||||||
ScopeTarget::Block(_) => bug!("can't `continue` to a non-loop block"),
|
ScopeTarget::Block(_) => bug!("can't `continue` to a non-loop block"),
|
||||||
ScopeTarget::Loop(LoopIdResult::Ok(node_id)) =>
|
ScopeTarget::Loop(LoopIdResult::Ok(node_id)) =>
|
||||||
visitor.visit_def_mention(Def::Label(node_id)),
|
visitor.visit_def_mention(Def::Label(node_id)),
|
||||||
ScopeTarget::Loop(LoopIdResult::Err(_)) => {},
|
ScopeTarget::Loop(LoopIdResult::Err(_)) => {},
|
||||||
};
|
};
|
||||||
visitor.visit_name(ident.span, ident.node.name);
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
ExprRet(ref optional_expression) => {
|
ExprRet(ref optional_expression) => {
|
||||||
walk_list!(visitor, visit_expr, optional_expression);
|
walk_list!(visitor, visit_expr, optional_expression);
|
||||||
|
|
|
@ -773,22 +773,22 @@ impl<'a> LoweringContext<'a> {
|
||||||
*self.name_map.entry(ident).or_insert_with(|| Symbol::from_ident(ident))
|
*self.name_map.entry(ident).or_insert_with(|| Symbol::from_ident(ident))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_opt_sp_ident(&mut self, o_id: Option<Spanned<Ident>>) -> Option<Spanned<Name>> {
|
fn lower_label(&mut self, label: Option<Label>) -> Option<hir::Label> {
|
||||||
o_id.map(|sp_ident| respan(sp_ident.span, sp_ident.node.name))
|
label.map(|label| hir::Label { name: label.ident.name, span: label.span })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_loop_destination(&mut self, destination: Option<(NodeId, Spanned<Ident>)>)
|
fn lower_loop_destination(&mut self, destination: Option<(NodeId, Label)>)
|
||||||
-> hir::Destination
|
-> hir::Destination
|
||||||
{
|
{
|
||||||
match destination {
|
match destination {
|
||||||
Some((id, label_ident)) => {
|
Some((id, label)) => {
|
||||||
let target = if let Def::Label(loop_id) = self.expect_full_def(id) {
|
let target = if let Def::Label(loop_id) = self.expect_full_def(id) {
|
||||||
hir::LoopIdResult::Ok(self.lower_node_id(loop_id).node_id)
|
hir::LoopIdResult::Ok(self.lower_node_id(loop_id).node_id)
|
||||||
} else {
|
} else {
|
||||||
hir::LoopIdResult::Err(hir::LoopIdError::UnresolvedLabel)
|
hir::LoopIdResult::Err(hir::LoopIdError::UnresolvedLabel)
|
||||||
};
|
};
|
||||||
hir::Destination {
|
hir::Destination {
|
||||||
ident: Some(label_ident),
|
label: self.lower_label(Some(label)),
|
||||||
target_id: hir::ScopeTarget::Loop(target),
|
target_id: hir::ScopeTarget::Loop(target),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -798,7 +798,7 @@ impl<'a> LoweringContext<'a> {
|
||||||
.map(|innermost_loop_id| *innermost_loop_id);
|
.map(|innermost_loop_id| *innermost_loop_id);
|
||||||
|
|
||||||
hir::Destination {
|
hir::Destination {
|
||||||
ident: None,
|
label: None,
|
||||||
target_id: hir::ScopeTarget::Loop(
|
target_id: hir::ScopeTarget::Loop(
|
||||||
loop_id.map(|id| Ok(self.lower_node_id(id).node_id))
|
loop_id.map(|id| Ok(self.lower_node_id(id).node_id))
|
||||||
.unwrap_or(Err(hir::LoopIdError::OutsideLoopScope))
|
.unwrap_or(Err(hir::LoopIdError::OutsideLoopScope))
|
||||||
|
@ -2751,17 +2751,17 @@ impl<'a> LoweringContext<'a> {
|
||||||
|
|
||||||
hir::ExprIf(P(self.lower_expr(cond)), P(then_expr), else_opt)
|
hir::ExprIf(P(self.lower_expr(cond)), P(then_expr), else_opt)
|
||||||
}
|
}
|
||||||
ExprKind::While(ref cond, ref body, opt_ident) => {
|
ExprKind::While(ref cond, ref body, opt_label) => {
|
||||||
self.with_loop_scope(e.id, |this|
|
self.with_loop_scope(e.id, |this|
|
||||||
hir::ExprWhile(
|
hir::ExprWhile(
|
||||||
this.with_loop_condition_scope(|this| P(this.lower_expr(cond))),
|
this.with_loop_condition_scope(|this| P(this.lower_expr(cond))),
|
||||||
this.lower_block(body, false),
|
this.lower_block(body, false),
|
||||||
this.lower_opt_sp_ident(opt_ident)))
|
this.lower_label(opt_label)))
|
||||||
}
|
}
|
||||||
ExprKind::Loop(ref body, opt_ident) => {
|
ExprKind::Loop(ref body, opt_label) => {
|
||||||
self.with_loop_scope(e.id, |this|
|
self.with_loop_scope(e.id, |this|
|
||||||
hir::ExprLoop(this.lower_block(body, false),
|
hir::ExprLoop(this.lower_block(body, false),
|
||||||
this.lower_opt_sp_ident(opt_ident),
|
this.lower_label(opt_label),
|
||||||
hir::LoopSource::Loop))
|
hir::LoopSource::Loop))
|
||||||
}
|
}
|
||||||
ExprKind::Catch(ref body) => {
|
ExprKind::Catch(ref body) => {
|
||||||
|
@ -2877,30 +2877,30 @@ impl<'a> LoweringContext<'a> {
|
||||||
hir::ExprPath(self.lower_qpath(e.id, qself, path, ParamMode::Optional,
|
hir::ExprPath(self.lower_qpath(e.id, qself, path, ParamMode::Optional,
|
||||||
ImplTraitContext::Disallowed))
|
ImplTraitContext::Disallowed))
|
||||||
}
|
}
|
||||||
ExprKind::Break(opt_ident, ref opt_expr) => {
|
ExprKind::Break(opt_label, ref opt_expr) => {
|
||||||
let label_result = if self.is_in_loop_condition && opt_ident.is_none() {
|
let destination = if self.is_in_loop_condition && opt_label.is_none() {
|
||||||
hir::Destination {
|
hir::Destination {
|
||||||
ident: opt_ident,
|
label: None,
|
||||||
target_id: hir::ScopeTarget::Loop(
|
target_id: hir::ScopeTarget::Loop(
|
||||||
Err(hir::LoopIdError::UnlabeledCfInWhileCondition).into()),
|
Err(hir::LoopIdError::UnlabeledCfInWhileCondition).into()),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.lower_loop_destination(opt_ident.map(|ident| (e.id, ident)))
|
self.lower_loop_destination(opt_label.map(|label| (e.id, label)))
|
||||||
};
|
};
|
||||||
hir::ExprBreak(
|
hir::ExprBreak(
|
||||||
label_result,
|
destination,
|
||||||
opt_expr.as_ref().map(|x| P(self.lower_expr(x))))
|
opt_expr.as_ref().map(|x| P(self.lower_expr(x))))
|
||||||
}
|
}
|
||||||
ExprKind::Continue(opt_ident) =>
|
ExprKind::Continue(opt_label) =>
|
||||||
hir::ExprAgain(
|
hir::ExprAgain(
|
||||||
if self.is_in_loop_condition && opt_ident.is_none() {
|
if self.is_in_loop_condition && opt_label.is_none() {
|
||||||
hir::Destination {
|
hir::Destination {
|
||||||
ident: opt_ident,
|
label: None,
|
||||||
target_id: hir::ScopeTarget::Loop(Err(
|
target_id: hir::ScopeTarget::Loop(Err(
|
||||||
hir::LoopIdError::UnlabeledCfInWhileCondition).into()),
|
hir::LoopIdError::UnlabeledCfInWhileCondition).into()),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.lower_loop_destination(opt_ident.map( |ident| (e.id, ident)))
|
self.lower_loop_destination(opt_label.map(|label| (e.id, label)))
|
||||||
}),
|
}),
|
||||||
ExprKind::Ret(ref e) => hir::ExprRet(e.as_ref().map(|x| P(self.lower_expr(x)))),
|
ExprKind::Ret(ref e) => hir::ExprRet(e.as_ref().map(|x| P(self.lower_expr(x)))),
|
||||||
ExprKind::InlineAsm(ref asm) => {
|
ExprKind::InlineAsm(ref asm) => {
|
||||||
|
@ -3000,7 +3000,7 @@ impl<'a> LoweringContext<'a> {
|
||||||
|
|
||||||
// Desugar ExprWhileLet
|
// Desugar ExprWhileLet
|
||||||
// From: `[opt_ident]: while let <pat> = <sub_expr> <body>`
|
// From: `[opt_ident]: while let <pat> = <sub_expr> <body>`
|
||||||
ExprKind::WhileLet(ref pat, ref sub_expr, ref body, opt_ident) => {
|
ExprKind::WhileLet(ref pat, ref sub_expr, ref body, opt_label) => {
|
||||||
// to:
|
// to:
|
||||||
//
|
//
|
||||||
// [opt_ident]: loop {
|
// [opt_ident]: loop {
|
||||||
|
@ -3041,7 +3041,7 @@ impl<'a> LoweringContext<'a> {
|
||||||
|
|
||||||
// `[opt_ident]: loop { ... }`
|
// `[opt_ident]: loop { ... }`
|
||||||
let loop_block = P(self.block_expr(P(match_expr)));
|
let loop_block = P(self.block_expr(P(match_expr)));
|
||||||
let loop_expr = hir::ExprLoop(loop_block, self.lower_opt_sp_ident(opt_ident),
|
let loop_expr = hir::ExprLoop(loop_block, self.lower_label(opt_label),
|
||||||
hir::LoopSource::WhileLet);
|
hir::LoopSource::WhileLet);
|
||||||
// add attributes to the outer returned expr node
|
// add attributes to the outer returned expr node
|
||||||
loop_expr
|
loop_expr
|
||||||
|
@ -3049,7 +3049,7 @@ impl<'a> LoweringContext<'a> {
|
||||||
|
|
||||||
// Desugar ExprForLoop
|
// Desugar ExprForLoop
|
||||||
// From: `[opt_ident]: for <pat> in <head> <body>`
|
// From: `[opt_ident]: for <pat> in <head> <body>`
|
||||||
ExprKind::ForLoop(ref pat, ref head, ref body, opt_ident) => {
|
ExprKind::ForLoop(ref pat, ref head, ref body, opt_label) => {
|
||||||
// to:
|
// to:
|
||||||
//
|
//
|
||||||
// {
|
// {
|
||||||
|
@ -3150,7 +3150,7 @@ impl<'a> LoweringContext<'a> {
|
||||||
None));
|
None));
|
||||||
|
|
||||||
// `[opt_ident]: loop { ... }`
|
// `[opt_ident]: loop { ... }`
|
||||||
let loop_expr = hir::ExprLoop(loop_block, self.lower_opt_sp_ident(opt_ident),
|
let loop_expr = hir::ExprLoop(loop_block, self.lower_label(opt_label),
|
||||||
hir::LoopSource::ForLoop);
|
hir::LoopSource::ForLoop);
|
||||||
let LoweredNodeId { node_id, hir_id } = self.lower_node_id(e.id);
|
let LoweredNodeId { node_id, hir_id } = self.lower_node_id(e.id);
|
||||||
let loop_expr = P(hir::Expr {
|
let loop_expr = P(hir::Expr {
|
||||||
|
@ -3270,7 +3270,7 @@ impl<'a> LoweringContext<'a> {
|
||||||
e.span,
|
e.span,
|
||||||
hir::ExprBreak(
|
hir::ExprBreak(
|
||||||
hir::Destination {
|
hir::Destination {
|
||||||
ident: None,
|
label: None,
|
||||||
target_id: hir::ScopeTarget::Block(catch_node),
|
target_id: hir::ScopeTarget::Block(catch_node),
|
||||||
},
|
},
|
||||||
Some(from_err_expr)
|
Some(from_err_expr)
|
||||||
|
|
|
@ -34,7 +34,7 @@ use util::nodemap::{NodeMap, FxHashSet};
|
||||||
use syntax_pos::{Span, DUMMY_SP};
|
use syntax_pos::{Span, DUMMY_SP};
|
||||||
use syntax::codemap::{self, Spanned};
|
use syntax::codemap::{self, Spanned};
|
||||||
use syntax::abi::Abi;
|
use syntax::abi::Abi;
|
||||||
use syntax::ast::{self, Ident, Name, NodeId, DUMMY_NODE_ID, AsmDialect};
|
use syntax::ast::{self, Name, NodeId, DUMMY_NODE_ID, AsmDialect};
|
||||||
use syntax::ast::{Attribute, Lit, StrStyle, FloatTy, IntTy, UintTy, MetaItem};
|
use syntax::ast::{Attribute, Lit, StrStyle, FloatTy, IntTy, UintTy, MetaItem};
|
||||||
use syntax::ext::hygiene::SyntaxContext;
|
use syntax::ext::hygiene::SyntaxContext;
|
||||||
use syntax::ptr::P;
|
use syntax::ptr::P;
|
||||||
|
@ -172,6 +172,18 @@ pub const DUMMY_HIR_ID: HirId = HirId {
|
||||||
|
|
||||||
pub const DUMMY_ITEM_LOCAL_ID: ItemLocalId = ItemLocalId(!0);
|
pub const DUMMY_ITEM_LOCAL_ID: ItemLocalId = ItemLocalId(!0);
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)]
|
||||||
|
pub struct Label {
|
||||||
|
pub name: Name,
|
||||||
|
pub span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for Label {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "label({:?})", self.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)]
|
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)]
|
||||||
pub struct Lifetime {
|
pub struct Lifetime {
|
||||||
pub id: NodeId,
|
pub id: NodeId,
|
||||||
|
@ -1276,11 +1288,11 @@ pub enum Expr_ {
|
||||||
/// A while loop, with an optional label
|
/// A while loop, with an optional label
|
||||||
///
|
///
|
||||||
/// `'label: while expr { block }`
|
/// `'label: while expr { block }`
|
||||||
ExprWhile(P<Expr>, P<Block>, Option<Spanned<Name>>),
|
ExprWhile(P<Expr>, P<Block>, Option<Label>),
|
||||||
/// Conditionless loop (can be exited with break, continue, or return)
|
/// Conditionless loop (can be exited with break, continue, or return)
|
||||||
///
|
///
|
||||||
/// `'label: loop { block }`
|
/// `'label: loop { block }`
|
||||||
ExprLoop(P<Block>, Option<Spanned<Name>>, LoopSource),
|
ExprLoop(P<Block>, Option<Label>, LoopSource),
|
||||||
/// A `match` block, with a source that indicates whether or not it is
|
/// A `match` block, with a source that indicates whether or not it is
|
||||||
/// the result of a desugaring, and if so, which kind.
|
/// the result of a desugaring, and if so, which kind.
|
||||||
ExprMatch(P<Expr>, HirVec<Arm>, MatchSource),
|
ExprMatch(P<Expr>, HirVec<Arm>, MatchSource),
|
||||||
|
@ -1459,7 +1471,7 @@ impl ScopeTarget {
|
||||||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
|
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
|
||||||
pub struct Destination {
|
pub struct Destination {
|
||||||
// This is `Some(_)` iff there is an explicit user-specified `label
|
// This is `Some(_)` iff there is an explicit user-specified `label
|
||||||
pub ident: Option<Spanned<Ident>>,
|
pub label: Option<Label>,
|
||||||
|
|
||||||
// These errors are caught and then reported during the diagnostics pass in
|
// These errors are caught and then reported during the diagnostics pass in
|
||||||
// librustc_passes/loops.rs
|
// librustc_passes/loops.rs
|
||||||
|
|
|
@ -1337,9 +1337,9 @@ impl<'a> State<'a> {
|
||||||
hir::ExprIf(ref test, ref blk, ref elseopt) => {
|
hir::ExprIf(ref test, ref blk, ref elseopt) => {
|
||||||
self.print_if(&test, &blk, elseopt.as_ref().map(|e| &**e))?;
|
self.print_if(&test, &blk, elseopt.as_ref().map(|e| &**e))?;
|
||||||
}
|
}
|
||||||
hir::ExprWhile(ref test, ref blk, opt_sp_name) => {
|
hir::ExprWhile(ref test, ref blk, opt_label) => {
|
||||||
if let Some(sp_name) = opt_sp_name {
|
if let Some(label) = opt_label {
|
||||||
self.print_name(sp_name.node)?;
|
self.print_name(label.name)?;
|
||||||
self.word_space(":")?;
|
self.word_space(":")?;
|
||||||
}
|
}
|
||||||
self.head("while")?;
|
self.head("while")?;
|
||||||
|
@ -1347,9 +1347,9 @@ impl<'a> State<'a> {
|
||||||
self.s.space()?;
|
self.s.space()?;
|
||||||
self.print_block(&blk)?;
|
self.print_block(&blk)?;
|
||||||
}
|
}
|
||||||
hir::ExprLoop(ref blk, opt_sp_name, _) => {
|
hir::ExprLoop(ref blk, opt_label, _) => {
|
||||||
if let Some(sp_name) = opt_sp_name {
|
if let Some(label) = opt_label {
|
||||||
self.print_name(sp_name.node)?;
|
self.print_name(label.name)?;
|
||||||
self.word_space(":")?;
|
self.word_space(":")?;
|
||||||
}
|
}
|
||||||
self.head("loop")?;
|
self.head("loop")?;
|
||||||
|
@ -1424,11 +1424,11 @@ impl<'a> State<'a> {
|
||||||
hir::ExprPath(ref qpath) => {
|
hir::ExprPath(ref qpath) => {
|
||||||
self.print_qpath(qpath, true)?
|
self.print_qpath(qpath, true)?
|
||||||
}
|
}
|
||||||
hir::ExprBreak(label, ref opt_expr) => {
|
hir::ExprBreak(destination, ref opt_expr) => {
|
||||||
self.s.word("break")?;
|
self.s.word("break")?;
|
||||||
self.s.space()?;
|
self.s.space()?;
|
||||||
if let Some(label_ident) = label.ident {
|
if let Some(label) = destination.label {
|
||||||
self.print_name(label_ident.node.name)?;
|
self.print_name(label.name)?;
|
||||||
self.s.space()?;
|
self.s.space()?;
|
||||||
}
|
}
|
||||||
if let Some(ref expr) = *opt_expr {
|
if let Some(ref expr) = *opt_expr {
|
||||||
|
@ -1436,11 +1436,11 @@ impl<'a> State<'a> {
|
||||||
self.s.space()?;
|
self.s.space()?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hir::ExprAgain(label) => {
|
hir::ExprAgain(destination) => {
|
||||||
self.s.word("continue")?;
|
self.s.word("continue")?;
|
||||||
self.s.space()?;
|
self.s.space()?;
|
||||||
if let Some(label_ident) = label.ident {
|
if let Some(label) = destination.label {
|
||||||
self.print_name(label_ident.node.name)?;
|
self.print_name(label.name)?;
|
||||||
self.s.space()?
|
self.s.space()?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -148,6 +148,11 @@ impl_stable_hash_for!(enum hir::LifetimeName {
|
||||||
Name(name)
|
Name(name)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
impl_stable_hash_for!(struct hir::Label {
|
||||||
|
span,
|
||||||
|
name
|
||||||
|
});
|
||||||
|
|
||||||
impl_stable_hash_for!(struct hir::Lifetime {
|
impl_stable_hash_for!(struct hir::Lifetime {
|
||||||
id,
|
id,
|
||||||
span,
|
span,
|
||||||
|
@ -619,7 +624,7 @@ impl_stable_hash_for!(enum hir::CaptureClause {
|
||||||
impl_stable_hash_for_spanned!(usize);
|
impl_stable_hash_for_spanned!(usize);
|
||||||
|
|
||||||
impl_stable_hash_for!(struct hir::Destination {
|
impl_stable_hash_for!(struct hir::Destination {
|
||||||
ident,
|
label,
|
||||||
target_id
|
target_id
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1018,7 +1018,7 @@ fn extract_labels(ctxt: &mut LifetimeContext<'_, '_>, body: &hir::Body) {
|
||||||
fn expression_label(ex: &hir::Expr) -> Option<(ast::Name, Span)> {
|
fn expression_label(ex: &hir::Expr) -> Option<(ast::Name, Span)> {
|
||||||
match ex.node {
|
match ex.node {
|
||||||
hir::ExprWhile(.., Some(label)) | hir::ExprLoop(_, Some(label), _) => {
|
hir::ExprWhile(.., Some(label)) | hir::ExprLoop(_, Some(label), _) => {
|
||||||
Some((label.node, label.span))
|
Some((label.name, label.span))
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
|
|
|
@ -141,14 +141,6 @@ impl<'a> AstValidator<'a> {
|
||||||
impl<'a> Visitor<'a> for AstValidator<'a> {
|
impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||||
fn visit_expr(&mut self, expr: &'a Expr) {
|
fn visit_expr(&mut self, expr: &'a Expr) {
|
||||||
match expr.node {
|
match expr.node {
|
||||||
ExprKind::While(.., Some(ident)) |
|
|
||||||
ExprKind::Loop(_, Some(ident)) |
|
|
||||||
ExprKind::WhileLet(.., Some(ident)) |
|
|
||||||
ExprKind::ForLoop(.., Some(ident)) |
|
|
||||||
ExprKind::Break(Some(ident), _) |
|
|
||||||
ExprKind::Continue(Some(ident)) => {
|
|
||||||
self.check_label(ident.node, ident.span);
|
|
||||||
}
|
|
||||||
ExprKind::InlineAsm(..) if !self.session.target.target.options.allow_asm => {
|
ExprKind::InlineAsm(..) if !self.session.target.target.options.allow_asm => {
|
||||||
span_err!(self.session, expr.span, E0472, "asm! is unsupported on this target");
|
span_err!(self.session, expr.span, E0472, "asm! is unsupported on this target");
|
||||||
}
|
}
|
||||||
|
@ -211,6 +203,11 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||||
visit::walk_use_tree(self, use_tree, id);
|
visit::walk_use_tree(self, use_tree, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_label(&mut self, label: &'a Label) {
|
||||||
|
self.check_label(label.ident, label.span);
|
||||||
|
visit::walk_label(self, label);
|
||||||
|
}
|
||||||
|
|
||||||
fn visit_lifetime(&mut self, lifetime: &'a Lifetime) {
|
fn visit_lifetime(&mut self, lifetime: &'a Lifetime) {
|
||||||
self.check_lifetime(lifetime);
|
self.check_lifetime(lifetime);
|
||||||
visit::walk_lifetime(self, lifetime);
|
visit::walk_lifetime(self, lifetime);
|
||||||
|
|
|
@ -55,7 +55,7 @@ use syntax::attr;
|
||||||
use syntax::ast::{Arm, BindingMode, Block, Crate, Expr, ExprKind};
|
use syntax::ast::{Arm, BindingMode, Block, Crate, Expr, ExprKind};
|
||||||
use syntax::ast::{FnDecl, ForeignItem, ForeignItemKind, GenericParam, Generics};
|
use syntax::ast::{FnDecl, ForeignItem, ForeignItemKind, GenericParam, Generics};
|
||||||
use syntax::ast::{Item, ItemKind, ImplItem, ImplItemKind};
|
use syntax::ast::{Item, ItemKind, ImplItem, ImplItemKind};
|
||||||
use syntax::ast::{Local, Mutability, Pat, PatKind, Path};
|
use syntax::ast::{Label, Local, Mutability, Pat, PatKind, Path};
|
||||||
use syntax::ast::{QSelf, TraitItemKind, TraitRef, Ty, TyKind};
|
use syntax::ast::{QSelf, TraitItemKind, TraitRef, Ty, TyKind};
|
||||||
use syntax::feature_gate::{feature_err, emit_feature_err, GateIssue};
|
use syntax::feature_gate::{feature_err, emit_feature_err, GateIssue};
|
||||||
use syntax::parse::token;
|
use syntax::parse::token;
|
||||||
|
@ -3415,13 +3415,13 @@ impl<'a> Resolver<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_resolved_label<F>(&mut self, label: Option<SpannedIdent>, id: NodeId, f: F)
|
fn with_resolved_label<F>(&mut self, label: Option<Label>, id: NodeId, f: F)
|
||||||
where F: FnOnce(&mut Resolver)
|
where F: FnOnce(&mut Resolver)
|
||||||
{
|
{
|
||||||
if let Some(label) = label {
|
if let Some(label) = label {
|
||||||
let def = Def::Label(id);
|
let def = Def::Label(id);
|
||||||
self.with_label_rib(|this| {
|
self.with_label_rib(|this| {
|
||||||
this.label_ribs.last_mut().unwrap().bindings.insert(label.node, def);
|
this.label_ribs.last_mut().unwrap().bindings.insert(label.ident, def);
|
||||||
f(this);
|
f(this);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
@ -3429,7 +3429,7 @@ impl<'a> Resolver<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_labeled_block(&mut self, label: Option<SpannedIdent>, id: NodeId, block: &Block) {
|
fn resolve_labeled_block(&mut self, label: Option<Label>, id: NodeId, block: &Block) {
|
||||||
self.with_resolved_label(label, id, |this| this.visit_block(block));
|
self.with_resolved_label(label, id, |this| this.visit_block(block));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3452,19 +3452,19 @@ impl<'a> Resolver<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
ExprKind::Break(Some(label), _) | ExprKind::Continue(Some(label)) => {
|
ExprKind::Break(Some(label), _) | ExprKind::Continue(Some(label)) => {
|
||||||
match self.search_label(label.node, |rib, id| rib.bindings.get(&id).cloned()) {
|
match self.search_label(label.ident, |rib, id| rib.bindings.get(&id).cloned()) {
|
||||||
None => {
|
None => {
|
||||||
// Search again for close matches...
|
// Search again for close matches...
|
||||||
// Picks the first label that is "close enough", which is not necessarily
|
// Picks the first label that is "close enough", which is not necessarily
|
||||||
// the closest match
|
// the closest match
|
||||||
let close_match = self.search_label(label.node, |rib, ident| {
|
let close_match = self.search_label(label.ident, |rib, ident| {
|
||||||
let names = rib.bindings.iter().map(|(id, _)| &id.name);
|
let names = rib.bindings.iter().map(|(id, _)| &id.name);
|
||||||
find_best_match_for_name(names, &*ident.name.as_str(), None)
|
find_best_match_for_name(names, &*ident.name.as_str(), None)
|
||||||
});
|
});
|
||||||
self.record_def(expr.id, err_path_resolution());
|
self.record_def(expr.id, err_path_resolution());
|
||||||
resolve_error(self,
|
resolve_error(self,
|
||||||
label.span,
|
label.span,
|
||||||
ResolutionError::UndeclaredLabel(&label.node.name.as_str(),
|
ResolutionError::UndeclaredLabel(&label.ident.name.as_str(),
|
||||||
close_match));
|
close_match));
|
||||||
}
|
}
|
||||||
Some(def @ Def::Label(_)) => {
|
Some(def @ Def::Label(_)) => {
|
||||||
|
|
|
@ -33,6 +33,18 @@ use std::fmt;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::u32;
|
use std::u32;
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)]
|
||||||
|
pub struct Label {
|
||||||
|
pub ident: Ident,
|
||||||
|
pub span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for Label {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "label({:?})", self.ident)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)]
|
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)]
|
||||||
pub struct Lifetime {
|
pub struct Lifetime {
|
||||||
pub id: NodeId,
|
pub id: NodeId,
|
||||||
|
@ -1078,23 +1090,23 @@ pub enum ExprKind {
|
||||||
/// A while loop, with an optional label
|
/// A while loop, with an optional label
|
||||||
///
|
///
|
||||||
/// `'label: while expr { block }`
|
/// `'label: while expr { block }`
|
||||||
While(P<Expr>, P<Block>, Option<SpannedIdent>),
|
While(P<Expr>, P<Block>, Option<Label>),
|
||||||
/// A while-let loop, with an optional label
|
/// A while-let loop, with an optional label
|
||||||
///
|
///
|
||||||
/// `'label: while let pat = expr { block }`
|
/// `'label: while let pat = expr { block }`
|
||||||
///
|
///
|
||||||
/// This is desugared to a combination of `loop` and `match` expressions.
|
/// This is desugared to a combination of `loop` and `match` expressions.
|
||||||
WhileLet(P<Pat>, P<Expr>, P<Block>, Option<SpannedIdent>),
|
WhileLet(P<Pat>, P<Expr>, P<Block>, Option<Label>),
|
||||||
/// A for loop, with an optional label
|
/// A for loop, with an optional label
|
||||||
///
|
///
|
||||||
/// `'label: for pat in expr { block }`
|
/// `'label: for pat in expr { block }`
|
||||||
///
|
///
|
||||||
/// This is desugared to a combination of `loop` and `match` expressions.
|
/// This is desugared to a combination of `loop` and `match` expressions.
|
||||||
ForLoop(P<Pat>, P<Expr>, P<Block>, Option<SpannedIdent>),
|
ForLoop(P<Pat>, P<Expr>, P<Block>, Option<Label>),
|
||||||
/// Conditionless loop (can be exited with break, continue, or return)
|
/// Conditionless loop (can be exited with break, continue, or return)
|
||||||
///
|
///
|
||||||
/// `'label: loop { block }`
|
/// `'label: loop { block }`
|
||||||
Loop(P<Block>, Option<SpannedIdent>),
|
Loop(P<Block>, Option<Label>),
|
||||||
/// A `match` block.
|
/// A `match` block.
|
||||||
Match(P<Expr>, Vec<Arm>),
|
Match(P<Expr>, Vec<Arm>),
|
||||||
/// A closure (for example, `move |a, b, c| a + b + c`)
|
/// A closure (for example, `move |a, b, c| a + b + c`)
|
||||||
|
@ -1133,9 +1145,9 @@ pub enum ExprKind {
|
||||||
/// A referencing operation (`&a` or `&mut a`)
|
/// A referencing operation (`&a` or `&mut a`)
|
||||||
AddrOf(Mutability, P<Expr>),
|
AddrOf(Mutability, P<Expr>),
|
||||||
/// A `break`, with an optional label to break, and an optional expression
|
/// A `break`, with an optional label to break, and an optional expression
|
||||||
Break(Option<SpannedIdent>, Option<P<Expr>>),
|
Break(Option<Label>, Option<P<Expr>>),
|
||||||
/// A `continue`, with an optional label
|
/// A `continue`, with an optional label
|
||||||
Continue(Option<SpannedIdent>),
|
Continue(Option<Label>),
|
||||||
/// A `return`, with an optional value to be returned
|
/// A `return`, with an optional value to be returned
|
||||||
Ret(Option<P<Expr>>),
|
Ret(Option<P<Expr>>),
|
||||||
|
|
||||||
|
|
|
@ -193,6 +193,10 @@ pub trait Folder : Sized {
|
||||||
noop_fold_macro_def(def, self)
|
noop_fold_macro_def(def, self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fold_label(&mut self, label: Label) -> Label {
|
||||||
|
noop_fold_label(label, self)
|
||||||
|
}
|
||||||
|
|
||||||
fn fold_lifetime(&mut self, l: Lifetime) -> Lifetime {
|
fn fold_lifetime(&mut self, l: Lifetime) -> Lifetime {
|
||||||
noop_fold_lifetime(l, self)
|
noop_fold_lifetime(l, self)
|
||||||
}
|
}
|
||||||
|
@ -696,6 +700,13 @@ pub fn noop_fold_generic_params<T: Folder>(
|
||||||
params.move_map(|p| fld.fold_generic_param(p))
|
params.move_map(|p| fld.fold_generic_param(p))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn noop_fold_label<T: Folder>(label: Label, fld: &mut T) -> Label {
|
||||||
|
Label {
|
||||||
|
ident: fld.fold_ident(label.ident),
|
||||||
|
span: fld.new_span(label.span),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn noop_fold_lifetime<T: Folder>(l: Lifetime, fld: &mut T) -> Lifetime {
|
pub fn noop_fold_lifetime<T: Folder>(l: Lifetime, fld: &mut T) -> Lifetime {
|
||||||
Lifetime {
|
Lifetime {
|
||||||
id: fld.new_id(l.id),
|
id: fld.new_id(l.id),
|
||||||
|
@ -1206,30 +1217,26 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span, attrs}: Expr, folder: &mu
|
||||||
folder.fold_block(tr),
|
folder.fold_block(tr),
|
||||||
fl.map(|x| folder.fold_expr(x)))
|
fl.map(|x| folder.fold_expr(x)))
|
||||||
}
|
}
|
||||||
ExprKind::While(cond, body, opt_ident) => {
|
ExprKind::While(cond, body, opt_label) => {
|
||||||
ExprKind::While(folder.fold_expr(cond),
|
ExprKind::While(folder.fold_expr(cond),
|
||||||
folder.fold_block(body),
|
folder.fold_block(body),
|
||||||
opt_ident.map(|label| respan(folder.new_span(label.span),
|
opt_label.map(|label| folder.fold_label(label)))
|
||||||
folder.fold_ident(label.node))))
|
|
||||||
}
|
}
|
||||||
ExprKind::WhileLet(pat, expr, body, opt_ident) => {
|
ExprKind::WhileLet(pat, expr, body, opt_label) => {
|
||||||
ExprKind::WhileLet(folder.fold_pat(pat),
|
ExprKind::WhileLet(folder.fold_pat(pat),
|
||||||
folder.fold_expr(expr),
|
folder.fold_expr(expr),
|
||||||
folder.fold_block(body),
|
folder.fold_block(body),
|
||||||
opt_ident.map(|label| respan(folder.new_span(label.span),
|
opt_label.map(|label| folder.fold_label(label)))
|
||||||
folder.fold_ident(label.node))))
|
|
||||||
}
|
}
|
||||||
ExprKind::ForLoop(pat, iter, body, opt_ident) => {
|
ExprKind::ForLoop(pat, iter, body, opt_label) => {
|
||||||
ExprKind::ForLoop(folder.fold_pat(pat),
|
ExprKind::ForLoop(folder.fold_pat(pat),
|
||||||
folder.fold_expr(iter),
|
folder.fold_expr(iter),
|
||||||
folder.fold_block(body),
|
folder.fold_block(body),
|
||||||
opt_ident.map(|label| respan(folder.new_span(label.span),
|
opt_label.map(|label| folder.fold_label(label)))
|
||||||
folder.fold_ident(label.node))))
|
|
||||||
}
|
}
|
||||||
ExprKind::Loop(body, opt_ident) => {
|
ExprKind::Loop(body, opt_label) => {
|
||||||
ExprKind::Loop(folder.fold_block(body),
|
ExprKind::Loop(folder.fold_block(body),
|
||||||
opt_ident.map(|label| respan(folder.new_span(label.span),
|
opt_label.map(|label| folder.fold_label(label)))
|
||||||
folder.fold_ident(label.node))))
|
|
||||||
}
|
}
|
||||||
ExprKind::Match(expr, arms) => {
|
ExprKind::Match(expr, arms) => {
|
||||||
ExprKind::Match(folder.fold_expr(expr),
|
ExprKind::Match(folder.fold_expr(expr),
|
||||||
|
@ -1278,15 +1285,13 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span, attrs}: Expr, folder: &mu
|
||||||
});
|
});
|
||||||
ExprKind::Path(qself, folder.fold_path(path))
|
ExprKind::Path(qself, folder.fold_path(path))
|
||||||
}
|
}
|
||||||
ExprKind::Break(opt_ident, opt_expr) => {
|
ExprKind::Break(opt_label, opt_expr) => {
|
||||||
ExprKind::Break(opt_ident.map(|label| respan(folder.new_span(label.span),
|
ExprKind::Break(opt_label.map(|label| folder.fold_label(label)),
|
||||||
folder.fold_ident(label.node))),
|
|
||||||
opt_expr.map(|e| folder.fold_expr(e)))
|
opt_expr.map(|e| folder.fold_expr(e)))
|
||||||
}
|
}
|
||||||
ExprKind::Continue(opt_ident) => ExprKind::Continue(opt_ident.map(|label|
|
ExprKind::Continue(opt_label) => {
|
||||||
respan(folder.new_span(label.span),
|
ExprKind::Continue(opt_label.map(|label| folder.fold_label(label)))
|
||||||
folder.fold_ident(label.node)))
|
}
|
||||||
),
|
|
||||||
ExprKind::Ret(e) => ExprKind::Ret(e.map(|x| folder.fold_expr(x))),
|
ExprKind::Ret(e) => ExprKind::Ret(e.map(|x| folder.fold_expr(x))),
|
||||||
ExprKind::InlineAsm(asm) => ExprKind::InlineAsm(asm.map(|asm| {
|
ExprKind::InlineAsm(asm) => ExprKind::InlineAsm(asm.map(|asm| {
|
||||||
InlineAsm {
|
InlineAsm {
|
||||||
|
|
|
@ -23,7 +23,7 @@ use ast::{Field, FnDecl};
|
||||||
use ast::{ForeignItem, ForeignItemKind, FunctionRetTy};
|
use ast::{ForeignItem, ForeignItemKind, FunctionRetTy};
|
||||||
use ast::GenericParam;
|
use ast::GenericParam;
|
||||||
use ast::{Ident, ImplItem, IsAuto, Item, ItemKind};
|
use ast::{Ident, ImplItem, IsAuto, Item, ItemKind};
|
||||||
use ast::{Lifetime, LifetimeDef, Lit, LitKind, UintTy};
|
use ast::{Label, Lifetime, LifetimeDef, Lit, LitKind, UintTy};
|
||||||
use ast::Local;
|
use ast::Local;
|
||||||
use ast::MacStmtStyle;
|
use ast::MacStmtStyle;
|
||||||
use ast::Mac_;
|
use ast::Mac_;
|
||||||
|
@ -1325,15 +1325,17 @@ impl<'a> Parser<'a> {
|
||||||
self.check_keyword(keywords::Extern)
|
self.check_keyword(keywords::Extern)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_label(&mut self) -> ast::Ident {
|
fn eat_label(&mut self) -> Option<Label> {
|
||||||
match self.token {
|
let ident = match self.token {
|
||||||
token::Lifetime(ref ident) => *ident,
|
token::Lifetime(ref ident) => *ident,
|
||||||
token::Interpolated(ref nt) => match nt.0 {
|
token::Interpolated(ref nt) => match nt.0 {
|
||||||
token::NtLifetime(lifetime) => lifetime.ident,
|
token::NtLifetime(lifetime) => lifetime.ident,
|
||||||
_ => self.bug("not a lifetime"),
|
_ => return None,
|
||||||
},
|
},
|
||||||
_ => self.bug("not a lifetime"),
|
_ => return None,
|
||||||
}
|
};
|
||||||
|
self.bump();
|
||||||
|
Some(Label { ident, span: self.prev_span })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// parse a TyKind::BareFn type:
|
/// parse a TyKind::BareFn type:
|
||||||
|
@ -2317,11 +2319,8 @@ impl<'a> Parser<'a> {
|
||||||
let lo = self.prev_span;
|
let lo = self.prev_span;
|
||||||
return self.parse_while_expr(None, lo, attrs);
|
return self.parse_while_expr(None, lo, attrs);
|
||||||
}
|
}
|
||||||
if self.token.is_lifetime() {
|
if let Some(label) = self.eat_label() {
|
||||||
let label = Spanned { node: self.get_label(),
|
let lo = label.span;
|
||||||
span: self.span };
|
|
||||||
let lo = self.span;
|
|
||||||
self.bump();
|
|
||||||
self.expect(&token::Colon)?;
|
self.expect(&token::Colon)?;
|
||||||
if self.eat_keyword(keywords::While) {
|
if self.eat_keyword(keywords::While) {
|
||||||
return self.parse_while_expr(Some(label), lo, attrs)
|
return self.parse_while_expr(Some(label), lo, attrs)
|
||||||
|
@ -2339,16 +2338,8 @@ impl<'a> Parser<'a> {
|
||||||
return self.parse_loop_expr(None, lo, attrs);
|
return self.parse_loop_expr(None, lo, attrs);
|
||||||
}
|
}
|
||||||
if self.eat_keyword(keywords::Continue) {
|
if self.eat_keyword(keywords::Continue) {
|
||||||
let ex = if self.token.is_lifetime() {
|
let label = self.eat_label();
|
||||||
let ex = ExprKind::Continue(Some(Spanned{
|
let ex = ExprKind::Continue(label);
|
||||||
node: self.get_label(),
|
|
||||||
span: self.span
|
|
||||||
}));
|
|
||||||
self.bump();
|
|
||||||
ex
|
|
||||||
} else {
|
|
||||||
ExprKind::Continue(None)
|
|
||||||
};
|
|
||||||
let hi = self.prev_span;
|
let hi = self.prev_span;
|
||||||
return Ok(self.mk_expr(lo.to(hi), ex, attrs));
|
return Ok(self.mk_expr(lo.to(hi), ex, attrs));
|
||||||
}
|
}
|
||||||
|
@ -2376,16 +2367,7 @@ impl<'a> Parser<'a> {
|
||||||
ex = ExprKind::Ret(None);
|
ex = ExprKind::Ret(None);
|
||||||
}
|
}
|
||||||
} else if self.eat_keyword(keywords::Break) {
|
} else if self.eat_keyword(keywords::Break) {
|
||||||
let lt = if self.token.is_lifetime() {
|
let label = self.eat_label();
|
||||||
let spanned_lt = Spanned {
|
|
||||||
node: self.get_label(),
|
|
||||||
span: self.span
|
|
||||||
};
|
|
||||||
self.bump();
|
|
||||||
Some(spanned_lt)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
let e = if self.token.can_begin_expr()
|
let e = if self.token.can_begin_expr()
|
||||||
&& !(self.token == token::OpenDelim(token::Brace)
|
&& !(self.token == token::OpenDelim(token::Brace)
|
||||||
&& self.restrictions.contains(
|
&& self.restrictions.contains(
|
||||||
|
@ -2394,7 +2376,7 @@ impl<'a> Parser<'a> {
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
ex = ExprKind::Break(lt, e);
|
ex = ExprKind::Break(label, e);
|
||||||
hi = self.prev_span;
|
hi = self.prev_span;
|
||||||
} else if self.eat_keyword(keywords::Yield) {
|
} else if self.eat_keyword(keywords::Yield) {
|
||||||
if self.token.can_begin_expr() {
|
if self.token.can_begin_expr() {
|
||||||
|
@ -3291,7 +3273,7 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a 'for' .. 'in' expression ('for' token already eaten)
|
/// Parse a 'for' .. 'in' expression ('for' token already eaten)
|
||||||
pub fn parse_for_expr(&mut self, opt_ident: Option<ast::SpannedIdent>,
|
pub fn parse_for_expr(&mut self, opt_label: Option<Label>,
|
||||||
span_lo: Span,
|
span_lo: Span,
|
||||||
mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
|
mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
|
||||||
// Parse: `for <src_pat> in <src_expr> <src_loop_block>`
|
// Parse: `for <src_pat> in <src_expr> <src_loop_block>`
|
||||||
|
@ -3309,25 +3291,25 @@ impl<'a> Parser<'a> {
|
||||||
attrs.extend(iattrs);
|
attrs.extend(iattrs);
|
||||||
|
|
||||||
let hi = self.prev_span;
|
let hi = self.prev_span;
|
||||||
Ok(self.mk_expr(span_lo.to(hi), ExprKind::ForLoop(pat, expr, loop_block, opt_ident), attrs))
|
Ok(self.mk_expr(span_lo.to(hi), ExprKind::ForLoop(pat, expr, loop_block, opt_label), attrs))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a 'while' or 'while let' expression ('while' token already eaten)
|
/// Parse a 'while' or 'while let' expression ('while' token already eaten)
|
||||||
pub fn parse_while_expr(&mut self, opt_ident: Option<ast::SpannedIdent>,
|
pub fn parse_while_expr(&mut self, opt_label: Option<Label>,
|
||||||
span_lo: Span,
|
span_lo: Span,
|
||||||
mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
|
mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
|
||||||
if self.token.is_keyword(keywords::Let) {
|
if self.token.is_keyword(keywords::Let) {
|
||||||
return self.parse_while_let_expr(opt_ident, span_lo, attrs);
|
return self.parse_while_let_expr(opt_label, span_lo, attrs);
|
||||||
}
|
}
|
||||||
let cond = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?;
|
let cond = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?;
|
||||||
let (iattrs, body) = self.parse_inner_attrs_and_block()?;
|
let (iattrs, body) = self.parse_inner_attrs_and_block()?;
|
||||||
attrs.extend(iattrs);
|
attrs.extend(iattrs);
|
||||||
let span = span_lo.to(body.span);
|
let span = span_lo.to(body.span);
|
||||||
return Ok(self.mk_expr(span, ExprKind::While(cond, body, opt_ident), attrs));
|
return Ok(self.mk_expr(span, ExprKind::While(cond, body, opt_label), attrs));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a 'while let' expression ('while' token already eaten)
|
/// Parse a 'while let' expression ('while' token already eaten)
|
||||||
pub fn parse_while_let_expr(&mut self, opt_ident: Option<ast::SpannedIdent>,
|
pub fn parse_while_let_expr(&mut self, opt_label: Option<Label>,
|
||||||
span_lo: Span,
|
span_lo: Span,
|
||||||
mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
|
mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
|
||||||
self.expect_keyword(keywords::Let)?;
|
self.expect_keyword(keywords::Let)?;
|
||||||
|
@ -3337,17 +3319,17 @@ impl<'a> Parser<'a> {
|
||||||
let (iattrs, body) = self.parse_inner_attrs_and_block()?;
|
let (iattrs, body) = self.parse_inner_attrs_and_block()?;
|
||||||
attrs.extend(iattrs);
|
attrs.extend(iattrs);
|
||||||
let span = span_lo.to(body.span);
|
let span = span_lo.to(body.span);
|
||||||
return Ok(self.mk_expr(span, ExprKind::WhileLet(pat, expr, body, opt_ident), attrs));
|
return Ok(self.mk_expr(span, ExprKind::WhileLet(pat, expr, body, opt_label), attrs));
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse `loop {...}`, `loop` token already eaten
|
// parse `loop {...}`, `loop` token already eaten
|
||||||
pub fn parse_loop_expr(&mut self, opt_ident: Option<ast::SpannedIdent>,
|
pub fn parse_loop_expr(&mut self, opt_label: Option<Label>,
|
||||||
span_lo: Span,
|
span_lo: Span,
|
||||||
mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
|
mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
|
||||||
let (iattrs, body) = self.parse_inner_attrs_and_block()?;
|
let (iattrs, body) = self.parse_inner_attrs_and_block()?;
|
||||||
attrs.extend(iattrs);
|
attrs.extend(iattrs);
|
||||||
let span = span_lo.to(body.span);
|
let span = span_lo.to(body.span);
|
||||||
Ok(self.mk_expr(span, ExprKind::Loop(body, opt_ident), attrs))
|
Ok(self.mk_expr(span, ExprKind::Loop(body, opt_label), attrs))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a `do catch {...}` expression (`do catch` token already eaten)
|
/// Parse a `do catch {...}` expression (`do catch` token already eaten)
|
||||||
|
|
|
@ -2104,9 +2104,9 @@ impl<'a> State<'a> {
|
||||||
ast::ExprKind::IfLet(ref pat, ref expr, ref blk, ref elseopt) => {
|
ast::ExprKind::IfLet(ref pat, ref expr, ref blk, ref elseopt) => {
|
||||||
self.print_if_let(pat, expr, blk, elseopt.as_ref().map(|e| &**e))?;
|
self.print_if_let(pat, expr, blk, elseopt.as_ref().map(|e| &**e))?;
|
||||||
}
|
}
|
||||||
ast::ExprKind::While(ref test, ref blk, opt_ident) => {
|
ast::ExprKind::While(ref test, ref blk, opt_label) => {
|
||||||
if let Some(ident) = opt_ident {
|
if let Some(label) = opt_label {
|
||||||
self.print_ident(ident.node)?;
|
self.print_ident(label.ident)?;
|
||||||
self.word_space(":")?;
|
self.word_space(":")?;
|
||||||
}
|
}
|
||||||
self.head("while")?;
|
self.head("while")?;
|
||||||
|
@ -2114,9 +2114,9 @@ impl<'a> State<'a> {
|
||||||
self.s.space()?;
|
self.s.space()?;
|
||||||
self.print_block_with_attrs(blk, attrs)?;
|
self.print_block_with_attrs(blk, attrs)?;
|
||||||
}
|
}
|
||||||
ast::ExprKind::WhileLet(ref pat, ref expr, ref blk, opt_ident) => {
|
ast::ExprKind::WhileLet(ref pat, ref expr, ref blk, opt_label) => {
|
||||||
if let Some(ident) = opt_ident {
|
if let Some(label) = opt_label {
|
||||||
self.print_ident(ident.node)?;
|
self.print_ident(label.ident)?;
|
||||||
self.word_space(":")?;
|
self.word_space(":")?;
|
||||||
}
|
}
|
||||||
self.head("while let")?;
|
self.head("while let")?;
|
||||||
|
@ -2127,9 +2127,9 @@ impl<'a> State<'a> {
|
||||||
self.s.space()?;
|
self.s.space()?;
|
||||||
self.print_block_with_attrs(blk, attrs)?;
|
self.print_block_with_attrs(blk, attrs)?;
|
||||||
}
|
}
|
||||||
ast::ExprKind::ForLoop(ref pat, ref iter, ref blk, opt_ident) => {
|
ast::ExprKind::ForLoop(ref pat, ref iter, ref blk, opt_label) => {
|
||||||
if let Some(ident) = opt_ident {
|
if let Some(label) = opt_label {
|
||||||
self.print_ident(ident.node)?;
|
self.print_ident(label.ident)?;
|
||||||
self.word_space(":")?;
|
self.word_space(":")?;
|
||||||
}
|
}
|
||||||
self.head("for")?;
|
self.head("for")?;
|
||||||
|
@ -2140,9 +2140,9 @@ impl<'a> State<'a> {
|
||||||
self.s.space()?;
|
self.s.space()?;
|
||||||
self.print_block_with_attrs(blk, attrs)?;
|
self.print_block_with_attrs(blk, attrs)?;
|
||||||
}
|
}
|
||||||
ast::ExprKind::Loop(ref blk, opt_ident) => {
|
ast::ExprKind::Loop(ref blk, opt_label) => {
|
||||||
if let Some(ident) = opt_ident {
|
if let Some(label) = opt_label {
|
||||||
self.print_ident(ident.node)?;
|
self.print_ident(label.ident)?;
|
||||||
self.word_space(":")?;
|
self.word_space(":")?;
|
||||||
}
|
}
|
||||||
self.head("loop")?;
|
self.head("loop")?;
|
||||||
|
@ -2238,11 +2238,11 @@ impl<'a> State<'a> {
|
||||||
ast::ExprKind::Path(Some(ref qself), ref path) => {
|
ast::ExprKind::Path(Some(ref qself), ref path) => {
|
||||||
self.print_qpath(path, qself, true)?
|
self.print_qpath(path, qself, true)?
|
||||||
}
|
}
|
||||||
ast::ExprKind::Break(opt_ident, ref opt_expr) => {
|
ast::ExprKind::Break(opt_label, ref opt_expr) => {
|
||||||
self.s.word("break")?;
|
self.s.word("break")?;
|
||||||
self.s.space()?;
|
self.s.space()?;
|
||||||
if let Some(ident) = opt_ident {
|
if let Some(label) = opt_label {
|
||||||
self.print_ident(ident.node)?;
|
self.print_ident(label.ident)?;
|
||||||
self.s.space()?;
|
self.s.space()?;
|
||||||
}
|
}
|
||||||
if let Some(ref expr) = *opt_expr {
|
if let Some(ref expr) = *opt_expr {
|
||||||
|
@ -2250,11 +2250,11 @@ impl<'a> State<'a> {
|
||||||
self.s.space()?;
|
self.s.space()?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::ExprKind::Continue(opt_ident) => {
|
ast::ExprKind::Continue(opt_label) => {
|
||||||
self.s.word("continue")?;
|
self.s.word("continue")?;
|
||||||
self.s.space()?;
|
self.s.space()?;
|
||||||
if let Some(ident) = opt_ident {
|
if let Some(label) = opt_label {
|
||||||
self.print_ident(ident.node)?;
|
self.print_ident(label.ident)?;
|
||||||
self.s.space()?
|
self.s.space()?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,6 +101,9 @@ pub trait Visitor<'ast>: Sized {
|
||||||
fn visit_variant(&mut self, v: &'ast Variant, g: &'ast Generics, item_id: NodeId) {
|
fn visit_variant(&mut self, v: &'ast Variant, g: &'ast Generics, item_id: NodeId) {
|
||||||
walk_variant(self, v, g, item_id)
|
walk_variant(self, v, g, item_id)
|
||||||
}
|
}
|
||||||
|
fn visit_label(&mut self, label: &'ast Label) {
|
||||||
|
walk_label(self, label)
|
||||||
|
}
|
||||||
fn visit_lifetime(&mut self, lifetime: &'ast Lifetime) {
|
fn visit_lifetime(&mut self, lifetime: &'ast Lifetime) {
|
||||||
walk_lifetime(self, lifetime)
|
walk_lifetime(self, lifetime)
|
||||||
}
|
}
|
||||||
|
@ -163,25 +166,6 @@ macro_rules! walk_list {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn walk_opt_name<'a, V: Visitor<'a>>(visitor: &mut V, span: Span, opt_name: Option<Name>) {
|
|
||||||
if let Some(name) = opt_name {
|
|
||||||
visitor.visit_name(span, name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn walk_opt_ident<'a, V: Visitor<'a>>(visitor: &mut V, span: Span, opt_ident: Option<Ident>) {
|
|
||||||
if let Some(ident) = opt_ident {
|
|
||||||
visitor.visit_ident(span, ident);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn walk_opt_sp_ident<'a, V: Visitor<'a>>(visitor: &mut V,
|
|
||||||
opt_sp_ident: &Option<Spanned<Ident>>) {
|
|
||||||
if let Some(ref sp_ident) = *opt_sp_ident {
|
|
||||||
visitor.visit_ident(sp_ident.span, sp_ident.node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn walk_ident<'a, V: Visitor<'a>>(visitor: &mut V, span: Span, ident: Ident) {
|
pub fn walk_ident<'a, V: Visitor<'a>>(visitor: &mut V, span: Span, ident: Ident) {
|
||||||
visitor.visit_name(span, ident.name);
|
visitor.visit_name(span, ident.name);
|
||||||
}
|
}
|
||||||
|
@ -204,6 +188,10 @@ pub fn walk_local<'a, V: Visitor<'a>>(visitor: &mut V, local: &'a Local) {
|
||||||
walk_list!(visitor, visit_expr, &local.init);
|
walk_list!(visitor, visit_expr, &local.init);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn walk_label<'a, V: Visitor<'a>>(visitor: &mut V, label: &'a Label) {
|
||||||
|
visitor.visit_ident(label.span, label.ident);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn walk_lifetime<'a, V: Visitor<'a>>(visitor: &mut V, lifetime: &'a Lifetime) {
|
pub fn walk_lifetime<'a, V: Visitor<'a>>(visitor: &mut V, lifetime: &'a Lifetime) {
|
||||||
visitor.visit_ident(lifetime.span, lifetime.ident);
|
visitor.visit_ident(lifetime.span, lifetime.ident);
|
||||||
}
|
}
|
||||||
|
@ -226,7 +214,9 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
|
||||||
visitor.visit_ident(item.span, item.ident);
|
visitor.visit_ident(item.span, item.ident);
|
||||||
match item.node {
|
match item.node {
|
||||||
ItemKind::ExternCrate(opt_name) => {
|
ItemKind::ExternCrate(opt_name) => {
|
||||||
walk_opt_name(visitor, item.span, opt_name)
|
if let Some(name) = opt_name {
|
||||||
|
visitor.visit_name(item.span, name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ItemKind::Use(ref use_tree) => {
|
ItemKind::Use(ref use_tree) => {
|
||||||
visitor.visit_use_tree(use_tree, item.id, false)
|
visitor.visit_use_tree(use_tree, item.id, false)
|
||||||
|
@ -622,7 +612,9 @@ pub fn walk_struct_def<'a, V: Visitor<'a>>(visitor: &mut V, struct_definition: &
|
||||||
|
|
||||||
pub fn walk_struct_field<'a, V: Visitor<'a>>(visitor: &mut V, struct_field: &'a StructField) {
|
pub fn walk_struct_field<'a, V: Visitor<'a>>(visitor: &mut V, struct_field: &'a StructField) {
|
||||||
visitor.visit_vis(&struct_field.vis);
|
visitor.visit_vis(&struct_field.vis);
|
||||||
walk_opt_ident(visitor, struct_field.span, struct_field.ident);
|
if let Some(ident) = struct_field.ident {
|
||||||
|
visitor.visit_ident(struct_field.span, ident);
|
||||||
|
}
|
||||||
visitor.visit_ty(&struct_field.ty);
|
visitor.visit_ty(&struct_field.ty);
|
||||||
walk_list!(visitor, visit_attribute, &struct_field.attrs);
|
walk_list!(visitor, visit_attribute, &struct_field.attrs);
|
||||||
}
|
}
|
||||||
|
@ -708,10 +700,10 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
|
||||||
visitor.visit_block(if_block);
|
visitor.visit_block(if_block);
|
||||||
walk_list!(visitor, visit_expr, optional_else);
|
walk_list!(visitor, visit_expr, optional_else);
|
||||||
}
|
}
|
||||||
ExprKind::While(ref subexpression, ref block, ref opt_sp_ident) => {
|
ExprKind::While(ref subexpression, ref block, ref opt_label) => {
|
||||||
|
walk_list!(visitor, visit_label, opt_label);
|
||||||
visitor.visit_expr(subexpression);
|
visitor.visit_expr(subexpression);
|
||||||
visitor.visit_block(block);
|
visitor.visit_block(block);
|
||||||
walk_opt_sp_ident(visitor, opt_sp_ident);
|
|
||||||
}
|
}
|
||||||
ExprKind::IfLet(ref pattern, ref subexpression, ref if_block, ref optional_else) => {
|
ExprKind::IfLet(ref pattern, ref subexpression, ref if_block, ref optional_else) => {
|
||||||
visitor.visit_pat(pattern);
|
visitor.visit_pat(pattern);
|
||||||
|
@ -719,21 +711,21 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
|
||||||
visitor.visit_block(if_block);
|
visitor.visit_block(if_block);
|
||||||
walk_list!(visitor, visit_expr, optional_else);
|
walk_list!(visitor, visit_expr, optional_else);
|
||||||
}
|
}
|
||||||
ExprKind::WhileLet(ref pattern, ref subexpression, ref block, ref opt_sp_ident) => {
|
ExprKind::WhileLet(ref pattern, ref subexpression, ref block, ref opt_label) => {
|
||||||
|
walk_list!(visitor, visit_label, opt_label);
|
||||||
visitor.visit_pat(pattern);
|
visitor.visit_pat(pattern);
|
||||||
visitor.visit_expr(subexpression);
|
visitor.visit_expr(subexpression);
|
||||||
visitor.visit_block(block);
|
visitor.visit_block(block);
|
||||||
walk_opt_sp_ident(visitor, opt_sp_ident);
|
|
||||||
}
|
}
|
||||||
ExprKind::ForLoop(ref pattern, ref subexpression, ref block, ref opt_sp_ident) => {
|
ExprKind::ForLoop(ref pattern, ref subexpression, ref block, ref opt_label) => {
|
||||||
|
walk_list!(visitor, visit_label, opt_label);
|
||||||
visitor.visit_pat(pattern);
|
visitor.visit_pat(pattern);
|
||||||
visitor.visit_expr(subexpression);
|
visitor.visit_expr(subexpression);
|
||||||
visitor.visit_block(block);
|
visitor.visit_block(block);
|
||||||
walk_opt_sp_ident(visitor, opt_sp_ident);
|
|
||||||
}
|
}
|
||||||
ExprKind::Loop(ref block, ref opt_sp_ident) => {
|
ExprKind::Loop(ref block, ref opt_label) => {
|
||||||
|
walk_list!(visitor, visit_label, opt_label);
|
||||||
visitor.visit_block(block);
|
visitor.visit_block(block);
|
||||||
walk_opt_sp_ident(visitor, opt_sp_ident);
|
|
||||||
}
|
}
|
||||||
ExprKind::Match(ref subexpression, ref arms) => {
|
ExprKind::Match(ref subexpression, ref arms) => {
|
||||||
visitor.visit_expr(subexpression);
|
visitor.visit_expr(subexpression);
|
||||||
|
@ -775,12 +767,12 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
|
||||||
}
|
}
|
||||||
visitor.visit_path(path, expression.id)
|
visitor.visit_path(path, expression.id)
|
||||||
}
|
}
|
||||||
ExprKind::Break(ref opt_sp_ident, ref opt_expr) => {
|
ExprKind::Break(ref opt_label, ref opt_expr) => {
|
||||||
walk_opt_sp_ident(visitor, opt_sp_ident);
|
walk_list!(visitor, visit_label, opt_label);
|
||||||
walk_list!(visitor, visit_expr, opt_expr);
|
walk_list!(visitor, visit_expr, opt_expr);
|
||||||
}
|
}
|
||||||
ExprKind::Continue(ref opt_sp_ident) => {
|
ExprKind::Continue(ref opt_label) => {
|
||||||
walk_opt_sp_ident(visitor, opt_sp_ident);
|
walk_list!(visitor, visit_label, opt_label);
|
||||||
}
|
}
|
||||||
ExprKind::Ret(ref optional_expression) => {
|
ExprKind::Ret(ref optional_expression) => {
|
||||||
walk_list!(visitor, visit_expr, optional_expression);
|
walk_list!(visitor, visit_expr, optional_expression);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue