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::ast::{NodeId, CRATE_NODE_ID, Name, Attribute};
|
||||
use syntax::codemap::Spanned;
|
||||
use syntax_pos::Span;
|
||||
use hir::*;
|
||||
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) {
|
||||
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) {
|
||||
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`.
|
||||
pub fn walk_crate<'v, V: Visitor<'v>>(visitor: &mut V, krate: &'v Crate) {
|
||||
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);
|
||||
}
|
||||
|
||||
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) {
|
||||
visitor.visit_id(lifetime.id);
|
||||
match lifetime.name {
|
||||
|
@ -452,7 +446,9 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
|
|||
match item.node {
|
||||
ItemExternCrate(opt_name) => {
|
||||
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, _) => {
|
||||
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);
|
||||
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_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);
|
||||
walk_opt_sp_name(visitor, opt_sp_name);
|
||||
}
|
||||
ExprMatch(ref subexpression, ref arms, _) => {
|
||||
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) => {
|
||||
visitor.visit_qpath(qpath, expression.id, expression.span);
|
||||
}
|
||||
ExprBreak(label, ref opt_expr) => {
|
||||
label.ident.map(|ident| {
|
||||
match label.target_id {
|
||||
ExprBreak(ref destination, ref opt_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(_)) => {},
|
||||
};
|
||||
visitor.visit_name(ident.span, ident.node.name);
|
||||
});
|
||||
}
|
||||
walk_list!(visitor, visit_expr, opt_expr);
|
||||
}
|
||||
ExprAgain(label) => {
|
||||
label.ident.map(|ident| {
|
||||
match label.target_id {
|
||||
ExprAgain(ref destination) => {
|
||||
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(_)) => {},
|
||||
};
|
||||
visitor.visit_name(ident.span, ident.node.name);
|
||||
});
|
||||
}
|
||||
}
|
||||
ExprRet(ref 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))
|
||||
}
|
||||
|
||||
fn lower_opt_sp_ident(&mut self, o_id: Option<Spanned<Ident>>) -> Option<Spanned<Name>> {
|
||||
o_id.map(|sp_ident| respan(sp_ident.span, sp_ident.node.name))
|
||||
fn lower_label(&mut self, label: Option<Label>) -> Option<hir::Label> {
|
||||
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
|
||||
{
|
||||
match destination {
|
||||
Some((id, label_ident)) => {
|
||||
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)
|
||||
} else {
|
||||
hir::LoopIdResult::Err(hir::LoopIdError::UnresolvedLabel)
|
||||
};
|
||||
hir::Destination {
|
||||
ident: Some(label_ident),
|
||||
label: self.lower_label(Some(label)),
|
||||
target_id: hir::ScopeTarget::Loop(target),
|
||||
}
|
||||
},
|
||||
|
@ -798,7 +798,7 @@ impl<'a> LoweringContext<'a> {
|
|||
.map(|innermost_loop_id| *innermost_loop_id);
|
||||
|
||||
hir::Destination {
|
||||
ident: None,
|
||||
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))
|
||||
|
@ -2751,17 +2751,17 @@ impl<'a> LoweringContext<'a> {
|
|||
|
||||
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|
|
||||
hir::ExprWhile(
|
||||
this.with_loop_condition_scope(|this| P(this.lower_expr(cond))),
|
||||
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|
|
||||
hir::ExprLoop(this.lower_block(body, false),
|
||||
this.lower_opt_sp_ident(opt_ident),
|
||||
this.lower_label(opt_label),
|
||||
hir::LoopSource::Loop))
|
||||
}
|
||||
ExprKind::Catch(ref body) => {
|
||||
|
@ -2877,30 +2877,30 @@ impl<'a> LoweringContext<'a> {
|
|||
hir::ExprPath(self.lower_qpath(e.id, qself, path, ParamMode::Optional,
|
||||
ImplTraitContext::Disallowed))
|
||||
}
|
||||
ExprKind::Break(opt_ident, ref opt_expr) => {
|
||||
let label_result = if self.is_in_loop_condition && opt_ident.is_none() {
|
||||
ExprKind::Break(opt_label, ref opt_expr) => {
|
||||
let destination = if self.is_in_loop_condition && opt_label.is_none() {
|
||||
hir::Destination {
|
||||
ident: opt_ident,
|
||||
label: None,
|
||||
target_id: hir::ScopeTarget::Loop(
|
||||
Err(hir::LoopIdError::UnlabeledCfInWhileCondition).into()),
|
||||
}
|
||||
} 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(
|
||||
label_result,
|
||||
destination,
|
||||
opt_expr.as_ref().map(|x| P(self.lower_expr(x))))
|
||||
}
|
||||
ExprKind::Continue(opt_ident) =>
|
||||
ExprKind::Continue(opt_label) =>
|
||||
hir::ExprAgain(
|
||||
if self.is_in_loop_condition && opt_ident.is_none() {
|
||||
if self.is_in_loop_condition && opt_label.is_none() {
|
||||
hir::Destination {
|
||||
ident: opt_ident,
|
||||
label: None,
|
||||
target_id: hir::ScopeTarget::Loop(Err(
|
||||
hir::LoopIdError::UnlabeledCfInWhileCondition).into()),
|
||||
}
|
||||
} 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::InlineAsm(ref asm) => {
|
||||
|
@ -3000,7 +3000,7 @@ impl<'a> LoweringContext<'a> {
|
|||
|
||||
// Desugar ExprWhileLet
|
||||
// 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:
|
||||
//
|
||||
// [opt_ident]: loop {
|
||||
|
@ -3041,7 +3041,7 @@ impl<'a> LoweringContext<'a> {
|
|||
|
||||
// `[opt_ident]: loop { ... }`
|
||||
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);
|
||||
// add attributes to the outer returned expr node
|
||||
loop_expr
|
||||
|
@ -3049,7 +3049,7 @@ impl<'a> LoweringContext<'a> {
|
|||
|
||||
// Desugar ExprForLoop
|
||||
// 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:
|
||||
//
|
||||
// {
|
||||
|
@ -3150,7 +3150,7 @@ impl<'a> LoweringContext<'a> {
|
|||
None));
|
||||
|
||||
// `[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);
|
||||
let LoweredNodeId { node_id, hir_id } = self.lower_node_id(e.id);
|
||||
let loop_expr = P(hir::Expr {
|
||||
|
@ -3270,7 +3270,7 @@ impl<'a> LoweringContext<'a> {
|
|||
e.span,
|
||||
hir::ExprBreak(
|
||||
hir::Destination {
|
||||
ident: None,
|
||||
label: None,
|
||||
target_id: hir::ScopeTarget::Block(catch_node),
|
||||
},
|
||||
Some(from_err_expr)
|
||||
|
|
|
@ -34,7 +34,7 @@ use util::nodemap::{NodeMap, FxHashSet};
|
|||
use syntax_pos::{Span, DUMMY_SP};
|
||||
use syntax::codemap::{self, Spanned};
|
||||
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::ext::hygiene::SyntaxContext;
|
||||
use syntax::ptr::P;
|
||||
|
@ -172,6 +172,18 @@ pub const DUMMY_HIR_ID: HirId = HirId {
|
|||
|
||||
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)]
|
||||
pub struct Lifetime {
|
||||
pub id: NodeId,
|
||||
|
@ -1276,11 +1288,11 @@ pub enum Expr_ {
|
|||
/// A while loop, with an optional label
|
||||
///
|
||||
/// `'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)
|
||||
///
|
||||
/// `'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
|
||||
/// the result of a desugaring, and if so, which kind.
|
||||
ExprMatch(P<Expr>, HirVec<Arm>, MatchSource),
|
||||
|
@ -1459,7 +1471,7 @@ impl ScopeTarget {
|
|||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
|
||||
pub struct Destination {
|
||||
// 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
|
||||
// librustc_passes/loops.rs
|
||||
|
|
|
@ -1337,9 +1337,9 @@ impl<'a> State<'a> {
|
|||
hir::ExprIf(ref test, ref blk, ref elseopt) => {
|
||||
self.print_if(&test, &blk, elseopt.as_ref().map(|e| &**e))?;
|
||||
}
|
||||
hir::ExprWhile(ref test, ref blk, opt_sp_name) => {
|
||||
if let Some(sp_name) = opt_sp_name {
|
||||
self.print_name(sp_name.node)?;
|
||||
hir::ExprWhile(ref test, ref blk, opt_label) => {
|
||||
if let Some(label) = opt_label {
|
||||
self.print_name(label.name)?;
|
||||
self.word_space(":")?;
|
||||
}
|
||||
self.head("while")?;
|
||||
|
@ -1347,9 +1347,9 @@ impl<'a> State<'a> {
|
|||
self.s.space()?;
|
||||
self.print_block(&blk)?;
|
||||
}
|
||||
hir::ExprLoop(ref blk, opt_sp_name, _) => {
|
||||
if let Some(sp_name) = opt_sp_name {
|
||||
self.print_name(sp_name.node)?;
|
||||
hir::ExprLoop(ref blk, opt_label, _) => {
|
||||
if let Some(label) = opt_label {
|
||||
self.print_name(label.name)?;
|
||||
self.word_space(":")?;
|
||||
}
|
||||
self.head("loop")?;
|
||||
|
@ -1424,11 +1424,11 @@ impl<'a> State<'a> {
|
|||
hir::ExprPath(ref qpath) => {
|
||||
self.print_qpath(qpath, true)?
|
||||
}
|
||||
hir::ExprBreak(label, ref opt_expr) => {
|
||||
hir::ExprBreak(destination, ref opt_expr) => {
|
||||
self.s.word("break")?;
|
||||
self.s.space()?;
|
||||
if let Some(label_ident) = label.ident {
|
||||
self.print_name(label_ident.node.name)?;
|
||||
if let Some(label) = destination.label {
|
||||
self.print_name(label.name)?;
|
||||
self.s.space()?;
|
||||
}
|
||||
if let Some(ref expr) = *opt_expr {
|
||||
|
@ -1436,11 +1436,11 @@ impl<'a> State<'a> {
|
|||
self.s.space()?;
|
||||
}
|
||||
}
|
||||
hir::ExprAgain(label) => {
|
||||
hir::ExprAgain(destination) => {
|
||||
self.s.word("continue")?;
|
||||
self.s.space()?;
|
||||
if let Some(label_ident) = label.ident {
|
||||
self.print_name(label_ident.node.name)?;
|
||||
if let Some(label) = destination.label {
|
||||
self.print_name(label.name)?;
|
||||
self.s.space()?
|
||||
}
|
||||
}
|
||||
|
|
|
@ -148,6 +148,11 @@ impl_stable_hash_for!(enum hir::LifetimeName {
|
|||
Name(name)
|
||||
});
|
||||
|
||||
impl_stable_hash_for!(struct hir::Label {
|
||||
span,
|
||||
name
|
||||
});
|
||||
|
||||
impl_stable_hash_for!(struct hir::Lifetime {
|
||||
id,
|
||||
span,
|
||||
|
@ -619,7 +624,7 @@ impl_stable_hash_for!(enum hir::CaptureClause {
|
|||
impl_stable_hash_for_spanned!(usize);
|
||||
|
||||
impl_stable_hash_for!(struct hir::Destination {
|
||||
ident,
|
||||
label,
|
||||
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)> {
|
||||
match ex.node {
|
||||
hir::ExprWhile(.., Some(label)) | hir::ExprLoop(_, Some(label), _) => {
|
||||
Some((label.node, label.span))
|
||||
Some((label.name, label.span))
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
|
|
|
@ -141,14 +141,6 @@ impl<'a> AstValidator<'a> {
|
|||
impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||
fn visit_expr(&mut self, expr: &'a Expr) {
|
||||
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 => {
|
||||
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);
|
||||
}
|
||||
|
||||
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) {
|
||||
self.check_lifetime(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::{FnDecl, ForeignItem, ForeignItemKind, GenericParam, Generics};
|
||||
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::feature_gate::{feature_err, emit_feature_err, GateIssue};
|
||||
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)
|
||||
{
|
||||
if let Some(label) = label {
|
||||
let def = Def::Label(id);
|
||||
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);
|
||||
});
|
||||
} 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));
|
||||
}
|
||||
|
||||
|
@ -3452,19 +3452,19 @@ impl<'a> Resolver<'a> {
|
|||
}
|
||||
|
||||
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 => {
|
||||
// Search again for close matches...
|
||||
// Picks the first label that is "close enough", which is not necessarily
|
||||
// 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);
|
||||
find_best_match_for_name(names, &*ident.name.as_str(), None)
|
||||
});
|
||||
self.record_def(expr.id, err_path_resolution());
|
||||
resolve_error(self,
|
||||
label.span,
|
||||
ResolutionError::UndeclaredLabel(&label.node.name.as_str(),
|
||||
ResolutionError::UndeclaredLabel(&label.ident.name.as_str(),
|
||||
close_match));
|
||||
}
|
||||
Some(def @ Def::Label(_)) => {
|
||||
|
|
|
@ -33,6 +33,18 @@ use std::fmt;
|
|||
use std::rc::Rc;
|
||||
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)]
|
||||
pub struct Lifetime {
|
||||
pub id: NodeId,
|
||||
|
@ -1078,23 +1090,23 @@ pub enum ExprKind {
|
|||
/// A while loop, with an optional label
|
||||
///
|
||||
/// `'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
|
||||
///
|
||||
/// `'label: while let pat = expr { block }`
|
||||
///
|
||||
/// 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
|
||||
///
|
||||
/// `'label: for pat in expr { block }`
|
||||
///
|
||||
/// 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)
|
||||
///
|
||||
/// `'label: loop { block }`
|
||||
Loop(P<Block>, Option<SpannedIdent>),
|
||||
Loop(P<Block>, Option<Label>),
|
||||
/// A `match` block.
|
||||
Match(P<Expr>, Vec<Arm>),
|
||||
/// 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`)
|
||||
AddrOf(Mutability, P<Expr>),
|
||||
/// 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
|
||||
Continue(Option<SpannedIdent>),
|
||||
Continue(Option<Label>),
|
||||
/// A `return`, with an optional value to be returned
|
||||
Ret(Option<P<Expr>>),
|
||||
|
||||
|
|
|
@ -193,6 +193,10 @@ pub trait Folder : Sized {
|
|||
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 {
|
||||
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))
|
||||
}
|
||||
|
||||
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 {
|
||||
Lifetime {
|
||||
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),
|
||||
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),
|
||||
folder.fold_block(body),
|
||||
opt_ident.map(|label| respan(folder.new_span(label.span),
|
||||
folder.fold_ident(label.node))))
|
||||
opt_label.map(|label| folder.fold_label(label)))
|
||||
}
|
||||
ExprKind::WhileLet(pat, expr, body, opt_ident) => {
|
||||
ExprKind::WhileLet(pat, expr, body, opt_label) => {
|
||||
ExprKind::WhileLet(folder.fold_pat(pat),
|
||||
folder.fold_expr(expr),
|
||||
folder.fold_block(body),
|
||||
opt_ident.map(|label| respan(folder.new_span(label.span),
|
||||
folder.fold_ident(label.node))))
|
||||
opt_label.map(|label| folder.fold_label(label)))
|
||||
}
|
||||
ExprKind::ForLoop(pat, iter, body, opt_ident) => {
|
||||
ExprKind::ForLoop(pat, iter, body, opt_label) => {
|
||||
ExprKind::ForLoop(folder.fold_pat(pat),
|
||||
folder.fold_expr(iter),
|
||||
folder.fold_block(body),
|
||||
opt_ident.map(|label| respan(folder.new_span(label.span),
|
||||
folder.fold_ident(label.node))))
|
||||
opt_label.map(|label| folder.fold_label(label)))
|
||||
}
|
||||
ExprKind::Loop(body, opt_ident) => {
|
||||
ExprKind::Loop(body, opt_label) => {
|
||||
ExprKind::Loop(folder.fold_block(body),
|
||||
opt_ident.map(|label| respan(folder.new_span(label.span),
|
||||
folder.fold_ident(label.node))))
|
||||
opt_label.map(|label| folder.fold_label(label)))
|
||||
}
|
||||
ExprKind::Match(expr, arms) => {
|
||||
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::Break(opt_ident, opt_expr) => {
|
||||
ExprKind::Break(opt_ident.map(|label| respan(folder.new_span(label.span),
|
||||
folder.fold_ident(label.node))),
|
||||
ExprKind::Break(opt_label, opt_expr) => {
|
||||
ExprKind::Break(opt_label.map(|label| folder.fold_label(label)),
|
||||
opt_expr.map(|e| folder.fold_expr(e)))
|
||||
}
|
||||
ExprKind::Continue(opt_ident) => ExprKind::Continue(opt_ident.map(|label|
|
||||
respan(folder.new_span(label.span),
|
||||
folder.fold_ident(label.node)))
|
||||
),
|
||||
ExprKind::Continue(opt_label) => {
|
||||
ExprKind::Continue(opt_label.map(|label| folder.fold_label(label)))
|
||||
}
|
||||
ExprKind::Ret(e) => ExprKind::Ret(e.map(|x| folder.fold_expr(x))),
|
||||
ExprKind::InlineAsm(asm) => ExprKind::InlineAsm(asm.map(|asm| {
|
||||
InlineAsm {
|
||||
|
|
|
@ -23,7 +23,7 @@ use ast::{Field, FnDecl};
|
|||
use ast::{ForeignItem, ForeignItemKind, FunctionRetTy};
|
||||
use ast::GenericParam;
|
||||
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::MacStmtStyle;
|
||||
use ast::Mac_;
|
||||
|
@ -1325,15 +1325,17 @@ impl<'a> Parser<'a> {
|
|||
self.check_keyword(keywords::Extern)
|
||||
}
|
||||
|
||||
fn get_label(&mut self) -> ast::Ident {
|
||||
match self.token {
|
||||
fn eat_label(&mut self) -> Option<Label> {
|
||||
let ident = match self.token {
|
||||
token::Lifetime(ref ident) => *ident,
|
||||
token::Interpolated(ref nt) => match nt.0 {
|
||||
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:
|
||||
|
@ -2317,11 +2319,8 @@ impl<'a> Parser<'a> {
|
|||
let lo = self.prev_span;
|
||||
return self.parse_while_expr(None, lo, attrs);
|
||||
}
|
||||
if self.token.is_lifetime() {
|
||||
let label = Spanned { node: self.get_label(),
|
||||
span: self.span };
|
||||
let lo = self.span;
|
||||
self.bump();
|
||||
if let Some(label) = self.eat_label() {
|
||||
let lo = label.span;
|
||||
self.expect(&token::Colon)?;
|
||||
if self.eat_keyword(keywords::While) {
|
||||
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);
|
||||
}
|
||||
if self.eat_keyword(keywords::Continue) {
|
||||
let ex = if self.token.is_lifetime() {
|
||||
let ex = ExprKind::Continue(Some(Spanned{
|
||||
node: self.get_label(),
|
||||
span: self.span
|
||||
}));
|
||||
self.bump();
|
||||
ex
|
||||
} else {
|
||||
ExprKind::Continue(None)
|
||||
};
|
||||
let label = self.eat_label();
|
||||
let ex = ExprKind::Continue(label);
|
||||
let hi = self.prev_span;
|
||||
return Ok(self.mk_expr(lo.to(hi), ex, attrs));
|
||||
}
|
||||
|
@ -2376,16 +2367,7 @@ impl<'a> Parser<'a> {
|
|||
ex = ExprKind::Ret(None);
|
||||
}
|
||||
} else if self.eat_keyword(keywords::Break) {
|
||||
let lt = if self.token.is_lifetime() {
|
||||
let spanned_lt = Spanned {
|
||||
node: self.get_label(),
|
||||
span: self.span
|
||||
};
|
||||
self.bump();
|
||||
Some(spanned_lt)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let label = self.eat_label();
|
||||
let e = if self.token.can_begin_expr()
|
||||
&& !(self.token == token::OpenDelim(token::Brace)
|
||||
&& self.restrictions.contains(
|
||||
|
@ -2394,7 +2376,7 @@ impl<'a> Parser<'a> {
|
|||
} else {
|
||||
None
|
||||
};
|
||||
ex = ExprKind::Break(lt, e);
|
||||
ex = ExprKind::Break(label, e);
|
||||
hi = self.prev_span;
|
||||
} else if self.eat_keyword(keywords::Yield) {
|
||||
if self.token.can_begin_expr() {
|
||||
|
@ -3291,7 +3273,7 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
|
||||
/// 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,
|
||||
mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
|
||||
// Parse: `for <src_pat> in <src_expr> <src_loop_block>`
|
||||
|
@ -3309,25 +3291,25 @@ impl<'a> Parser<'a> {
|
|||
attrs.extend(iattrs);
|
||||
|
||||
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)
|
||||
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,
|
||||
mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
|
||||
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 (iattrs, body) = self.parse_inner_attrs_and_block()?;
|
||||
attrs.extend(iattrs);
|
||||
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)
|
||||
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,
|
||||
mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
|
||||
self.expect_keyword(keywords::Let)?;
|
||||
|
@ -3337,17 +3319,17 @@ impl<'a> Parser<'a> {
|
|||
let (iattrs, body) = self.parse_inner_attrs_and_block()?;
|
||||
attrs.extend(iattrs);
|
||||
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
|
||||
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,
|
||||
mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
|
||||
let (iattrs, body) = self.parse_inner_attrs_and_block()?;
|
||||
attrs.extend(iattrs);
|
||||
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)
|
||||
|
|
|
@ -2104,9 +2104,9 @@ impl<'a> State<'a> {
|
|||
ast::ExprKind::IfLet(ref pat, ref expr, ref blk, ref elseopt) => {
|
||||
self.print_if_let(pat, expr, blk, elseopt.as_ref().map(|e| &**e))?;
|
||||
}
|
||||
ast::ExprKind::While(ref test, ref blk, opt_ident) => {
|
||||
if let Some(ident) = opt_ident {
|
||||
self.print_ident(ident.node)?;
|
||||
ast::ExprKind::While(ref test, ref blk, opt_label) => {
|
||||
if let Some(label) = opt_label {
|
||||
self.print_ident(label.ident)?;
|
||||
self.word_space(":")?;
|
||||
}
|
||||
self.head("while")?;
|
||||
|
@ -2114,9 +2114,9 @@ impl<'a> State<'a> {
|
|||
self.s.space()?;
|
||||
self.print_block_with_attrs(blk, attrs)?;
|
||||
}
|
||||
ast::ExprKind::WhileLet(ref pat, ref expr, ref blk, opt_ident) => {
|
||||
if let Some(ident) = opt_ident {
|
||||
self.print_ident(ident.node)?;
|
||||
ast::ExprKind::WhileLet(ref pat, ref expr, ref blk, opt_label) => {
|
||||
if let Some(label) = opt_label {
|
||||
self.print_ident(label.ident)?;
|
||||
self.word_space(":")?;
|
||||
}
|
||||
self.head("while let")?;
|
||||
|
@ -2127,9 +2127,9 @@ impl<'a> State<'a> {
|
|||
self.s.space()?;
|
||||
self.print_block_with_attrs(blk, attrs)?;
|
||||
}
|
||||
ast::ExprKind::ForLoop(ref pat, ref iter, ref blk, opt_ident) => {
|
||||
if let Some(ident) = opt_ident {
|
||||
self.print_ident(ident.node)?;
|
||||
ast::ExprKind::ForLoop(ref pat, ref iter, ref blk, opt_label) => {
|
||||
if let Some(label) = opt_label {
|
||||
self.print_ident(label.ident)?;
|
||||
self.word_space(":")?;
|
||||
}
|
||||
self.head("for")?;
|
||||
|
@ -2140,9 +2140,9 @@ impl<'a> State<'a> {
|
|||
self.s.space()?;
|
||||
self.print_block_with_attrs(blk, attrs)?;
|
||||
}
|
||||
ast::ExprKind::Loop(ref blk, opt_ident) => {
|
||||
if let Some(ident) = opt_ident {
|
||||
self.print_ident(ident.node)?;
|
||||
ast::ExprKind::Loop(ref blk, opt_label) => {
|
||||
if let Some(label) = opt_label {
|
||||
self.print_ident(label.ident)?;
|
||||
self.word_space(":")?;
|
||||
}
|
||||
self.head("loop")?;
|
||||
|
@ -2238,11 +2238,11 @@ impl<'a> State<'a> {
|
|||
ast::ExprKind::Path(Some(ref qself), ref path) => {
|
||||
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.space()?;
|
||||
if let Some(ident) = opt_ident {
|
||||
self.print_ident(ident.node)?;
|
||||
if let Some(label) = opt_label {
|
||||
self.print_ident(label.ident)?;
|
||||
self.s.space()?;
|
||||
}
|
||||
if let Some(ref expr) = *opt_expr {
|
||||
|
@ -2250,11 +2250,11 @@ impl<'a> State<'a> {
|
|||
self.s.space()?;
|
||||
}
|
||||
}
|
||||
ast::ExprKind::Continue(opt_ident) => {
|
||||
ast::ExprKind::Continue(opt_label) => {
|
||||
self.s.word("continue")?;
|
||||
self.s.space()?;
|
||||
if let Some(ident) = opt_ident {
|
||||
self.print_ident(ident.node)?;
|
||||
if let Some(label) = opt_label {
|
||||
self.print_ident(label.ident)?;
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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);
|
||||
}
|
||||
|
||||
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) {
|
||||
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);
|
||||
match item.node {
|
||||
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) => {
|
||||
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) {
|
||||
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);
|
||||
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);
|
||||
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_block(block);
|
||||
walk_opt_sp_ident(visitor, opt_sp_ident);
|
||||
}
|
||||
ExprKind::IfLet(ref pattern, ref subexpression, ref if_block, ref optional_else) => {
|
||||
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);
|
||||
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_expr(subexpression);
|
||||
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_expr(subexpression);
|
||||
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);
|
||||
walk_opt_sp_ident(visitor, opt_sp_ident);
|
||||
}
|
||||
ExprKind::Match(ref subexpression, ref arms) => {
|
||||
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)
|
||||
}
|
||||
ExprKind::Break(ref opt_sp_ident, ref opt_expr) => {
|
||||
walk_opt_sp_ident(visitor, opt_sp_ident);
|
||||
ExprKind::Break(ref opt_label, ref opt_expr) => {
|
||||
walk_list!(visitor, visit_label, opt_label);
|
||||
walk_list!(visitor, visit_expr, opt_expr);
|
||||
}
|
||||
ExprKind::Continue(ref opt_sp_ident) => {
|
||||
walk_opt_sp_ident(visitor, opt_sp_ident);
|
||||
ExprKind::Continue(ref opt_label) => {
|
||||
walk_list!(visitor, visit_label, opt_label);
|
||||
}
|
||||
ExprKind::Ret(ref optional_expression) => {
|
||||
walk_list!(visitor, visit_expr, optional_expression);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue