diff options
| author | Alex Crichton <alex@alexcrichton.com> | 2018-01-25 12:48:49 -0600 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-01-25 12:48:49 -0600 |
| commit | 98b375483c44c68009d699a4cd4b7b0a3d5d97a3 (patch) | |
| tree | 1cba42b1aa98db0d012cbecfb36d7d2dea428232 | |
| parent | 304885d959cae6b1fd6cb9aa64b70df6269d04b4 (diff) | |
| parent | 2d56abfbebdc905dafc9cf9edc0a6f58e4de7cbd (diff) | |
| download | rust-98b375483c44c68009d699a4cd4b7b0a3d5d97a3.tar.gz rust-98b375483c44c68009d699a4cd4b7b0a3d5d97a3.zip | |
Rollup merge of #47502 - petrochenkov:label, r=eddyb
AST/HIR: Add a separate structure for labels
| -rw-r--r-- | src/librustc/hir/intravisit.rs | 52 | ||||
| -rw-r--r-- | src/librustc/hir/lowering.rs | 48 | ||||
| -rw-r--r-- | src/librustc/hir/mod.rs | 20 | ||||
| -rw-r--r-- | src/librustc/hir/print.rs | 24 | ||||
| -rw-r--r-- | src/librustc/ich/impls_hir.rs | 7 | ||||
| -rw-r--r-- | src/librustc/middle/resolve_lifetime.rs | 2 | ||||
| -rw-r--r-- | src/librustc_passes/ast_validation.rs | 13 | ||||
| -rw-r--r-- | src/librustc_resolve/lib.rs | 14 | ||||
| -rw-r--r-- | src/libsyntax/ast.rs | 24 | ||||
| -rw-r--r-- | src/libsyntax/fold.rs | 43 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 64 | ||||
| -rw-r--r-- | src/libsyntax/print/pprust.rs | 36 | ||||
| -rw-r--r-- | src/libsyntax/visit.rs | 58 |
13 files changed, 203 insertions, 202 deletions
diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index ce35e6552ca..97cf9b01410 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -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); diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index e76f39a8fb1..dc2f2583c01 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -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) diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 8921fecf1b8..2854b9da147 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -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; @@ -173,6 +173,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, pub span: Span, @@ -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 diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index 4cfa7a470a4..30c1ad01d14 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.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()? } } diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index 59d9db48bdc..7dca96f94e6 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -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 }); diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index 935dfd75dd8..944d7705163 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -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, } diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 3f49128d2e8..6971033c899 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -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); diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 55c7e5f3924..1df19b6b678 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -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(_)) => { diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index d6e26057ea8..73810b3fe81 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -34,6 +34,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, pub span: Span, @@ -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>>), diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 1e605ba3ecd..0f8fe57e380 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -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 { diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 8213d604b91..d393cab4718 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -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) diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 345c592a011..ae459c668aa 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -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()? } } diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 8aeacf79cee..bbb123dab28 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -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); |
