From 973ab7d08f6075b833aba0d8f96c28710b1cdfa3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 1 Nov 2025 18:23:19 +0000 Subject: [PATCH 1/7] Make "add param to inner item" suggestion verbose ``` error[E0401]: can't use generic parameters from outer item --> $DIR/enum-definition-with-outer-generic-parameter-5997.rs:3:16 | LL | fn f() -> bool { | - type parameter from outer item LL | enum E { V(Z) } | ^ use of generic parameter from outer item | help: try introducing a local generic parameter here | LL | enum E { V(Z) } | +++ ``` --- compiler/rustc_resolve/src/errors.rs | 7 +++- .../early/const-param-from-outer-fn.stderr | 6 +++- tests/ui/delegation/target-expr.stderr | 9 +++-- tests/ui/error-codes/E0401.stderr | 17 +++++---- ...n-with-outer-generic-parameter-5997.stderr | 9 +++-- ...eneric-params-nested-fn-scope-error.stderr | 18 ++++++---- tests/ui/generics/issue-98432.stderr | 9 +++-- tests/ui/resolve/bad-type-env-capture.stderr | 9 +++-- ...m-in-const-item.generic_const_items.stderr | 24 ++++++++----- tests/ui/resolve/issue-3021-c.stderr | 18 ++++++---- tests/ui/resolve/issue-3214.stderr | 6 +++- ...resolve-type-param-in-item-in-trait.stderr | 36 ++++++++++++------- tests/ui/type/type-arg-out-of-scope.stderr | 18 ++++++---- 13 files changed, 126 insertions(+), 60 deletions(-) diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs index f0ea97ba8a0c0..3465c7fb16473 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -47,7 +47,12 @@ pub(crate) enum GenericParamsFromOuterItemLabel { } #[derive(Subdiagnostic)] -#[suggestion(resolve_suggestion, code = "{snippet}", applicability = "maybe-incorrect")] +#[suggestion( + resolve_suggestion, + code = "{snippet}", + applicability = "maybe-incorrect", + style = "verbose" +)] pub(crate) struct GenericParamsFromOuterItemSugg { #[primary_span] pub(crate) span: Span, diff --git a/tests/ui/const-generics/early/const-param-from-outer-fn.stderr b/tests/ui/const-generics/early/const-param-from-outer-fn.stderr index faba4ce10a1b4..0f7c7fbc6be01 100644 --- a/tests/ui/const-generics/early/const-param-from-outer-fn.stderr +++ b/tests/ui/const-generics/early/const-param-from-outer-fn.stderr @@ -4,9 +4,13 @@ error[E0401]: can't use generic parameters from outer item LL | fn foo() { | - const parameter from outer item LL | fn bar() -> u32 { - | - help: try introducing a local generic parameter here: `` LL | X | ^ use of generic parameter from outer item + | +help: try introducing a local generic parameter here + | +LL | fn bar() -> u32 { + | +++ error: aborting due to 1 previous error diff --git a/tests/ui/delegation/target-expr.stderr b/tests/ui/delegation/target-expr.stderr index f5556bf9f4514..8bb25ad9e96e2 100644 --- a/tests/ui/delegation/target-expr.stderr +++ b/tests/ui/delegation/target-expr.stderr @@ -3,11 +3,14 @@ error[E0401]: can't use generic parameters from outer item | LL | fn bar(_: T) { | - type parameter from outer item -LL | reuse Trait::static_method { - | - help: try introducing a local generic parameter here: `T,` -LL | +... LL | let _ = T::Default(); | ^^^^^^^^^^ use of generic parameter from outer item + | +help: try introducing a local generic parameter here + | +LL | reuse Trait::static_methodT, { + | ++ error[E0434]: can't capture dynamic environment in a fn item --> $DIR/target-expr.rs:26:17 diff --git a/tests/ui/error-codes/E0401.stderr b/tests/ui/error-codes/E0401.stderr index 5d6878620c89a..fedb064c6bea6 100644 --- a/tests/ui/error-codes/E0401.stderr +++ b/tests/ui/error-codes/E0401.stderr @@ -4,9 +4,12 @@ error[E0401]: can't use generic parameters from outer item LL | fn foo(x: T) { | - type parameter from outer item LL | fn bfnr, W: Fn()>(y: T) { - | - ^ use of generic parameter from outer item - | | - | help: try introducing a local generic parameter here: `T,` + | ^ use of generic parameter from outer item + | +help: try introducing a local generic parameter here + | +LL | fn bfnr, W: Fn()>(y: T) { + | ++ error[E0401]: can't use generic parameters from outer item --> $DIR/E0401.rs:9:16 @@ -14,11 +17,13 @@ error[E0401]: can't use generic parameters from outer item LL | fn foo(x: T) { | - type parameter from outer item ... -LL | fn baz $DIR/E0401.rs:22:25 diff --git a/tests/ui/generics/enum-definition-with-outer-generic-parameter-5997.stderr b/tests/ui/generics/enum-definition-with-outer-generic-parameter-5997.stderr index aea0f049b07d3..cded8ce319616 100644 --- a/tests/ui/generics/enum-definition-with-outer-generic-parameter-5997.stderr +++ b/tests/ui/generics/enum-definition-with-outer-generic-parameter-5997.stderr @@ -4,9 +4,12 @@ error[E0401]: can't use generic parameters from outer item LL | fn f() -> bool { | - type parameter from outer item LL | enum E { V(Z) } - | - ^ use of generic parameter from outer item - | | - | help: try introducing a local generic parameter here: `` + | ^ use of generic parameter from outer item + | +help: try introducing a local generic parameter here + | +LL | enum E { V(Z) } + | +++ error: aborting due to 1 previous error diff --git a/tests/ui/generics/generic-params-nested-fn-scope-error.stderr b/tests/ui/generics/generic-params-nested-fn-scope-error.stderr index 7fd1069c651fa..8c3b65d1edea9 100644 --- a/tests/ui/generics/generic-params-nested-fn-scope-error.stderr +++ b/tests/ui/generics/generic-params-nested-fn-scope-error.stderr @@ -4,9 +4,12 @@ error[E0401]: can't use generic parameters from outer item LL | fn foo(v: Vec) -> U { | - type parameter from outer item LL | fn bar(w: [U]) -> U { - | - ^ use of generic parameter from outer item - | | - | help: try introducing a local generic parameter here: `` + | ^ use of generic parameter from outer item + | +help: try introducing a local generic parameter here + | +LL | fn bar(w: [U]) -> U { + | +++ error[E0401]: can't use generic parameters from outer item --> $DIR/generic-params-nested-fn-scope-error.rs:5:23 @@ -14,9 +17,12 @@ error[E0401]: can't use generic parameters from outer item LL | fn foo(v: Vec) -> U { | - type parameter from outer item LL | fn bar(w: [U]) -> U { - | - ^ use of generic parameter from outer item - | | - | help: try introducing a local generic parameter here: `` + | ^ use of generic parameter from outer item + | +help: try introducing a local generic parameter here + | +LL | fn bar(w: [U]) -> U { + | +++ error: aborting due to 2 previous errors diff --git a/tests/ui/generics/issue-98432.stderr b/tests/ui/generics/issue-98432.stderr index 2b09d43960f62..f20f779d884c0 100644 --- a/tests/ui/generics/issue-98432.stderr +++ b/tests/ui/generics/issue-98432.stderr @@ -5,9 +5,12 @@ LL | impl Struct { | - type parameter from outer item LL | const CONST: fn() = || { LL | struct _Obligation where T:; - | - ^ use of generic parameter from outer item - | | - | help: try introducing a local generic parameter here: `` + | ^ use of generic parameter from outer item + | +help: try introducing a local generic parameter here + | +LL | struct _Obligation where T:; + | +++ error: aborting due to 1 previous error diff --git a/tests/ui/resolve/bad-type-env-capture.stderr b/tests/ui/resolve/bad-type-env-capture.stderr index 3f9bc9149c24a..272672beb4fbb 100644 --- a/tests/ui/resolve/bad-type-env-capture.stderr +++ b/tests/ui/resolve/bad-type-env-capture.stderr @@ -4,9 +4,12 @@ error[E0401]: can't use generic parameters from outer item LL | fn foo() { | - type parameter from outer item LL | fn bar(b: T) { } - | - ^ use of generic parameter from outer item - | | - | help: try introducing a local generic parameter here: `` + | ^ use of generic parameter from outer item + | +help: try introducing a local generic parameter here + | +LL | fn bar(b: T) { } + | +++ error: aborting due to 1 previous error diff --git a/tests/ui/resolve/generic-params-from-outer-item-in-const-item.generic_const_items.stderr b/tests/ui/resolve/generic-params-from-outer-item-in-const-item.generic_const_items.stderr index 60aa94038c3ad..3852b84fee2e0 100644 --- a/tests/ui/resolve/generic-params-from-outer-item-in-const-item.generic_const_items.stderr +++ b/tests/ui/resolve/generic-params-from-outer-item-in-const-item.generic_const_items.stderr @@ -4,11 +4,13 @@ error[E0401]: can't use generic parameters from outer item LL | fn outer() { // outer function | - type parameter from outer item LL | const K: u32 = T::C; - | - ^^^^ use of generic parameter from outer item - | | - | help: try introducing a local generic parameter here: `` + | ^^^^ use of generic parameter from outer item | = note: a `const` is a separate item from the item that contains it +help: try introducing a local generic parameter here + | +LL | const K: u32 = T::C; + | +++ error[E0401]: can't use generic parameters from outer item --> $DIR/generic-params-from-outer-item-in-const-item.rs:19:24 @@ -17,11 +19,13 @@ LL | impl Tr for T { // outer impl block | - type parameter from outer item LL | const C: u32 = { LL | const I: u32 = T::C; - | - ^^^^ use of generic parameter from outer item - | | - | help: try introducing a local generic parameter here: `` + | ^^^^ use of generic parameter from outer item | = note: a `const` is a separate item from the item that contains it +help: try introducing a local generic parameter here + | +LL | const I: u32 = T::C; + | +++ error[E0401]: can't use generic parameters from outer item --> $DIR/generic-params-from-outer-item-in-const-item.rs:27:20 @@ -29,11 +33,13 @@ error[E0401]: can't use generic parameters from outer item LL | struct S(U32<{ // outer struct | - type parameter from outer item LL | const _: u32 = T::C; - | - ^^^^ use of generic parameter from outer item - | | - | help: try introducing a local generic parameter here: `` + | ^^^^ use of generic parameter from outer item | = note: a `const` is a separate item from the item that contains it +help: try introducing a local generic parameter here + | +LL | const _: u32 = T::C; + | +++ error: aborting due to 3 previous errors diff --git a/tests/ui/resolve/issue-3021-c.stderr b/tests/ui/resolve/issue-3021-c.stderr index 537bbaf7b6a56..dcbaf2afd10c6 100644 --- a/tests/ui/resolve/issue-3021-c.stderr +++ b/tests/ui/resolve/issue-3021-c.stderr @@ -3,22 +3,28 @@ error[E0401]: can't use generic parameters from outer item | LL | fn siphash() { | - type parameter from outer item -LL | -LL | trait U { - | - help: try introducing a local generic parameter here: `` +... LL | fn g(&self, x: T) -> T; | ^ use of generic parameter from outer item + | +help: try introducing a local generic parameter here + | +LL | trait U { + | +++ error[E0401]: can't use generic parameters from outer item --> $DIR/issue-3021-c.rs:4:30 | LL | fn siphash() { | - type parameter from outer item -LL | -LL | trait U { - | - help: try introducing a local generic parameter here: `` +... LL | fn g(&self, x: T) -> T; | ^ use of generic parameter from outer item + | +help: try introducing a local generic parameter here + | +LL | trait U { + | +++ error: aborting due to 2 previous errors diff --git a/tests/ui/resolve/issue-3214.stderr b/tests/ui/resolve/issue-3214.stderr index 1c64fdc1711fd..5e5872f2a5fbd 100644 --- a/tests/ui/resolve/issue-3214.stderr +++ b/tests/ui/resolve/issue-3214.stderr @@ -4,9 +4,13 @@ error[E0401]: can't use generic parameters from outer item LL | fn foo() { | - type parameter from outer item LL | struct Foo { - | - help: try introducing a local generic parameter here: `` LL | x: T, | ^ use of generic parameter from outer item + | +help: try introducing a local generic parameter here + | +LL | struct Foo { + | +++ error[E0107]: struct takes 0 generic arguments but 1 generic argument was supplied --> $DIR/issue-3214.rs:6:22 diff --git a/tests/ui/resolve/resolve-type-param-in-item-in-trait.stderr b/tests/ui/resolve/resolve-type-param-in-item-in-trait.stderr index 1ab56fdc50441..086418df7a253 100644 --- a/tests/ui/resolve/resolve-type-param-in-item-in-trait.stderr +++ b/tests/ui/resolve/resolve-type-param-in-item-in-trait.stderr @@ -3,11 +3,14 @@ error[E0401]: can't use generic parameters from outer item | LL | trait TraitA { | - type parameter from outer item -LL | fn outer(&self) { -LL | enum Foo { - | - help: try introducing a local generic parameter here: `A,` +... LL | Variance(A) | ^ use of generic parameter from outer item + | +help: try introducing a local generic parameter here + | +LL | enum Foo { + | ++ error[E0401]: can't use generic parameters from outer item --> $DIR/resolve-type-param-in-item-in-trait.rs:16:23 @@ -16,9 +19,12 @@ LL | trait TraitB { | - type parameter from outer item LL | fn outer(&self) { LL | struct Foo(A); - | - ^ use of generic parameter from outer item - | | - | help: try introducing a local generic parameter here: `A,` + | ^ use of generic parameter from outer item + | +help: try introducing a local generic parameter here + | +LL | struct Foo(A); + | ++ error[E0401]: can't use generic parameters from outer item --> $DIR/resolve-type-param-in-item-in-trait.rs:23:28 @@ -27,9 +33,12 @@ LL | trait TraitC { | - type parameter from outer item LL | fn outer(&self) { LL | struct Foo { a: A } - | - ^ use of generic parameter from outer item - | | - | help: try introducing a local generic parameter here: `A,` + | ^ use of generic parameter from outer item + | +help: try introducing a local generic parameter here + | +LL | struct Foo { a: A } + | ++ error[E0401]: can't use generic parameters from outer item --> $DIR/resolve-type-param-in-item-in-trait.rs:30:22 @@ -38,9 +47,12 @@ LL | trait TraitD { | - type parameter from outer item LL | fn outer(&self) { LL | fn foo(a: A) { } - | - ^ use of generic parameter from outer item - | | - | help: try introducing a local generic parameter here: `A,` + | ^ use of generic parameter from outer item + | +help: try introducing a local generic parameter here + | +LL | fn foo(a: A) { } + | ++ error: aborting due to 4 previous errors diff --git a/tests/ui/type/type-arg-out-of-scope.stderr b/tests/ui/type/type-arg-out-of-scope.stderr index fcaaca1770f67..f4fbcdac53b66 100644 --- a/tests/ui/type/type-arg-out-of-scope.stderr +++ b/tests/ui/type/type-arg-out-of-scope.stderr @@ -4,9 +4,12 @@ error[E0401]: can't use generic parameters from outer item LL | fn foo(x: T) { | - type parameter from outer item LL | fn bar(f: Box T>) { } - | - ^ use of generic parameter from outer item - | | - | help: try introducing a local generic parameter here: `` + | ^ use of generic parameter from outer item + | +help: try introducing a local generic parameter here + | +LL | fn bar(f: Box T>) { } + | +++ error[E0401]: can't use generic parameters from outer item --> $DIR/type-arg-out-of-scope.rs:2:35 @@ -14,9 +17,12 @@ error[E0401]: can't use generic parameters from outer item LL | fn foo(x: T) { | - type parameter from outer item LL | fn bar(f: Box T>) { } - | - ^ use of generic parameter from outer item - | | - | help: try introducing a local generic parameter here: `` + | ^ use of generic parameter from outer item + | +help: try introducing a local generic parameter here + | +LL | fn bar(f: Box T>) { } + | +++ error: aborting due to 2 previous errors From f6938709c8aef58ade5577ae8ff77fbcb99d0845 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 1 Nov 2025 18:29:46 +0000 Subject: [PATCH 2/7] Point at inner item when using outer item type param ``` error[E0401]: can't use generic parameters from outer item --> $DIR/E0401.rs:4:39 | LL | fn foo(x: T) { | - type parameter from outer item LL | fn bfnr, W: Fn()>(y: T) { | ---- ^ use of generic parameter from outer item | | | generic parameter used in this inner function | help: try introducing a local generic parameter here | LL | fn bfnr, W: Fn()>(y: T) { | ++ ``` --- compiler/rustc_resolve/messages.ftl | 5 ++++ compiler/rustc_resolve/src/diagnostics.rs | 7 ++++++ compiler/rustc_resolve/src/errors.rs | 10 ++++++++ compiler/rustc_resolve/src/ident.rs | 25 ++++++++++++++++++- compiler/rustc_resolve/src/late.rs | 15 +++++++---- compiler/rustc_resolve/src/lib.rs | 2 +- tests/ui/delegation/target-expr.stderr | 4 ++- tests/ui/error-codes/E0401.stderr | 16 ++++++++---- ...n-with-outer-generic-parameter-5997.stderr | 4 ++- ...eneric-params-nested-fn-scope-error.stderr | 8 ++++-- tests/ui/generics/issue-98432.stderr | 4 ++- tests/ui/resolve/bad-type-env-capture.stderr | 4 ++- ...om-outer-item-in-const-item.default.stderr | 12 ++++++--- ...m-in-const-item.generic_const_items.stderr | 12 ++++++--- tests/ui/resolve/issue-12796.stderr | 9 ++++--- tests/ui/resolve/issue-3021-c.stderr | 8 ++++-- tests/ui/resolve/issue-3214.stderr | 1 + ...65025-extern-static-parent-generics.stderr | 13 ++++++---- ...e-65035-static-with-parent-generics.stderr | 17 ++++++++----- ...resolve-type-param-in-item-in-trait.stderr | 16 +++++++++--- tests/ui/resolve/use-self-in-inner-fn.rs | 1 + tests/ui/resolve/use-self-in-inner-fn.stderr | 9 ++++--- .../static-generic-param-soundness.stderr | 4 ++- tests/ui/type/type-arg-out-of-scope.stderr | 8 ++++-- 24 files changed, 162 insertions(+), 52 deletions(-) diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl index 5bf90d2637df5..d462ff589f0da 100644 --- a/compiler/rustc_resolve/messages.ftl +++ b/compiler/rustc_resolve/messages.ftl @@ -180,6 +180,11 @@ resolve_generic_params_from_outer_item_const = a `const` is a separate item from resolve_generic_params_from_outer_item_const_param = const parameter from outer item +resolve_generic_params_from_outer_item_inner_item = {$is_self -> + [true] `Self` + *[false] generic parameter + } used in this inner {$descr} + resolve_generic_params_from_outer_item_self_ty_alias = `Self` type implicitly declared here, by this `impl` resolve_generic_params_from_outer_item_self_ty_param = can't use `Self` here diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 236ab1f09d35f..f302da356e1e1 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -557,6 +557,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { outer_res, has_generic_params, def_kind, + item, ) => { use errs::GenericParamsFromOuterItemLabel as Label; let static_or_const = match def_kind { @@ -575,6 +576,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { sugg: None, static_or_const, is_self, + item: item.map(|(span, descr)| errs::GenericParamsFromOuterItemInnerItem { + span, + descr, + }), }; let sm = self.tcx.sess.source_map(); @@ -2506,6 +2511,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { None, &ribs[ns_to_try], ignore_binding, + None, ) { // we found a locally-imported or available item/module Some(LexicalScopeBinding::Item(binding)) => Some(binding), @@ -2556,6 +2562,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { None, &ribs[ValueNS], ignore_binding, + None, ) } else { None diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs index 3465c7fb16473..5c5938a3260ed 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -24,6 +24,16 @@ pub(crate) struct GenericParamsFromOuterItem { #[subdiagnostic] pub(crate) static_or_const: Option, pub(crate) is_self: bool, + #[subdiagnostic] + pub(crate) item: Option, +} + +#[derive(Subdiagnostic)] +#[label(resolve_generic_params_from_outer_item_inner_item)] +pub(crate) struct GenericParamsFromOuterItemInnerItem { + #[primary_span] + pub(crate) span: Span, + pub(crate) descr: String, } #[derive(Subdiagnostic)] diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 2a195c8068dac..4856b1e7cf970 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -12,7 +12,9 @@ use tracing::{debug, instrument}; use crate::errors::{ParamKindInEnumDiscriminant, ParamKindInNonTrivialAnonConst}; use crate::imports::{Import, NameResolution}; -use crate::late::{ConstantHasGenerics, NoConstantGenericsReason, PathSource, Rib, RibKind}; +use crate::late::{ + ConstantHasGenerics, DiagMetadata, NoConstantGenericsReason, PathSource, Rib, RibKind, +}; use crate::macros::{MacroRulesScope, sub_namespace_match}; use crate::{ AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, BindingKey, CmResolver, Determinacy, @@ -295,6 +297,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { finalize: Option, ribs: &[Rib<'ra>], ignore_binding: Option>, + diag_metadata: Option<&DiagMetadata<'_>>, ) -> Option> { assert!(ns == TypeNS || ns == ValueNS); let orig_ident = ident; @@ -326,6 +329,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { finalize.map(|finalize| finalize.path_span), *original_rib_ident_def, ribs, + diag_metadata, ))); } else if let RibKind::Block(Some(module)) = rib.kind && let Ok(binding) = self.cm().resolve_ident_in_module_unadjusted( @@ -1193,6 +1197,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { finalize: Option, original_rib_ident_def: Ident, all_ribs: &[Rib<'ra>], + diag_metadata: Option<&DiagMetadata<'_>>, ) -> Res { debug!("validate_res_from_ribs({:?})", res); let ribs = &all_ribs[rib_index + 1..]; @@ -1391,12 +1396,25 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { }; if let Some(span) = finalize { + let item = if let Some(diag_metadata) = diag_metadata + && let Some(current_item) = diag_metadata.current_item + { + let span = current_item + .kind + .ident() + .map(|i| i.span) + .unwrap_or(current_item.span); + Some((span, current_item.kind.descr().to_string())) + } else { + None + }; self.report_error( span, ResolutionError::GenericParamsFromOuterItem( res, has_generic_params, def_kind, + item, ), ); } @@ -1472,6 +1490,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { res, has_generic_params, def_kind, + None, ), ); } @@ -1501,6 +1520,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { None, None, ignore_import, + None, ) } #[instrument(level = "debug", skip(self))] @@ -1522,6 +1542,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { None, ignore_binding, ignore_import, + None, ) } @@ -1535,6 +1556,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ribs: Option<&PerNS>>>, ignore_binding: Option>, ignore_import: Option>, + diag_metadata: Option<&DiagMetadata<'_>>, ) -> PathResult<'ra> { let mut module = None; let mut module_had_parse_errors = false; @@ -1675,6 +1697,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { finalize, &ribs[ns], ignore_binding, + diag_metadata, ) { // we found a locally-imported or available item/module Some(LexicalScopeBinding::Item(binding)) => Ok(binding), diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index e3051dc38eca2..198fef0cd630c 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -667,7 +667,7 @@ pub(crate) struct UnnecessaryQualification<'ra> { } #[derive(Default, Debug)] -struct DiagMetadata<'ast> { +pub(crate) struct DiagMetadata<'ast> { /// The current trait's associated items' ident, used for diagnostic suggestions. current_trait_assoc_items: Option<&'ast [Box]>, @@ -678,7 +678,7 @@ struct DiagMetadata<'ast> { current_self_item: Option, /// The current trait (used to suggest). - current_item: Option<&'ast Item>, + pub(crate) current_item: Option<&'ast Item>, /// When processing generic arguments and encountering an unresolved ident not found, /// suggest introducing a type or const param depending on the context. @@ -885,6 +885,7 @@ impl<'ast, 'ra, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'ra, 'tc TypeNS, Some(Finalize::new(ty.id, ty.span)), None, + None, ) .map_or(Res::Err, |d| d.res()); self.r.record_partial_res(ty.id, PartialRes::new(res)); @@ -1457,6 +1458,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { None, &self.ribs[ns], None, + None, ) } @@ -1466,6 +1468,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { ns: Namespace, finalize: Option, ignore_binding: Option>, + diag_metadata: Option<&crate::late::DiagMetadata<'_>>, ) -> Option> { self.r.resolve_ident_in_lexical_scope( ident, @@ -1474,6 +1477,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { finalize, &self.ribs[ns], ignore_binding, + diag_metadata, ) } @@ -1493,6 +1497,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { Some(&self.ribs), None, None, + Some(&self.diag_metadata), ) } @@ -2551,8 +2556,8 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { report_error(self, ns); } Some(LexicalScopeBinding::Item(binding)) => { - if let Some(LexicalScopeBinding::Res(..)) = - self.resolve_ident_in_lexical_scope(ident, ns, None, Some(binding)) + if let Some(LexicalScopeBinding::Res(..)) = self + .resolve_ident_in_lexical_scope(ident, ns, None, Some(binding), None) { report_error(self, ns); } @@ -5105,7 +5110,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { // use the type namespace let ns = if i + 1 == path.len() { ns } else { TypeNS }; let res = self.r.partial_res_map.get(&seg.id?)?.full_res()?; - let binding = self.resolve_ident_in_lexical_scope(seg.ident, ns, None, None)?; + let binding = self.resolve_ident_in_lexical_scope(seg.ident, ns, None, None, None)?; (res == binding.res()).then_some((seg, binding)) }); diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index f6a4f59cb339a..c7f5ec76c0751 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -241,7 +241,7 @@ struct BindingError { #[derive(Debug)] enum ResolutionError<'ra> { /// Error E0401: can't use type or const parameters from outer item. - GenericParamsFromOuterItem(Res, HasGenericParams, DefKind), + GenericParamsFromOuterItem(Res, HasGenericParams, DefKind, Option<(Span, String)>), /// Error E0403: the name is already used for a type or const parameter in this generic /// parameter list. NameAlreadyUsedInParameterList(Ident, Span), diff --git a/tests/ui/delegation/target-expr.stderr b/tests/ui/delegation/target-expr.stderr index 8bb25ad9e96e2..f2e6c331193f0 100644 --- a/tests/ui/delegation/target-expr.stderr +++ b/tests/ui/delegation/target-expr.stderr @@ -3,7 +3,9 @@ error[E0401]: can't use generic parameters from outer item | LL | fn bar(_: T) { | - type parameter from outer item -... +LL | reuse Trait::static_method { + | ------------- generic parameter used in this inner delegated function +LL | LL | let _ = T::Default(); | ^^^^^^^^^^ use of generic parameter from outer item | diff --git a/tests/ui/error-codes/E0401.stderr b/tests/ui/error-codes/E0401.stderr index fedb064c6bea6..8daaf09df1592 100644 --- a/tests/ui/error-codes/E0401.stderr +++ b/tests/ui/error-codes/E0401.stderr @@ -4,7 +4,9 @@ error[E0401]: can't use generic parameters from outer item LL | fn foo(x: T) { | - type parameter from outer item LL | fn bfnr, W: Fn()>(y: T) { - | ^ use of generic parameter from outer item + | ---- ^ use of generic parameter from outer item + | | + | generic parameter used in this inner function | help: try introducing a local generic parameter here | @@ -17,6 +19,9 @@ error[E0401]: can't use generic parameters from outer item LL | fn foo(x: T) { | - type parameter from outer item ... +LL | fn baz Iterator for A { | ---- `Self` type implicitly declared here, by this `impl` ... LL | fn helper(sel: &Self) -> u8 { - | ^^^^ - | | - | use of `Self` from outer item - | refer to the type directly here instead + | ------ ^^^^ + | | | + | | use of `Self` from outer item + | | refer to the type directly here instead + | `Self` used in this inner function error: aborting due to 3 previous errors diff --git a/tests/ui/generics/enum-definition-with-outer-generic-parameter-5997.stderr b/tests/ui/generics/enum-definition-with-outer-generic-parameter-5997.stderr index cded8ce319616..fb2d2f247b65b 100644 --- a/tests/ui/generics/enum-definition-with-outer-generic-parameter-5997.stderr +++ b/tests/ui/generics/enum-definition-with-outer-generic-parameter-5997.stderr @@ -4,7 +4,9 @@ error[E0401]: can't use generic parameters from outer item LL | fn f() -> bool { | - type parameter from outer item LL | enum E { V(Z) } - | ^ use of generic parameter from outer item + | - ^ use of generic parameter from outer item + | | + | generic parameter used in this inner enum | help: try introducing a local generic parameter here | diff --git a/tests/ui/generics/generic-params-nested-fn-scope-error.stderr b/tests/ui/generics/generic-params-nested-fn-scope-error.stderr index 8c3b65d1edea9..f809740ed381f 100644 --- a/tests/ui/generics/generic-params-nested-fn-scope-error.stderr +++ b/tests/ui/generics/generic-params-nested-fn-scope-error.stderr @@ -4,7 +4,9 @@ error[E0401]: can't use generic parameters from outer item LL | fn foo(v: Vec) -> U { | - type parameter from outer item LL | fn bar(w: [U]) -> U { - | ^ use of generic parameter from outer item + | --- ^ use of generic parameter from outer item + | | + | generic parameter used in this inner function | help: try introducing a local generic parameter here | @@ -17,7 +19,9 @@ error[E0401]: can't use generic parameters from outer item LL | fn foo(v: Vec) -> U { | - type parameter from outer item LL | fn bar(w: [U]) -> U { - | ^ use of generic parameter from outer item + | --- ^ use of generic parameter from outer item + | | + | generic parameter used in this inner function | help: try introducing a local generic parameter here | diff --git a/tests/ui/generics/issue-98432.stderr b/tests/ui/generics/issue-98432.stderr index f20f779d884c0..a1efee78cb7df 100644 --- a/tests/ui/generics/issue-98432.stderr +++ b/tests/ui/generics/issue-98432.stderr @@ -5,7 +5,9 @@ LL | impl Struct { | - type parameter from outer item LL | const CONST: fn() = || { LL | struct _Obligation where T:; - | ^ use of generic parameter from outer item + | ----------- ^ use of generic parameter from outer item + | | + | generic parameter used in this inner struct | help: try introducing a local generic parameter here | diff --git a/tests/ui/resolve/bad-type-env-capture.stderr b/tests/ui/resolve/bad-type-env-capture.stderr index 272672beb4fbb..c565997ca2a26 100644 --- a/tests/ui/resolve/bad-type-env-capture.stderr +++ b/tests/ui/resolve/bad-type-env-capture.stderr @@ -4,7 +4,9 @@ error[E0401]: can't use generic parameters from outer item LL | fn foo() { | - type parameter from outer item LL | fn bar(b: T) { } - | ^ use of generic parameter from outer item + | --- ^ use of generic parameter from outer item + | | + | generic parameter used in this inner function | help: try introducing a local generic parameter here | diff --git a/tests/ui/resolve/generic-params-from-outer-item-in-const-item.default.stderr b/tests/ui/resolve/generic-params-from-outer-item-in-const-item.default.stderr index fbb9ede8aa175..bc67e9dce4e3b 100644 --- a/tests/ui/resolve/generic-params-from-outer-item-in-const-item.default.stderr +++ b/tests/ui/resolve/generic-params-from-outer-item-in-const-item.default.stderr @@ -4,7 +4,9 @@ error[E0401]: can't use generic parameters from outer item LL | fn outer() { // outer function | - type parameter from outer item LL | const K: u32 = T::C; - | ^^^^ use of generic parameter from outer item + | - ^^^^ use of generic parameter from outer item + | | + | generic parameter used in this inner constant item | = note: a `const` is a separate item from the item that contains it @@ -15,7 +17,9 @@ LL | impl Tr for T { // outer impl block | - type parameter from outer item LL | const C: u32 = { LL | const I: u32 = T::C; - | ^^^^ use of generic parameter from outer item + | - ^^^^ use of generic parameter from outer item + | | + | generic parameter used in this inner constant item | = note: a `const` is a separate item from the item that contains it @@ -25,7 +29,9 @@ error[E0401]: can't use generic parameters from outer item LL | struct S(U32<{ // outer struct | - type parameter from outer item LL | const _: u32 = T::C; - | ^^^^ use of generic parameter from outer item + | - ^^^^ use of generic parameter from outer item + | | + | generic parameter used in this inner constant item | = note: a `const` is a separate item from the item that contains it diff --git a/tests/ui/resolve/generic-params-from-outer-item-in-const-item.generic_const_items.stderr b/tests/ui/resolve/generic-params-from-outer-item-in-const-item.generic_const_items.stderr index 3852b84fee2e0..3959d117c7c9a 100644 --- a/tests/ui/resolve/generic-params-from-outer-item-in-const-item.generic_const_items.stderr +++ b/tests/ui/resolve/generic-params-from-outer-item-in-const-item.generic_const_items.stderr @@ -4,7 +4,9 @@ error[E0401]: can't use generic parameters from outer item LL | fn outer() { // outer function | - type parameter from outer item LL | const K: u32 = T::C; - | ^^^^ use of generic parameter from outer item + | - ^^^^ use of generic parameter from outer item + | | + | generic parameter used in this inner constant item | = note: a `const` is a separate item from the item that contains it help: try introducing a local generic parameter here @@ -19,7 +21,9 @@ LL | impl Tr for T { // outer impl block | - type parameter from outer item LL | const C: u32 = { LL | const I: u32 = T::C; - | ^^^^ use of generic parameter from outer item + | - ^^^^ use of generic parameter from outer item + | | + | generic parameter used in this inner constant item | = note: a `const` is a separate item from the item that contains it help: try introducing a local generic parameter here @@ -33,7 +37,9 @@ error[E0401]: can't use generic parameters from outer item LL | struct S(U32<{ // outer struct | - type parameter from outer item LL | const _: u32 = T::C; - | ^^^^ use of generic parameter from outer item + | - ^^^^ use of generic parameter from outer item + | | + | generic parameter used in this inner constant item | = note: a `const` is a separate item from the item that contains it help: try introducing a local generic parameter here diff --git a/tests/ui/resolve/issue-12796.stderr b/tests/ui/resolve/issue-12796.stderr index 2305971303a71..b5828c6f5fc86 100644 --- a/tests/ui/resolve/issue-12796.stderr +++ b/tests/ui/resolve/issue-12796.stderr @@ -2,10 +2,11 @@ error[E0401]: can't use `Self` from outer item --> $DIR/issue-12796.rs:3:22 | LL | fn inner(_: &Self) { - | ^^^^ - | | - | use of `Self` from outer item - | can't use `Self` here + | ----- ^^^^ + | | | + | | use of `Self` from outer item + | | can't use `Self` here + | `Self` used in this inner function error: aborting due to 1 previous error diff --git a/tests/ui/resolve/issue-3021-c.stderr b/tests/ui/resolve/issue-3021-c.stderr index dcbaf2afd10c6..8c554fd1b97dc 100644 --- a/tests/ui/resolve/issue-3021-c.stderr +++ b/tests/ui/resolve/issue-3021-c.stderr @@ -3,7 +3,9 @@ error[E0401]: can't use generic parameters from outer item | LL | fn siphash() { | - type parameter from outer item -... +LL | +LL | trait U { + | - generic parameter used in this inner trait LL | fn g(&self, x: T) -> T; | ^ use of generic parameter from outer item | @@ -17,7 +19,9 @@ error[E0401]: can't use generic parameters from outer item | LL | fn siphash() { | - type parameter from outer item -... +LL | +LL | trait U { + | - generic parameter used in this inner trait LL | fn g(&self, x: T) -> T; | ^ use of generic parameter from outer item | diff --git a/tests/ui/resolve/issue-3214.stderr b/tests/ui/resolve/issue-3214.stderr index 5e5872f2a5fbd..ab12676bdd805 100644 --- a/tests/ui/resolve/issue-3214.stderr +++ b/tests/ui/resolve/issue-3214.stderr @@ -4,6 +4,7 @@ error[E0401]: can't use generic parameters from outer item LL | fn foo() { | - type parameter from outer item LL | struct Foo { + | --- generic parameter used in this inner struct LL | x: T, | ^ use of generic parameter from outer item | diff --git a/tests/ui/resolve/issue-65025-extern-static-parent-generics.stderr b/tests/ui/resolve/issue-65025-extern-static-parent-generics.stderr index ca32147d19765..2d21ed0155a70 100644 --- a/tests/ui/resolve/issue-65025-extern-static-parent-generics.stderr +++ b/tests/ui/resolve/issue-65025-extern-static-parent-generics.stderr @@ -1,11 +1,14 @@ error[E0401]: can't use generic parameters from outer item --> $DIR/issue-65025-extern-static-parent-generics.rs:3:28 | -LL | unsafe fn foo() { - | - type parameter from outer item -LL | extern "C" { -LL | static baz: *const A; - | ^ use of generic parameter from outer item +LL | unsafe fn foo() { + | - type parameter from outer item +LL | / extern "C" { +LL | | static baz: *const A; + | | ^ use of generic parameter from outer item +LL | | +LL | | } + | |_____- generic parameter used in this inner extern block | = note: a `static` is a separate item from the item that contains it diff --git a/tests/ui/resolve/issue-65035-static-with-parent-generics.stderr b/tests/ui/resolve/issue-65035-static-with-parent-generics.stderr index 98ffb4567f164..869e1729cb853 100644 --- a/tests/ui/resolve/issue-65035-static-with-parent-generics.stderr +++ b/tests/ui/resolve/issue-65035-static-with-parent-generics.stderr @@ -1,11 +1,14 @@ error[E0401]: can't use generic parameters from outer item --> $DIR/issue-65035-static-with-parent-generics.rs:3:26 | -LL | fn f() { - | - type parameter from outer item -LL | extern "C" { -LL | static a: *const T; - | ^ use of generic parameter from outer item +LL | fn f() { + | - type parameter from outer item +LL | / extern "C" { +LL | | static a: *const T; + | | ^ use of generic parameter from outer item +LL | | +LL | | } + | |_____- generic parameter used in this inner extern block | = note: a `static` is a separate item from the item that contains it @@ -15,7 +18,9 @@ error[E0401]: can't use generic parameters from outer item LL | fn g() { | - type parameter from outer item LL | static a: *const T = Default::default(); - | ^ use of generic parameter from outer item + | - ^ use of generic parameter from outer item + | | + | generic parameter used in this inner static item | = note: a `static` is a separate item from the item that contains it diff --git a/tests/ui/resolve/resolve-type-param-in-item-in-trait.stderr b/tests/ui/resolve/resolve-type-param-in-item-in-trait.stderr index 086418df7a253..00aa645688e7f 100644 --- a/tests/ui/resolve/resolve-type-param-in-item-in-trait.stderr +++ b/tests/ui/resolve/resolve-type-param-in-item-in-trait.stderr @@ -3,7 +3,9 @@ error[E0401]: can't use generic parameters from outer item | LL | trait TraitA { | - type parameter from outer item -... +LL | fn outer(&self) { +LL | enum Foo { + | --- generic parameter used in this inner enum LL | Variance(A) | ^ use of generic parameter from outer item | @@ -19,7 +21,9 @@ LL | trait TraitB { | - type parameter from outer item LL | fn outer(&self) { LL | struct Foo(A); - | ^ use of generic parameter from outer item + | --- ^ use of generic parameter from outer item + | | + | generic parameter used in this inner struct | help: try introducing a local generic parameter here | @@ -33,7 +37,9 @@ LL | trait TraitC { | - type parameter from outer item LL | fn outer(&self) { LL | struct Foo { a: A } - | ^ use of generic parameter from outer item + | --- ^ use of generic parameter from outer item + | | + | generic parameter used in this inner struct | help: try introducing a local generic parameter here | @@ -47,7 +53,9 @@ LL | trait TraitD { | - type parameter from outer item LL | fn outer(&self) { LL | fn foo(a: A) { } - | ^ use of generic parameter from outer item + | --- ^ use of generic parameter from outer item + | | + | generic parameter used in this inner function | help: try introducing a local generic parameter here | diff --git a/tests/ui/resolve/use-self-in-inner-fn.rs b/tests/ui/resolve/use-self-in-inner-fn.rs index 62f9dc5664ffe..ed64ee885271c 100644 --- a/tests/ui/resolve/use-self-in-inner-fn.rs +++ b/tests/ui/resolve/use-self-in-inner-fn.rs @@ -6,6 +6,7 @@ impl A { fn peach(this: &Self) { //~^ ERROR can't use `Self` from outer item //~| NOTE use of `Self` from outer item + //~| NOTE `Self` used in this inner function //~| NOTE refer to the type directly here instead } } diff --git a/tests/ui/resolve/use-self-in-inner-fn.stderr b/tests/ui/resolve/use-self-in-inner-fn.stderr index 9c388df8bc20c..645875f6e726d 100644 --- a/tests/ui/resolve/use-self-in-inner-fn.stderr +++ b/tests/ui/resolve/use-self-in-inner-fn.stderr @@ -5,10 +5,11 @@ LL | impl A { | ---- `Self` type implicitly declared here, by this `impl` ... LL | fn peach(this: &Self) { - | ^^^^ - | | - | use of `Self` from outer item - | refer to the type directly here instead + | ----- ^^^^ + | | | + | | use of `Self` from outer item + | | refer to the type directly here instead + | `Self` used in this inner function error: aborting due to 1 previous error diff --git a/tests/ui/statics/static-generic-param-soundness.stderr b/tests/ui/statics/static-generic-param-soundness.stderr index 47554c7fcb0f0..72f65e2bac7cb 100644 --- a/tests/ui/statics/static-generic-param-soundness.stderr +++ b/tests/ui/statics/static-generic-param-soundness.stderr @@ -4,7 +4,9 @@ error[E0401]: can't use generic parameters from outer item LL | fn foo() { | - type parameter from outer item LL | static a: Bar = Bar::What; - | ^ use of generic parameter from outer item + | - ^ use of generic parameter from outer item + | | + | generic parameter used in this inner static item | = note: a `static` is a separate item from the item that contains it diff --git a/tests/ui/type/type-arg-out-of-scope.stderr b/tests/ui/type/type-arg-out-of-scope.stderr index f4fbcdac53b66..3d8850ebccea5 100644 --- a/tests/ui/type/type-arg-out-of-scope.stderr +++ b/tests/ui/type/type-arg-out-of-scope.stderr @@ -4,7 +4,9 @@ error[E0401]: can't use generic parameters from outer item LL | fn foo(x: T) { | - type parameter from outer item LL | fn bar(f: Box T>) { } - | ^ use of generic parameter from outer item + | --- ^ use of generic parameter from outer item + | | + | generic parameter used in this inner function | help: try introducing a local generic parameter here | @@ -17,7 +19,9 @@ error[E0401]: can't use generic parameters from outer item LL | fn foo(x: T) { | - type parameter from outer item LL | fn bar(f: Box T>) { } - | ^ use of generic parameter from outer item + | --- ^ use of generic parameter from outer item + | | + | generic parameter used in this inner function | help: try introducing a local generic parameter here | From 8fdd34713dc02907cd6c601cfc62315ff8d59406 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 1 Nov 2025 19:09:56 +0000 Subject: [PATCH 3/7] Point at inner item on E0401 generated by hir_typeck ``` error[E0401]: can't reference `Self` constructor from outer item --> $DIR/do-not-ice-on-note_and_explain.rs:6:13 | LL | impl A { | ------------ the inner item doesn't inherit generics from this impl, so `Self` is invalid to reference LL | fn d() { LL | fn d() { | - `Self` used in this inner item LL | Self(1) | ^^^^ help: replace `Self` with the actual type: `A` ``` --- compiler/rustc_hir_typeck/messages.ftl | 2 ++ compiler/rustc_hir_typeck/src/errors.rs | 11 +++++++++++ compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs | 11 +++++++++++ .../malformed/do-not-ice-on-note_and_explain.stderr | 4 +++- tests/ui/self/self-ctor-nongeneric.stderr | 6 +++++- tests/ui/self/self-ctor.stderr | 6 +++++- .../ice-index-out-of-bounds-issue-117446.stderr | 3 +++ 7 files changed, 40 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_hir_typeck/messages.ftl b/compiler/rustc_hir_typeck/messages.ftl index 1ed0756fdd6a7..bb705dce6a4ba 100644 --- a/compiler/rustc_hir_typeck/messages.ftl +++ b/compiler/rustc_hir_typeck/messages.ftl @@ -262,6 +262,8 @@ hir_typeck_self_ctor_from_outer_item = can't reference `Self` constructor from o .label = the inner item doesn't inherit generics from this impl, so `Self` is invalid to reference .suggestion = replace `Self` with the actual type +hir_typeck_self_ctor_from_outer_item_inner_item = `Self` used in this inner item + hir_typeck_slicing_suggestion = consider slicing here hir_typeck_struct_expr_non_exhaustive = diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index d15d092b7d3da..2ed3a542bae8e 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -978,6 +978,15 @@ pub(crate) struct SelfCtorFromOuterItem { pub impl_span: Span, #[subdiagnostic] pub sugg: Option, + #[subdiagnostic] + pub item: Option, +} + +#[derive(Subdiagnostic)] +#[label(hir_typeck_self_ctor_from_outer_item_inner_item)] +pub(crate) struct InnerItem { + #[primary_span] + pub span: Span, } #[derive(LintDiagnostic)] @@ -987,6 +996,8 @@ pub(crate) struct SelfCtorFromOuterItemLint { pub impl_span: Span, #[subdiagnostic] pub sugg: Option, + #[subdiagnostic] + pub item: Option, } #[derive(Subdiagnostic)] diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index f4e65b42cd423..38586c844445b 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -1094,11 +1094,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span: path_span, name: self.tcx.item_name(def.did()).to_ident_string(), }); + let item = match self + .tcx + .hir_node_by_def_id(self.tcx.hir_get_parent_item(hir_id).def_id) + { + hir::Node::Item(item) => Some(errors::InnerItem { + span: item.kind.ident().map(|i| i.span).unwrap_or(item.span), + }), + _ => None, + }; if ty.raw.has_param() { let guar = self.dcx().emit_err(errors::SelfCtorFromOuterItem { span: path_span, impl_span: tcx.def_span(impl_def_id), sugg, + item, }); return (Ty::new_error(self.tcx, guar), res); } else { @@ -1109,6 +1119,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { errors::SelfCtorFromOuterItemLint { impl_span: tcx.def_span(impl_def_id), sugg, + item, }, ); } diff --git a/tests/ui/malformed/do-not-ice-on-note_and_explain.stderr b/tests/ui/malformed/do-not-ice-on-note_and_explain.stderr index 11a8c01e49094..63de7099797ca 100644 --- a/tests/ui/malformed/do-not-ice-on-note_and_explain.stderr +++ b/tests/ui/malformed/do-not-ice-on-note_and_explain.stderr @@ -3,7 +3,9 @@ error[E0401]: can't reference `Self` constructor from outer item | LL | impl A { | ------------ the inner item doesn't inherit generics from this impl, so `Self` is invalid to reference -... +LL | fn d() { +LL | fn d() { + | - `Self` used in this inner item LL | Self(1) | ^^^^ help: replace `Self` with the actual type: `A` diff --git a/tests/ui/self/self-ctor-nongeneric.stderr b/tests/ui/self/self-ctor-nongeneric.stderr index b53ecbe55b594..c3ae7df2ad25e 100644 --- a/tests/ui/self/self-ctor-nongeneric.stderr +++ b/tests/ui/self/self-ctor-nongeneric.stderr @@ -5,7 +5,9 @@ LL | impl S0 { | ------- the inner item doesn't inherit generics from this impl, so `Self` is invalid to reference LL | fn foo() { LL | const C: S0 = Self(0); - | ^^^^ help: replace `Self` with the actual type: `S0` + | - ^^^^ help: replace `Self` with the actual type: `S0` + | | + | `Self` used in this inner item | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #124186 @@ -17,6 +19,8 @@ warning: can't reference `Self` constructor from outer item LL | impl S0 { | ------- the inner item doesn't inherit generics from this impl, so `Self` is invalid to reference ... +LL | fn bar() -> S0 { + | --- `Self` used in this inner item LL | Self(0) | ^^^^ help: replace `Self` with the actual type: `S0` | diff --git a/tests/ui/self/self-ctor.stderr b/tests/ui/self/self-ctor.stderr index 0cb22baaa1a05..b8dfd324c3f36 100644 --- a/tests/ui/self/self-ctor.stderr +++ b/tests/ui/self/self-ctor.stderr @@ -5,7 +5,9 @@ LL | impl S0 { | ------------- the inner item doesn't inherit generics from this impl, so `Self` is invalid to reference LL | fn foo() { LL | const C: S0 = Self(0); - | ^^^^ help: replace `Self` with the actual type: `S0` + | - ^^^^ help: replace `Self` with the actual type: `S0` + | | + | `Self` used in this inner item error[E0401]: can't reference `Self` constructor from outer item --> $DIR/self-ctor.rs:8:13 @@ -13,6 +15,8 @@ error[E0401]: can't reference `Self` constructor from outer item LL | impl S0 { | ------------- the inner item doesn't inherit generics from this impl, so `Self` is invalid to reference ... +LL | fn bar() -> S0 { + | --- `Self` used in this inner item LL | Self(0) | ^^^^ help: replace `Self` with the actual type: `S0` diff --git a/tests/ui/traits/ice-index-out-of-bounds-issue-117446.stderr b/tests/ui/traits/ice-index-out-of-bounds-issue-117446.stderr index ad33a70ed3bb6..2e75003c49b8a 100644 --- a/tests/ui/traits/ice-index-out-of-bounds-issue-117446.stderr +++ b/tests/ui/traits/ice-index-out-of-bounds-issue-117446.stderr @@ -24,6 +24,9 @@ error[E0401]: can't reference `Self` constructor from outer item LL | impl<'a, T> Foo<'a> for Repeated { | ----------------------------------- the inner item doesn't inherit generics from this impl, so `Self` is invalid to reference ... +LL | fn inner(value: Option<()>) -> Repeated { + | ----- `Self` used in this inner item +LL | match value { LL | _ => Self(unimplemented!()), | ^^^^ help: replace `Self` with the actual type: `Repeated` From 44ece2e9cef484368cfef98f0e287e5a6d1011dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 1 Nov 2025 19:21:27 +0000 Subject: [PATCH 4/7] Point at inner item when using outer const param ``` error[E0401]: can't use generic parameters from outer item --> $DIR/const-param-from-outer-fn.rs:3:9 | LL | fn foo() { | - const parameter from outer item LL | fn bar() -> u32 { | --- generic parameter used in this inner function LL | X | ^ use of generic parameter from outer item | help: try introducing a local generic parameter here | LL | fn bar() -> u32 { | +++ ``` --- compiler/rustc_resolve/src/ident.rs | 14 ++++++++++++- .../early/const-param-from-outer-fn.stderr | 1 + ...e-65035-static-with-parent-generics.stderr | 21 ++++++++++++------- 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 4856b1e7cf970..2abf129e94565 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -1484,13 +1484,25 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // This was an attempt to use a const parameter outside its scope. if let Some(span) = finalize { + let item = if let Some(diag_metadata) = diag_metadata + && let Some(current_item) = diag_metadata.current_item + { + let span = current_item + .kind + .ident() + .map(|i| i.span) + .unwrap_or(current_item.span); + Some((span, current_item.kind.descr().to_string())) + } else { + None + }; self.report_error( span, ResolutionError::GenericParamsFromOuterItem( res, has_generic_params, def_kind, - None, + item, ), ); } diff --git a/tests/ui/const-generics/early/const-param-from-outer-fn.stderr b/tests/ui/const-generics/early/const-param-from-outer-fn.stderr index 0f7c7fbc6be01..3c25dff41aa22 100644 --- a/tests/ui/const-generics/early/const-param-from-outer-fn.stderr +++ b/tests/ui/const-generics/early/const-param-from-outer-fn.stderr @@ -4,6 +4,7 @@ error[E0401]: can't use generic parameters from outer item LL | fn foo() { | - const parameter from outer item LL | fn bar() -> u32 { + | --- generic parameter used in this inner function LL | X | ^ use of generic parameter from outer item | diff --git a/tests/ui/resolve/issue-65035-static-with-parent-generics.stderr b/tests/ui/resolve/issue-65035-static-with-parent-generics.stderr index 869e1729cb853..b22bfb719bd50 100644 --- a/tests/ui/resolve/issue-65035-static-with-parent-generics.stderr +++ b/tests/ui/resolve/issue-65035-static-with-parent-generics.stderr @@ -27,11 +27,14 @@ LL | static a: *const T = Default::default(); error[E0401]: can't use generic parameters from outer item --> $DIR/issue-65035-static-with-parent-generics.rs:15:24 | -LL | fn h() { - | - const parameter from outer item -LL | extern "C" { -LL | static a: [u8; N]; - | ^ use of generic parameter from outer item +LL | fn h() { + | - const parameter from outer item +LL | / extern "C" { +LL | | static a: [u8; N]; + | | ^ use of generic parameter from outer item +LL | | +LL | | } + | |_____- generic parameter used in this inner extern block | = note: a `static` is a separate item from the item that contains it @@ -41,7 +44,9 @@ error[E0401]: can't use generic parameters from outer item LL | fn i() { | - const parameter from outer item LL | static a: [u8; N] = [0; N]; - | ^ use of generic parameter from outer item + | - ^ use of generic parameter from outer item + | | + | generic parameter used in this inner static item | = note: a `static` is a separate item from the item that contains it @@ -51,7 +56,9 @@ error[E0401]: can't use generic parameters from outer item LL | fn i() { | - const parameter from outer item LL | static a: [u8; N] = [0; N]; - | ^ use of generic parameter from outer item + | - ^ use of generic parameter from outer item + | | + | generic parameter used in this inner static item | = note: a `static` is a separate item from the item that contains it From 86d755618be25e3b03d16f0c13bdc51d4c2de2a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 1 Nov 2025 19:55:35 +0000 Subject: [PATCH 5/7] Pass `DiagMetadata` through in more cases --- compiler/rustc_resolve/src/diagnostics.rs | 7 ++++--- compiler/rustc_resolve/src/ident.rs | 1 + compiler/rustc_resolve/src/late.rs | 12 +++++------- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index f302da356e1e1..4a5d304f49bf9 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -40,7 +40,7 @@ use crate::errors::{ MaybeMissingMacroRulesName, }; use crate::imports::{Import, ImportKind}; -use crate::late::{PatternSource, Rib}; +use crate::late::{DiagMetadata, PatternSource, Rib}; use crate::{ AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, BindingError, BindingKey, Finalize, ForwardGenericParamBanReason, HasGenericParams, LexicalScopeBinding, MacroRulesScope, Module, @@ -2406,6 +2406,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { module: Option>, failed_segment_idx: usize, ident: Ident, + diag_metadata: Option<&DiagMetadata<'_>>, ) -> (String, Option) { let is_last = failed_segment_idx == path.len() - 1; let ns = if is_last { opt_ns.unwrap_or(TypeNS) } else { TypeNS }; @@ -2511,7 +2512,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { None, &ribs[ns_to_try], ignore_binding, - None, + diag_metadata, ) { // we found a locally-imported or available item/module Some(LexicalScopeBinding::Item(binding)) => Some(binding), @@ -2562,7 +2563,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { None, &ribs[ValueNS], ignore_binding, - None, + diag_metadata, ) } else { None diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 2abf129e94565..2ab024df9a207 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -1835,6 +1835,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { module, segment_idx, ident, + diag_metadata, ) }, ); diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 198fef0cd630c..3d79b94c25e79 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -885,7 +885,6 @@ impl<'ast, 'ra, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'ra, 'tc TypeNS, Some(Finalize::new(ty.id, ty.span)), None, - None, ) .map_or(Res::Err, |d| d.res()); self.r.record_partial_res(ty.id, PartialRes::new(res)); @@ -1458,7 +1457,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { None, &self.ribs[ns], None, - None, + Some(&self.diag_metadata), ) } @@ -1468,7 +1467,6 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { ns: Namespace, finalize: Option, ignore_binding: Option>, - diag_metadata: Option<&crate::late::DiagMetadata<'_>>, ) -> Option> { self.r.resolve_ident_in_lexical_scope( ident, @@ -1477,7 +1475,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { finalize, &self.ribs[ns], ignore_binding, - diag_metadata, + Some(&self.diag_metadata), ) } @@ -2556,8 +2554,8 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { report_error(self, ns); } Some(LexicalScopeBinding::Item(binding)) => { - if let Some(LexicalScopeBinding::Res(..)) = self - .resolve_ident_in_lexical_scope(ident, ns, None, Some(binding), None) + if let Some(LexicalScopeBinding::Res(..)) = + self.resolve_ident_in_lexical_scope(ident, ns, None, Some(binding)) { report_error(self, ns); } @@ -5110,7 +5108,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { // use the type namespace let ns = if i + 1 == path.len() { ns } else { TypeNS }; let res = self.r.partial_res_map.get(&seg.id?)?.full_res()?; - let binding = self.resolve_ident_in_lexical_scope(seg.ident, ns, None, None, None)?; + let binding = self.resolve_ident_in_lexical_scope(seg.ident, ns, None, None)?; (res == binding.res()).then_some((seg, binding)) }); From c962b95a16e8766c3b6f39399d60536459381222 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 2 Nov 2025 19:58:24 +0000 Subject: [PATCH 6/7] review comments --- compiler/rustc_resolve/src/diagnostics.rs | 10 +++++----- compiler/rustc_resolve/src/ident.rs | 20 ++++++++++---------- compiler/rustc_resolve/src/late.rs | 2 +- compiler/rustc_resolve/src/lib.rs | 7 ++++++- 4 files changed, 22 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 4a5d304f49bf9..bc41ffc63c3cd 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -553,12 +553,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { resolution_error: ResolutionError<'ra>, ) -> Diag<'_> { match resolution_error { - ResolutionError::GenericParamsFromOuterItem( + ResolutionError::GenericParamsFromOuterItem { outer_res, has_generic_params, def_kind, - item, - ) => { + inner_item, + } => { use errs::GenericParamsFromOuterItemLabel as Label; let static_or_const = match def_kind { DefKind::Static { .. } => { @@ -576,9 +576,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { sugg: None, static_or_const, is_self, - item: item.map(|(span, descr)| errs::GenericParamsFromOuterItemInnerItem { + item: inner_item.map(|(span, kind)| errs::GenericParamsFromOuterItemInnerItem { span, - descr, + descr: kind.descr().to_string(), }), }; diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 2ab024df9a207..278c0fe35b7d8 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -1404,18 +1404,18 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { .ident() .map(|i| i.span) .unwrap_or(current_item.span); - Some((span, current_item.kind.descr().to_string())) + Some((span, current_item.kind.clone())) } else { None }; self.report_error( span, - ResolutionError::GenericParamsFromOuterItem( - res, + ResolutionError::GenericParamsFromOuterItem { + outer_res: res, has_generic_params, def_kind, - item, - ), + inner_item: item, + }, ); } return Res::Err; @@ -1492,18 +1492,18 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { .ident() .map(|i| i.span) .unwrap_or(current_item.span); - Some((span, current_item.kind.descr().to_string())) + Some((span, current_item.kind.clone())) } else { None }; self.report_error( span, - ResolutionError::GenericParamsFromOuterItem( - res, + ResolutionError::GenericParamsFromOuterItem { + outer_res: res, has_generic_params, def_kind, - item, - ), + inner_item: item, + }, ); } return Res::Err; diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 3d79b94c25e79..7bc5943123c1b 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -677,7 +677,7 @@ pub(crate) struct DiagMetadata<'ast> { /// The current self item if inside an ADT (used for better errors). current_self_item: Option, - /// The current trait (used to suggest). + /// The current item being evaluated (used for suggestions and more detail in errors). pub(crate) current_item: Option<&'ast Item>, /// When processing generic arguments and encountering an unresolved ident not found, diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index c7f5ec76c0751..6b671df433b3d 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -241,7 +241,12 @@ struct BindingError { #[derive(Debug)] enum ResolutionError<'ra> { /// Error E0401: can't use type or const parameters from outer item. - GenericParamsFromOuterItem(Res, HasGenericParams, DefKind, Option<(Span, String)>), + GenericParamsFromOuterItem { + outer_res: Res, + has_generic_params: HasGenericParams, + def_kind: DefKind, + inner_item: Option<(Span, ast::ItemKind)>, + }, /// Error E0403: the name is already used for a type or const parameter in this generic /// parameter list. NameAlreadyUsedInParameterList(Ident, Span), From f171c41a837120c4ba12c9e1567dd44ad46894ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 2 Nov 2025 20:05:48 +0000 Subject: [PATCH 7/7] Do not suggest adding type param to fn delegation --- compiler/rustc_resolve/src/diagnostics.rs | 12 ++++++++---- tests/ui/delegation/target-expr.stderr | 5 ----- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index bc41ffc63c3cd..3020ecb6e7113 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -576,9 +576,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { sugg: None, static_or_const, is_self, - item: inner_item.map(|(span, kind)| errs::GenericParamsFromOuterItemInnerItem { - span, - descr: kind.descr().to_string(), + item: inner_item.as_ref().map(|(span, kind)| { + errs::GenericParamsFromOuterItemInnerItem { + span: *span, + descr: kind.descr().to_string(), + } }), }; @@ -613,7 +615,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } }; - if let HasGenericParams::Yes(span) = has_generic_params { + if let HasGenericParams::Yes(span) = has_generic_params + && !matches!(inner_item, Some((_, ItemKind::Delegation(..)))) + { let name = self.tcx.item_name(def_id); let (span, snippet) = if span.is_empty() { let snippet = format!("<{name}>"); diff --git a/tests/ui/delegation/target-expr.stderr b/tests/ui/delegation/target-expr.stderr index f2e6c331193f0..edd1a584eab26 100644 --- a/tests/ui/delegation/target-expr.stderr +++ b/tests/ui/delegation/target-expr.stderr @@ -8,11 +8,6 @@ LL | reuse Trait::static_method { LL | LL | let _ = T::Default(); | ^^^^^^^^^^ use of generic parameter from outer item - | -help: try introducing a local generic parameter here - | -LL | reuse Trait::static_methodT, { - | ++ error[E0434]: can't capture dynamic environment in a fn item --> $DIR/target-expr.rs:26:17