From 292f0c599fee4e5feae66d57a00be0af505c74d2 Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 29 Sep 2022 12:14:39 +0200 Subject: [PATCH 1/7] only allow `ConstEquate` with `feature(gce)` --- .../src/traits/fulfill.rs | 25 ++++++++++--------- .../src/traits/select/mod.rs | 24 ++++++++++-------- 2 files changed, 26 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index f13736a76b214..19efc29762143 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -495,19 +495,20 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { } ty::PredicateKind::ConstEquate(c1, c2) => { + assert!( + self.selcx.tcx().features().generic_const_exprs, + "`ConstEquate` without a feature gate: {c1:?} {c2:?}", + ); debug!(?c1, ?c2, "equating consts"); - let tcx = self.selcx.tcx(); - if tcx.features().generic_const_exprs { - // FIXME: we probably should only try to unify abstract constants - // if the constants depend on generic parameters. - // - // Let's just see where this breaks :shrug: - if let (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b)) = - (c1.kind(), c2.kind()) - { - if infcx.try_unify_abstract_consts(a, b, obligation.param_env) { - return ProcessResult::Changed(vec![]); - } + // FIXME: we probably should only try to unify abstract constants + // if the constants depend on generic parameters. + // + // Let's just see where this breaks :shrug: + if let (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b)) = + (c1.kind(), c2.kind()) + { + if infcx.try_unify_abstract_consts(a, b, obligation.param_env) { + return ProcessResult::Changed(vec![]); } } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 0ed59223337a5..256102eb98c08 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -677,19 +677,21 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } ty::PredicateKind::ConstEquate(c1, c2) => { + assert!( + self.tcx().features().generic_const_exprs, + "`ConstEquate` without a feature gate: {c1:?} {c2:?}", + ); debug!(?c1, ?c2, "evaluate_predicate_recursively: equating consts"); - if self.tcx().features().generic_const_exprs { - // FIXME: we probably should only try to unify abstract constants - // if the constants depend on generic parameters. - // - // Let's just see where this breaks :shrug: - if let (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b)) = - (c1.kind(), c2.kind()) - { - if self.infcx.try_unify_abstract_consts(a, b, obligation.param_env) { - return Ok(EvaluatedToOk); - } + // FIXME: we probably should only try to unify abstract constants + // if the constants depend on generic parameters. + // + // Let's just see where this breaks :shrug: + if let (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b)) = + (c1.kind(), c2.kind()) + { + if self.infcx.try_unify_abstract_consts(a, b, obligation.param_env) { + return Ok(EvaluatedToOk); } } From 5dd44d4d4c4545f65f15f890e93fac68214cfe54 Mon Sep 17 00:00:00 2001 From: yukang Date: Thu, 29 Sep 2022 13:16:47 +0800 Subject: [PATCH 2/7] fix #102396, suggest parentheses for possible range methods --- .../locales/en-US/hir_analysis.ftl | 5 + .../src/check/method/suggest.rs | 75 +++++++- compiler/rustc_hir_analysis/src/errors.rs | 25 +++ src/test/ui/methods/issues/issue-90315.rs | 73 +++++++- src/test/ui/methods/issues/issue-90315.stderr | 176 +++++++++++++++++- 5 files changed, 339 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl b/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl index c6a4ff6f0e02f..827c3c93a73d9 100644 --- a/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl +++ b/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl @@ -133,3 +133,8 @@ hir_analysis_extern_crate_not_idiomatic = .suggestion = convert it to a `{$msg_code}` hir_analysis_expected_used_symbol = expected `used`, `used(compiler)` or `used(linker)` +hir_analysis_expected_used_symbol = expected `used`, `used(compiler)` or `used(linker)` + +hir_analysis_missing_parentheses_in_range = `{$ty_str}` is not an iterator + +hir_analysis_add_missing_parentheses_in_range = you must surround the range in parentheses to call the `{$func_name}` function diff --git a/compiler/rustc_hir_analysis/src/check/method/suggest.rs b/compiler/rustc_hir_analysis/src/check/method/suggest.rs index 0e82e4956c7c1..d7189e70d064e 100644 --- a/compiler/rustc_hir_analysis/src/check/method/suggest.rs +++ b/compiler/rustc_hir_analysis/src/check/method/suggest.rs @@ -2,6 +2,7 @@ //! found or is otherwise invalid. use crate::check::FnCtxt; +use crate::errors; use rustc_ast::ast::Mutability; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{ @@ -12,7 +13,7 @@ use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; -use rustc_hir::{ExprKind, Node, QPath}; +use rustc_hir::{is_range_literal, ExprKind, Node, QPath}; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_middle::traits::util::supertraits; use rustc_middle::ty::fast_reject::{simplify_type, TreatParams}; @@ -271,9 +272,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } }; - if self.suggest_constraining_numerical_ty( - tcx, actual, source, span, item_kind, item_name, &ty_str, - ) { + if self.suggest_range_for_iter(tcx, actual, source, span, item_name, &ty_str) + || self.suggest_constraining_numerical_ty( + tcx, actual, source, span, item_kind, item_name, &ty_str, + ) + { return None; } @@ -1201,6 +1204,69 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { false } + fn suggest_range_for_iter( + &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 { + let mut search_limit = 5; + for (_, parent) in tcx.hir().parent_iter(expr.hir_id) { + search_limit -= 1; + if search_limit == 0 { + break; + } + + if let Node::Expr(parent_expr) = parent && is_range_literal(parent_expr) { + 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.lang_items().range_struct().unwrap(); + let range_ty = self.tcx.bound_type_of(range_def_id).subst(self.tcx, &[actual.into()]); + + // avoid suggesting when the method name is not implemented for a `range` + let pick = self.lookup_probe( + span, + item_name, + range_ty, + expr, + ProbeScope::AllTraits + ); + + if pick.is_ok() { + let range_span = parent_expr.span.with_hi(expr.span.hi()); + tcx.sess.emit_err(errors::MissingParentheseInRange { + span: span, + ty_str: ty_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 + } + fn suggest_constraining_numerical_ty( &self, tcx: TyCtxt<'tcx>, @@ -1263,7 +1329,6 @@ impl<'a, 'tcx> FnCtxt<'a, '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!( diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index d891171b82468..6634444c636d4 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -346,3 +346,28 @@ pub struct ExpectedUsedSymbol { #[primary_span] pub span: Span, } + +#[derive(Diagnostic)] +#[diag(hir_analysis::missing_parentheses_in_range, code = "E0599")] +pub struct MissingParentheseInRange { + #[primary_span] + #[label(hir_analysis::missing_parentheses_in_range)] + pub span: Span, + pub ty_str: String, + + #[subdiagnostic] + pub add_missing_parentheses: Option, +} + +#[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, +} diff --git a/src/test/ui/methods/issues/issue-90315.rs b/src/test/ui/methods/issues/issue-90315.rs index 01bf9f4840246..74cd2b3583481 100644 --- a/src/test/ui/methods/issues/issue-90315.rs +++ b/src/test/ui/methods/issues/issue-90315.rs @@ -1,7 +1,70 @@ +#![allow(unused)] fn main() { - 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. - } + let arr = &[0, 1, 2, 3]; + for _i in 0..arr.len().rev() { + //~^ ERROR not an iterator + //~| 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 not an iterator + //~| HELP surround the range in parentheses + } + + let end: usize = 10; + for i in 1..end.rev() { + //~^ ERROR not an iterator + //~| HELP surround the range in parentheses + } + + for i in 1..(end + 1).rev() { + //~^ ERROR not an iterator + //~| HELP surround the range in parentheses + } + + if 1..(end + 1).is_empty() { + //~^ ERROR not an iterator + //~| ERROR mismatched types [E0308] + //~| HELP surround the range in parentheses + } + + if 1..(end + 1).is_sorted() { + //~^ ERROR mismatched types [E0308] + //~| ERROR `usize` is not an iterator [E0599] + //~| HELP surround the range in parentheses + } + + let _res: i32 = 3..6.take(2).sum(); + //~^ ERROR `{integer}` is not an iterator [E0599] + //~| ERROR mismatched types [E0308] + //~| HELP surround the range in parentheses + + let _sum: i32 = 3..6.sum(); + //~^ ERROR `{integer}` is not an iterator [E0599] + //~| 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 not an iterator + //~| HELP surround the range in parentheses + } + + let _res = ..10.contains(3); + //~^ ERROR not an iterator + //~| 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 not an iterator } diff --git a/src/test/ui/methods/issues/issue-90315.stderr b/src/test/ui/methods/issues/issue-90315.stderr index c6a76c9e79018..f2084b593c290 100644 --- a/src/test/ui/methods/issues/issue-90315.stderr +++ b/src/test/ui/methods/issues/issue-90315.stderr @@ -1,13 +1,179 @@ error[E0599]: `usize` is not an iterator - --> $DIR/issue-90315.rs:3:26 + --> $DIR/issue-90315.rs:4:28 | -LL | for _i in 0..arr.len().rev() { - | ^^^ `usize` is not an iterator +LL | for _i in 0..arr.len().rev() { + | ^^^ `usize` is not an iterator + | +help: you must surround the range in parentheses to call the `rev` function + | +LL | for _i in (0..arr.len()).rev() { + | + + + +error[E0599]: `{integer}` is not an iterator + --> $DIR/issue-90315.rs:12:20 + | +LL | for i in 1..11.rev() { + | ^^^ `{integer}` is not an iterator + | +help: you must surround the range in parentheses to call the `rev` function + | +LL | for i in (1..11).rev() { + | + + + +error[E0599]: `usize` is not an iterator + --> $DIR/issue-90315.rs:18:21 + | +LL | for i in 1..end.rev() { + | ^^^ `usize` is not an iterator + | +help: you must surround the range in parentheses to call the `rev` function + | +LL | for i in (1..end).rev() { + | + + + +error[E0599]: `usize` is not an iterator + --> $DIR/issue-90315.rs:23:27 + | +LL | for i in 1..(end + 1).rev() { + | ^^^ `usize` is not an iterator + | +help: you must surround the range in parentheses to call the `rev` function + | +LL | for i in (1..(end + 1)).rev() { + | + + + +error[E0599]: `usize` is not an iterator + --> $DIR/issue-90315.rs:28:21 + | +LL | if 1..(end + 1).is_empty() { + | ^^^^^^^^ `usize` is not an iterator + | +help: you must surround the range in parentheses to call the `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[E0599]: `usize` is not an iterator + --> $DIR/issue-90315.rs:34:21 + | +LL | if 1..(end + 1).is_sorted() { + | ^^^^^^^^^ `usize` is not an iterator + | +help: you must surround the range in parentheses to call the `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[E0599]: `{integer}` is not an iterator + --> $DIR/issue-90315.rs:40:26 + | +LL | let _res: i32 = 3..6.take(2).sum(); + | ^^^^ `{integer}` is not an iterator + | +help: you must surround the range in parentheses to call the `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[E0599]: `{integer}` is not an iterator + --> $DIR/issue-90315.rs:45:26 + | +LL | let _sum: i32 = 3..6.sum(); + | ^^^ `{integer}` is not an iterator + | +help: you must surround the range in parentheses to call the `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[E0599]: `usize` is not an iterator + --> $DIR/issue-90315.rs:53:21 + | +LL | for _a in a..=b.rev() { + | ^^^ `usize` is not an iterator + | +help: you must surround the range in parentheses to call the `rev` function + | +LL | for _a in (a..=b).rev() { + | + + + +error[E0599]: `{integer}` is not an iterator + --> $DIR/issue-90315.rs:58:21 + | +LL | let _res = ..10.contains(3); + | ^^^^^^^^ `{integer}` is not an iterator + | +help: you must surround the range in parentheses to call the `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}>` + +error[E0599]: `usize` is not an iterator + --> $DIR/issue-90315.rs:68:18 + | +LL | let _res = b.take(1)..a; + | ^^^^ `usize` is not an iterator | = note: the following trait bounds were not satisfied: `usize: Iterator` which is required by `&mut usize: Iterator` -error: aborting due to previous error +error: aborting due to 17 previous errors -For more information about this error, try `rustc --explain E0599`. +Some errors have detailed explanations: E0308, E0599. +For more information about an error, try `rustc --explain E0308`. From e747201ad83d384a418dc2b31bf3d3024e2c2a3c Mon Sep 17 00:00:00 2001 From: yukang Date: Mon, 3 Oct 2022 04:22:59 +0800 Subject: [PATCH 3/7] find the correct lang item for ranges --- .../locales/en-US/hir_analysis.ftl | 3 +- .../src/check/method/suggest.rs | 76 +++++++++++-------- compiler/rustc_hir_analysis/src/errors.rs | 3 +- src/test/ui/methods/issues/issue-90315.rs | 28 ++++--- src/test/ui/methods/issues/issue-90315.stderr | 66 ++++++++++------ 5 files changed, 108 insertions(+), 68 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl b/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl index 827c3c93a73d9..5a7aee9c1c147 100644 --- a/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl +++ b/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl @@ -133,8 +133,7 @@ hir_analysis_extern_crate_not_idiomatic = .suggestion = convert it to a `{$msg_code}` hir_analysis_expected_used_symbol = expected `used`, `used(compiler)` or `used(linker)` -hir_analysis_expected_used_symbol = expected `used`, `used(compiler)` or `used(linker)` -hir_analysis_missing_parentheses_in_range = `{$ty_str}` is not an iterator +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 the `{$func_name}` function diff --git a/compiler/rustc_hir_analysis/src/check/method/suggest.rs b/compiler/rustc_hir_analysis/src/check/method/suggest.rs index d7189e70d064e..9aa1b2e2c0a51 100644 --- a/compiler/rustc_hir_analysis/src/check/method/suggest.rs +++ b/compiler/rustc_hir_analysis/src/check/method/suggest.rs @@ -13,7 +13,7 @@ use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; -use rustc_hir::{is_range_literal, ExprKind, Node, QPath}; +use rustc_hir::{ExprKind, Node, QPath}; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_middle::traits::util::supertraits; use rustc_middle::ty::fast_reject::{simplify_type, TreatParams}; @@ -1214,50 +1214,62 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty_str: &str, ) -> bool { if let SelfSource::MethodCall(expr) = source { - let mut search_limit = 5; - for (_, parent) in tcx.hir().parent_iter(expr.hir_id) { - search_limit -= 1; - if search_limit == 0 { - break; - } + 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; + } - if let Node::Expr(parent_expr) = parent && is_range_literal(parent_expr) { 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, + 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.lang_items().range_struct().unwrap(); - let range_ty = self.tcx.bound_type_of(range_def_id).subst(self.tcx, &[actual.into()]); - - // avoid suggesting when the method name is not implemented for a `range` - let pick = self.lookup_probe( - span, - item_name, - range_ty, - expr, - ProbeScope::AllTraits - ); + debug!("lang_item: {:?}", lang_item); + 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.lookup_probe(span, item_name, range_ty, expr, ProbeScope::AllTraits); if pick.is_ok() { let range_span = parent_expr.span.with_hi(expr.span.hi()); tcx.sess.emit_err(errors::MissingParentheseInRange { - span: span, + span, ty_str: ty_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(), - } - ) + 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; } diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 6634444c636d4..41f73323d9a9a 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -348,12 +348,13 @@ pub struct ExpectedUsedSymbol { } #[derive(Diagnostic)] -#[diag(hir_analysis::missing_parentheses_in_range, code = "E0599")] +#[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, diff --git a/src/test/ui/methods/issues/issue-90315.rs b/src/test/ui/methods/issues/issue-90315.rs index 74cd2b3583481..79cdc41959a74 100644 --- a/src/test/ui/methods/issues/issue-90315.rs +++ b/src/test/ui/methods/issues/issue-90315.rs @@ -2,7 +2,7 @@ fn main() { let arr = &[0, 1, 2, 3]; for _i in 0..arr.len().rev() { - //~^ ERROR not an iterator + //~^ 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. @@ -10,40 +10,40 @@ fn main() { // Test for #102396 for i in 1..11.rev() { - //~^ ERROR not an iterator + //~^ ERROR can't call method //~| HELP surround the range in parentheses } let end: usize = 10; for i in 1..end.rev() { - //~^ ERROR not an iterator + //~^ ERROR can't call method //~| HELP surround the range in parentheses } for i in 1..(end + 1).rev() { - //~^ ERROR not an iterator + //~^ ERROR can't call method //~| HELP surround the range in parentheses } if 1..(end + 1).is_empty() { - //~^ ERROR not an iterator + //~^ 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 `usize` is not an iterator [E0599] + //~| ERROR can't call method //~| HELP surround the range in parentheses } let _res: i32 = 3..6.take(2).sum(); - //~^ ERROR `{integer}` is not an iterator [E0599] + //~^ ERROR can't call method //~| ERROR mismatched types [E0308] //~| HELP surround the range in parentheses let _sum: i32 = 3..6.sum(); - //~^ ERROR `{integer}` is not an iterator [E0599] + //~^ ERROR can't call method //~| ERROR mismatched types [E0308] //~| HELP surround the range in parentheses @@ -51,12 +51,12 @@ fn main() { let b = 10 as usize; for _a in a..=b.rev() { - //~^ ERROR not an iterator + //~^ ERROR can't call method //~| HELP surround the range in parentheses } let _res = ..10.contains(3); - //~^ ERROR not an iterator + //~^ ERROR can't call method //~| HELP surround the range in parentheses if 1..end.error_method() { @@ -66,5 +66,11 @@ fn main() { } let _res = b.take(1)..a; - //~^ ERROR not an iterator + //~^ 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` } diff --git a/src/test/ui/methods/issues/issue-90315.stderr b/src/test/ui/methods/issues/issue-90315.stderr index f2084b593c290..581d6fb4fc9e4 100644 --- a/src/test/ui/methods/issues/issue-90315.stderr +++ b/src/test/ui/methods/issues/issue-90315.stderr @@ -1,52 +1,52 @@ -error[E0599]: `usize` is not an iterator +error[E0689]: can't call method `rev` on type `usize` --> $DIR/issue-90315.rs:4:28 | LL | for _i in 0..arr.len().rev() { - | ^^^ `usize` is not an iterator + | ^^^ can't call method `rev` on type `usize` | help: you must surround the range in parentheses to call the `rev` function | LL | for _i in (0..arr.len()).rev() { | + + -error[E0599]: `{integer}` is not an iterator +error[E0689]: can't call method `rev` on type `{integer}` --> $DIR/issue-90315.rs:12:20 | LL | for i in 1..11.rev() { - | ^^^ `{integer}` is not an iterator + | ^^^ can't call method `rev` on type `{integer}` | help: you must surround the range in parentheses to call the `rev` function | LL | for i in (1..11).rev() { | + + -error[E0599]: `usize` is not an iterator +error[E0689]: can't call method `rev` on type `usize` --> $DIR/issue-90315.rs:18:21 | LL | for i in 1..end.rev() { - | ^^^ `usize` is not an iterator + | ^^^ can't call method `rev` on type `usize` | help: you must surround the range in parentheses to call the `rev` function | LL | for i in (1..end).rev() { | + + -error[E0599]: `usize` is not an iterator +error[E0689]: can't call method `rev` on type `usize` --> $DIR/issue-90315.rs:23:27 | LL | for i in 1..(end + 1).rev() { - | ^^^ `usize` is not an iterator + | ^^^ can't call method `rev` on type `usize` | help: you must surround the range in parentheses to call the `rev` function | LL | for i in (1..(end + 1)).rev() { | + + -error[E0599]: `usize` is not an iterator +error[E0689]: can't call method `is_empty` on type `usize` --> $DIR/issue-90315.rs:28:21 | LL | if 1..(end + 1).is_empty() { - | ^^^^^^^^ `usize` is not an iterator + | ^^^^^^^^ can't call method `is_empty` on type `usize` | help: you must surround the range in parentheses to call the `is_empty` function | @@ -62,11 +62,11 @@ LL | if 1..(end + 1).is_empty() { = note: expected type `bool` found struct `std::ops::Range<{integer}>` -error[E0599]: `usize` is not an iterator +error[E0689]: can't call method `is_sorted` on type `usize` --> $DIR/issue-90315.rs:34:21 | LL | if 1..(end + 1).is_sorted() { - | ^^^^^^^^^ `usize` is not an iterator + | ^^^^^^^^^ can't call method `is_sorted` on type `usize` | help: you must surround the range in parentheses to call the `is_sorted` function | @@ -82,11 +82,11 @@ LL | if 1..(end + 1).is_sorted() { = note: expected type `bool` found struct `std::ops::Range<{integer}>` -error[E0599]: `{integer}` is not an iterator +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(); - | ^^^^ `{integer}` is not an iterator + | ^^^^ can't call method `take` on type `{integer}` | help: you must surround the range in parentheses to call the `take` function | @@ -104,11 +104,11 @@ LL | let _res: i32 = 3..6.take(2).sum(); = note: expected type `i32` found struct `std::ops::Range<{integer}>` -error[E0599]: `{integer}` is not an iterator +error[E0689]: can't call method `sum` on type `{integer}` --> $DIR/issue-90315.rs:45:26 | LL | let _sum: i32 = 3..6.sum(); - | ^^^ `{integer}` is not an iterator + | ^^^ can't call method `sum` on type `{integer}` | help: you must surround the range in parentheses to call the `sum` function | @@ -126,22 +126,22 @@ LL | let _sum: i32 = 3..6.sum(); = note: expected type `i32` found struct `std::ops::Range<{integer}>` -error[E0599]: `usize` is not an iterator +error[E0689]: can't call method `rev` on type `usize` --> $DIR/issue-90315.rs:53:21 | LL | for _a in a..=b.rev() { - | ^^^ `usize` is not an iterator + | ^^^ can't call method `rev` on type `usize` | help: you must surround the range in parentheses to call the `rev` function | LL | for _a in (a..=b).rev() { | + + -error[E0599]: `{integer}` is not an iterator +error[E0689]: can't call method `contains` on type `{integer}` --> $DIR/issue-90315.rs:58:21 | LL | let _res = ..10.contains(3); - | ^^^^^^^^ `{integer}` is not an iterator + | ^^^^^^^^ can't call method `contains` on type `{integer}` | help: you must surround the range in parentheses to call the `contains` function | @@ -173,7 +173,29 @@ LL | let _res = b.take(1)..a; `usize: Iterator` which is required by `&mut usize: Iterator` -error: aborting due to 17 previous errors +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 -Some errors have detailed explanations: E0308, E0599. +Some errors have detailed explanations: E0308, E0599, E0689. For more information about an error, try `rustc --explain E0308`. From 3021598fdbba9ce32d313bba6b49e03c7701da1f Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 12 Oct 2022 04:03:59 +0000 Subject: [PATCH 4/7] Do not register placeholder region outlives when considering_regions is false --- .../src/traits/fulfill.rs | 2 +- .../higher-rank-trait-bounds/issue-100689.rs | 29 +++++++++++++++++ .../higher-rank-trait-bounds/issue-102899.rs | 32 +++++++++++++++++++ 3 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/higher-rank-trait-bounds/issue-100689.rs create mode 100644 src/test/ui/higher-rank-trait-bounds/issue-102899.rs diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 6eb0239568556..ee752a1c73dd5 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -355,7 +355,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { } ty::PredicateKind::RegionOutlives(data) => { - if infcx.considering_regions || data.has_placeholders() { + if infcx.considering_regions { infcx.region_outlives_predicate(&obligation.cause, Binder::dummy(data)); } diff --git a/src/test/ui/higher-rank-trait-bounds/issue-100689.rs b/src/test/ui/higher-rank-trait-bounds/issue-100689.rs new file mode 100644 index 0000000000000..2db7f8a354cf5 --- /dev/null +++ b/src/test/ui/higher-rank-trait-bounds/issue-100689.rs @@ -0,0 +1,29 @@ +// check-pass + +struct Foo<'a> { + foo: &'a mut usize, +} + +trait Bar<'a> { + type FooRef<'b> + where + 'a: 'b; + fn uwu(foo: Foo<'a>, f: impl for<'b> FnMut(Self::FooRef<'b>)); +} +impl<'a> Bar<'a> for () { + type FooRef<'b> + = + &'b Foo<'a> + where + 'a : 'b, + ; + + fn uwu( + foo: Foo<'a>, + mut f: impl for<'b> FnMut(&'b Foo<'a>), //relevant part + ) { + f(&foo); + } +} + +fn main() {} diff --git a/src/test/ui/higher-rank-trait-bounds/issue-102899.rs b/src/test/ui/higher-rank-trait-bounds/issue-102899.rs new file mode 100644 index 0000000000000..952b81584f30d --- /dev/null +++ b/src/test/ui/higher-rank-trait-bounds/issue-102899.rs @@ -0,0 +1,32 @@ +// check-pass + +pub trait BufferTrait<'buffer> { + type Subset<'channel> + where + 'buffer: 'channel; + + fn for_each_subset(&self, f: F) + where + F: for<'channel> Fn(Self::Subset<'channel>); +} + +pub struct SomeBuffer<'buffer> { + samples: &'buffer [()], +} + +impl<'buffer> BufferTrait<'buffer> for SomeBuffer<'buffer> { + type Subset<'subset> = Subset<'subset> where 'buffer: 'subset; + + fn for_each_subset(&self, _f: F) + where + F: for<'subset> Fn(Subset<'subset>), + { + todo!() + } +} + +pub struct Subset<'subset> { + buffer: &'subset [()], +} + +fn main() {} From e9b29228045d2dede4ba72c172218286fed60b3b Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sat, 15 Oct 2022 10:20:25 -0700 Subject: [PATCH 5/7] rustdoc: remove unused HTML class `sidebar-title` Since 6a5f8b1aef1417d7dc85b5d0a229d2db1930eb7c, this class is no longer styled. --- src/librustdoc/html/render/mod.rs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 1e162bf314b87..cd56d73e7d47b 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -2259,13 +2259,7 @@ fn extract_for_impl_name(item: &clean::Item, cx: &Context<'_>) -> Option<(String } fn print_sidebar_title(buf: &mut Buffer, id: &str, title: &str) { - write!( - buf, - "

\ - {}\ -

", - id, title - ); + write!(buf, "

{}

", id, title); } fn print_sidebar_block( From f0371d123868b2a63db886d8549e2d116d58b21f Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sat, 15 Oct 2022 11:53:47 -0700 Subject: [PATCH 6/7] rustdoc: update test cases for `.sidebar-title` -> `.sidebar-elems h3` --- src/test/rustdoc-gui/sidebar-mobile.goml | 2 +- src/test/rustdoc/associated-consts.rs | 8 ++++---- src/test/rustdoc/deref-recursive-pathbuf.rs | 4 ++-- src/test/rustdoc/deref-recursive.rs | 4 ++-- src/test/rustdoc/deref-typedef.rs | 2 +- src/test/rustdoc/escape-deref-methods.rs | 2 +- src/test/rustdoc/negative-impl-sidebar.rs | 2 +- src/test/rustdoc/sidebar-items.rs | 18 +++++++++--------- .../rustdoc/sidebar-links-to-foreign-impl.rs | 2 +- src/test/rustdoc/tuple-struct-fields-doc.rs | 2 +- 10 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/test/rustdoc-gui/sidebar-mobile.goml b/src/test/rustdoc-gui/sidebar-mobile.goml index 4cded2c773d4a..4b3ec79273d40 100644 --- a/src/test/rustdoc-gui/sidebar-mobile.goml +++ b/src/test/rustdoc-gui/sidebar-mobile.goml @@ -13,7 +13,7 @@ click: ".sidebar-menu-toggle" assert-css: (".sidebar", {"display": "block", "left": "-1000px"}) // Force the sidebar open by focusing a link inside it. // This makes it easier for keyboard users to get to it. -focus: ".sidebar-title a" +focus: ".sidebar-elems h3 a" assert-css: (".sidebar", {"display": "block", "left": "0px"}) // When we tab out of the sidebar, close it. focus: ".search-input" diff --git a/src/test/rustdoc/associated-consts.rs b/src/test/rustdoc/associated-consts.rs index 9319a073bb792..adb155bb52589 100644 --- a/src/test/rustdoc/associated-consts.rs +++ b/src/test/rustdoc/associated-consts.rs @@ -9,7 +9,7 @@ pub trait Trait { pub struct Bar; // @has 'foo/struct.Bar.html' -// @!has - '//h3[@class="sidebar-title"]' 'Associated Constants' +// @!has - '//div[@class="sidebar-elems"]//h3' 'Associated Constants' // @!has - '//div[@class="sidebar-elems"]//a' 'FOO' impl Trait for Bar { const FOO: u32 = 1; @@ -22,7 +22,7 @@ pub enum Foo { } // @has 'foo/enum.Foo.html' -// @!has - '//h3[@class="sidebar-title"]' 'Associated Constants' +// @!has - '//div[@class="sidebar-elems"]//h3' 'Associated Constants' // @!has - '//div[@class="sidebar-elems"]//a' 'FOO' impl Trait for Foo { const FOO: u32 = 1; @@ -33,7 +33,7 @@ impl Trait for Foo { pub struct Baz; // @has 'foo/struct.Baz.html' -// @has - '//h3[@class="sidebar-title"]' 'Associated Constants' +// @has - '//div[@class="sidebar-elems"]//h3' 'Associated Constants' // @has - '//div[@class="sidebar-elems"]//a' 'FOO' impl Baz { pub const FOO: u32 = 42; @@ -44,7 +44,7 @@ pub enum Quux { } // @has 'foo/enum.Quux.html' -// @has - '//h3[@class="sidebar-title"]' 'Associated Constants' +// @has - '//div[@class="sidebar-elems"]//h3' 'Associated Constants' // @has - '//div[@class="sidebar-elems"]//a' 'FOO' impl Quux { pub const FOO: u32 = 42; diff --git a/src/test/rustdoc/deref-recursive-pathbuf.rs b/src/test/rustdoc/deref-recursive-pathbuf.rs index 746df9c804ebb..be2b42b5ac611 100644 --- a/src/test/rustdoc/deref-recursive-pathbuf.rs +++ b/src/test/rustdoc/deref-recursive-pathbuf.rs @@ -7,9 +7,9 @@ // @has '-' '//*[@class="impl-items"]//*[@id="method.as_path"]' 'pub fn as_path(&self)' // @has '-' '//*[@id="deref-methods-Path"]' 'Methods from Deref' // @has '-' '//*[@class="impl-items"]//*[@id="method.exists"]' 'pub fn exists(&self)' -// @has '-' '//*[@class="sidebar-title"]/a[@href="#deref-methods-PathBuf"]' 'Methods from Deref' +// @has '-' '//div[@class="sidebar-elems"]//h3/a[@href="#deref-methods-PathBuf"]' 'Methods from Deref' // @has '-' '//*[@class="sidebar-elems"]//*[@class="block"]//a[@href="#method.as_path"]' 'as_path' -// @has '-' '//*[@class="sidebar-title"]/a[@href="#deref-methods-Path"]' 'Methods from Deref' +// @has '-' '//div[@class="sidebar-elems"]//h3/a[@href="#deref-methods-Path"]' 'Methods from Deref' // @has '-' '//*[@class="sidebar-elems"]//*[@class="block"]//a[@href="#method.exists"]' 'exists' #![crate_name = "foo"] diff --git a/src/test/rustdoc/deref-recursive.rs b/src/test/rustdoc/deref-recursive.rs index d5f8473f2842d..0436f2f86f594 100644 --- a/src/test/rustdoc/deref-recursive.rs +++ b/src/test/rustdoc/deref-recursive.rs @@ -7,9 +7,9 @@ // @has '-' '//*[@class="impl-items"]//*[@id="method.bar"]' 'pub fn bar(&self)' // @has '-' '//*[@id="deref-methods-Baz"]' 'Methods from Deref' // @has '-' '//*[@class="impl-items"]//*[@id="method.baz"]' 'pub fn baz(&self)' -// @has '-' '//*[@class="sidebar-title"]/a[@href="#deref-methods-Bar"]' 'Methods from Deref' +// @has '-' '//div[@class="sidebar-elems"]//h3/a[@href="#deref-methods-Bar"]' 'Methods from Deref' // @has '-' '//*[@class="sidebar-elems"]//section//a[@href="#method.bar"]' 'bar' -// @has '-' '//*[@class="sidebar-title"]/a[@href="#deref-methods-Baz"]' 'Methods from Deref' +// @has '-' '//div[@class="sidebar-elems"]//h3/a[@href="#deref-methods-Baz"]' 'Methods from Deref' // @has '-' '//*[@class="sidebar-elems"]//section//a[@href="#method.baz"]' 'baz' #![crate_name = "foo"] diff --git a/src/test/rustdoc/deref-typedef.rs b/src/test/rustdoc/deref-typedef.rs index 28f977e315abf..32424d13eb855 100644 --- a/src/test/rustdoc/deref-typedef.rs +++ b/src/test/rustdoc/deref-typedef.rs @@ -6,7 +6,7 @@ // @has '-' '//*[@class="impl-items"]//*[@id="method.foo_b"]' 'pub fn foo_b(&self)' // @has '-' '//*[@class="impl-items"]//*[@id="method.foo_c"]' 'pub fn foo_c(&self)' // @has '-' '//*[@class="impl-items"]//*[@id="method.foo_j"]' 'pub fn foo_j(&self)' -// @has '-' '//*[@class="sidebar-title"]/a[@href="#deref-methods-FooJ"]' 'Methods from Deref' +// @has '-' '//div[@class="sidebar-elems"]//h3/a[@href="#deref-methods-FooJ"]' 'Methods from Deref' // @has '-' '//*[@class="sidebar-elems"]//section//a[@href="#method.foo_a"]' 'foo_a' // @has '-' '//*[@class="sidebar-elems"]//section//a[@href="#method.foo_b"]' 'foo_b' // @has '-' '//*[@class="sidebar-elems"]//section//a[@href="#method.foo_c"]' 'foo_c' diff --git a/src/test/rustdoc/escape-deref-methods.rs b/src/test/rustdoc/escape-deref-methods.rs index a62ad2c400173..66919d73eeb63 100644 --- a/src/test/rustdoc/escape-deref-methods.rs +++ b/src/test/rustdoc/escape-deref-methods.rs @@ -27,7 +27,7 @@ impl Deref for TitleList { } // @has foo/struct.TitleList.html -// @has - '//*[@class="sidebar-title"]' 'Methods from Deref>' +// @has - '//div[@class="sidebar-elems"]//h3' 'Methods from Deref>' impl DerefMut for TitleList { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.members diff --git a/src/test/rustdoc/negative-impl-sidebar.rs b/src/test/rustdoc/negative-impl-sidebar.rs index b995fff1f9aa7..4af6d0084925f 100644 --- a/src/test/rustdoc/negative-impl-sidebar.rs +++ b/src/test/rustdoc/negative-impl-sidebar.rs @@ -4,6 +4,6 @@ pub struct Foo; // @has foo/struct.Foo.html -// @has - '//*[@class="sidebar-title"]/a[@href="#trait-implementations"]' 'Trait Implementations' +// @has - '//div[@class="sidebar-elems"]//h3/a[@href="#trait-implementations"]' 'Trait Implementations' // @has - '//*[@class="sidebar-elems"]//section//a' '!Sync' impl !Sync for Foo {} diff --git a/src/test/rustdoc/sidebar-items.rs b/src/test/rustdoc/sidebar-items.rs index b5b681ab085bf..6f7afa59bddc7 100644 --- a/src/test/rustdoc/sidebar-items.rs +++ b/src/test/rustdoc/sidebar-items.rs @@ -2,17 +2,17 @@ #![crate_name = "foo"] // @has foo/trait.Foo.html -// @has - '//*[@class="sidebar-title"]/a[@href="#required-methods"]' 'Required Methods' +// @has - '//div[@class="sidebar-elems"]//h3/a[@href="#required-methods"]' 'Required Methods' // @has - '//*[@class="sidebar-elems"]//section//a' 'bar' -// @has - '//*[@class="sidebar-title"]/a[@href="#provided-methods"]' 'Provided Methods' +// @has - '//div[@class="sidebar-elems"]//h3/a[@href="#provided-methods"]' 'Provided Methods' // @has - '//*[@class="sidebar-elems"]//section//a' 'foo' -// @has - '//*[@class="sidebar-title"]/a[@href="#required-associated-consts"]' 'Required Associated Constants' +// @has - '//div[@class="sidebar-elems"]//h3/a[@href="#required-associated-consts"]' 'Required Associated Constants' // @has - '//*[@class="sidebar-elems"]//section//a' 'FOO' -// @has - '//*[@class="sidebar-title"]/a[@href="#provided-associated-consts"]' 'Provided Associated Constants' +// @has - '//div[@class="sidebar-elems"]//h3/a[@href="#provided-associated-consts"]' 'Provided Associated Constants' // @has - '//*[@class="sidebar-elems"]//section//a' 'BAR' -// @has - '//*[@class="sidebar-title"]/a[@href="#required-associated-types"]' 'Required Associated Types' +// @has - '//div[@class="sidebar-elems"]//h3/a[@href="#required-associated-types"]' 'Required Associated Types' // @has - '//*[@class="sidebar-elems"]//section//a' 'Output' -// @has - '//*[@class="sidebar-title"]/a[@href="#provided-associated-types"]' 'Provided Associated Types' +// @has - '//div[@class="sidebar-elems"]//h3/a[@href="#provided-associated-types"]' 'Provided Associated Types' // @has - '//*[@class="sidebar-elems"]//section//a' 'Extra' pub trait Foo { const FOO: usize; @@ -25,7 +25,7 @@ pub trait Foo { } // @has foo/struct.Bar.html -// @has - '//*[@class="sidebar-title"]/a[@href="#fields"]' 'Fields' +// @has - '//div[@class="sidebar-elems"]//h3/a[@href="#fields"]' 'Fields' // @has - '//*[@class="sidebar-elems"]//section//a[@href="#structfield.f"]' 'f' // @has - '//*[@class="sidebar-elems"]//section//a[@href="#structfield.u"]' 'u' // @!has - '//*[@class="sidebar-elems"]//section//a' 'waza' @@ -36,7 +36,7 @@ pub struct Bar { } // @has foo/enum.En.html -// @has - '//*[@class="sidebar-title"]/a[@href="#variants"]' 'Variants' +// @has - '//div[@class="sidebar-elems"]//h3/a[@href="#variants"]' 'Variants' // @has - '//*[@class="sidebar-elems"]//section//a' 'Foo' // @has - '//*[@class="sidebar-elems"]//section//a' 'Bar' pub enum En { @@ -45,7 +45,7 @@ pub enum En { } // @has foo/union.MyUnion.html -// @has - '//*[@class="sidebar-title"]/a[@href="#fields"]' 'Fields' +// @has - '//div[@class="sidebar-elems"]//h3/a[@href="#fields"]' 'Fields' // @has - '//*[@class="sidebar-elems"]//section//a[@href="#structfield.f1"]' 'f1' // @has - '//*[@class="sidebar-elems"]//section//a[@href="#structfield.f2"]' 'f2' // @!has - '//*[@class="sidebar-elems"]//section//a' 'waza' diff --git a/src/test/rustdoc/sidebar-links-to-foreign-impl.rs b/src/test/rustdoc/sidebar-links-to-foreign-impl.rs index 6712af527a377..11e946948026d 100644 --- a/src/test/rustdoc/sidebar-links-to-foreign-impl.rs +++ b/src/test/rustdoc/sidebar-links-to-foreign-impl.rs @@ -3,7 +3,7 @@ #![crate_name = "foo"] // @has foo/trait.Foo.html -// @has - '//*[@class="sidebar-title"]/a[@href="#foreign-impls"]' 'Implementations on Foreign Types' +// @has - '//div[@class="sidebar-elems"]//h3/a[@href="#foreign-impls"]' 'Implementations on Foreign Types' // @has - '//h2[@id="foreign-impls"]' 'Implementations on Foreign Types' // @has - '//*[@class="sidebar-elems"]//section//a[@href="#impl-Foo-for-u32"]' 'u32' // @has - '//*[@id="impl-Foo-for-u32"]//h3[@class="code-header"]' 'impl Foo for u32' diff --git a/src/test/rustdoc/tuple-struct-fields-doc.rs b/src/test/rustdoc/tuple-struct-fields-doc.rs index 66bb409325c99..8ab1143d1f70e 100644 --- a/src/test/rustdoc/tuple-struct-fields-doc.rs +++ b/src/test/rustdoc/tuple-struct-fields-doc.rs @@ -2,7 +2,7 @@ // @has foo/struct.Foo.html // @has - '//h2[@id="fields"]' 'Tuple Fields' -// @has - '//h3[@class="sidebar-title"]/a[@href="#fields"]' 'Tuple Fields' +// @has - '//div[@class="sidebar-elems"]//h3/a[@href="#fields"]' 'Tuple Fields' // @has - '//*[@id="structfield.0"]' '0: u32' // @has - '//*[@id="main-content"]/div[@class="docblock"]' 'hello' // @!has - '//*[@id="structfield.1"]' '' From 151001c1cb1c054d7f259e90ed44b31c25ba2db7 Mon Sep 17 00:00:00 2001 From: yukang Date: Mon, 17 Oct 2022 08:32:08 +0800 Subject: [PATCH 7/7] trivial fix for comments feedback --- .../locales/en-US/hir_analysis.ftl | 2 +- .../src/check/method/suggest.rs | 26 ++++++++++++------- src/test/ui/methods/issues/issue-90315.stderr | 20 +++++++------- 3 files changed, 28 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl b/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl index 5a7aee9c1c147..357c6900a70e5 100644 --- a/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl +++ b/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl @@ -136,4 +136,4 @@ hir_analysis_expected_used_symbol = expected `used`, `used(compiler)` or `used(l 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 the `{$func_name}` function +hir_analysis_add_missing_parentheses_in_range = you must surround the range in parentheses to call its `{$func_name}` function diff --git a/compiler/rustc_hir_analysis/src/check/method/suggest.rs b/compiler/rustc_hir_analysis/src/check/method/suggest.rs index 9aa1b2e2c0a51..6e9ea5d7f52fa 100644 --- a/compiler/rustc_hir_analysis/src/check/method/suggest.rs +++ b/compiler/rustc_hir_analysis/src/check/method/suggest.rs @@ -272,11 +272,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } }; - if self.suggest_range_for_iter(tcx, actual, source, span, item_name, &ty_str) - || self.suggest_constraining_numerical_ty( - tcx, actual, source, span, item_kind, item_name, &ty_str, - ) - { + if self.suggest_wrapping_range_with_parens( + tcx, actual, source, span, item_name, &ty_str, + ) || self.suggest_constraining_numerical_ty( + tcx, actual, source, span, item_kind, item_name, &ty_str, + ) { return None; } @@ -1204,7 +1204,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { false } - fn suggest_range_for_iter( + /// 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>, @@ -1252,13 +1254,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { continue; } - debug!("lang_item: {:?}", lang_item); 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.lookup_probe(span, item_name, range_ty, expr, ProbeScope::AllTraits); + 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 { diff --git a/src/test/ui/methods/issues/issue-90315.stderr b/src/test/ui/methods/issues/issue-90315.stderr index 581d6fb4fc9e4..070cd3054369b 100644 --- a/src/test/ui/methods/issues/issue-90315.stderr +++ b/src/test/ui/methods/issues/issue-90315.stderr @@ -4,7 +4,7 @@ error[E0689]: can't call method `rev` on type `usize` 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 the `rev` function +help: you must surround the range in parentheses to call its `rev` function | LL | for _i in (0..arr.len()).rev() { | + + @@ -15,7 +15,7 @@ error[E0689]: can't call method `rev` on type `{integer}` 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 the `rev` function +help: you must surround the range in parentheses to call its `rev` function | LL | for i in (1..11).rev() { | + + @@ -26,7 +26,7 @@ error[E0689]: can't call method `rev` on type `usize` 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 the `rev` function +help: you must surround the range in parentheses to call its `rev` function | LL | for i in (1..end).rev() { | + + @@ -37,7 +37,7 @@ error[E0689]: can't call method `rev` on type `usize` 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 the `rev` function +help: you must surround the range in parentheses to call its `rev` function | LL | for i in (1..(end + 1)).rev() { | + + @@ -48,7 +48,7 @@ error[E0689]: can't call method `is_empty` on type `usize` 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 the `is_empty` function +help: you must surround the range in parentheses to call its `is_empty` function | LL | if (1..(end + 1)).is_empty() { | + + @@ -68,7 +68,7 @@ error[E0689]: can't call method `is_sorted` on type `usize` 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 the `is_sorted` function +help: you must surround the range in parentheses to call its `is_sorted` function | LL | if (1..(end + 1)).is_sorted() { | + + @@ -88,7 +88,7 @@ error[E0689]: can't call method `take` on type `{integer}` 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 the `take` function +help: you must surround the range in parentheses to call its `take` function | LL | let _res: i32 = (3..6).take(2).sum(); | + + @@ -110,7 +110,7 @@ error[E0689]: can't call method `sum` on type `{integer}` 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 the `sum` function +help: you must surround the range in parentheses to call its `sum` function | LL | let _sum: i32 = (3..6).sum(); | + + @@ -132,7 +132,7 @@ error[E0689]: can't call method `rev` on type `usize` 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 the `rev` function +help: you must surround the range in parentheses to call its `rev` function | LL | for _a in (a..=b).rev() { | + + @@ -143,7 +143,7 @@ error[E0689]: can't call method `contains` on type `{integer}` LL | let _res = ..10.contains(3); | ^^^^^^^^ can't call method `contains` on type `{integer}` | -help: you must surround the range in parentheses to call the `contains` function +help: you must surround the range in parentheses to call its `contains` function | LL | let _res = (..10).contains(3); | + +