From 503e6af36324742e8325babdb957b70e850982bc Mon Sep 17 00:00:00 2001 From: GTimothy <22472919+GTimothy@users.noreply.github.com> Date: Wed, 6 May 2026 12:08:35 +0200 Subject: [PATCH 1/3] add import suggestion generic parameter filtering test add test bless test --- tests/ui/imports/generic-param-filter.rs | 4 ++++ tests/ui/imports/generic-param-filter.stderr | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 tests/ui/imports/generic-param-filter.rs create mode 100644 tests/ui/imports/generic-param-filter.stderr diff --git a/tests/ui/imports/generic-param-filter.rs b/tests/ui/imports/generic-param-filter.rs new file mode 100644 index 0000000000000..288e5d9503560 --- /dev/null +++ b/tests/ui/imports/generic-param-filter.rs @@ -0,0 +1,4 @@ +fn test_cloned(_x: cloned<(), ()>){} +//~^ ERROR: cannot find type `cloned` in this scope + +fn main(){} diff --git a/tests/ui/imports/generic-param-filter.stderr b/tests/ui/imports/generic-param-filter.stderr new file mode 100644 index 0000000000000..8151d907ff304 --- /dev/null +++ b/tests/ui/imports/generic-param-filter.stderr @@ -0,0 +1,18 @@ +error[E0425]: cannot find type `cloned` in this scope + --> $DIR/generic-param-filter.rs:1:20 + | +LL | fn test_cloned(_x: cloned<(), ()>){} + | ^^^^^^ + | + --> $SRC_DIR/core/src/clone.rs:LL:COL + | + = note: similarly named trait `Clone` defined here +help: a trait with a similar name exists + | +LL - fn test_cloned(_x: cloned<(), ()>){} +LL + fn test_cloned(_x: Clone<(), ()>){} + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0425`. From d8e21ff822e48efec72652b056aedc9e4fefee8e Mon Sep 17 00:00:00 2001 From: GTimothy <22472919+GTimothy@users.noreply.github.com> Date: Sun, 31 May 2026 20:33:44 +0200 Subject: [PATCH 2/3] do not suggest typos lacking generic parameters when some required --- compiler/rustc_resolve/src/late.rs | 12 ++++++++++++ compiler/rustc_resolve/src/late/diagnostics.rs | 12 +++++++++++- compiler/rustc_resolve/src/lib.rs | 13 +++++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index c21d3653a13be..3ff659dfc1c3d 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -5607,6 +5607,18 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, 'ast, '_, '_> { .filter(|param| matches!(param.kind, ast::GenericParamKind::Lifetime { .. })) .count(); self.r.item_generics_num_lifetimes.insert(def_id, count); + let type_or_const_count = generics + .params + .iter() + .filter(|param| { + matches!( + param.kind, + ast::GenericParamKind::Type { .. } + | ast::GenericParamKind::Const { .. } + ) + }) + .count(); + self.r.item_generics_num_type_or_const_params.insert(def_id, type_or_const_count); } ItemKind::ForeignMod(ForeignMod { items, .. }) => { diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index b126272583692..6d7408b71d4b4 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1322,7 +1322,17 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { let mut fallback = false; let typo_sugg = typo_sugg .to_opt_suggestion() - .filter(|sugg| !suggested_candidates.contains(sugg.candidate.as_str())); + .filter(|sugg| !suggested_candidates.contains(sugg.candidate.as_str())) + // this filters out suggestions that require parameters when no parameter is present + .filter(|sugg| { + if !path.last().is_some_and(|s| s.has_generic_args) { + return true; + } + let Some(def_id) = sugg.res.opt_def_id() else { + return true; + }; + self.r.item_generics_num_type_or_const_params(def_id) > 0 + }); if !self.r.add_typo_suggestion(err, typo_sugg, ident_span) { fallback = true; match self.diag_metadata.current_let_binding { diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index b7e57ad8ec37e..d1740decd92c8 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1499,6 +1499,8 @@ pub struct Resolver<'ra, 'tcx> { /// Amount of lifetime parameters for each item in the crate. item_generics_num_lifetimes: FxHashMap = default::fx_hash_map(), + /// Amount of type or const parameters for each item in the crate. + item_generics_num_type_or_const_params: FxHashMap = default::fx_hash_map(), /// Generic args to suggest for required params (e.g. `<'_>`, `<_, _>`), if any. item_required_generic_args_suggestions: FxHashMap = default::fx_hash_map(), delegation_fn_sigs: LocalDefIdMap = Default::default(), @@ -1709,6 +1711,17 @@ impl<'tcx> Resolver<'_, 'tcx> { self.tcx.generics_of(def_id).own_counts().lifetimes } } + // Get count of expected parameters + fn item_generics_num_type_or_const_params(&self, def_id: DefId) -> usize { + if let Some(def_id) = def_id.as_local() { + self.item_generics_num_type_or_const_params.get(&def_id).copied().unwrap_or(0) + } else { + let generics = self.tcx.generics_of(def_id); + let counts = generics.own_counts(); + // saturating_sub may not be strictly necessary, better safe than sorry + counts.types.saturating_sub(generics.has_own_self() as usize) + counts.consts + } + } fn item_required_generic_args_suggestion(&self, def_id: DefId) -> String { if let Some(def_id) = def_id.as_local() { From 31792bf9e4388bb0ab6e6caa8645364982aa4b3c Mon Sep 17 00:00:00 2001 From: GTimothy <22472919+GTimothy@users.noreply.github.com> Date: Sat, 15 Aug 2026 23:48:59 +0200 Subject: [PATCH 3/3] bless tests --- .../mgca/unused_speculative_def_id.stderr | 11 +---------- tests/ui/imports/generic-param-filter.stderr | 11 +---------- 2 files changed, 2 insertions(+), 20 deletions(-) diff --git a/tests/ui/const-generics/mgca/unused_speculative_def_id.stderr b/tests/ui/const-generics/mgca/unused_speculative_def_id.stderr index e087e046ec35d..14f80b6b1d71a 100644 --- a/tests/ui/const-generics/mgca/unused_speculative_def_id.stderr +++ b/tests/ui/const-generics/mgca/unused_speculative_def_id.stderr @@ -2,16 +2,7 @@ error[E0425]: cannot find value `ERR` in this scope --> $DIR/unused_speculative_def_id.rs:20:16 | LL | field: A<{ ERR:: }>, - | ^^^ - | - --> $SRC_DIR/core/src/result.rs:LL:COL - | - = note: similarly named tuple variant `Err` defined here -help: a tuple variant with a similar name exists - | -LL - field: A<{ ERR:: }>, -LL + field: A<{ Err:: }>, - | + | ^^^ not found in this scope error: aborting due to 1 previous error diff --git a/tests/ui/imports/generic-param-filter.stderr b/tests/ui/imports/generic-param-filter.stderr index 8151d907ff304..8437aed28fd31 100644 --- a/tests/ui/imports/generic-param-filter.stderr +++ b/tests/ui/imports/generic-param-filter.stderr @@ -2,16 +2,7 @@ error[E0425]: cannot find type `cloned` in this scope --> $DIR/generic-param-filter.rs:1:20 | LL | fn test_cloned(_x: cloned<(), ()>){} - | ^^^^^^ - | - --> $SRC_DIR/core/src/clone.rs:LL:COL - | - = note: similarly named trait `Clone` defined here -help: a trait with a similar name exists - | -LL - fn test_cloned(_x: cloned<(), ()>){} -LL + fn test_cloned(_x: Clone<(), ()>){} - | + | ^^^^^^ not found in this scope error: aborting due to 1 previous error