Add loop head span to hir
This commit is contained in:
parent
a701ff981d
commit
060dba67b7
@ -10,9 +10,9 @@ use rustc_errors::struct_span_err;
|
|||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::Res;
|
use rustc_hir::def::Res;
|
||||||
use rustc_session::parse::feature_err;
|
use rustc_session::parse::feature_err;
|
||||||
use rustc_span::hygiene::ForLoopLoc;
|
|
||||||
use rustc_span::source_map::{respan, DesugaringKind, Span, Spanned};
|
use rustc_span::source_map::{respan, DesugaringKind, Span, Spanned};
|
||||||
use rustc_span::symbol::{sym, Ident, Symbol};
|
use rustc_span::symbol::{sym, Ident, Symbol};
|
||||||
|
use rustc_span::{hygiene::ForLoopLoc, DUMMY_SP};
|
||||||
use rustc_target::asm;
|
use rustc_target::asm;
|
||||||
use std::collections::hash_map::Entry;
|
use std::collections::hash_map::Entry;
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
@ -102,6 +102,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
this.lower_block(body, false),
|
this.lower_block(body, false),
|
||||||
opt_label,
|
opt_label,
|
||||||
hir::LoopSource::Loop,
|
hir::LoopSource::Loop,
|
||||||
|
DUMMY_SP,
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
ExprKind::TryBlock(ref body) => self.lower_expr_try_block(body),
|
ExprKind::TryBlock(ref body) => self.lower_expr_try_block(body),
|
||||||
@ -453,7 +454,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
self.expr_match(span, scrutinee, arena_vec![self; then_arm, else_arm], desugar);
|
self.expr_match(span, scrutinee, arena_vec![self; then_arm, else_arm], desugar);
|
||||||
|
|
||||||
// `[opt_ident]: loop { ... }`
|
// `[opt_ident]: loop { ... }`
|
||||||
hir::ExprKind::Loop(self.block_expr(self.arena.alloc(match_expr)), opt_label, source)
|
hir::ExprKind::Loop(
|
||||||
|
self.block_expr(self.arena.alloc(match_expr)),
|
||||||
|
opt_label,
|
||||||
|
source,
|
||||||
|
span.with_hi(cond.span.hi()),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Desugar `try { <stmts>; <expr> }` into `{ <stmts>; ::std::ops::Try::from_ok(<expr>) }`,
|
/// Desugar `try { <stmts>; <expr> }` into `{ <stmts>; ::std::ops::Try::from_ok(<expr>) }`,
|
||||||
@ -748,7 +754,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
// loop { .. }
|
// loop { .. }
|
||||||
let loop_expr = self.arena.alloc(hir::Expr {
|
let loop_expr = self.arena.alloc(hir::Expr {
|
||||||
hir_id: loop_hir_id,
|
hir_id: loop_hir_id,
|
||||||
kind: hir::ExprKind::Loop(loop_block, None, hir::LoopSource::Loop),
|
kind: hir::ExprKind::Loop(loop_block, None, hir::LoopSource::Loop, span),
|
||||||
span,
|
span,
|
||||||
attrs: ThinVec::new(),
|
attrs: ThinVec::new(),
|
||||||
});
|
});
|
||||||
@ -1709,7 +1715,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// `[opt_ident]: loop { ... }`
|
// `[opt_ident]: loop { ... }`
|
||||||
let kind = hir::ExprKind::Loop(loop_block, opt_label, hir::LoopSource::ForLoop);
|
let kind = hir::ExprKind::Loop(
|
||||||
|
loop_block,
|
||||||
|
opt_label,
|
||||||
|
hir::LoopSource::ForLoop,
|
||||||
|
e.span.with_hi(orig_head_span.hi()),
|
||||||
|
);
|
||||||
let loop_expr = self.arena.alloc(hir::Expr {
|
let loop_expr = self.arena.alloc(hir::Expr {
|
||||||
hir_id: self.lower_node_id(e.id),
|
hir_id: self.lower_node_id(e.id),
|
||||||
kind,
|
kind,
|
||||||
|
@ -1617,7 +1617,9 @@ pub enum ExprKind<'hir> {
|
|||||||
/// A conditionless loop (can be exited with `break`, `continue`, or `return`).
|
/// A conditionless loop (can be exited with `break`, `continue`, or `return`).
|
||||||
///
|
///
|
||||||
/// I.e., `'label: loop { <block> }`.
|
/// I.e., `'label: loop { <block> }`.
|
||||||
Loop(&'hir Block<'hir>, Option<Label>, LoopSource),
|
///
|
||||||
|
/// The `Span` is the loop header (`for x in y`/`while let pat = expr`).
|
||||||
|
Loop(&'hir Block<'hir>, Option<Label>, LoopSource, Span),
|
||||||
/// 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.
|
||||||
Match(&'hir Expr<'hir>, &'hir [Arm<'hir>], MatchSource),
|
Match(&'hir Expr<'hir>, &'hir [Arm<'hir>], MatchSource),
|
||||||
|
@ -1151,7 +1151,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
|
|||||||
visitor.visit_expr(then);
|
visitor.visit_expr(then);
|
||||||
walk_list!(visitor, visit_expr, else_opt);
|
walk_list!(visitor, visit_expr, else_opt);
|
||||||
}
|
}
|
||||||
ExprKind::Loop(ref block, ref opt_label, _) => {
|
ExprKind::Loop(ref block, ref opt_label, _, _) => {
|
||||||
walk_list!(visitor, visit_label, opt_label);
|
walk_list!(visitor, visit_label, opt_label);
|
||||||
visitor.visit_block(block);
|
visitor.visit_block(block);
|
||||||
}
|
}
|
||||||
|
@ -1396,7 +1396,7 @@ impl<'a> State<'a> {
|
|||||||
hir::ExprKind::If(ref test, ref blk, ref elseopt) => {
|
hir::ExprKind::If(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::ExprKind::Loop(ref blk, opt_label, _) => {
|
hir::ExprKind::Loop(ref blk, opt_label, _, _) => {
|
||||||
if let Some(label) = opt_label {
|
if let Some(label) = opt_label {
|
||||||
self.print_ident(label.ident);
|
self.print_ident(label.ident);
|
||||||
self.word_space(":");
|
self.word_space(":");
|
||||||
|
@ -546,9 +546,7 @@ fn make_mirror_unadjusted<'a, 'tcx>(
|
|||||||
scrutinee: discr.to_ref(),
|
scrutinee: discr.to_ref(),
|
||||||
arms: arms.iter().map(|a| convert_arm(cx, a)).collect(),
|
arms: arms.iter().map(|a| convert_arm(cx, a)).collect(),
|
||||||
},
|
},
|
||||||
hir::ExprKind::Loop(ref body, _, _) => {
|
hir::ExprKind::Loop(ref body, ..) => ExprKind::Loop { body: block::to_expr_ref(cx, body) },
|
||||||
ExprKind::Loop { body: block::to_expr_ref(cx, body) }
|
|
||||||
}
|
|
||||||
hir::ExprKind::Field(ref source, ..) => ExprKind::Field {
|
hir::ExprKind::Field(ref source, ..) => ExprKind::Field {
|
||||||
lhs: source.to_ref(),
|
lhs: source.to_ref(),
|
||||||
name: Field::new(cx.tcx.field_index(expr.hir_id, cx.typeck_results)),
|
name: Field::new(cx.tcx.field_index(expr.hir_id, cx.typeck_results)),
|
||||||
|
@ -199,7 +199,7 @@ impl<'tcx> Visitor<'tcx> for CheckConstVisitor<'tcx> {
|
|||||||
// Skip the following checks if we are not currently in a const context.
|
// Skip the following checks if we are not currently in a const context.
|
||||||
_ if self.const_kind.is_none() => {}
|
_ if self.const_kind.is_none() => {}
|
||||||
|
|
||||||
hir::ExprKind::Loop(_, _, source) => {
|
hir::ExprKind::Loop(_, _, source, _) => {
|
||||||
self.const_check_violated(NonConstExpr::Loop(*source), e.span);
|
self.const_check_violated(NonConstExpr::Loop(*source), e.span);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -844,7 +844,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
|||||||
|
|
||||||
// Note that labels have been resolved, so we don't need to look
|
// Note that labels have been resolved, so we don't need to look
|
||||||
// at the label ident
|
// at the label ident
|
||||||
hir::ExprKind::Loop(ref blk, _, _) => self.propagate_through_loop(expr, &blk, succ),
|
hir::ExprKind::Loop(ref blk, ..) => self.propagate_through_loop(expr, &blk, succ),
|
||||||
|
|
||||||
hir::ExprKind::If(ref cond, ref then, ref else_opt) => {
|
hir::ExprKind::If(ref cond, ref then, ref else_opt) => {
|
||||||
//
|
//
|
||||||
|
@ -53,7 +53,7 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> {
|
|||||||
|
|
||||||
fn visit_expr(&mut self, e: &'hir hir::Expr<'hir>) {
|
fn visit_expr(&mut self, e: &'hir hir::Expr<'hir>) {
|
||||||
match e.kind {
|
match e.kind {
|
||||||
hir::ExprKind::Loop(ref b, _, source) => {
|
hir::ExprKind::Loop(ref b, _, source, _) => {
|
||||||
self.with_context(Loop(source), |v| v.visit_block(&b));
|
self.with_context(Loop(source), |v| v.visit_block(&b));
|
||||||
}
|
}
|
||||||
hir::ExprKind::Closure(_, ref function_decl, b, span, movability) => {
|
hir::ExprKind::Closure(_, ref function_decl, b, span, movability) => {
|
||||||
@ -89,8 +89,7 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> {
|
|||||||
Err(hir::LoopIdError::UnresolvedLabel) => None,
|
Err(hir::LoopIdError::UnresolvedLabel) => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(loop_id) = loop_id {
|
if let Some(Node::Block(_)) = loop_id.and_then(|id| self.hir_map.find(id)) {
|
||||||
if let Node::Block(_) = self.hir_map.find(loop_id).unwrap() {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -252,7 +252,7 @@ fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx h
|
|||||||
terminating(then.hir_id.local_id);
|
terminating(then.hir_id.local_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
hir::ExprKind::Loop(ref body, _, _) => {
|
hir::ExprKind::Loop(ref body, _, _, _) => {
|
||||||
terminating(body.hir_id.local_id);
|
terminating(body.hir_id.local_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1173,7 +1173,7 @@ fn extract_labels(ctxt: &mut LifetimeContext<'_, '_>, body: &hir::Body<'_>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn expression_label(ex: &hir::Expr<'_>) -> Option<Ident> {
|
fn expression_label(ex: &hir::Expr<'_>) -> Option<Ident> {
|
||||||
if let hir::ExprKind::Loop(_, Some(label), _) = ex.kind { Some(label.ident) } else { None }
|
if let hir::ExprKind::Loop(_, Some(label), ..) = ex.kind { Some(label.ident) } else { None }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_if_label_shadows_lifetime(tcx: TyCtxt<'_>, mut scope: ScopeRef<'_>, label: Ident) {
|
fn check_if_label_shadows_lifetime(tcx: TyCtxt<'_>, mut scope: ScopeRef<'_>, label: Ident) {
|
||||||
|
@ -266,7 +266,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExprKind::Ret(ref expr_opt) => self.check_expr_return(expr_opt.as_deref(), expr),
|
ExprKind::Ret(ref expr_opt) => self.check_expr_return(expr_opt.as_deref(), expr),
|
||||||
ExprKind::Loop(ref body, _, source) => {
|
ExprKind::Loop(ref body, _, source, _) => {
|
||||||
self.check_expr_loop(body, source, expected, expr)
|
self.check_expr_loop(body, source, expected, expr)
|
||||||
}
|
}
|
||||||
ExprKind::Match(ref discrim, ref arms, match_src) => {
|
ExprKind::Match(ref discrim, ref arms, match_src) => {
|
||||||
|
@ -289,7 +289,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
|
|||||||
| hir::ExprKind::ConstBlock(..)
|
| hir::ExprKind::ConstBlock(..)
|
||||||
| hir::ExprKind::Err => {}
|
| hir::ExprKind::Err => {}
|
||||||
|
|
||||||
hir::ExprKind::Loop(ref blk, _, _) => {
|
hir::ExprKind::Loop(ref blk, ..) => {
|
||||||
self.walk_block(blk);
|
self.walk_block(blk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -533,7 +533,7 @@ impl<'tcx> LateLintPass<'tcx> for Loops {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check for never_loop
|
// check for never_loop
|
||||||
if let ExprKind::Loop(ref block, _, _) = expr.kind {
|
if let ExprKind::Loop(ref block, _, _, _) = expr.kind {
|
||||||
match never_loop_block(block, expr.hir_id) {
|
match never_loop_block(block, expr.hir_id) {
|
||||||
NeverLoopResult::AlwaysBreak => span_lint(cx, NEVER_LOOP, expr.span, "this loop never actually loops"),
|
NeverLoopResult::AlwaysBreak => span_lint(cx, NEVER_LOOP, expr.span, "this loop never actually loops"),
|
||||||
NeverLoopResult::MayContinueMainLoop | NeverLoopResult::Otherwise => (),
|
NeverLoopResult::MayContinueMainLoop | NeverLoopResult::Otherwise => (),
|
||||||
@ -543,7 +543,7 @@ impl<'tcx> LateLintPass<'tcx> for Loops {
|
|||||||
// check for `loop { if let {} else break }` that could be `while let`
|
// check for `loop { if let {} else break }` that could be `while let`
|
||||||
// (also matches an explicit "match" instead of "if let")
|
// (also matches an explicit "match" instead of "if let")
|
||||||
// (even if the "match" or "if let" is used for declaration)
|
// (even if the "match" or "if let" is used for declaration)
|
||||||
if let ExprKind::Loop(ref block, _, LoopSource::Loop) = expr.kind {
|
if let ExprKind::Loop(ref block, _, LoopSource::Loop, _) = expr.kind {
|
||||||
// also check for empty `loop {}` statements, skipping those in #[panic_handler]
|
// also check for empty `loop {}` statements, skipping those in #[panic_handler]
|
||||||
if block.stmts.is_empty() && block.expr.is_none() && !is_in_panic_handler(cx, expr) {
|
if block.stmts.is_empty() && block.expr.is_none() && !is_in_panic_handler(cx, expr) {
|
||||||
let msg = "empty `loop {}` wastes CPU cycles";
|
let msg = "empty `loop {}` wastes CPU cycles";
|
||||||
@ -738,7 +738,7 @@ fn never_loop_expr(expr: &Expr<'_>, main_loop_id: HirId) -> NeverLoopResult {
|
|||||||
| ExprKind::Assign(ref e1, ref e2, _)
|
| ExprKind::Assign(ref e1, ref e2, _)
|
||||||
| ExprKind::AssignOp(_, ref e1, ref e2)
|
| ExprKind::AssignOp(_, ref e1, ref e2)
|
||||||
| ExprKind::Index(ref e1, ref e2) => never_loop_expr_all(&mut [&**e1, &**e2].iter().cloned(), main_loop_id),
|
| ExprKind::Index(ref e1, ref e2) => never_loop_expr_all(&mut [&**e1, &**e2].iter().cloned(), main_loop_id),
|
||||||
ExprKind::Loop(ref b, _, _) => {
|
ExprKind::Loop(ref b, _, _, _) => {
|
||||||
// Break can come from the inner loop so remove them.
|
// Break can come from the inner loop so remove them.
|
||||||
absorb_break(&never_loop_block(b, main_loop_id))
|
absorb_break(&never_loop_block(b, main_loop_id))
|
||||||
},
|
},
|
||||||
@ -1314,7 +1314,7 @@ impl<'a, 'tcx> Visitor<'tcx> for SameItemPushVisitor<'a, 'tcx> {
|
|||||||
fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
|
fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
|
||||||
match &expr.kind {
|
match &expr.kind {
|
||||||
// Non-determinism may occur ... don't give a lint
|
// Non-determinism may occur ... don't give a lint
|
||||||
ExprKind::Loop(_, _, _) | ExprKind::Match(_, _, _) => self.should_lint = false,
|
ExprKind::Loop(..) | ExprKind::Match(..) => self.should_lint = false,
|
||||||
ExprKind::Block(block, _) => self.visit_block(block),
|
ExprKind::Block(block, _) => self.visit_block(block),
|
||||||
_ => {},
|
_ => {},
|
||||||
}
|
}
|
||||||
|
@ -221,7 +221,7 @@ where
|
|||||||
{
|
{
|
||||||
if let ast::ExprKind::While(_, loop_block, label)
|
if let ast::ExprKind::While(_, loop_block, label)
|
||||||
| ast::ExprKind::ForLoop(_, _, loop_block, label)
|
| ast::ExprKind::ForLoop(_, _, loop_block, label)
|
||||||
| ast::ExprKind::Loop(loop_block, label) = &expr.kind
|
| ast::ExprKind::Loop(loop_block, label, _) = &expr.kind
|
||||||
{
|
{
|
||||||
func(loop_block, label.as_ref());
|
func(loop_block, label.as_ref());
|
||||||
}
|
}
|
||||||
|
@ -325,7 +325,7 @@ fn check_expr<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, bindings: &mut
|
|||||||
| ExprKind::Field(ref e, _)
|
| ExprKind::Field(ref e, _)
|
||||||
| ExprKind::AddrOf(_, _, ref e)
|
| ExprKind::AddrOf(_, _, ref e)
|
||||||
| ExprKind::Box(ref e) => check_expr(cx, e, bindings),
|
| ExprKind::Box(ref e) => check_expr(cx, e, bindings),
|
||||||
ExprKind::Block(ref block, _) | ExprKind::Loop(ref block, _, _) => check_block(cx, block, bindings),
|
ExprKind::Block(ref block, _) | ExprKind::Loop(ref block, ..) => check_block(cx, block, bindings),
|
||||||
// ExprKind::Call
|
// ExprKind::Call
|
||||||
// ExprKind::MethodCall
|
// ExprKind::MethodCall
|
||||||
ExprKind::Array(v) | ExprKind::Tup(v) => {
|
ExprKind::Array(v) | ExprKind::Tup(v) => {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user