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<T>(x: T) {
   |        - type parameter from outer item
LL |     fn bfnr<U, V: Baz<U>, 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<T, U, V: Baz<U>, W: Fn()>(y: T) {
   |             ++
```
This commit is contained in:
Esteban Küber 2025-11-01 18:29:46 +00:00
parent 973ab7d08f
commit f6938709c8
24 changed files with 162 additions and 52 deletions

View file

@ -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

View file

@ -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

View file

@ -24,6 +24,16 @@ pub(crate) struct GenericParamsFromOuterItem {
#[subdiagnostic]
pub(crate) static_or_const: Option<GenericParamsFromOuterItemStaticOrConst>,
pub(crate) is_self: bool,
#[subdiagnostic]
pub(crate) item: Option<GenericParamsFromOuterItemInnerItem>,
}
#[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)]

View file

@ -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<Finalize>,
ribs: &[Rib<'ra>],
ignore_binding: Option<NameBinding<'ra>>,
diag_metadata: Option<&DiagMetadata<'_>>,
) -> Option<LexicalScopeBinding<'ra>> {
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<Span>,
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<Vec<Rib<'ra>>>>,
ignore_binding: Option<NameBinding<'ra>>,
ignore_import: Option<Import<'ra>>,
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),

View file

@ -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<AssocItem>]>,
@ -678,7 +678,7 @@ struct DiagMetadata<'ast> {
current_self_item: Option<NodeId>,
/// 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<Finalize>,
ignore_binding: Option<NameBinding<'ra>>,
diag_metadata: Option<&crate::late::DiagMetadata<'_>>,
) -> Option<LexicalScopeBinding<'ra>> {
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))
});

View file

@ -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),

View file

@ -3,7 +3,9 @@ error[E0401]: can't use generic parameters from outer item
|
LL | fn bar<T: Default>(_: 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
|

View file

@ -4,7 +4,9 @@ error[E0401]: can't use generic parameters from outer item
LL | fn foo<T>(x: T) {
| - type parameter from outer item
LL | fn bfnr<U, V: Baz<U>, 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<T>(x: T) {
| - type parameter from outer item
...
LL | fn baz<U,
| --- generic parameter used in this inner function
...
LL | (y: T) {
| ^ use of generic parameter from outer item
|
@ -32,10 +37,11 @@ LL | impl<T> Iterator for A<T> {
| ---- `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

View file

@ -4,7 +4,9 @@ error[E0401]: can't use generic parameters from outer item
LL | fn f<Z>() -> 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
|

View file

@ -4,7 +4,9 @@ error[E0401]: can't use generic parameters from outer item
LL | fn foo<U>(v: Vec<U>) -> 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<U>(v: Vec<U>) -> 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
|

View file

@ -5,7 +5,9 @@ LL | impl<T> Struct<T> {
| - 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
|

View file

@ -4,7 +4,9 @@ error[E0401]: can't use generic parameters from outer item
LL | fn foo<T>() {
| - 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
|

View file

@ -4,7 +4,9 @@ error[E0401]: can't use generic parameters from outer item
LL | fn outer<T: Tr>() { // 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<T> 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<T: Tr>(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

View file

@ -4,7 +4,9 @@ error[E0401]: can't use generic parameters from outer item
LL | fn outer<T: Tr>() { // 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<T> 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<T: Tr>(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

View file

@ -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

View file

@ -3,7 +3,9 @@ error[E0401]: can't use generic parameters from outer item
|
LL | fn siphash<T>() {
| - 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<T>() {
| - 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
|

View file

@ -4,6 +4,7 @@ error[E0401]: can't use generic parameters from outer item
LL | fn foo<T>() {
| - 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
|

View file

@ -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<A>() {
| - type parameter from outer item
LL | extern "C" {
LL | static baz: *const A;
| ^ use of generic parameter from outer item
LL | unsafe fn foo<A>() {
| - 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

View file

@ -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<T>() {
| - type parameter from outer item
LL | extern "C" {
LL | static a: *const T;
| ^ use of generic parameter from outer item
LL | fn f<T>() {
| - 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<T: Default>() {
| - 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

View file

@ -3,7 +3,9 @@ error[E0401]: can't use generic parameters from outer item
|
LL | trait TraitA<A> {
| - type parameter from outer item
...
LL | fn outer(&self) {
LL | enum Foo<B> {
| --- generic parameter used in this inner enum
LL | Variance(A)
| ^ use of generic parameter from outer item
|
@ -19,7 +21,9 @@ LL | trait TraitB<A> {
| - type parameter from outer item
LL | fn outer(&self) {
LL | struct Foo<B>(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<A> {
| - type parameter from outer item
LL | fn outer(&self) {
LL | struct Foo<B> { 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<A> {
| - type parameter from outer item
LL | fn outer(&self) {
LL | fn foo<B>(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
|

View file

@ -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
}
}

View file

@ -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

View file

@ -4,7 +4,9 @@ error[E0401]: can't use generic parameters from outer item
LL | fn foo<T>() {
| - type parameter from outer item
LL | static a: Bar<T> = 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

View file

@ -4,7 +4,9 @@ error[E0401]: can't use generic parameters from outer item
LL | fn foo<T>(x: T) {
| - type parameter from outer item
LL | fn bar(f: Box<dyn FnMut(T) -> 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<T>(x: T) {
| - type parameter from outer item
LL | fn bar(f: Box<dyn FnMut(T) -> 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
|