diff options
33 files changed, 522 insertions, 138 deletions
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 1b9ccbd850b..31360158e2b 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -10,9 +10,9 @@ use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def::Res; use rustc_session::parse::feature_err; -use rustc_span::hygiene::ForLoopLoc; use rustc_span::source_map::{respan, DesugaringKind, Span, Spanned}; use rustc_span::symbol::{sym, Ident, Symbol}; +use rustc_span::{hygiene::ForLoopLoc, DUMMY_SP}; use rustc_target::asm; use std::collections::hash_map::Entry; use std::fmt::Write; @@ -102,6 +102,7 @@ impl<'hir> LoweringContext<'_, 'hir> { this.lower_block(body, false), opt_label, hir::LoopSource::Loop, + DUMMY_SP, ) }), 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); // `[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>) }`, @@ -748,7 +754,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // loop { .. } let loop_expr = self.arena.alloc(hir::Expr { 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, attrs: ThinVec::new(), }); @@ -1709,7 +1715,12 @@ impl<'hir> LoweringContext<'_, 'hir> { ); // `[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 { hir_id: self.lower_node_id(e.id), kind, diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 3673e5c8bf3..35170fa7c1d 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1617,7 +1617,9 @@ pub enum ExprKind<'hir> { /// A conditionless loop (can be exited with `break`, `continue`, or `return`). /// /// 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 /// the result of a desugaring, and if so, which kind. Match(&'hir Expr<'hir>, &'hir [Arm<'hir>], MatchSource), diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 8707a84a98f..6c1bee2335a 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -1151,7 +1151,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>) visitor.visit_expr(then); 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); visitor.visit_block(block); } diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index a3ab1d96e1d..f1c2a6b7e6e 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -1396,7 +1396,7 @@ impl<'a> State<'a> { hir::ExprKind::If(ref test, ref blk, ref elseopt) => { 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 { self.print_ident(label.ident); self.word_space(":"); diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 8cdb33ea317..b37660e4a90 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -96,18 +96,24 @@ fn pierce_parens(mut expr: &ast::Expr) -> &ast::Expr { impl EarlyLintPass for WhileTrue { fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) { - if let ast::ExprKind::While(cond, ..) = &e.kind { + if let ast::ExprKind::While(cond, _, label) = &e.kind { if let ast::ExprKind::Lit(ref lit) = pierce_parens(cond).kind { if let ast::LitKind::Bool(true) = lit.kind { if !lit.span.from_expansion() { let msg = "denote infinite loops with `loop { ... }`"; - let condition_span = cx.sess.source_map().guess_head_span(e.span); + let condition_span = e.span.with_hi(cond.span.hi()); cx.struct_span_lint(WHILE_TRUE, condition_span, |lint| { lint.build(msg) .span_suggestion_short( condition_span, "use `loop`", - "loop".to_owned(), + format!( + "{}loop", + label.map_or_else(String::new, |label| format!( + "{}: ", + label.ident, + )) + ), Applicability::MachineApplicable, ) .emit(); diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 595458702e9..2962cbe8157 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -546,9 +546,7 @@ fn make_mirror_unadjusted<'a, 'tcx>( scrutinee: discr.to_ref(), arms: arms.iter().map(|a| convert_arm(cx, a)).collect(), }, - hir::ExprKind::Loop(ref body, _, _) => { - ExprKind::Loop { body: block::to_expr_ref(cx, body) } - } + hir::ExprKind::Loop(ref body, ..) => ExprKind::Loop { body: block::to_expr_ref(cx, body) }, hir::ExprKind::Field(ref source, ..) => ExprKind::Field { lhs: source.to_ref(), name: Field::new(cx.tcx.field_index(expr.hir_id, cx.typeck_results)), diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 47869f775fe..cfd7ad48222 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -585,7 +585,7 @@ impl<'a> Parser<'a> { lhs_span: Span, expr_kind: fn(P<Expr>, P<Ty>) -> ExprKind, ) -> PResult<'a, P<Expr>> { - let mk_expr = |this: &mut Self, rhs: P<Ty>| { + let mk_expr = |this: &mut Self, lhs: P<Expr>, rhs: P<Ty>| { this.mk_expr( this.mk_expr_sp(&lhs, lhs_span, rhs.span), expr_kind(lhs, rhs), @@ -597,13 +597,49 @@ impl<'a> Parser<'a> { // LessThan comparison after this cast. let parser_snapshot_before_type = self.clone(); let cast_expr = match self.parse_ty_no_plus() { - Ok(rhs) => mk_expr(self, rhs), + Ok(rhs) => mk_expr(self, lhs, rhs), Err(mut type_err) => { // Rewind to before attempting to parse the type with generics, to recover // from situations like `x as usize < y` in which we first tried to parse // `usize < y` as a type with generic arguments. let parser_snapshot_after_type = mem::replace(self, parser_snapshot_before_type); + // Check for typo of `'a: loop { break 'a }` with a missing `'`. + match (&lhs.kind, &self.token.kind) { + ( + // `foo: ` + ExprKind::Path(None, ast::Path { segments, .. }), + TokenKind::Ident(kw::For | kw::Loop | kw::While, false), + ) if segments.len() == 1 => { + let snapshot = self.clone(); + let label = Label { + ident: Ident::from_str_and_span( + &format!("'{}", segments[0].ident), + segments[0].ident.span, + ), + }; + match self.parse_labeled_expr(label, AttrVec::new(), false) { + Ok(expr) => { + type_err.cancel(); + self.struct_span_err(label.ident.span, "malformed loop label") + .span_suggestion( + label.ident.span, + "use the correct loop label format", + label.ident.to_string(), + Applicability::MachineApplicable, + ) + .emit(); + return Ok(expr); + } + Err(mut err) => { + err.cancel(); + *self = snapshot; + } + } + } + _ => {} + } + match self.parse_path(PathStyle::Expr) { Ok(path) => { let (op_noun, op_verb) = match self.token.kind { @@ -630,7 +666,8 @@ impl<'a> Parser<'a> { op_noun, ); let span_after_type = parser_snapshot_after_type.token.span; - let expr = mk_expr(self, self.mk_ty(path.span, TyKind::Path(None, path))); + let expr = + mk_expr(self, lhs, self.mk_ty(path.span, TyKind::Path(None, path))); let expr_str = self .span_to_snippet(expr.span) @@ -1067,7 +1104,7 @@ impl<'a> Parser<'a> { } else if self.eat_keyword(kw::While) { self.parse_while_expr(None, self.prev_token.span, attrs) } else if let Some(label) = self.eat_label() { - self.parse_labeled_expr(label, attrs) + self.parse_labeled_expr(label, attrs, true) } else if self.eat_keyword(kw::Loop) { self.parse_loop_expr(None, self.prev_token.span, attrs) } else if self.eat_keyword(kw::Continue) { @@ -1228,7 +1265,12 @@ impl<'a> Parser<'a> { } /// Parse `'label: $expr`. The label is already parsed. - fn parse_labeled_expr(&mut self, label: Label, attrs: AttrVec) -> PResult<'a, P<Expr>> { + fn parse_labeled_expr( + &mut self, + label: Label, + attrs: AttrVec, + consume_colon: bool, + ) -> PResult<'a, P<Expr>> { let lo = label.ident.span; let label = Some(label); let ate_colon = self.eat(&token::Colon); @@ -1247,7 +1289,7 @@ impl<'a> Parser<'a> { self.parse_expr() }?; - if !ate_colon { + if !ate_colon && consume_colon { self.error_labeled_expr_must_be_followed_by_colon(lo, expr.span); } diff --git a/compiler/rustc_passes/src/check_const.rs b/compiler/rustc_passes/src/check_const.rs index c887a860303..8950f9b33b6 100644 --- a/compiler/rustc_passes/src/check_const.rs +++ b/compiler/rustc_passes/src/check_const.rs @@ -199,7 +199,7 @@ impl<'tcx> Visitor<'tcx> for CheckConstVisitor<'tcx> { // Skip the following checks if we are not currently in a const context. _ if self.const_kind.is_none() => {} - hir::ExprKind::Loop(_, _, source) => { + hir::ExprKind::Loop(_, _, source, _) => { self.const_check_violated(NonConstExpr::Loop(*source), e.span); } diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index 6202cc312fc..c11dc231d48 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -844,7 +844,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { // Note that labels have been resolved, so we don't need to look // 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) => { // diff --git a/compiler/rustc_passes/src/loops.rs b/compiler/rustc_passes/src/loops.rs index 9b4da71e5e9..4bfac1b7298 100644 --- a/compiler/rustc_passes/src/loops.rs +++ b/compiler/rustc_passes/src/loops.rs @@ -53,7 +53,7 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> { fn visit_expr(&mut self, e: &'hir hir::Expr<'hir>) { 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)); } hir::ExprKind::Closure(_, ref function_decl, b, span, movability) => { @@ -68,18 +68,18 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> { hir::ExprKind::Block(ref b, Some(_label)) => { self.with_context(LabeledBlock, |v| v.visit_block(&b)); } - hir::ExprKind::Break(label, ref opt_expr) => { + hir::ExprKind::Break(break_label, ref opt_expr) => { if let Some(e) = opt_expr { self.visit_expr(e); } - if self.require_label_in_labeled_block(e.span, &label, "break") { + if self.require_label_in_labeled_block(e.span, &break_label, "break") { // If we emitted an error about an unlabeled break in a labeled // block, we don't need any further checking for this break any more return; } - let loop_id = match label.target_id { + let loop_id = match break_label.target_id { Ok(loop_id) => Some(loop_id), Err(hir::LoopIdError::OutsideLoopScope) => None, Err(hir::LoopIdError::UnlabeledCfInWhileCondition) => { @@ -89,49 +89,89 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> { Err(hir::LoopIdError::UnresolvedLabel) => None, }; - if let Some(loop_id) = loop_id { - if let Node::Block(_) = self.hir_map.find(loop_id).unwrap() { - return; - } + if let Some(Node::Block(_)) = loop_id.and_then(|id| self.hir_map.find(id)) { + return; } - if opt_expr.is_some() { - let loop_kind = if let Some(loop_id) = loop_id { - Some(match self.hir_map.expect_expr(loop_id).kind { - hir::ExprKind::Loop(_, _, source) => source, + if let Some(break_expr) = opt_expr { + let (head, loop_label, loop_kind) = if let Some(loop_id) = loop_id { + match self.hir_map.expect_expr(loop_id).kind { + hir::ExprKind::Loop(_, label, source, sp) => { + (Some(sp), label, Some(source)) + } ref r => { span_bug!(e.span, "break label resolved to a non-loop: {:?}", r) } - }) + } } else { - None + (None, None, None) }; match loop_kind { None | Some(hir::LoopSource::Loop) => (), Some(kind) => { - struct_span_err!( + let mut err = struct_span_err!( self.sess, e.span, E0571, "`break` with value from a `{}` loop", kind.name() - ) - .span_label( + ); + err.span_label( e.span, - "can only break with a value inside \ - `loop` or breakable block", - ) - .span_suggestion( + "can only break with a value inside `loop` or breakable block", + ); + if let Some(head) = head { + err.span_label( + head, + &format!( + "you can't `break` with a value in a `{}` loop", + kind.name() + ), + ); + } + err.span_suggestion( e.span, &format!( - "instead, use `break` on its own \ - without a value inside this `{}` loop", - kind.name() + "use `break` on its own without a value inside this `{}` loop", + kind.name(), + ), + format!( + "break{}", + break_label + .label + .map_or_else(String::new, |l| format!(" {}", l.ident)) ), - "break".to_string(), Applicability::MaybeIncorrect, - ) - .emit(); + ); + if let (Some(label), None) = (loop_label, break_label.label) { + match break_expr.kind { + hir::ExprKind::Path(hir::QPath::Resolved( + None, + hir::Path { + segments: [segment], + res: hir::def::Res::Err, + .. + }, + )) if label.ident.to_string() + == format!("'{}", segment.ident) => + { + // This error is redundant, we will have already emitted a + // suggestion to use the label when `segment` wasn't found + // (hence the `Res::Err` check). + err.delay_as_bug(); + } + _ => { + err.span_suggestion( + break_expr.span, + "alternatively, you might have meant to use the \ + available loop label", + label.ident.to_string(), + Applicability::MaybeIncorrect, + ); + } + } + } + err.emit(); } } } diff --git a/compiler/rustc_passes/src/region.rs b/compiler/rustc_passes/src/region.rs index 91421d7f5f2..64356f73f6c 100644 --- a/compiler/rustc_passes/src/region.rs +++ b/compiler/rustc_passes/src/region.rs @@ -252,7 +252,7 @@ fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx h terminating(then.hir_id.local_id); } - hir::ExprKind::Loop(ref body, _, _) => { + hir::ExprKind::Loop(ref body, _, _, _) => { terminating(body.hir_id.local_id); } diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index fff14747e57..eaeb28388d4 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -2266,6 +2266,12 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { visit::walk_expr(self, expr); } + ExprKind::Break(None, Some(ref e)) => { + // We use this instead of `visit::walk_expr` to keep the parent expr around for + // better diagnostics. + self.resolve_expr(e, Some(&expr)); + } + ExprKind::Let(ref pat, ref scrutinee) => { self.visit_expr(scrutinee); self.resolve_pattern_top(pat, PatternSource::Let); diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 3945afb4724..bed7a350ea8 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -545,17 +545,23 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { if let Some(err_code) = &err.code { if err_code == &rustc_errors::error_code!(E0425) { for label_rib in &self.label_ribs { - for (label_ident, _) in &label_rib.bindings { + for (label_ident, node_id) in &label_rib.bindings { if format!("'{}", ident) == label_ident.to_string() { - let msg = "a label with a similar name exists"; - // FIXME: consider only emitting this suggestion if a label would be valid here - // which is pretty much only the case for `break` expressions. - err.span_suggestion( - span, - &msg, - label_ident.name.to_string(), - Applicability::MaybeIncorrect, - ); + err.span_label(label_ident.span, "a label with a similar name exists"); + if let PathSource::Expr(Some(Expr { + kind: ExprKind::Break(None, Some(_)), + .. + })) = source + { + err.span_suggestion( + span, + "use the similarly named label", + label_ident.name.to_string(), + Applicability::MaybeIncorrect, + ); + // Do not lint against unused label when we suggest them. + self.diagnostic_metadata.unused_labels.remove(node_id); + } } } } diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index 64cc113dffe..95ac2a31dd3 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -1173,7 +1173,7 @@ fn extract_labels(ctxt: &mut LifetimeContext<'_, '_>, body: &hir::Body<'_>) { } 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) { diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index 8aa6c6d924a..8f463af73c4 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -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::Loop(ref body, _, source) => { + ExprKind::Loop(ref body, _, source, _) => { self.check_expr_loop(body, source, expected, expr) } ExprKind::Match(ref discrim, ref arms, match_src) => { diff --git a/compiler/rustc_typeck/src/expr_use_visitor.rs b/compiler/rustc_typeck/src/expr_use_visitor.rs index 01519e4c8f7..24364c6954e 100644 --- a/compiler/rustc_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_typeck/src/expr_use_visitor.rs @@ -289,7 +289,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { | hir::ExprKind::ConstBlock(..) | hir::ExprKind::Err => {} - hir::ExprKind::Loop(ref blk, _, _) => { + hir::ExprKind::Loop(ref blk, ..) => { self.walk_block(blk); } diff --git a/src/test/ui/issues/issue-1962.fixed b/src/test/ui/issues/issue-1962.fixed index b810a90ef37..897fd172b29 100644 --- a/src/test/ui/issues/issue-1962.fixed +++ b/src/test/ui/issues/issue-1962.fixed @@ -3,8 +3,8 @@ fn main() { let mut i = 0; - loop { //~ ERROR denote infinite loops with `loop + 'a: loop { //~ ERROR denote infinite loops with `loop i += 1; - if i == 5 { break; } + if i == 5 { break 'a; } } } diff --git a/src/test/ui/issues/issue-1962.rs b/src/test/ui/issues/issue-1962.rs index 00d2bbd2850..71e87410087 100644 --- a/src/test/ui/issues/issue-1962.rs +++ b/src/test/ui/issues/issue-1962.rs @@ -3,8 +3,8 @@ fn main() { let mut i = 0; - while true { //~ ERROR denote infinite loops with `loop + 'a: while true { //~ ERROR denote infinite loops with `loop i += 1; - if i == 5 { break; } + if i == 5 { break 'a; } } } diff --git a/src/test/ui/issues/issue-1962.stderr b/src/test/ui/issues/issue-1962.stderr index 17142912696..4c32a4cf3dd 100644 --- a/src/test/ui/issues/issue-1962.stderr +++ b/src/test/ui/issues/issue-1962.stderr @@ -1,8 +1,8 @@ error: denote infinite loops with `loop { ... }` --> $DIR/issue-1962.rs:6:5 | -LL | while true { - | ^^^^^^^^^^ help: use `loop` +LL | 'a: while true { + | ^^^^^^^^^^^^^^ help: use `loop` | = note: requested on the command line with `-D while-true` diff --git a/src/test/ui/issues/issue-27042.stderr b/src/test/ui/issues/issue-27042.stderr index 7dee1a6a5f0..59ef28481d0 100644 --- a/src/test/ui/issues/issue-27042.stderr +++ b/src/test/ui/issues/issue-27042.stderr @@ -4,7 +4,7 @@ warning: denote infinite loops with `loop { ... }` LL | / 'b: LL | | LL | | while true { break }; // but here we cite the whole loop - | |____________________________^ help: use `loop` + | |__________________^ help: use `loop` | = note: `#[warn(while_true)]` on by default diff --git a/src/test/ui/label/label_misspelled.rs b/src/test/ui/label/label_misspelled.rs index ebfd5642c9f..e3180b06ecb 100644 --- a/src/test/ui/label/label_misspelled.rs +++ b/src/test/ui/label/label_misspelled.rs @@ -1,18 +1,62 @@ +#![warn(unused_labels)] + fn main() { + 'while_loop: while true { //~ WARN denote infinite loops with + //~^ WARN unused label + while_loop; + //~^ ERROR cannot find value `while_loop` in this scope + }; + 'while_let: while let Some(_) = Some(()) { + //~^ WARN unused label + while_let; + //~^ ERROR cannot find value `while_let` in this scope + } + 'for_loop: for _ in 0..3 { + //~^ WARN unused label + for_loop; + //~^ ERROR cannot find value `for_loop` in this scope + }; 'LOOP: loop { + //~^ WARN unused label LOOP; //~^ ERROR cannot find value `LOOP` in this scope }; +} + +fn foo() { + 'LOOP: loop { + break LOOP; + //~^ ERROR cannot find value `LOOP` in this scope + }; 'while_loop: while true { //~ WARN denote infinite loops with - while_loop; + break while_loop; //~^ ERROR cannot find value `while_loop` in this scope }; 'while_let: while let Some(_) = Some(()) { - while_let; + break while_let; //~^ ERROR cannot find value `while_let` in this scope } 'for_loop: for _ in 0..3 { - for_loop; + break for_loop; //~^ ERROR cannot find value `for_loop` in this scope }; } + +fn bar() { + let foo = (); + 'while_loop: while true { //~ WARN denote infinite loops with + //~^ WARN unused label + break foo; + //~^ ERROR `break` with value from a `while` loop + }; + 'while_let: while let Some(_) = Some(()) { + //~^ WARN unused label + break foo; + //~^ ERROR `break` with value from a `while` loop + } + 'for_loop: for _ in 0..3 { + //~^ WARN unused label + break foo; + //~^ ERROR `break` with value from a `for` loop + }; +} diff --git a/src/test/ui/label/label_misspelled.stderr b/src/test/ui/label/label_misspelled.stderr index 1368ca4126c..b09695787a4 100644 --- a/src/test/ui/label/label_misspelled.stderr +++ b/src/test/ui/label/label_misspelled.stderr @@ -1,47 +1,206 @@ -error[E0425]: cannot find value `LOOP` in this scope - --> $DIR/label_misspelled.rs:3:9 - | -LL | LOOP; - | ^^^^ - | | - | not found in this scope - | help: a label with a similar name exists: `'LOOP` - error[E0425]: cannot find value `while_loop` in this scope - --> $DIR/label_misspelled.rs:7:9 + --> $DIR/label_misspelled.rs:6:9 | +LL | 'while_loop: while true { + | ----------- a label with a similar name exists +LL | LL | while_loop; - | ^^^^^^^^^^ - | | - | not found in this scope - | help: a label with a similar name exists: `'while_loop` + | ^^^^^^^^^^ not found in this scope error[E0425]: cannot find value `while_let` in this scope --> $DIR/label_misspelled.rs:11:9 | +LL | 'while_let: while let Some(_) = Some(()) { + | ---------- a label with a similar name exists +LL | LL | while_let; - | ^^^^^^^^^ - | | - | not found in this scope - | help: a label with a similar name exists: `'while_let` + | ^^^^^^^^^ not found in this scope error[E0425]: cannot find value `for_loop` in this scope - --> $DIR/label_misspelled.rs:15:9 + --> $DIR/label_misspelled.rs:16:9 | +LL | 'for_loop: for _ in 0..3 { + | --------- a label with a similar name exists +LL | LL | for_loop; - | ^^^^^^^^ - | | - | not found in this scope - | help: a label with a similar name exists: `'for_loop` + | ^^^^^^^^ not found in this scope + +error[E0425]: cannot find value `LOOP` in this scope + --> $DIR/label_misspelled.rs:21:9 + | +LL | 'LOOP: loop { + | ----- a label with a similar name exists +LL | +LL | LOOP; + | ^^^^ not found in this scope + +error[E0425]: cannot find value `LOOP` in this scope + --> $DIR/label_misspelled.rs:28:15 + | +LL | 'LOOP: loop { + | ----- a label with a similar name exists +LL | break LOOP; + | ^^^^ + | | + | not found in this scope + | help: use the similarly named label: `'LOOP` + +error[E0425]: cannot find value `while_loop` in this scope + --> $DIR/label_misspelled.rs:32:15 + | +LL | 'while_loop: while true { + | ----------- a label with a similar name exists +LL | break while_loop; + | ^^^^^^^^^^ + | | + | not found in this scope + | help: use the similarly named label: `'while_loop` + +error[E0425]: cannot find value `while_let` in this scope + --> $DIR/label_misspelled.rs:36:15 + | +LL | 'while_let: while let Some(_) = Some(()) { + | ---------- a label with a similar name exists +LL | break while_let; + | ^^^^^^^^^ + | | + | not found in this scope + | help: use the similarly named label: `'while_let` + +error[E0425]: cannot find value `for_loop` in this scope + --> $DIR/label_misspelled.rs:40:15 + | +LL | 'for_loop: for _ in 0..3 { + | --------- a label with a similar name exists +LL | break for_loop; + | ^^^^^^^^ + | | + | not found in this scope + | help: use the similarly named label: `'for_loop` + +warning: unused label + --> $DIR/label_misspelled.rs:4:5 + | +LL | 'while_loop: while true { + | ^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/label_misspelled.rs:1:9 + | +LL | #![warn(unused_labels)] + | ^^^^^^^^^^^^^ warning: denote infinite loops with `loop { ... }` - --> $DIR/label_misspelled.rs:6:5 + --> $DIR/label_misspelled.rs:4:5 | LL | 'while_loop: while true { | ^^^^^^^^^^^^^^^^^^^^^^^ help: use `loop` | = note: `#[warn(while_true)]` on by default -error: aborting due to 4 previous errors; 1 warning emitted +warning: unused label + --> $DIR/label_misspelled.rs:9:5 + | +LL | 'while_let: while let Some(_) = Some(()) { + | ^^^^^^^^^^ + +warning: unused label + --> $DIR/label_misspelled.rs:14:5 + | +LL | 'for_loop: for _ in 0..3 { + | ^^^^^^^^^ + +warning: unused label + --> $DIR/label_misspelled.rs:19:5 + | +LL | 'LOOP: loop { + | ^^^^^ + +warning: denote infinite loops with `loop { ... }` + --> $DIR/label_misspelled.rs:31:5 + | +LL | 'while_loop: while true { + | ^^^^^^^^^^^^^^^^^^^^^^^ help: use `loop` + +warning: unused label + --> $DIR/label_misspelled.rs:47:5 + | +LL | 'while_loop: while true { + | ^^^^^^^^^^^ + +warning: denote infinite loops with `loop { ... }` + --> $DIR/label_misspelled.rs:47:5 + | +LL | 'while_loop: while true { + | ^^^^^^^^^^^^^^^^^^^^^^^ help: use `loop` + +warning: unused label + --> $DIR/label_misspelled.rs:52:5 + | +LL | 'while_let: while let Some(_) = Some(()) { + | ^^^^^^^^^^ + +warning: unused label + --> $DIR/label_misspelled.rs:57:5 + | +LL | 'for_loop: for _ in 0..3 { + | ^^^^^^^^^ + +error[E0571]: `break` with value from a `while` loop + --> $DIR/label_misspelled.rs:49:9 + | +LL | 'while_loop: while true { + | ----------------------- you can't `break` with a value in a `while` loop +LL | +LL | break foo; + | ^^^^^^^^^ can only break with a value inside `loop` or breakable block + | +help: use `break` on its own without a value inside this `while` loop + | +LL | break; + | ^^^^^ +help: alternatively, you might have meant to use the available loop label + | +LL | break 'while_loop; + | ^^^^^^^^^^^ + +error[E0571]: `break` with value from a `while` loop + --> $DIR/label_misspelled.rs:54:9 + | +LL | 'while_let: while let Some(_) = Some(()) { + | ---------------------------------------- you can't `break` with a value in a `while` loop +LL | +LL | break foo; + | ^^^^^^^^^ can only break with a value inside `loop` or breakable block + | +help: use `break` on its own without a value inside this `while` loop + | +LL | break; + | ^^^^^ +help: alternatively, you might have meant to use the available loop label + | +LL | break 'while_let; + | ^^^^^^^^^^ + +error[E0571]: `break` with value from a `for` loop + --> $DIR/label_misspelled.rs:59:9 + | +LL | 'for_loop: for _ in 0..3 { + | ------------------------ you can't `break` with a value in a `for` loop +LL | +LL | break foo; + | ^^^^^^^^^ can only break with a value inside `loop` or breakable block + | +help: use `break` on its own without a value inside this `for` loop + | +LL | break; + | ^^^^^ +help: alternatively, you might have meant to use the available loop label + | +LL | break 'for_loop; + | ^^^^^^^^^ + +error: aborting due to 11 previous errors; 10 warnings emitted -For more information about this error, try `rustc --explain E0425`. +Some errors have detailed explanations: E0425, E0571. +For more information about an error, try `rustc --explain E0425`. diff --git a/src/test/ui/label/label_misspelled_2.rs b/src/test/ui/label/label_misspelled_2.rs new file mode 100644 index 00000000000..55bbe6b30a5 --- /dev/null +++ b/src/test/ui/label/label_misspelled_2.rs @@ -0,0 +1,16 @@ +#![warn(unused_labels)] + +fn main() { + 'a: for _ in 0..1 { + break 'a; + } + 'b: for _ in 0..1 { + break b; //~ ERROR cannot find value `b` in this scope + } + c: for _ in 0..1 { //~ ERROR malformed loop label + break 'c; + } + d: for _ in 0..1 { //~ ERROR malformed loop label + break d; //~ ERROR cannot find value `d` in this scope + } +} diff --git a/src/test/ui/label/label_misspelled_2.stderr b/src/test/ui/label/label_misspelled_2.stderr new file mode 100644 index 00000000000..960646d9894 --- /dev/null +++ b/src/test/ui/label/label_misspelled_2.stderr @@ -0,0 +1,37 @@ +error: malformed loop label + --> $DIR/label_misspelled_2.rs:10:5 + | +LL | c: for _ in 0..1 { + | ^ help: use the correct loop label format: `'c` + +error: malformed loop label + --> $DIR/label_misspelled_2.rs:13:5 + | +LL | d: for _ in 0..1 { + | ^ help: use the correct loop label format: `'d` + +error[E0425]: cannot find value `b` in this scope + --> $DIR/label_misspelled_2.rs:8:15 + | +LL | 'b: for _ in 0..1 { + | -- a label with a similar name exists +LL | break b; + | ^ + | | + | not found in this scope + | help: use the similarly named label: `'b` + +error[E0425]: cannot find value `d` in this scope + --> $DIR/label_misspelled_2.rs:14:15 + | +LL | d: for _ in 0..1 { + | - a label with a similar name exists +LL | break d; + | ^ + | | + | not found in this scope + | help: use the similarly named label: `'d` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/loops/loop-break-value-no-repeat.stderr b/src/test/ui/loops/loop-break-value-no-repeat.stderr index ff93e9220e9..1c0d39a6e5a 100644 --- a/src/test/ui/loops/loop-break-value-no-repeat.stderr +++ b/src/test/ui/loops/loop-break-value-no-repeat.stderr @@ -1,10 +1,12 @@ error[E0571]: `break` with value from a `for` loop --> $DIR/loop-break-value-no-repeat.rs:12:9 | +LL | for _ in &[1,2,3] { + | ----------------- you can't `break` with a value in a `for` loop LL | break 22 | ^^^^^^^^ can only break with a value inside `loop` or breakable block | -help: instead, use `break` on its own without a value inside this `for` loop +help: use `break` on its own without a value inside this `for` loop | LL | break | ^^^^^ diff --git a/src/test/ui/loops/loop-break-value.rs b/src/test/ui/loops/loop-break-value.rs index 8a080cfdf49..51c9a36a039 100644 --- a/src/test/ui/loops/loop-break-value.rs +++ b/src/test/ui/loops/loop-break-value.rs @@ -94,6 +94,5 @@ fn main() { 'LOOP: for _ in 0 .. 9 { break LOOP; //~^ ERROR cannot find value `LOOP` in this scope - //~| ERROR `break` with value from a `for` loop } } diff --git a/src/test/ui/loops/loop-break-value.stderr b/src/test/ui/loops/loop-break-value.stderr index 0237435c8b4..adb099f9b17 100644 --- a/src/test/ui/loops/loop-break-value.stderr +++ b/src/test/ui/loops/loop-break-value.stderr @@ -1,11 +1,13 @@ error[E0425]: cannot find value `LOOP` in this scope --> $DIR/loop-break-value.rs:95:15 | +LL | 'LOOP: for _ in 0 .. 9 { + | ----- a label with a similar name exists LL | break LOOP; | ^^^^ | | | not found in this scope - | help: a label with a similar name exists: `'LOOP` + | help: use the similarly named label: `'LOOP` warning: denote infinite loops with `loop { ... }` --> $DIR/loop-break-value.rs:26:5 @@ -18,32 +20,44 @@ LL | 'while_loop: while true { error[E0571]: `break` with value from a `while` loop --> $DIR/loop-break-value.rs:28:9 | +LL | 'while_loop: while true { + | ----------------------- you can't `break` with a value in a `while` loop +LL | break; LL | break (); | ^^^^^^^^ can only break with a value inside `loop` or breakable block | -help: instead, use `break` on its own without a value inside this `while` loop +help: use `break` on its own without a value inside this `while` loop | LL | break; | ^^^^^ +help: alternatively, you might have meant to use the available loop label + | +LL | break 'while_loop; + | ^^^^^^^^^^^ error[E0571]: `break` with value from a `while` loop --> $DIR/loop-break-value.rs:30:13 | +LL | 'while_loop: while true { + | ----------------------- you can't `break` with a value in a `while` loop +... LL | break 'while_loop 123; | ^^^^^^^^^^^^^^^^^^^^^ can only break with a value inside `loop` or breakable block | -help: instead, use `break` on its own without a value inside this `while` loop +help: use `break` on its own without a value inside this `while` loop | -LL | break; - | ^^^^^ +LL | break 'while_loop; + | ^^^^^^^^^^^^^^^^^ error[E0571]: `break` with value from a `while` loop --> $DIR/loop-break-value.rs:38:12 | +LL | while let Some(_) = Some(()) { + | ---------------------------- you can't `break` with a value in a `while` loop LL | if break () { | ^^^^^^^^ can only break with a value inside `loop` or breakable block | -help: instead, use `break` on its own without a value inside this `while` loop +help: use `break` on its own without a value inside this `while` loop | LL | if break { | ^^^^^ @@ -51,10 +65,12 @@ LL | if break { error[E0571]: `break` with value from a `while` loop --> $DIR/loop-break-value.rs:43:9 | +LL | while let Some(_) = Some(()) { + | ---------------------------- you can't `break` with a value in a `while` loop LL | break None; | ^^^^^^^^^^ can only break with a value inside `loop` or breakable block | -help: instead, use `break` on its own without a value inside this `while` loop +help: use `break` on its own without a value inside this `while` loop | LL | break; | ^^^^^ @@ -62,21 +78,26 @@ LL | break; error[E0571]: `break` with value from a `while` loop --> $DIR/loop-break-value.rs:49:13 | +LL | 'while_let_loop: while let Some(_) = Some(()) { + | --------------------------------------------- you can't `break` with a value in a `while` loop +LL | loop { LL | break 'while_let_loop "nope"; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can only break with a value inside `loop` or breakable block | -help: instead, use `break` on its own without a value inside this `while` loop +help: use `break` on its own without a value inside this `while` loop | -LL | break; - | ^^^^^ +LL | break 'while_let_loop; + | ^^^^^^^^^^^^^^^^^^^^^ error[E0571]: `break` with value from a `for` loop --> $DIR/loop-break-value.rs:56:9 | +LL | for _ in &[1,2,3] { + | ----------------- you can't `break` with a value in a `for` loop LL | break (); | ^^^^^^^^ can only break with a value inside `loop` or breakable block | -help: instead, use `break` on its own without a value inside this `for` loop +help: use `break` on its own without a value inside this `for` loop | LL | break; | ^^^^^ @@ -84,10 +105,13 @@ LL | break; error[E0571]: `break` with value from a `for` loop --> $DIR/loop-break-value.rs:57:9 | +LL | for _ in &[1,2,3] { + | ----------------- you can't `break` with a value in a `for` loop +LL | break (); LL | break [()]; | ^^^^^^^^^^ can only break with a value inside `loop` or breakable block | -help: instead, use `break` on its own without a value inside this `for` loop +help: use `break` on its own without a value inside this `for` loop | LL | break; | ^^^^^ @@ -95,24 +119,16 @@ LL | break; error[E0571]: `break` with value from a `for` loop --> $DIR/loop-break-value.rs:64:13 | +LL | 'for_loop: for _ in &[1,2,3] { + | ---------------------------- you can't `break` with a value in a `for` loop +... LL | break 'for_loop Some(17); | ^^^^^^^^^^^^^^^^^^^^^^^^ can only break with a value inside `loop` or breakable block | -help: instead, use `break` on its own without a value inside this `for` loop - | -LL | break; - | ^^^^^ - -error[E0571]: `break` with value from a `for` loop - --> $DIR/loop-break-value.rs:95:9 - | -LL | break LOOP; - | ^^^^^^^^^^ can only break with a value inside `loop` or breakable block +help: use `break` on its own without a value inside this `for` loop | -help: instead, use `break` on its own without a value inside this `for` loop - | -LL | break; - | ^^^^^ +LL | break 'for_loop; + | ^^^^^^^^^^^^^^^ error[E0308]: mismatched types --> $DIR/loop-break-value.rs:4:31 @@ -171,7 +187,7 @@ LL | break; | expected integer, found `()` | help: give it a value of the expected type: `break value` -error: aborting due to 18 previous errors; 1 warning emitted +error: aborting due to 17 previous errors; 1 warning emitted Some errors have detailed explanations: E0308, E0425, E0571. For more information about an error, try `rustc --explain E0308`. diff --git a/src/tools/clippy/clippy_lints/src/loops.rs b/src/tools/clippy/clippy_lints/src/loops.rs index 1c5ab2874b0..bbcea387de2 100644 --- a/src/tools/clippy/clippy_lints/src/loops.rs +++ b/src/tools/clippy/clippy_lints/src/loops.rs @@ -533,7 +533,7 @@ impl<'tcx> LateLintPass<'tcx> for Loops { } // 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) { NeverLoopResult::AlwaysBreak => span_lint(cx, NEVER_LOOP, expr.span, "this loop never actually loops"), 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` // (also matches an explicit "match" instead of "if let") // (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] if block.stmts.is_empty() && block.expr.is_none() && !is_in_panic_handler(cx, expr) { 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::AssignOp(_, ref e1, ref e2) | 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. 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<'_>) { match &expr.kind { // 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), _ => {}, } diff --git a/src/tools/clippy/clippy_lints/src/needless_continue.rs b/src/tools/clippy/clippy_lints/src/needless_continue.rs index a971d041ca6..603071a5f4a 100644 --- a/src/tools/clippy/clippy_lints/src/needless_continue.rs +++ b/src/tools/clippy/clippy_lints/src/needless_continue.rs @@ -221,7 +221,7 @@ where { if let ast::ExprKind::While(_, 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()); } diff --git a/src/tools/clippy/clippy_lints/src/shadow.rs b/src/tools/clippy/clippy_lints/src/shadow.rs index 24da056770c..d5b1767e945 100644 --- a/src/tools/clippy/clippy_lints/src/shadow.rs +++ b/src/tools/clippy/clippy_lints/src/shadow.rs @@ -325,7 +325,7 @@ fn check_expr<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, bindings: &mut | ExprKind::Field(ref e, _) | ExprKind::AddrOf(_, _, ref e) | 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::MethodCall ExprKind::Array(v) | ExprKind::Tup(v) => { diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs index 43afa65de3e..ca60d335262 100644 --- a/src/tools/clippy/clippy_lints/src/utils/author.rs +++ b/src/tools/clippy/clippy_lints/src/utils/author.rs @@ -317,7 +317,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { self.current = cast_pat; self.visit_expr(expr); }, - ExprKind::Loop(ref body, _, desugaring) => { + ExprKind::Loop(ref body, _, desugaring, _) => { let body_pat = self.next("body"); let des = loop_desugaring_name(desugaring); let label_pat = self.next("label"); diff --git a/src/tools/clippy/clippy_lints/src/utils/higher.rs b/src/tools/clippy/clippy_lints/src/utils/higher.rs index 9b3585865da..42ab9a1e7d2 100644 --- a/src/tools/clippy/clippy_lints/src/utils/higher.rs +++ b/src/tools/clippy/clippy_lints/src/utils/higher.rs @@ -142,7 +142,7 @@ pub fn for_loop<'tcx>( if let hir::ExprKind::Match(ref iterexpr, ref arms, hir::MatchSource::ForLoopDesugar) = expr.kind; if let hir::ExprKind::Call(_, ref iterargs) = iterexpr.kind; if iterargs.len() == 1 && arms.len() == 1 && arms[0].guard.is_none(); - if let hir::ExprKind::Loop(ref block, _, _) = arms[0].body.kind; + if let hir::ExprKind::Loop(ref block, ..) = arms[0].body.kind; if block.expr.is_none(); if let [ _, _, ref let_stmt, ref body ] = *block.stmts; if let hir::StmtKind::Local(ref local) = let_stmt.kind; @@ -158,7 +158,7 @@ pub fn for_loop<'tcx>( /// `while cond { body }` becomes `(cond, body)`. pub fn while_loop<'tcx>(expr: &'tcx hir::Expr<'tcx>) -> Option<(&'tcx hir::Expr<'tcx>, &'tcx hir::Expr<'tcx>)> { if_chain! { - if let hir::ExprKind::Loop(block, _, hir::LoopSource::While) = &expr.kind; + if let hir::ExprKind::Loop(block, _, hir::LoopSource::While, _) = &expr.kind; if let hir::Block { expr: Some(expr), .. } = &**block; if let hir::ExprKind::Match(cond, arms, hir::MatchSource::WhileDesugar) = &expr.kind; if let hir::ExprKind::DropTemps(cond) = &cond.kind; diff --git a/src/tools/clippy/clippy_lints/src/utils/hir_utils.rs b/src/tools/clippy/clippy_lints/src/utils/hir_utils.rs index 10120a8805d..6066383f2ef 100644 --- a/src/tools/clippy/clippy_lints/src/utils/hir_utils.rs +++ b/src/tools/clippy/clippy_lints/src/utils/hir_utils.rs @@ -123,7 +123,7 @@ impl<'a, 'tcx> SpanlessEq<'a, 'tcx> { self.eq_expr(lc, rc) && self.eq_expr(&**lt, &**rt) && both(le, re, |l, r| self.eq_expr(l, r)) }, (&ExprKind::Lit(ref l), &ExprKind::Lit(ref r)) => l.node == r.node, - (&ExprKind::Loop(ref lb, ref ll, ref lls), &ExprKind::Loop(ref rb, ref rl, ref rls)) => { + (&ExprKind::Loop(ref lb, ref ll, ref lls, _), &ExprKind::Loop(ref rb, ref rl, ref rls, _)) => { lls == rls && self.eq_block(lb, rb) && both(ll, rl, |l, r| l.ident.name == r.ident.name) }, (&ExprKind::Match(ref le, ref la, ref ls), &ExprKind::Match(ref re, ref ra, ref rs)) => { @@ -560,7 +560,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { ExprKind::Lit(ref l) => { l.node.hash(&mut self.s); }, - ExprKind::Loop(ref b, ref i, _) => { + ExprKind::Loop(ref b, ref i, ..) => { self.hash_block(b); if let Some(i) = *i { self.hash_name(i.ident.name); |
