提交 2d56abfb 编写于 作者: V Vadim Petrochenkov

AST/HIR: Add a separate structure for labels

上级 fdc18b30
......@@ -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 @@ fn visit_enum_def(&mut self,
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 @@ fn visit_defaultness(&mut self, defaultness: &'v Defaultness) {
}
}
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);
......
......@@ -768,22 +768,22 @@ fn lower_ident(&mut self, ident: Ident) -> Name {
*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),
}
},
......@@ -793,7 +793,7 @@ fn lower_loop_destination(&mut self, destination: Option<(NodeId, Spanned<Ident>
.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))
......@@ -2746,17 +2746,17 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
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) => {
......@@ -2860,30 +2860,30 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
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) => {
......@@ -2983,7 +2983,7 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
// 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 {
......@@ -3024,7 +3024,7 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
// `[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
......@@ -3032,7 +3032,7 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
// 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:
//
// {
......@@ -3133,7 +3133,7 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
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 {
......@@ -3253,7 +3253,7 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
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 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 @@ fn index(self) -> usize {
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 @@ pub fn opt_id(self) -> Option<NodeId> {
#[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 @@ pub fn print_expr(&mut self, expr: &hir::Expr) -> io::Result<()> {
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 @@ pub fn print_expr(&mut self, expr: &hir::Expr) -> io::Result<()> {
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 @@ pub fn print_expr(&mut self, expr: &hir::Expr) -> io::Result<()> {
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 @@ pub fn print_expr(&mut self, expr: &hir::Expr) -> io::Result<()> {
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 @@ fn hash_stable<W: StableHasherResult>(&self,
Name(name)
});
impl_stable_hash_for!(struct hir::Label {
span,
name
});
impl_stable_hash_for!(struct hir::Lifetime {
id,
span,
......@@ -614,7 +619,7 @@ fn hash_stable<W: StableHasherResult>(&self,
impl_stable_hash_for_spanned!(usize);
impl_stable_hash_for!(struct hir::Destination {
ident,
label,
target_id
});
......
......@@ -1018,7 +1018,7 @@ fn visit_expr(&mut self, ex: &hir::Expr) {
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 @@ fn check_expr_within_pat(&self, expr: &Expr, allow_paths: bool) {
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 @@ fn visit_use_tree(&mut self, use_tree: &'a UseTree, id: NodeId, _nested: bool) {
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::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;
......@@ -3354,13 +3354,13 @@ fn lookup_typo_candidate<FilterFn>(&mut self,
}
}
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 {
......@@ -3368,7 +3368,7 @@ fn with_resolved_label<F>(&mut self, label: Option<SpannedIdent>, id: NodeId, f:
}
}
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));
}
......@@ -3391,19 +3391,19 @@ fn resolve_expr(&mut self, expr: &Expr, parent: Option<&Expr>) {
}
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::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 @@ fn fold_macro_def(&mut self, def: MacroDef) -> MacroDef {
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),
......@@ -1277,15 +1284,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::{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 @@ pub fn token_is_bare_fn_keyword(&mut self) -> bool {
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:
......@@ -2319,11 +2321,8 @@ fn parse_bottom_expr(&mut self) -> PResult<'a, P<Expr>> {
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)
......@@ -2341,16 +2340,8 @@ fn parse_bottom_expr(&mut self) -> PResult<'a, P<Expr>> {
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));
}
......@@ -2378,16 +2369,7 @@ fn parse_bottom_expr(&mut self) -> PResult<'a, P<Expr>> {
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(
......@@ -2396,7 +2378,7 @@ fn parse_bottom_expr(&mut self) -> PResult<'a, P<Expr>> {
} 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() {
......@@ -3284,7 +3266,7 @@ pub fn parse_else_expr(&mut self) -> PResult<'a, P<Expr>> {
}
/// 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>`
......@@ -3302,25 +3284,25 @@ pub fn parse_for_expr(&mut self, opt_ident: Option<ast::SpannedIdent>,
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)?;
......@@ -3330,17 +3312,17 @@ pub fn parse_while_let_expr(&mut self, opt_ident: Option<ast::SpannedIdent>,
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 @@ fn print_expr_outer_attr_style(&mut self,
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 @@ fn print_expr_outer_attr_style(&mut self,
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 @@ fn print_expr_outer_attr_style(&mut self,
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 @@ fn print_expr_outer_attr_style(&mut self,
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")?;
......@@ -2237,11 +2237,11 @@ fn print_expr_outer_attr_style(&mut self,
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 {
......@@ -2249,11 +2249,11 @@ fn print_expr_outer_attr_style(&mut self,
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 @@ fn visit_enum_def(&mut self, enum_definition: &'ast EnumDef,
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 @@ fn visit_fn_ret_ty(&mut self, ret_ty: &'ast FunctionRetTy) {
}
}
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);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册