Change:
<!-- Thank you for filing a bug report! Please provide a short summary of the bug, along with any information you feel relevant to replicating the bug. If you cannot produce a minimal reproduction case (something that would work in isolation), please provide the steps or even link to a repository that causes the problematic output to occur. --Given the following code: The current output is: <!-- The following is not always necessary. --Ideally the output should something like this: label +D-confusing +D-invalid-suggestion <!-- If the problem is not self-explanatory, please provide a rationale for the change. --<!-- If dramatically different output is caused by small changes, consider also adding them here. If you're using the stable version of the compiler, you should also check if the bug also exists in the beta or nightly versions. The output might also be different depending on the Edition. --<!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
claim

Discussion:
.suggestion = convert it to a `{$msg_code}` hir_analysis_expected_used_symbol = expected `used`, `used(compiler)` or `used(linker)` <ins> hir_analysis_missing_parentheses_in_range = can't call method `{$method_name}` on type `{$ty_str}` hir_analysis_add_missing_parentheses_in_range = you must surround the range in parentheses to call its `{$func_name}` function </ins>

//! found or is otherwise invalid. use crate::check::FnCtxt; <ins> use crate::errors; </ins> use rustc_ast::ast::Mutability; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{

} }; <del> if self.suggest_constraining_numerical_ty( </del> <ins> if self.suggest_wrapping_range_with_parens( tcx, actual, source, span, item_name, &ty_str, ) || self.suggest_constraining_numerical_ty( </ins> tcx, actual, source, span, item_kind, item_name, &ty_str, ) { return None;

false } <ins> /// Suggest possible range with adding parentheses, for example: /// when encountering `0..1.map(|i| i + 1)` suggest `(0..1).map(|i| i + 1)`. fn suggest_wrapping_range_with_parens( &self, tcx: TyCtxt<'tcx>, actual: Ty<'tcx>, source: SelfSource<'tcx>, span: Span, item_name: Ident, ty_str: &str, ) -> bool { if let SelfSource::MethodCall(expr) = source { for (_, parent) in tcx.hir().parent_iter(expr.hir_id).take(5) { if let Node::Expr(parent_expr) = parent { let lang_item = match parent_expr.kind { ExprKind::Struct(ref qpath, _, _) => match **qpath { QPath::LangItem(LangItem::Range, ..) => Some(LangItem::Range), QPath::LangItem(LangItem::RangeTo, ..) => Some(LangItem::RangeTo), QPath::LangItem(LangItem::RangeToInclusive, ..) => { Some(LangItem::RangeToInclusive) } _ => None, }, ExprKind::Call(ref func, _) => match func.kind { // `..=` desugars into `::std::ops::RangeInclusive::new(...)`. ExprKind::Path(QPath::LangItem(LangItem::RangeInclusiveNew, ..)) => { Some(LangItem::RangeInclusiveStruct) } _ => None, }, _ => None, }; if lang_item.is_none() { continue; } let span_included = match parent_expr.kind { hir::ExprKind::Struct(_, eps, _) => { eps.len() > 0 && eps.last().map_or(false, |ep| ep.span.contains(span)) } // `..=` desugars into `::std::ops::RangeInclusive::new(...)`. hir::ExprKind::Call(ref func, ..) => func.span.contains(span), _ => false, }; if !span_included { continue; } let range_def_id = self.tcx.require_lang_item(lang_item.unwrap(), None); let range_ty = self.tcx.bound_type_of(range_def_id).subst(self.tcx, &[actual.into()]); let pick = self.probe_for_name( span, Mode::MethodCall, item_name, IsSuggestion(true), range_ty, expr.hir_id, ProbeScope::AllTraits, ); if pick.is_ok() { let range_span = parent_expr.span.with_hi(expr.span.hi()); tcx.sess.emit_err(errors::MissingParentheseInRange { span, ty_str: ty_str.to_string(), method_name: item_name.as_str().to_string(), add_missing_parentheses: Some(errors::AddMissingParenthesesInRange { func_name: item_name.name.as_str().to_string(), left: range_span.shrink_to_lo(), right: range_span.shrink_to_hi(), }), }); return true; } } } } false } </ins> fn suggest_constraining_numerical_ty( &self, tcx: TyCtxt<'tcx>,

// If this is a floating point literal that ends with '.', // get rid of it to stop this from becoming a member access. let snippet = snippet.strip_suffix('.').unwrap_or(&snippet); err.span_suggestion( lit.span, &format!(

#[primary_span] pub span: Span, } <ins> #[derive(Diagnostic)] #[diag(hir_analysis::missing_parentheses_in_range, code = "E0689")] pub struct MissingParentheseInRange { #[primary_span] #[label(hir_analysis::missing_parentheses_in_range)] pub span: Span, pub ty_str: String, pub method_name: String, #[subdiagnostic] pub add_missing_parentheses: Option<AddMissingParenthesesInRange>, } #[derive(Subdiagnostic)] #[multipart_suggestion_verbose( hir_analysis::add_missing_parentheses_in_range, applicability = "maybe-incorrect" )] pub struct AddMissingParenthesesInRange { pub func_name: String, #[suggestion_part(code = "(")] pub left: Span, #[suggestion_part(code = ")")] pub right: Span, } </ins>

<ins> #![allow(unused)] </ins> fn main() { <del> let arr = &[0,1,2,3]; for _i in 0..arr.len().rev() { //~ERROR not an iterator // The above error used to say “the method `rev` exists for type `usize`”. // This regression test ensures it doesn't say that any more. } </del> <ins> let arr = &[0, 1, 2, 3]; for _i in 0..arr.len().rev() { //~^ ERROR can't call method //~| surround the range in parentheses // The above error used to say “the method `rev` exists for type `usize`”. // This regression test ensures it doesn't say that any more. } // Test for #102396 for i in 1..11.rev() { //~^ ERROR can't call method //~| HELP surround the range in parentheses } let end: usize = 10; for i in 1..end.rev() { //~^ ERROR can't call method //~| HELP surround the range in parentheses } for i in 1..(end + 1).rev() { //~^ ERROR can't call method //~| HELP surround the range in parentheses } if 1..(end + 1).is_empty() { //~^ ERROR can't call method //~| ERROR mismatched types [E0308] //~| HELP surround the range in parentheses } if 1..(end + 1).is_sorted() { //~^ ERROR mismatched types [E0308] //~| ERROR can't call method //~| HELP surround the range in parentheses } let _res: i32 = 3..6.take(2).sum(); //~^ ERROR can't call method //~| ERROR mismatched types [E0308] //~| HELP surround the range in parentheses let _sum: i32 = 3..6.sum(); //~^ ERROR can't call method //~| ERROR mismatched types [E0308] //~| HELP surround the range in parentheses let a = 1 as usize; let b = 10 as usize; for _a in a..=b.rev() { //~^ ERROR can't call method //~| HELP surround the range in parentheses } let _res = ..10.contains(3); //~^ ERROR can't call method //~| HELP surround the range in parentheses if 1..end.error_method() { //~^ ERROR no method named `error_method` //~| ERROR mismatched types [E0308] // Won't suggest } let _res = b.take(1)..a; //~^ ERROR `usize` is not an iterator let _res: i32 = ..6.take(2).sum(); //~^ can't call method `take` on ambiguous numeric type //~| ERROR mismatched types [E0308] //~| HELP you must specify a concrete type for this numeric value // Won't suggest because `RangeTo` dest not implemented `take` </ins> }

<ins> error[E0689]: can't call method `rev` on type `usize` --> $DIR/issue-90315.rs:4:28 | LL |     for _i in 0..arr.len().rev() { |                            ^^^ can't call method `rev` on type `usize` | help: you must surround the range in parentheses to call its `rev` function | LL |     for _i in (0..arr.len()).rev() { |               +            + error[E0689]: can't call method `rev` on type `{integer}` --> $DIR/issue-90315.rs:12:20 | LL |     for i in 1..11.rev() { |                    ^^^ can't call method `rev` on type `{integer}` | help: you must surround the range in parentheses to call its `rev` function | LL |     for i in (1..11).rev() { |              +     + error[E0689]: can't call method `rev` on type `usize` --> $DIR/issue-90315.rs:18:21 | LL |     for i in 1..end.rev() { |                     ^^^ can't call method `rev` on type `usize` | help: you must surround the range in parentheses to call its `rev` function | LL |     for i in (1..end).rev() { |              +      + error[E0689]: can't call method `rev` on type `usize` --> $DIR/issue-90315.rs:23:27 | LL |     for i in 1..(end + 1).rev() { |                           ^^^ can't call method `rev` on type `usize` | help: you must surround the range in parentheses to call its `rev` function | LL |     for i in (1..(end + 1)).rev() { |              +            + error[E0689]: can't call method `is_empty` on type `usize` --> $DIR/issue-90315.rs:28:21 | LL |     if 1..(end + 1).is_empty() { |                     ^^^^^^^^ can't call method `is_empty` on type `usize` | help: you must surround the range in parentheses to call its `is_empty` function | LL |     if (1..(end + 1)).is_empty() { |        +            + error[E0308]: mismatched types --> $DIR/issue-90315.rs:28:8 | LL |     if 1..(end + 1).is_empty() { |        ^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range` | = note: expected type `bool` found struct `std::ops::Range<{integer}>` error[E0689]: can't call method `is_sorted` on type `usize` --> $DIR/issue-90315.rs:34:21 | LL |     if 1..(end + 1).is_sorted() { |                     ^^^^^^^^^ can't call method `is_sorted` on type `usize` | help: you must surround the range in parentheses to call its `is_sorted` function | LL |     if (1..(end + 1)).is_sorted() { |        +            + error[E0308]: mismatched types --> $DIR/issue-90315.rs:34:8 | LL |     if 1..(end + 1).is_sorted() { |        ^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range` | = note: expected type `bool` found struct `std::ops::Range<{integer}>` error[E0689]: can't call method `take` on type `{integer}` --> $DIR/issue-90315.rs:40:26 | LL |     let _res: i32 = 3..6.take(2).sum(); |                          ^^^^ can't call method `take` on type `{integer}` | help: you must surround the range in parentheses to call its `take` function | LL |     let _res: i32 = (3..6).take(2).sum(); |                     +    + error[E0308]: mismatched types --> $DIR/issue-90315.rs:40:21 | LL |     let _res: i32 = 3..6.take(2).sum(); |               ---   ^^^^^^^^^^^^^^^^^^ expected `i32`, found struct `std::ops::Range` |               | |               expected due to this | = note: expected type `i32` found struct `std::ops::Range<{integer}>` error[E0689]: can't call method `sum` on type `{integer}` --> $DIR/issue-90315.rs:45:26 | LL |     let _sum: i32 = 3..6.sum(); |                          ^^^ can't call method `sum` on type `{integer}` | help: you must surround the range in parentheses to call its `sum` function | LL |     let _sum: i32 = (3..6).sum(); |                     +    + error[E0308]: mismatched types --> $DIR/issue-90315.rs:45:21 | LL |     let _sum: i32 = 3..6.sum(); |               ---   ^^^^^^^^^^ expected `i32`, found struct `std::ops::Range` |               | |               expected due to this | = note: expected type `i32` found struct `std::ops::Range<{integer}>` error[E0689]: can't call method `rev` on type `usize` --> $DIR/issue-90315.rs:53:21 | LL |     for _a in a..=b.rev() { |                     ^^^ can't call method `rev` on type `usize` | help: you must surround the range in parentheses to call its `rev` function | LL |     for _a in (a..=b).rev() { |               +     + error[E0689]: can't call method `contains` on type `{integer}` --> $DIR/issue-90315.rs:58:21 | LL |     let _res = ..10.contains(3); |                     ^^^^^^^^ can't call method `contains` on type `{integer}` | help: you must surround the range in parentheses to call its `contains` function | LL |     let _res = (..10).contains(3); |                +    + error[E0599]: no method named `error_method` found for type `usize` in the current scope --> $DIR/issue-90315.rs:62:15 | LL |     if 1..end.error_method() { |               ^^^^^^^^^^^^ method not found in `usize` error[E0308]: mismatched types --> $DIR/issue-90315.rs:62:8 | LL |     if 1..end.error_method() { |        ^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range` | = note: expected type `bool` found struct `std::ops::Range<{integer}>` </ins> error[E0599]: `usize` is not an iterator <del> --> $DIR/issue-90315.rs:3:26 </del> <ins> --> $DIR/issue-90315.rs:68:18 </ins> | <del> LL |   for _i in 0..arr.len().rev() { |                          ^^^ `usize` is not an iterator </del> <ins> LL |     let _res = b.take(1)..a; |                  ^^^^ `usize` is not an iterator </ins> | = note: the following trait bounds were not satisfied: `usize: Iterator` which is required by `&mut usize: Iterator` <del> error: aborting due to previous error </del> <ins> error[E0689]: can't call method `take` on ambiguous numeric type `{integer}` --> $DIR/issue-90315.rs:71:25 | LL |     let _res: i32 = ..6.take(2).sum(); |                         ^^^^ | help: you must specify a concrete type for this numeric value, like `i32` | LL |     let _res: i32 = ..6_i32.take(2).sum(); |                       ~~~~~ error[E0308]: mismatched types --> $DIR/issue-90315.rs:71:21 | LL |     let _res: i32 = ..6.take(2).sum(); |               ---   ^^^^^^^^^^^^^^^^^ expected `i32`, found struct `RangeTo` |               | |               expected due to this | = note: expected type `i32` found struct `RangeTo<_>` error: aborting due to 19 previous errors </ins> <del> For more information about this error, try `rustc --explain E0599`. </del> <ins> Some errors have detailed explanations: E0308, E0599, E0689. For more information about an error, try `rustc --explain E0308`. </ins>