Skip to content

Commit f693870

Browse files
committed
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) { | ++ ```
1 parent 973ab7d commit f693870

24 files changed

+162
-52
lines changed

compiler/rustc_resolve/messages.ftl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,11 @@ resolve_generic_params_from_outer_item_const = a `const` is a separate item from
180180
181181
resolve_generic_params_from_outer_item_const_param = const parameter from outer item
182182
183+
resolve_generic_params_from_outer_item_inner_item = {$is_self ->
184+
[true] `Self`
185+
*[false] generic parameter
186+
} used in this inner {$descr}
187+
183188
resolve_generic_params_from_outer_item_self_ty_alias = `Self` type implicitly declared here, by this `impl`
184189
185190
resolve_generic_params_from_outer_item_self_ty_param = can't use `Self` here

compiler/rustc_resolve/src/diagnostics.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
557557
outer_res,
558558
has_generic_params,
559559
def_kind,
560+
item,
560561
) => {
561562
use errs::GenericParamsFromOuterItemLabel as Label;
562563
let static_or_const = match def_kind {
@@ -575,6 +576,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
575576
sugg: None,
576577
static_or_const,
577578
is_self,
579+
item: item.map(|(span, descr)| errs::GenericParamsFromOuterItemInnerItem {
580+
span,
581+
descr,
582+
}),
578583
};
579584

580585
let sm = self.tcx.sess.source_map();
@@ -2506,6 +2511,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
25062511
None,
25072512
&ribs[ns_to_try],
25082513
ignore_binding,
2514+
None,
25092515
) {
25102516
// we found a locally-imported or available item/module
25112517
Some(LexicalScopeBinding::Item(binding)) => Some(binding),
@@ -2556,6 +2562,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
25562562
None,
25572563
&ribs[ValueNS],
25582564
ignore_binding,
2565+
None,
25592566
)
25602567
} else {
25612568
None

compiler/rustc_resolve/src/errors.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,16 @@ pub(crate) struct GenericParamsFromOuterItem {
2424
#[subdiagnostic]
2525
pub(crate) static_or_const: Option<GenericParamsFromOuterItemStaticOrConst>,
2626
pub(crate) is_self: bool,
27+
#[subdiagnostic]
28+
pub(crate) item: Option<GenericParamsFromOuterItemInnerItem>,
29+
}
30+
31+
#[derive(Subdiagnostic)]
32+
#[label(resolve_generic_params_from_outer_item_inner_item)]
33+
pub(crate) struct GenericParamsFromOuterItemInnerItem {
34+
#[primary_span]
35+
pub(crate) span: Span,
36+
pub(crate) descr: String,
2737
}
2838

2939
#[derive(Subdiagnostic)]

compiler/rustc_resolve/src/ident.rs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ use tracing::{debug, instrument};
1212

1313
use crate::errors::{ParamKindInEnumDiscriminant, ParamKindInNonTrivialAnonConst};
1414
use crate::imports::{Import, NameResolution};
15-
use crate::late::{ConstantHasGenerics, NoConstantGenericsReason, PathSource, Rib, RibKind};
15+
use crate::late::{
16+
ConstantHasGenerics, DiagMetadata, NoConstantGenericsReason, PathSource, Rib, RibKind,
17+
};
1618
use crate::macros::{MacroRulesScope, sub_namespace_match};
1719
use crate::{
1820
AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, BindingKey, CmResolver, Determinacy,
@@ -295,6 +297,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
295297
finalize: Option<Finalize>,
296298
ribs: &[Rib<'ra>],
297299
ignore_binding: Option<NameBinding<'ra>>,
300+
diag_metadata: Option<&DiagMetadata<'_>>,
298301
) -> Option<LexicalScopeBinding<'ra>> {
299302
assert!(ns == TypeNS || ns == ValueNS);
300303
let orig_ident = ident;
@@ -326,6 +329,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
326329
finalize.map(|finalize| finalize.path_span),
327330
*original_rib_ident_def,
328331
ribs,
332+
diag_metadata,
329333
)));
330334
} else if let RibKind::Block(Some(module)) = rib.kind
331335
&& let Ok(binding) = self.cm().resolve_ident_in_module_unadjusted(
@@ -1193,6 +1197,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
11931197
finalize: Option<Span>,
11941198
original_rib_ident_def: Ident,
11951199
all_ribs: &[Rib<'ra>],
1200+
diag_metadata: Option<&DiagMetadata<'_>>,
11961201
) -> Res {
11971202
debug!("validate_res_from_ribs({:?})", res);
11981203
let ribs = &all_ribs[rib_index + 1..];
@@ -1391,12 +1396,25 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
13911396
};
13921397

13931398
if let Some(span) = finalize {
1399+
let item = if let Some(diag_metadata) = diag_metadata
1400+
&& let Some(current_item) = diag_metadata.current_item
1401+
{
1402+
let span = current_item
1403+
.kind
1404+
.ident()
1405+
.map(|i| i.span)
1406+
.unwrap_or(current_item.span);
1407+
Some((span, current_item.kind.descr().to_string()))
1408+
} else {
1409+
None
1410+
};
13941411
self.report_error(
13951412
span,
13961413
ResolutionError::GenericParamsFromOuterItem(
13971414
res,
13981415
has_generic_params,
13991416
def_kind,
1417+
item,
14001418
),
14011419
);
14021420
}
@@ -1472,6 +1490,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
14721490
res,
14731491
has_generic_params,
14741492
def_kind,
1493+
None,
14751494
),
14761495
);
14771496
}
@@ -1501,6 +1520,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
15011520
None,
15021521
None,
15031522
ignore_import,
1523+
None,
15041524
)
15051525
}
15061526
#[instrument(level = "debug", skip(self))]
@@ -1522,6 +1542,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
15221542
None,
15231543
ignore_binding,
15241544
ignore_import,
1545+
None,
15251546
)
15261547
}
15271548

@@ -1535,6 +1556,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
15351556
ribs: Option<&PerNS<Vec<Rib<'ra>>>>,
15361557
ignore_binding: Option<NameBinding<'ra>>,
15371558
ignore_import: Option<Import<'ra>>,
1559+
diag_metadata: Option<&DiagMetadata<'_>>,
15381560
) -> PathResult<'ra> {
15391561
let mut module = None;
15401562
let mut module_had_parse_errors = false;
@@ -1675,6 +1697,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
16751697
finalize,
16761698
&ribs[ns],
16771699
ignore_binding,
1700+
diag_metadata,
16781701
) {
16791702
// we found a locally-imported or available item/module
16801703
Some(LexicalScopeBinding::Item(binding)) => Ok(binding),

compiler/rustc_resolve/src/late.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -667,7 +667,7 @@ pub(crate) struct UnnecessaryQualification<'ra> {
667667
}
668668

669669
#[derive(Default, Debug)]
670-
struct DiagMetadata<'ast> {
670+
pub(crate) struct DiagMetadata<'ast> {
671671
/// The current trait's associated items' ident, used for diagnostic suggestions.
672672
current_trait_assoc_items: Option<&'ast [Box<AssocItem>]>,
673673

@@ -678,7 +678,7 @@ struct DiagMetadata<'ast> {
678678
current_self_item: Option<NodeId>,
679679

680680
/// The current trait (used to suggest).
681-
current_item: Option<&'ast Item>,
681+
pub(crate) current_item: Option<&'ast Item>,
682682

683683
/// When processing generic arguments and encountering an unresolved ident not found,
684684
/// 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
885885
TypeNS,
886886
Some(Finalize::new(ty.id, ty.span)),
887887
None,
888+
None,
888889
)
889890
.map_or(Res::Err, |d| d.res());
890891
self.r.record_partial_res(ty.id, PartialRes::new(res));
@@ -1457,6 +1458,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
14571458
None,
14581459
&self.ribs[ns],
14591460
None,
1461+
None,
14601462
)
14611463
}
14621464

@@ -1466,6 +1468,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
14661468
ns: Namespace,
14671469
finalize: Option<Finalize>,
14681470
ignore_binding: Option<NameBinding<'ra>>,
1471+
diag_metadata: Option<&crate::late::DiagMetadata<'_>>,
14691472
) -> Option<LexicalScopeBinding<'ra>> {
14701473
self.r.resolve_ident_in_lexical_scope(
14711474
ident,
@@ -1474,6 +1477,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
14741477
finalize,
14751478
&self.ribs[ns],
14761479
ignore_binding,
1480+
diag_metadata,
14771481
)
14781482
}
14791483

@@ -1493,6 +1497,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
14931497
Some(&self.ribs),
14941498
None,
14951499
None,
1500+
Some(&self.diag_metadata),
14961501
)
14971502
}
14981503

@@ -2551,8 +2556,8 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
25512556
report_error(self, ns);
25522557
}
25532558
Some(LexicalScopeBinding::Item(binding)) => {
2554-
if let Some(LexicalScopeBinding::Res(..)) =
2555-
self.resolve_ident_in_lexical_scope(ident, ns, None, Some(binding))
2559+
if let Some(LexicalScopeBinding::Res(..)) = self
2560+
.resolve_ident_in_lexical_scope(ident, ns, None, Some(binding), None)
25562561
{
25572562
report_error(self, ns);
25582563
}
@@ -5105,7 +5110,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
51055110
// use the type namespace
51065111
let ns = if i + 1 == path.len() { ns } else { TypeNS };
51075112
let res = self.r.partial_res_map.get(&seg.id?)?.full_res()?;
5108-
let binding = self.resolve_ident_in_lexical_scope(seg.ident, ns, None, None)?;
5113+
let binding = self.resolve_ident_in_lexical_scope(seg.ident, ns, None, None, None)?;
51095114
(res == binding.res()).then_some((seg, binding))
51105115
});
51115116

compiler/rustc_resolve/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ struct BindingError {
241241
#[derive(Debug)]
242242
enum ResolutionError<'ra> {
243243
/// Error E0401: can't use type or const parameters from outer item.
244-
GenericParamsFromOuterItem(Res, HasGenericParams, DefKind),
244+
GenericParamsFromOuterItem(Res, HasGenericParams, DefKind, Option<(Span, String)>),
245245
/// Error E0403: the name is already used for a type or const parameter in this generic
246246
/// parameter list.
247247
NameAlreadyUsedInParameterList(Ident, Span),

tests/ui/delegation/target-expr.stderr

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ error[E0401]: can't use generic parameters from outer item
33
|
44
LL | fn bar<T: Default>(_: T) {
55
| - type parameter from outer item
6-
...
6+
LL | reuse Trait::static_method {
7+
| ------------- generic parameter used in this inner delegated function
8+
LL |
79
LL | let _ = T::Default();
810
| ^^^^^^^^^^ use of generic parameter from outer item
911
|

tests/ui/error-codes/E0401.stderr

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ error[E0401]: can't use generic parameters from outer item
44
LL | fn foo<T>(x: T) {
55
| - type parameter from outer item
66
LL | fn bfnr<U, V: Baz<U>, W: Fn()>(y: T) {
7-
| ^ use of generic parameter from outer item
7+
| ---- ^ use of generic parameter from outer item
8+
| |
9+
| generic parameter used in this inner function
810
|
911
help: try introducing a local generic parameter here
1012
|
@@ -17,6 +19,9 @@ error[E0401]: can't use generic parameters from outer item
1719
LL | fn foo<T>(x: T) {
1820
| - type parameter from outer item
1921
...
22+
LL | fn baz<U,
23+
| --- generic parameter used in this inner function
24+
...
2025
LL | (y: T) {
2126
| ^ use of generic parameter from outer item
2227
|
@@ -32,10 +37,11 @@ LL | impl<T> Iterator for A<T> {
3237
| ---- `Self` type implicitly declared here, by this `impl`
3338
...
3439
LL | fn helper(sel: &Self) -> u8 {
35-
| ^^^^
36-
| |
37-
| use of `Self` from outer item
38-
| refer to the type directly here instead
40+
| ------ ^^^^
41+
| | |
42+
| | use of `Self` from outer item
43+
| | refer to the type directly here instead
44+
| `Self` used in this inner function
3945

4046
error: aborting due to 3 previous errors
4147

tests/ui/generics/enum-definition-with-outer-generic-parameter-5997.stderr

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ error[E0401]: can't use generic parameters from outer item
44
LL | fn f<Z>() -> bool {
55
| - type parameter from outer item
66
LL | enum E { V(Z) }
7-
| ^ use of generic parameter from outer item
7+
| - ^ use of generic parameter from outer item
8+
| |
9+
| generic parameter used in this inner enum
810
|
911
help: try introducing a local generic parameter here
1012
|

tests/ui/generics/generic-params-nested-fn-scope-error.stderr

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ error[E0401]: can't use generic parameters from outer item
44
LL | fn foo<U>(v: Vec<U>) -> U {
55
| - type parameter from outer item
66
LL | fn bar(w: [U]) -> U {
7-
| ^ use of generic parameter from outer item
7+
| --- ^ use of generic parameter from outer item
8+
| |
9+
| generic parameter used in this inner function
810
|
911
help: try introducing a local generic parameter here
1012
|
@@ -17,7 +19,9 @@ error[E0401]: can't use generic parameters from outer item
1719
LL | fn foo<U>(v: Vec<U>) -> U {
1820
| - type parameter from outer item
1921
LL | fn bar(w: [U]) -> U {
20-
| ^ use of generic parameter from outer item
22+
| --- ^ use of generic parameter from outer item
23+
| |
24+
| generic parameter used in this inner function
2125
|
2226
help: try introducing a local generic parameter here
2327
|

0 commit comments

Comments
 (0)