syntax/hir: give loop labels a span
This makes the "shadowing labels" warning *not* print the entire loop as a span, but only the lifetime. Also makes #31719 go away, but does not fix its root cause (the span of the expanded loop is still wonky, but not used anymore).
This commit is contained in:
parent
dd6e8d45e1
commit
2e812e10f4
14 changed files with 99 additions and 83 deletions
|
@ -1009,11 +1009,15 @@ pub fn noop_fold_expr<T: Folder>(Expr { id, node, span, attrs }: Expr, folder: &
|
||||||
ExprWhile(cond, body, opt_name) => {
|
ExprWhile(cond, body, opt_name) => {
|
||||||
ExprWhile(folder.fold_expr(cond),
|
ExprWhile(folder.fold_expr(cond),
|
||||||
folder.fold_block(body),
|
folder.fold_block(body),
|
||||||
opt_name.map(|i| folder.fold_name(i)))
|
opt_name.map(|label| {
|
||||||
|
respan(folder.new_span(label.span), folder.fold_name(label.node))
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
ExprLoop(body, opt_name) => {
|
ExprLoop(body, opt_name) => {
|
||||||
ExprLoop(folder.fold_block(body),
|
ExprLoop(folder.fold_block(body),
|
||||||
opt_name.map(|i| folder.fold_name(i)))
|
opt_name.map(|label| {
|
||||||
|
respan(folder.new_span(label.span), folder.fold_name(label.node))
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
ExprMatch(expr, arms, source) => {
|
ExprMatch(expr, arms, source) => {
|
||||||
ExprMatch(folder.fold_expr(expr),
|
ExprMatch(folder.fold_expr(expr),
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
use syntax::abi::Abi;
|
use syntax::abi::Abi;
|
||||||
use syntax::ast::{NodeId, CRATE_NODE_ID, Name, Attribute};
|
use syntax::ast::{NodeId, CRATE_NODE_ID, Name, Attribute};
|
||||||
use syntax::attr::ThinAttributesExt;
|
use syntax::attr::ThinAttributesExt;
|
||||||
use syntax::codemap::Span;
|
use syntax::codemap::{Span, Spanned};
|
||||||
use hir::*;
|
use hir::*;
|
||||||
|
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
|
@ -203,11 +203,17 @@ pub trait Visitor<'v> : Sized {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn walk_opt_name<'v, V: Visitor<'v>>(visitor: &mut V, span: Span, opt_name: Option<Name>) {
|
pub fn walk_opt_name<'v, V: Visitor<'v>>(visitor: &mut V, span: Span, opt_name: Option<Name>) {
|
||||||
for name in opt_name {
|
if let Some(name) = opt_name {
|
||||||
visitor.visit_name(span, name);
|
visitor.visit_name(span, name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn walk_opt_sp_name<'v, V: Visitor<'v>>(visitor: &mut V, opt_sp_name: &Option<Spanned<Name>>) {
|
||||||
|
if let Some(ref sp_name) = *opt_sp_name {
|
||||||
|
visitor.visit_name(sp_name.span, sp_name.node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Walks the contents of a crate. See also `Crate::visit_all_items`.
|
/// Walks the contents of a crate. See also `Crate::visit_all_items`.
|
||||||
pub fn walk_crate<'v, V: Visitor<'v>>(visitor: &mut V, krate: &'v Crate) {
|
pub fn walk_crate<'v, V: Visitor<'v>>(visitor: &mut V, krate: &'v Crate) {
|
||||||
visitor.visit_mod(&krate.module, krate.span, CRATE_NODE_ID);
|
visitor.visit_mod(&krate.module, krate.span, CRATE_NODE_ID);
|
||||||
|
@ -737,14 +743,14 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
|
||||||
visitor.visit_block(if_block);
|
visitor.visit_block(if_block);
|
||||||
walk_list!(visitor, visit_expr, optional_else);
|
walk_list!(visitor, visit_expr, optional_else);
|
||||||
}
|
}
|
||||||
ExprWhile(ref subexpression, ref block, opt_name) => {
|
ExprWhile(ref subexpression, ref block, ref opt_sp_name) => {
|
||||||
visitor.visit_expr(subexpression);
|
visitor.visit_expr(subexpression);
|
||||||
visitor.visit_block(block);
|
visitor.visit_block(block);
|
||||||
walk_opt_name(visitor, expression.span, opt_name)
|
walk_opt_sp_name(visitor, opt_sp_name);
|
||||||
}
|
}
|
||||||
ExprLoop(ref block, opt_name) => {
|
ExprLoop(ref block, ref opt_sp_name) => {
|
||||||
visitor.visit_block(block);
|
visitor.visit_block(block);
|
||||||
walk_opt_name(visitor, expression.span, opt_name)
|
walk_opt_sp_name(visitor, opt_sp_name);
|
||||||
}
|
}
|
||||||
ExprMatch(ref subexpression, ref arms, _) => {
|
ExprMatch(ref subexpression, ref arms, _) => {
|
||||||
visitor.visit_expr(subexpression);
|
visitor.visit_expr(subexpression);
|
||||||
|
@ -784,9 +790,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
|
||||||
visitor.visit_path(path, expression.id)
|
visitor.visit_path(path, expression.id)
|
||||||
}
|
}
|
||||||
ExprBreak(ref opt_sp_name) | ExprAgain(ref opt_sp_name) => {
|
ExprBreak(ref opt_sp_name) | ExprAgain(ref opt_sp_name) => {
|
||||||
for sp_name in opt_sp_name {
|
walk_opt_sp_name(visitor, opt_sp_name);
|
||||||
visitor.visit_name(sp_name.span, sp_name.node);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ExprRet(ref optional_expression) => {
|
ExprRet(ref optional_expression) => {
|
||||||
walk_list!(visitor, visit_expr, optional_expression);
|
walk_list!(visitor, visit_expr, optional_expression);
|
||||||
|
|
|
@ -192,6 +192,10 @@ impl<'a> LoweringContext<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn lower_opt_sp_ident(&mut self, o_id: Option<Spanned<Ident>>) -> Option<Spanned<Name>> {
|
||||||
|
o_id.map(|sp_ident| respan(sp_ident.span, self.lower_ident(sp_ident.node)))
|
||||||
|
}
|
||||||
|
|
||||||
fn lower_attrs(&mut self, attrs: &Vec<Attribute>) -> hir::HirVec<Attribute> {
|
fn lower_attrs(&mut self, attrs: &Vec<Attribute>) -> hir::HirVec<Attribute> {
|
||||||
attrs.clone().into()
|
attrs.clone().into()
|
||||||
}
|
}
|
||||||
|
@ -1122,11 +1126,10 @@ impl<'a> LoweringContext<'a> {
|
||||||
}
|
}
|
||||||
ExprKind::While(ref cond, ref body, opt_ident) => {
|
ExprKind::While(ref cond, ref body, opt_ident) => {
|
||||||
hir::ExprWhile(self.lower_expr(cond), self.lower_block(body),
|
hir::ExprWhile(self.lower_expr(cond), self.lower_block(body),
|
||||||
opt_ident.map(|ident| self.lower_ident(ident)))
|
self.lower_opt_sp_ident(opt_ident))
|
||||||
}
|
}
|
||||||
ExprKind::Loop(ref body, opt_ident) => {
|
ExprKind::Loop(ref body, opt_ident) => {
|
||||||
hir::ExprLoop(self.lower_block(body),
|
hir::ExprLoop(self.lower_block(body), self.lower_opt_sp_ident(opt_ident))
|
||||||
opt_ident.map(|ident| self.lower_ident(ident)))
|
|
||||||
}
|
}
|
||||||
ExprKind::Match(ref expr, ref arms) => {
|
ExprKind::Match(ref expr, ref arms) => {
|
||||||
hir::ExprMatch(self.lower_expr(expr),
|
hir::ExprMatch(self.lower_expr(expr),
|
||||||
|
@ -1243,12 +1246,8 @@ impl<'a> LoweringContext<'a> {
|
||||||
};
|
};
|
||||||
hir::ExprPath(hir_qself, self.lower_path_full(path, rename))
|
hir::ExprPath(hir_qself, self.lower_path_full(path, rename))
|
||||||
}
|
}
|
||||||
ExprKind::Break(opt_ident) => hir::ExprBreak(opt_ident.map(|sp_ident| {
|
ExprKind::Break(opt_ident) => hir::ExprBreak(self.lower_opt_sp_ident(opt_ident)),
|
||||||
respan(sp_ident.span, self.lower_ident(sp_ident.node))
|
ExprKind::Again(opt_ident) => hir::ExprAgain(self.lower_opt_sp_ident(opt_ident)),
|
||||||
})),
|
|
||||||
ExprKind::Again(opt_ident) => hir::ExprAgain(opt_ident.map(|sp_ident| {
|
|
||||||
respan(sp_ident.span, self.lower_ident(sp_ident.node))
|
|
||||||
})),
|
|
||||||
ExprKind::Ret(ref e) => hir::ExprRet(e.as_ref().map(|x| self.lower_expr(x))),
|
ExprKind::Ret(ref e) => hir::ExprRet(e.as_ref().map(|x| self.lower_expr(x))),
|
||||||
ExprKind::InlineAsm(InlineAsm {
|
ExprKind::InlineAsm(InlineAsm {
|
||||||
ref inputs,
|
ref inputs,
|
||||||
|
@ -1422,8 +1421,7 @@ impl<'a> LoweringContext<'a> {
|
||||||
|
|
||||||
// `[opt_ident]: loop { ... }`
|
// `[opt_ident]: loop { ... }`
|
||||||
let loop_block = self.block_expr(match_expr);
|
let loop_block = self.block_expr(match_expr);
|
||||||
let loop_expr = hir::ExprLoop(loop_block,
|
let loop_expr = hir::ExprLoop(loop_block, self.lower_opt_sp_ident(opt_ident));
|
||||||
opt_ident.map(|ident| self.lower_ident(ident)));
|
|
||||||
// add attributes to the outer returned expr node
|
// add attributes to the outer returned expr node
|
||||||
let attrs = e.attrs.clone();
|
let attrs = e.attrs.clone();
|
||||||
return P(hir::Expr { id: e.id, node: loop_expr, span: e.span, attrs: attrs });
|
return P(hir::Expr { id: e.id, node: loop_expr, span: e.span, attrs: attrs });
|
||||||
|
@ -1503,8 +1501,7 @@ impl<'a> LoweringContext<'a> {
|
||||||
|
|
||||||
// `[opt_ident]: loop { ... }`
|
// `[opt_ident]: loop { ... }`
|
||||||
let loop_block = self.block_expr(match_expr);
|
let loop_block = self.block_expr(match_expr);
|
||||||
let loop_expr = hir::ExprLoop(loop_block,
|
let loop_expr = hir::ExprLoop(loop_block, self.lower_opt_sp_ident(opt_ident));
|
||||||
opt_ident.map(|ident| self.lower_ident(ident)));
|
|
||||||
let loop_expr =
|
let loop_expr =
|
||||||
P(hir::Expr { id: e.id, node: loop_expr, span: e.span, attrs: None });
|
P(hir::Expr { id: e.id, node: loop_expr, span: e.span, attrs: None });
|
||||||
|
|
||||||
|
|
|
@ -873,11 +873,11 @@ pub enum Expr_ {
|
||||||
/// A while loop, with an optional label
|
/// A while loop, with an optional label
|
||||||
///
|
///
|
||||||
/// `'label: while expr { block }`
|
/// `'label: while expr { block }`
|
||||||
ExprWhile(P<Expr>, P<Block>, Option<Name>),
|
ExprWhile(P<Expr>, P<Block>, Option<Spanned<Name>>),
|
||||||
/// Conditionless loop (can be exited with break, continue, or return)
|
/// Conditionless loop (can be exited with break, continue, or return)
|
||||||
///
|
///
|
||||||
/// `'label: loop { block }`
|
/// `'label: loop { block }`
|
||||||
ExprLoop(P<Block>, Option<Name>),
|
ExprLoop(P<Block>, Option<Spanned<Name>>),
|
||||||
/// A `match` block, with a source that indicates whether or not it is
|
/// A `match` block, with a source that indicates whether or not it is
|
||||||
/// the result of a desugaring, and if so, which kind.
|
/// the result of a desugaring, and if so, which kind.
|
||||||
ExprMatch(P<Expr>, HirVec<Arm>, MatchSource),
|
ExprMatch(P<Expr>, HirVec<Arm>, MatchSource),
|
||||||
|
|
|
@ -1351,9 +1351,9 @@ impl<'a> State<'a> {
|
||||||
hir::ExprIf(ref test, ref blk, ref elseopt) => {
|
hir::ExprIf(ref test, ref blk, ref elseopt) => {
|
||||||
self.print_if(&test, &blk, elseopt.as_ref().map(|e| &**e))?;
|
self.print_if(&test, &blk, elseopt.as_ref().map(|e| &**e))?;
|
||||||
}
|
}
|
||||||
hir::ExprWhile(ref test, ref blk, opt_name) => {
|
hir::ExprWhile(ref test, ref blk, opt_sp_name) => {
|
||||||
if let Some(name) = opt_name {
|
if let Some(sp_name) = opt_sp_name {
|
||||||
self.print_name(name)?;
|
self.print_name(sp_name.node)?;
|
||||||
self.word_space(":")?;
|
self.word_space(":")?;
|
||||||
}
|
}
|
||||||
self.head("while")?;
|
self.head("while")?;
|
||||||
|
@ -1361,9 +1361,9 @@ impl<'a> State<'a> {
|
||||||
space(&mut self.s)?;
|
space(&mut self.s)?;
|
||||||
self.print_block(&blk)?;
|
self.print_block(&blk)?;
|
||||||
}
|
}
|
||||||
hir::ExprLoop(ref blk, opt_name) => {
|
hir::ExprLoop(ref blk, opt_sp_name) => {
|
||||||
if let Some(name) = opt_name {
|
if let Some(sp_name) = opt_sp_name {
|
||||||
self.print_name(name)?;
|
self.print_name(sp_name.node)?;
|
||||||
self.word_space(":")?;
|
self.word_space(":")?;
|
||||||
}
|
}
|
||||||
self.head("loop")?;
|
self.head("loop")?;
|
||||||
|
|
|
@ -404,23 +404,23 @@ fn extract_labels<'v, 'a>(ctxt: &mut LifetimeContext<'a>, b: &'v hir::Block) {
|
||||||
if let hir::ExprClosure(..) = ex.node {
|
if let hir::ExprClosure(..) = ex.node {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if let Some(label) = expression_label(ex) {
|
if let Some((label, label_span)) = expression_label(ex) {
|
||||||
for &(prior, prior_span) in &self.labels_in_fn[..] {
|
for &(prior, prior_span) in &self.labels_in_fn[..] {
|
||||||
// FIXME (#24278): non-hygienic comparison
|
// FIXME (#24278): non-hygienic comparison
|
||||||
if label == prior {
|
if label == prior {
|
||||||
signal_shadowing_problem(self.sess,
|
signal_shadowing_problem(self.sess,
|
||||||
label,
|
label,
|
||||||
original_label(prior_span),
|
original_label(prior_span),
|
||||||
shadower_label(ex.span));
|
shadower_label(label_span));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
check_if_label_shadows_lifetime(self.sess,
|
check_if_label_shadows_lifetime(self.sess,
|
||||||
self.scope,
|
self.scope,
|
||||||
label,
|
label,
|
||||||
ex.span);
|
label_span);
|
||||||
|
|
||||||
self.labels_in_fn.push((label, ex.span));
|
self.labels_in_fn.push((label, label_span));
|
||||||
}
|
}
|
||||||
intravisit::walk_expr(self, ex)
|
intravisit::walk_expr(self, ex)
|
||||||
}
|
}
|
||||||
|
@ -430,10 +430,11 @@ fn extract_labels<'v, 'a>(ctxt: &mut LifetimeContext<'a>, b: &'v hir::Block) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expression_label(ex: &hir::Expr) -> Option<ast::Name> {
|
fn expression_label(ex: &hir::Expr) -> Option<(ast::Name, Span)> {
|
||||||
match ex.node {
|
match ex.node {
|
||||||
hir::ExprWhile(_, _, Some(label)) |
|
hir::ExprWhile(_, _, Some(label)) |
|
||||||
hir::ExprLoop(_, Some(label)) => Some(label.unhygienize()),
|
hir::ExprLoop(_, Some(label)) => Some((label.node.unhygienize(),
|
||||||
|
label.span)),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -251,7 +251,7 @@ mod svh_visitor {
|
||||||
ExprType(..) => SawExprType,
|
ExprType(..) => SawExprType,
|
||||||
ExprIf(..) => SawExprIf,
|
ExprIf(..) => SawExprIf,
|
||||||
ExprWhile(..) => SawExprWhile,
|
ExprWhile(..) => SawExprWhile,
|
||||||
ExprLoop(_, id) => SawExprLoop(id.map(|id| id.as_str())),
|
ExprLoop(_, id) => SawExprLoop(id.map(|id| id.node.as_str())),
|
||||||
ExprMatch(..) => SawExprMatch,
|
ExprMatch(..) => SawExprMatch,
|
||||||
ExprClosure(..) => SawExprClosure,
|
ExprClosure(..) => SawExprClosure,
|
||||||
ExprBlock(..) => SawExprBlock,
|
ExprBlock(..) => SawExprBlock,
|
||||||
|
|
|
@ -3086,7 +3086,7 @@ impl<'a> Resolver<'a> {
|
||||||
|
|
||||||
{
|
{
|
||||||
let rib = this.label_ribs.last_mut().unwrap();
|
let rib = this.label_ribs.last_mut().unwrap();
|
||||||
rib.bindings.insert(mtwt::resolve(label), def);
|
rib.bindings.insert(mtwt::resolve(label.node), def);
|
||||||
}
|
}
|
||||||
|
|
||||||
visit::walk_expr(this, expr);
|
visit::walk_expr(this, expr);
|
||||||
|
@ -3131,7 +3131,7 @@ impl<'a> Resolver<'a> {
|
||||||
self.value_ribs.push(Rib::new(NormalRibKind));
|
self.value_ribs.push(Rib::new(NormalRibKind));
|
||||||
self.resolve_pattern(pattern, RefutableMode, &mut HashMap::new());
|
self.resolve_pattern(pattern, RefutableMode, &mut HashMap::new());
|
||||||
|
|
||||||
self.resolve_labeled_block(label, expr.id, block);
|
self.resolve_labeled_block(label.map(|l| l.node), expr.id, block);
|
||||||
|
|
||||||
self.value_ribs.pop();
|
self.value_ribs.pop();
|
||||||
}
|
}
|
||||||
|
@ -3141,7 +3141,7 @@ impl<'a> Resolver<'a> {
|
||||||
self.value_ribs.push(Rib::new(NormalRibKind));
|
self.value_ribs.push(Rib::new(NormalRibKind));
|
||||||
self.resolve_pattern(pattern, LocalIrrefutableMode, &mut HashMap::new());
|
self.resolve_pattern(pattern, LocalIrrefutableMode, &mut HashMap::new());
|
||||||
|
|
||||||
self.resolve_labeled_block(label, expr.id, block);
|
self.resolve_labeled_block(label.map(|l| l.node), expr.id, block);
|
||||||
|
|
||||||
self.value_ribs.pop();
|
self.value_ribs.pop();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1007,23 +1007,23 @@ pub enum ExprKind {
|
||||||
/// A while loop, with an optional label
|
/// A while loop, with an optional label
|
||||||
///
|
///
|
||||||
/// `'label: while expr { block }`
|
/// `'label: while expr { block }`
|
||||||
While(P<Expr>, P<Block>, Option<Ident>),
|
While(P<Expr>, P<Block>, Option<SpannedIdent>),
|
||||||
/// A while-let loop, with an optional label
|
/// A while-let loop, with an optional label
|
||||||
///
|
///
|
||||||
/// `'label: while let pat = expr { block }`
|
/// `'label: while let pat = expr { block }`
|
||||||
///
|
///
|
||||||
/// This is desugared to a combination of `loop` and `match` expressions.
|
/// This is desugared to a combination of `loop` and `match` expressions.
|
||||||
WhileLet(P<Pat>, P<Expr>, P<Block>, Option<Ident>),
|
WhileLet(P<Pat>, P<Expr>, P<Block>, Option<SpannedIdent>),
|
||||||
/// A for loop, with an optional label
|
/// A for loop, with an optional label
|
||||||
///
|
///
|
||||||
/// `'label: for pat in expr { block }`
|
/// `'label: for pat in expr { block }`
|
||||||
///
|
///
|
||||||
/// This is desugared to a combination of `loop` and `match` expressions.
|
/// This is desugared to a combination of `loop` and `match` expressions.
|
||||||
ForLoop(P<Pat>, P<Expr>, P<Block>, Option<Ident>),
|
ForLoop(P<Pat>, P<Expr>, P<Block>, Option<SpannedIdent>),
|
||||||
/// Conditionless loop (can be exited with break, continue, or return)
|
/// Conditionless loop (can be exited with break, continue, or return)
|
||||||
///
|
///
|
||||||
/// `'label: loop { block }`
|
/// `'label: loop { block }`
|
||||||
Loop(P<Block>, Option<Ident>),
|
Loop(P<Block>, Option<SpannedIdent>),
|
||||||
/// A `match` block.
|
/// A `match` block.
|
||||||
Match(P<Expr>, Vec<Arm>),
|
Match(P<Expr>, Vec<Arm>),
|
||||||
/// A closure (for example, `move |a, b, c| {a + b + c}`)
|
/// A closure (for example, `move |a, b, c| {a + b + c}`)
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use ast::{Block, Crate, DeclKind, PatKind};
|
use ast::{Block, Crate, DeclKind, PatKind};
|
||||||
use ast::{Local, Ident, Mac_, Name};
|
use ast::{Local, Ident, Mac_, Name, SpannedIdent};
|
||||||
use ast::{MacStmtStyle, Mrk, Stmt, StmtKind, ItemKind};
|
use ast::{MacStmtStyle, Mrk, Stmt, StmtKind, ItemKind};
|
||||||
use ast::TokenTree;
|
use ast::TokenTree;
|
||||||
use ast;
|
use ast;
|
||||||
|
@ -277,12 +277,12 @@ fn expand_mac_invoc<T, F, G>(mac: ast::Mac,
|
||||||
/// body is in a block enclosed by loop head so the renaming of loop label
|
/// body is in a block enclosed by loop head so the renaming of loop label
|
||||||
/// must be propagated to the enclosed context.
|
/// must be propagated to the enclosed context.
|
||||||
fn expand_loop_block(loop_block: P<Block>,
|
fn expand_loop_block(loop_block: P<Block>,
|
||||||
opt_ident: Option<Ident>,
|
opt_ident: Option<SpannedIdent>,
|
||||||
fld: &mut MacroExpander) -> (P<Block>, Option<Ident>) {
|
fld: &mut MacroExpander) -> (P<Block>, Option<SpannedIdent>) {
|
||||||
match opt_ident {
|
match opt_ident {
|
||||||
Some(label) => {
|
Some(label) => {
|
||||||
let new_label = fresh_name(label);
|
let new_label = fresh_name(label.node);
|
||||||
let rename = (label, new_label);
|
let rename = (label.node, new_label);
|
||||||
|
|
||||||
// The rename *must not* be added to the pending list of current
|
// The rename *must not* be added to the pending list of current
|
||||||
// syntax context otherwise an unrelated `break` or `continue` in
|
// syntax context otherwise an unrelated `break` or `continue` in
|
||||||
|
@ -290,7 +290,7 @@ fn expand_loop_block(loop_block: P<Block>,
|
||||||
// and be renamed incorrectly.
|
// and be renamed incorrectly.
|
||||||
let mut rename_list = vec!(rename);
|
let mut rename_list = vec!(rename);
|
||||||
let mut rename_fld = IdentRenamer{renames: &mut rename_list};
|
let mut rename_fld = IdentRenamer{renames: &mut rename_list};
|
||||||
let renamed_ident = rename_fld.fold_ident(label);
|
let renamed_ident = rename_fld.fold_ident(label.node);
|
||||||
|
|
||||||
// The rename *must* be added to the enclosed syntax context for
|
// The rename *must* be added to the enclosed syntax context for
|
||||||
// `break` or `continue` to pick up because by definition they are
|
// `break` or `continue` to pick up because by definition they are
|
||||||
|
@ -300,7 +300,7 @@ fn expand_loop_block(loop_block: P<Block>,
|
||||||
let expanded_block = expand_block_elts(loop_block, fld);
|
let expanded_block = expand_block_elts(loop_block, fld);
|
||||||
fld.cx.syntax_env.pop_frame();
|
fld.cx.syntax_env.pop_frame();
|
||||||
|
|
||||||
(expanded_block, Some(renamed_ident))
|
(expanded_block, Some(Spanned { node: renamed_ident, span: label.span }))
|
||||||
}
|
}
|
||||||
None => (fld.fold_block(loop_block), opt_ident)
|
None => (fld.fold_block(loop_block), opt_ident)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1212,23 +1212,27 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span, attrs}: Expr, folder: &mu
|
||||||
ExprKind::While(cond, body, opt_ident) => {
|
ExprKind::While(cond, body, opt_ident) => {
|
||||||
ExprKind::While(folder.fold_expr(cond),
|
ExprKind::While(folder.fold_expr(cond),
|
||||||
folder.fold_block(body),
|
folder.fold_block(body),
|
||||||
opt_ident.map(|i| folder.fold_ident(i)))
|
opt_ident.map(|label| respan(folder.new_span(label.span),
|
||||||
|
folder.fold_ident(label.node))))
|
||||||
}
|
}
|
||||||
ExprKind::WhileLet(pat, expr, body, opt_ident) => {
|
ExprKind::WhileLet(pat, expr, body, opt_ident) => {
|
||||||
ExprKind::WhileLet(folder.fold_pat(pat),
|
ExprKind::WhileLet(folder.fold_pat(pat),
|
||||||
folder.fold_expr(expr),
|
folder.fold_expr(expr),
|
||||||
folder.fold_block(body),
|
folder.fold_block(body),
|
||||||
opt_ident.map(|i| folder.fold_ident(i)))
|
opt_ident.map(|label| respan(folder.new_span(label.span),
|
||||||
|
folder.fold_ident(label.node))))
|
||||||
}
|
}
|
||||||
ExprKind::ForLoop(pat, iter, body, opt_ident) => {
|
ExprKind::ForLoop(pat, iter, body, opt_ident) => {
|
||||||
ExprKind::ForLoop(folder.fold_pat(pat),
|
ExprKind::ForLoop(folder.fold_pat(pat),
|
||||||
folder.fold_expr(iter),
|
folder.fold_expr(iter),
|
||||||
folder.fold_block(body),
|
folder.fold_block(body),
|
||||||
opt_ident.map(|i| folder.fold_ident(i)))
|
opt_ident.map(|label| respan(folder.new_span(label.span),
|
||||||
|
folder.fold_ident(label.node))))
|
||||||
}
|
}
|
||||||
ExprKind::Loop(body, opt_ident) => {
|
ExprKind::Loop(body, opt_ident) => {
|
||||||
ExprKind::Loop(folder.fold_block(body),
|
ExprKind::Loop(folder.fold_block(body),
|
||||||
opt_ident.map(|i| folder.fold_ident(i)))
|
opt_ident.map(|label| respan(folder.new_span(label.span),
|
||||||
|
folder.fold_ident(label.node))))
|
||||||
}
|
}
|
||||||
ExprKind::Match(expr, arms) => {
|
ExprKind::Match(expr, arms) => {
|
||||||
ExprKind::Match(folder.fold_expr(expr),
|
ExprKind::Match(folder.fold_expr(expr),
|
||||||
|
|
|
@ -2283,18 +2283,19 @@ impl<'a> Parser<'a> {
|
||||||
return self.parse_while_expr(None, lo, attrs);
|
return self.parse_while_expr(None, lo, attrs);
|
||||||
}
|
}
|
||||||
if self.token.is_lifetime() {
|
if self.token.is_lifetime() {
|
||||||
let lifetime = self.get_lifetime();
|
let label = Spanned { node: self.get_lifetime(),
|
||||||
|
span: self.span };
|
||||||
let lo = self.span.lo;
|
let lo = self.span.lo;
|
||||||
self.bump();
|
self.bump();
|
||||||
self.expect(&token::Colon)?;
|
self.expect(&token::Colon)?;
|
||||||
if self.eat_keyword(keywords::While) {
|
if self.eat_keyword(keywords::While) {
|
||||||
return self.parse_while_expr(Some(lifetime), lo, attrs)
|
return self.parse_while_expr(Some(label), lo, attrs)
|
||||||
}
|
}
|
||||||
if self.eat_keyword(keywords::For) {
|
if self.eat_keyword(keywords::For) {
|
||||||
return self.parse_for_expr(Some(lifetime), lo, attrs)
|
return self.parse_for_expr(Some(label), lo, attrs)
|
||||||
}
|
}
|
||||||
if self.eat_keyword(keywords::Loop) {
|
if self.eat_keyword(keywords::Loop) {
|
||||||
return self.parse_loop_expr(Some(lifetime), lo, attrs)
|
return self.parse_loop_expr(Some(label), lo, attrs)
|
||||||
}
|
}
|
||||||
return Err(self.fatal("expected `while`, `for`, or `loop` after a label"))
|
return Err(self.fatal("expected `while`, `for`, or `loop` after a label"))
|
||||||
}
|
}
|
||||||
|
@ -3264,7 +3265,7 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a 'for' .. 'in' expression ('for' token already eaten)
|
/// Parse a 'for' .. 'in' expression ('for' token already eaten)
|
||||||
pub fn parse_for_expr(&mut self, opt_ident: Option<ast::Ident>,
|
pub fn parse_for_expr(&mut self, opt_ident: Option<ast::SpannedIdent>,
|
||||||
span_lo: BytePos,
|
span_lo: BytePos,
|
||||||
attrs: ThinAttributes) -> PResult<'a, P<Expr>> {
|
attrs: ThinAttributes) -> PResult<'a, P<Expr>> {
|
||||||
// Parse: `for <src_pat> in <src_expr> <src_loop_block>`
|
// Parse: `for <src_pat> in <src_expr> <src_loop_block>`
|
||||||
|
@ -3283,7 +3284,7 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a 'while' or 'while let' expression ('while' token already eaten)
|
/// Parse a 'while' or 'while let' expression ('while' token already eaten)
|
||||||
pub fn parse_while_expr(&mut self, opt_ident: Option<ast::Ident>,
|
pub fn parse_while_expr(&mut self, opt_ident: Option<ast::SpannedIdent>,
|
||||||
span_lo: BytePos,
|
span_lo: BytePos,
|
||||||
attrs: ThinAttributes) -> PResult<'a, P<Expr>> {
|
attrs: ThinAttributes) -> PResult<'a, P<Expr>> {
|
||||||
if self.token.is_keyword(keywords::Let) {
|
if self.token.is_keyword(keywords::Let) {
|
||||||
|
@ -3298,7 +3299,7 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a 'while let' expression ('while' token already eaten)
|
/// Parse a 'while let' expression ('while' token already eaten)
|
||||||
pub fn parse_while_let_expr(&mut self, opt_ident: Option<ast::Ident>,
|
pub fn parse_while_let_expr(&mut self, opt_ident: Option<ast::SpannedIdent>,
|
||||||
span_lo: BytePos,
|
span_lo: BytePos,
|
||||||
attrs: ThinAttributes) -> PResult<'a, P<Expr>> {
|
attrs: ThinAttributes) -> PResult<'a, P<Expr>> {
|
||||||
self.expect_keyword(keywords::Let)?;
|
self.expect_keyword(keywords::Let)?;
|
||||||
|
@ -3312,7 +3313,7 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse `loop {...}`, `loop` token already eaten
|
// parse `loop {...}`, `loop` token already eaten
|
||||||
pub fn parse_loop_expr(&mut self, opt_ident: Option<ast::Ident>,
|
pub fn parse_loop_expr(&mut self, opt_ident: Option<ast::SpannedIdent>,
|
||||||
span_lo: BytePos,
|
span_lo: BytePos,
|
||||||
attrs: ThinAttributes) -> PResult<'a, P<Expr>> {
|
attrs: ThinAttributes) -> PResult<'a, P<Expr>> {
|
||||||
let (iattrs, body) = self.parse_inner_attrs_and_block()?;
|
let (iattrs, body) = self.parse_inner_attrs_and_block()?;
|
||||||
|
|
|
@ -2021,7 +2021,7 @@ impl<'a> State<'a> {
|
||||||
}
|
}
|
||||||
ast::ExprKind::While(ref test, ref blk, opt_ident) => {
|
ast::ExprKind::While(ref test, ref blk, opt_ident) => {
|
||||||
if let Some(ident) = opt_ident {
|
if let Some(ident) = opt_ident {
|
||||||
self.print_ident(ident)?;
|
self.print_ident(ident.node)?;
|
||||||
self.word_space(":")?;
|
self.word_space(":")?;
|
||||||
}
|
}
|
||||||
self.head("while")?;
|
self.head("while")?;
|
||||||
|
@ -2031,7 +2031,7 @@ impl<'a> State<'a> {
|
||||||
}
|
}
|
||||||
ast::ExprKind::WhileLet(ref pat, ref expr, ref blk, opt_ident) => {
|
ast::ExprKind::WhileLet(ref pat, ref expr, ref blk, opt_ident) => {
|
||||||
if let Some(ident) = opt_ident {
|
if let Some(ident) = opt_ident {
|
||||||
self.print_ident(ident)?;
|
self.print_ident(ident.node)?;
|
||||||
self.word_space(":")?;
|
self.word_space(":")?;
|
||||||
}
|
}
|
||||||
self.head("while let")?;
|
self.head("while let")?;
|
||||||
|
@ -2044,7 +2044,7 @@ impl<'a> State<'a> {
|
||||||
}
|
}
|
||||||
ast::ExprKind::ForLoop(ref pat, ref iter, ref blk, opt_ident) => {
|
ast::ExprKind::ForLoop(ref pat, ref iter, ref blk, opt_ident) => {
|
||||||
if let Some(ident) = opt_ident {
|
if let Some(ident) = opt_ident {
|
||||||
self.print_ident(ident)?;
|
self.print_ident(ident.node)?;
|
||||||
self.word_space(":")?;
|
self.word_space(":")?;
|
||||||
}
|
}
|
||||||
self.head("for")?;
|
self.head("for")?;
|
||||||
|
@ -2057,7 +2057,7 @@ impl<'a> State<'a> {
|
||||||
}
|
}
|
||||||
ast::ExprKind::Loop(ref blk, opt_ident) => {
|
ast::ExprKind::Loop(ref blk, opt_ident) => {
|
||||||
if let Some(ident) = opt_ident {
|
if let Some(ident) = opt_ident {
|
||||||
self.print_ident(ident)?;
|
self.print_ident(ident.node)?;
|
||||||
self.word_space(":")?;
|
self.word_space(":")?;
|
||||||
}
|
}
|
||||||
self.head("loop")?;
|
self.head("loop")?;
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
use abi::Abi;
|
use abi::Abi;
|
||||||
use ast::*;
|
use ast::*;
|
||||||
use attr::ThinAttributesExt;
|
use attr::ThinAttributesExt;
|
||||||
use codemap::Span;
|
use codemap::{Span, Spanned};
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||||
pub enum FnKind<'a> {
|
pub enum FnKind<'a> {
|
||||||
|
@ -149,17 +149,24 @@ macro_rules! walk_list {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn walk_opt_name<'v, V: Visitor<'v>>(visitor: &mut V, span: Span, opt_name: Option<Name>) {
|
pub fn walk_opt_name<'v, V: Visitor<'v>>(visitor: &mut V, span: Span, opt_name: Option<Name>) {
|
||||||
for name in opt_name {
|
if let Some(name) = opt_name {
|
||||||
visitor.visit_name(span, name);
|
visitor.visit_name(span, name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn walk_opt_ident<'v, V: Visitor<'v>>(visitor: &mut V, span: Span, opt_ident: Option<Ident>) {
|
pub fn walk_opt_ident<'v, V: Visitor<'v>>(visitor: &mut V, span: Span, opt_ident: Option<Ident>) {
|
||||||
for ident in opt_ident {
|
if let Some(ident) = opt_ident {
|
||||||
visitor.visit_ident(span, ident);
|
visitor.visit_ident(span, ident);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn walk_opt_sp_ident<'v, V: Visitor<'v>>(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<'v, V: Visitor<'v>>(visitor: &mut V, span: Span, ident: Ident) {
|
pub fn walk_ident<'v, V: Visitor<'v>>(visitor: &mut V, span: Span, ident: Ident) {
|
||||||
visitor.visit_name(span, ident.name);
|
visitor.visit_name(span, ident.name);
|
||||||
}
|
}
|
||||||
|
@ -712,10 +719,10 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
|
||||||
visitor.visit_block(if_block);
|
visitor.visit_block(if_block);
|
||||||
walk_list!(visitor, visit_expr, optional_else);
|
walk_list!(visitor, visit_expr, optional_else);
|
||||||
}
|
}
|
||||||
ExprKind::While(ref subexpression, ref block, opt_ident) => {
|
ExprKind::While(ref subexpression, ref block, ref opt_sp_ident) => {
|
||||||
visitor.visit_expr(subexpression);
|
visitor.visit_expr(subexpression);
|
||||||
visitor.visit_block(block);
|
visitor.visit_block(block);
|
||||||
walk_opt_ident(visitor, expression.span, opt_ident)
|
walk_opt_sp_ident(visitor, opt_sp_ident);
|
||||||
}
|
}
|
||||||
ExprKind::IfLet(ref pattern, ref subexpression, ref if_block, ref optional_else) => {
|
ExprKind::IfLet(ref pattern, ref subexpression, ref if_block, ref optional_else) => {
|
||||||
visitor.visit_pat(pattern);
|
visitor.visit_pat(pattern);
|
||||||
|
@ -723,21 +730,21 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
|
||||||
visitor.visit_block(if_block);
|
visitor.visit_block(if_block);
|
||||||
walk_list!(visitor, visit_expr, optional_else);
|
walk_list!(visitor, visit_expr, optional_else);
|
||||||
}
|
}
|
||||||
ExprKind::WhileLet(ref pattern, ref subexpression, ref block, opt_ident) => {
|
ExprKind::WhileLet(ref pattern, ref subexpression, ref block, ref opt_sp_ident) => {
|
||||||
visitor.visit_pat(pattern);
|
visitor.visit_pat(pattern);
|
||||||
visitor.visit_expr(subexpression);
|
visitor.visit_expr(subexpression);
|
||||||
visitor.visit_block(block);
|
visitor.visit_block(block);
|
||||||
walk_opt_ident(visitor, expression.span, opt_ident)
|
walk_opt_sp_ident(visitor, opt_sp_ident);
|
||||||
}
|
}
|
||||||
ExprKind::ForLoop(ref pattern, ref subexpression, ref block, opt_ident) => {
|
ExprKind::ForLoop(ref pattern, ref subexpression, ref block, ref opt_sp_ident) => {
|
||||||
visitor.visit_pat(pattern);
|
visitor.visit_pat(pattern);
|
||||||
visitor.visit_expr(subexpression);
|
visitor.visit_expr(subexpression);
|
||||||
visitor.visit_block(block);
|
visitor.visit_block(block);
|
||||||
walk_opt_ident(visitor, expression.span, opt_ident)
|
walk_opt_sp_ident(visitor, opt_sp_ident);
|
||||||
}
|
}
|
||||||
ExprKind::Loop(ref block, opt_ident) => {
|
ExprKind::Loop(ref block, ref opt_sp_ident) => {
|
||||||
visitor.visit_block(block);
|
visitor.visit_block(block);
|
||||||
walk_opt_ident(visitor, expression.span, opt_ident)
|
walk_opt_sp_ident(visitor, opt_sp_ident);
|
||||||
}
|
}
|
||||||
ExprKind::Match(ref subexpression, ref arms) => {
|
ExprKind::Match(ref subexpression, ref arms) => {
|
||||||
visitor.visit_expr(subexpression);
|
visitor.visit_expr(subexpression);
|
||||||
|
@ -781,9 +788,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
|
||||||
visitor.visit_path(path, expression.id)
|
visitor.visit_path(path, expression.id)
|
||||||
}
|
}
|
||||||
ExprKind::Break(ref opt_sp_ident) | ExprKind::Again(ref opt_sp_ident) => {
|
ExprKind::Break(ref opt_sp_ident) | ExprKind::Again(ref opt_sp_ident) => {
|
||||||
for sp_ident in opt_sp_ident {
|
walk_opt_sp_ident(visitor, opt_sp_ident);
|
||||||
visitor.visit_ident(sp_ident.span, sp_ident.node);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ExprKind::Ret(ref optional_expression) => {
|
ExprKind::Ret(ref optional_expression) => {
|
||||||
walk_list!(visitor, visit_expr, optional_expression);
|
walk_list!(visitor, visit_expr, optional_expression);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue