about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>2018-01-16 01:44:32 +0300
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>2018-01-22 23:13:12 +0300
commit2d56abfbebdc905dafc9cf9edc0a6f58e4de7cbd (patch)
treecdef1c08f23c517c133ca7a266f5622a218fb393 /src/libsyntax
parentfdc18b3067b5bad257ccbe7400e3c4fb617e9e18 (diff)
downloadrust-2d56abfbebdc905dafc9cf9edc0a6f58e4de7cbd.tar.gz
rust-2d56abfbebdc905dafc9cf9edc0a6f58e4de7cbd.zip
AST/HIR: Add a separate structure for labels
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ast.rs24
-rw-r--r--src/libsyntax/fold.rs43
-rw-r--r--src/libsyntax/parse/parser.rs64
-rw-r--r--src/libsyntax/print/pprust.rs36
-rw-r--r--src/libsyntax/visit.rs58
5 files changed, 108 insertions, 117 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index a64f1e9e400..926997f6567 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 c304e3a9f50..b94e8f5389b 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),
@@ -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 {
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 3d58104260f..174ebc46e86 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:
@@ -2319,11 +2321,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)
@@ -2341,16 +2340,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));
                 }
@@ -2378,16 +2369,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(
@@ -2396,7 +2378,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() {
@@ -3284,7 +3266,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>`
@@ -3302,25 +3284,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)?;
@@ -3330,17 +3312,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 ff065b57b8d..e7c2fd1ca09 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")?;
@@ -2237,11 +2237,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 {
@@ -2249,11 +2249,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 b5fc9236ad3..6d68c20770f 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);