Skip to content

Commit c10e1e4

Browse files
authored
Rollup merge of rust-lang#148370 - estebank:outer-param, r=JonathanBrouwer
Point at inner item when it uses generic type param from outer item or `Self` Partially address rust-lang#37892. In E0401 generated in resolve: ``` 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) { | ++ ``` In E0401 generated in 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<B> A<B> { | ------------ 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` ```
2 parents 4b28573 + f171c41 commit c10e1e4

32 files changed

+339
-102
lines changed

compiler/rustc_hir_typeck/messages.ftl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,8 @@ hir_typeck_self_ctor_from_outer_item = can't reference `Self` constructor from o
266266
.label = the inner item doesn't inherit generics from this impl, so `Self` is invalid to reference
267267
.suggestion = replace `Self` with the actual type
268268
269+
hir_typeck_self_ctor_from_outer_item_inner_item = `Self` used in this inner item
270+
269271
hir_typeck_slicing_suggestion = consider slicing here
270272
271273
hir_typeck_struct_expr_non_exhaustive =

compiler/rustc_hir_typeck/src/errors.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -978,6 +978,15 @@ pub(crate) struct SelfCtorFromOuterItem {
978978
pub impl_span: Span,
979979
#[subdiagnostic]
980980
pub sugg: Option<ReplaceWithName>,
981+
#[subdiagnostic]
982+
pub item: Option<InnerItem>,
983+
}
984+
985+
#[derive(Subdiagnostic)]
986+
#[label(hir_typeck_self_ctor_from_outer_item_inner_item)]
987+
pub(crate) struct InnerItem {
988+
#[primary_span]
989+
pub span: Span,
981990
}
982991

983992
#[derive(LintDiagnostic)]
@@ -987,6 +996,8 @@ pub(crate) struct SelfCtorFromOuterItemLint {
987996
pub impl_span: Span,
988997
#[subdiagnostic]
989998
pub sugg: Option<ReplaceWithName>,
999+
#[subdiagnostic]
1000+
pub item: Option<InnerItem>,
9901001
}
9911002

9921003
#[derive(Subdiagnostic)]

compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1094,11 +1094,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10941094
span: path_span,
10951095
name: self.tcx.item_name(def.did()).to_ident_string(),
10961096
});
1097+
let item = match self
1098+
.tcx
1099+
.hir_node_by_def_id(self.tcx.hir_get_parent_item(hir_id).def_id)
1100+
{
1101+
hir::Node::Item(item) => Some(errors::InnerItem {
1102+
span: item.kind.ident().map(|i| i.span).unwrap_or(item.span),
1103+
}),
1104+
_ => None,
1105+
};
10971106
if ty.raw.has_param() {
10981107
let guar = self.dcx().emit_err(errors::SelfCtorFromOuterItem {
10991108
span: path_span,
11001109
impl_span: tcx.def_span(impl_def_id),
11011110
sugg,
1111+
item,
11021112
});
11031113
return (Ty::new_error(self.tcx, guar), res);
11041114
} else {
@@ -1109,6 +1119,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11091119
errors::SelfCtorFromOuterItemLint {
11101120
impl_span: tcx.def_span(impl_def_id),
11111121
sugg,
1122+
item,
11121123
},
11131124
);
11141125
}

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: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ use crate::errors::{
4040
MaybeMissingMacroRulesName,
4141
};
4242
use crate::imports::{Import, ImportKind};
43-
use crate::late::{PatternSource, Rib};
43+
use crate::late::{DiagMetadata, PatternSource, Rib};
4444
use crate::{
4545
AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, BindingError, BindingKey, Finalize,
4646
ForwardGenericParamBanReason, HasGenericParams, LexicalScopeBinding, MacroRulesScope, Module,
@@ -553,11 +553,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
553553
resolution_error: ResolutionError<'ra>,
554554
) -> Diag<'_> {
555555
match resolution_error {
556-
ResolutionError::GenericParamsFromOuterItem(
556+
ResolutionError::GenericParamsFromOuterItem {
557557
outer_res,
558558
has_generic_params,
559559
def_kind,
560-
) => {
560+
inner_item,
561+
} => {
561562
use errs::GenericParamsFromOuterItemLabel as Label;
562563
let static_or_const = match def_kind {
563564
DefKind::Static { .. } => {
@@ -575,6 +576,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
575576
sugg: None,
576577
static_or_const,
577578
is_self,
579+
item: inner_item.as_ref().map(|(span, kind)| {
580+
errs::GenericParamsFromOuterItemInnerItem {
581+
span: *span,
582+
descr: kind.descr().to_string(),
583+
}
584+
}),
578585
};
579586

580587
let sm = self.tcx.sess.source_map();
@@ -608,7 +615,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
608615
}
609616
};
610617

611-
if let HasGenericParams::Yes(span) = has_generic_params {
618+
if let HasGenericParams::Yes(span) = has_generic_params
619+
&& !matches!(inner_item, Some((_, ItemKind::Delegation(..))))
620+
{
612621
let name = self.tcx.item_name(def_id);
613622
let (span, snippet) = if span.is_empty() {
614623
let snippet = format!("<{name}>");
@@ -2401,6 +2410,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
24012410
module: Option<ModuleOrUniformRoot<'ra>>,
24022411
failed_segment_idx: usize,
24032412
ident: Ident,
2413+
diag_metadata: Option<&DiagMetadata<'_>>,
24042414
) -> (String, Option<Suggestion>) {
24052415
let is_last = failed_segment_idx == path.len() - 1;
24062416
let ns = if is_last { opt_ns.unwrap_or(TypeNS) } else { TypeNS };
@@ -2506,6 +2516,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
25062516
None,
25072517
&ribs[ns_to_try],
25082518
ignore_binding,
2519+
diag_metadata,
25092520
) {
25102521
// we found a locally-imported or available item/module
25112522
Some(LexicalScopeBinding::Item(binding)) => Some(binding),
@@ -2556,6 +2567,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
25562567
None,
25572568
&ribs[ValueNS],
25582569
ignore_binding,
2570+
diag_metadata,
25592571
)
25602572
} else {
25612573
None

compiler/rustc_resolve/src/errors.rs

Lines changed: 16 additions & 1 deletion
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)]
@@ -47,7 +57,12 @@ pub(crate) enum GenericParamsFromOuterItemLabel {
4757
}
4858

4959
#[derive(Subdiagnostic)]
50-
#[suggestion(resolve_suggestion, code = "{snippet}", applicability = "maybe-incorrect")]
60+
#[suggestion(
61+
resolve_suggestion,
62+
code = "{snippet}",
63+
applicability = "maybe-incorrect",
64+
style = "verbose"
65+
)]
5166
pub(crate) struct GenericParamsFromOuterItemSugg {
5267
#[primary_span]
5368
pub(crate) span: Span,

compiler/rustc_resolve/src/ident.rs

Lines changed: 43 additions & 7 deletions
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,13 +1396,26 @@ 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.clone()))
1408+
} else {
1409+
None
1410+
};
13941411
self.report_error(
13951412
span,
1396-
ResolutionError::GenericParamsFromOuterItem(
1397-
res,
1413+
ResolutionError::GenericParamsFromOuterItem {
1414+
outer_res: res,
13981415
has_generic_params,
13991416
def_kind,
1400-
),
1417+
inner_item: item,
1418+
},
14011419
);
14021420
}
14031421
return Res::Err;
@@ -1466,13 +1484,26 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
14661484

14671485
// This was an attempt to use a const parameter outside its scope.
14681486
if let Some(span) = finalize {
1487+
let item = if let Some(diag_metadata) = diag_metadata
1488+
&& let Some(current_item) = diag_metadata.current_item
1489+
{
1490+
let span = current_item
1491+
.kind
1492+
.ident()
1493+
.map(|i| i.span)
1494+
.unwrap_or(current_item.span);
1495+
Some((span, current_item.kind.clone()))
1496+
} else {
1497+
None
1498+
};
14691499
self.report_error(
14701500
span,
1471-
ResolutionError::GenericParamsFromOuterItem(
1472-
res,
1501+
ResolutionError::GenericParamsFromOuterItem {
1502+
outer_res: res,
14731503
has_generic_params,
14741504
def_kind,
1475-
),
1505+
inner_item: item,
1506+
},
14761507
);
14771508
}
14781509
return Res::Err;
@@ -1501,6 +1532,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
15011532
None,
15021533
None,
15031534
ignore_import,
1535+
None,
15041536
)
15051537
}
15061538
#[instrument(level = "debug", skip(self))]
@@ -1522,6 +1554,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
15221554
None,
15231555
ignore_binding,
15241556
ignore_import,
1557+
None,
15251558
)
15261559
}
15271560

@@ -1535,6 +1568,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
15351568
ribs: Option<&PerNS<Vec<Rib<'ra>>>>,
15361569
ignore_binding: Option<NameBinding<'ra>>,
15371570
ignore_import: Option<Import<'ra>>,
1571+
diag_metadata: Option<&DiagMetadata<'_>>,
15381572
) -> PathResult<'ra> {
15391573
let mut module = None;
15401574
let mut module_had_parse_errors = false;
@@ -1675,6 +1709,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
16751709
finalize,
16761710
&ribs[ns],
16771711
ignore_binding,
1712+
diag_metadata,
16781713
) {
16791714
// we found a locally-imported or available item/module
16801715
Some(LexicalScopeBinding::Item(binding)) => Ok(binding),
@@ -1800,6 +1835,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
18001835
module,
18011836
segment_idx,
18021837
ident,
1838+
diag_metadata,
18031839
)
18041840
},
18051841
);

compiler/rustc_resolve/src/late.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -670,7 +670,7 @@ pub(crate) struct UnnecessaryQualification<'ra> {
670670
}
671671

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

@@ -680,8 +680,8 @@ struct DiagMetadata<'ast> {
680680
/// The current self item if inside an ADT (used for better errors).
681681
current_self_item: Option<NodeId>,
682682

683-
/// The current trait (used to suggest).
684-
current_item: Option<&'ast Item>,
683+
/// The current item being evaluated (used for suggestions and more detail in errors).
684+
pub(crate) current_item: Option<&'ast Item>,
685685

686686
/// When processing generic arguments and encountering an unresolved ident not found,
687687
/// suggest introducing a type or const param depending on the context.
@@ -1460,6 +1460,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
14601460
None,
14611461
&self.ribs[ns],
14621462
None,
1463+
Some(&self.diag_metadata),
14631464
)
14641465
}
14651466

@@ -1477,6 +1478,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
14771478
finalize,
14781479
&self.ribs[ns],
14791480
ignore_binding,
1481+
Some(&self.diag_metadata),
14801482
)
14811483
}
14821484

@@ -1496,6 +1498,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
14961498
Some(&self.ribs),
14971499
None,
14981500
None,
1501+
Some(&self.diag_metadata),
14991502
)
15001503
}
15011504

compiler/rustc_resolve/src/lib.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,12 @@ 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 {
245+
outer_res: Res,
246+
has_generic_params: HasGenericParams,
247+
def_kind: DefKind,
248+
inner_item: Option<(Span, ast::ItemKind)>,
249+
},
245250
/// Error E0403: the name is already used for a type or const parameter in this generic
246251
/// parameter list.
247252
NameAlreadyUsedInParameterList(Ident, Span),

tests/ui/const-generics/early/const-param-from-outer-fn.stderr

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,14 @@ error[E0401]: can't use generic parameters from outer item
44
LL | fn foo<const X: u32>() {
55
| - const parameter from outer item
66
LL | fn bar() -> u32 {
7-
| - help: try introducing a local generic parameter here: `<X>`
7+
| --- generic parameter used in this inner function
88
LL | X
99
| ^ use of generic parameter from outer item
10+
|
11+
help: try introducing a local generic parameter here
12+
|
13+
LL | fn bar<X>() -> u32 {
14+
| +++
1015

1116
error: aborting due to 1 previous error
1217

0 commit comments

Comments
 (0)