Skip to content

Commit 00b5de4

Browse files
authored
Unrolled build for rust-lang#115744
Rollup merge of rust-lang#115744 - fmease:fix-e0401, r=compiler-errors Improve diagnostic for generic params from outer items (E0401) Generalize the wording of E0401 to talk about *outer items* instead of *outer functions* since the current phrasing is outdated. The outer item can be a function, constant, trait, ADT or impl block (see the new UI test for the more exotic examples). Further, don't suggest introducing generic parameters to constant items unless the feature `generic_const_items` is enabled. Lastly, make E0401 translatable while we're at it. Fixes rust-lang#115720.
2 parents 3ebb562 + daf3c45 commit 00b5de4

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+306
-183
lines changed

compiler/rustc_error_codes/src/error_codes/E0401.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Inner items do not inherit type or const parameters from the functions
1+
Inner items do not inherit the generic parameters from the items
22
they are embedded in.
33

44
Erroneous code example:
@@ -32,8 +32,8 @@ fn foo<T>(x: T) {
3232
}
3333
```
3434

35-
Items inside functions are basically just like top-level items, except
36-
that they can only be used from the function they are in.
35+
Items nested inside other items are basically just like top-level items, except
36+
that they can only be used from the item they are in.
3737

3838
There are a couple of solutions for this.
3939

compiler/rustc_resolve/messages.ftl

+13-16
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,6 @@ resolve_cannot_find_ident_in_this_scope =
6868
resolve_cannot_glob_import_possible_crates =
6969
cannot glob-import all possible crates
7070
71-
resolve_cannot_use_self_type_here =
72-
can't use `Self` here
73-
7471
resolve_change_import_binding =
7572
you can use `as` to change the binding name of the import
7673
@@ -90,9 +87,6 @@ resolve_const_not_member_of_trait =
9087
const `{$const_}` is not a member of trait `{$trait_}`
9188
.label = not a member of trait `{$trait_}`
9289
93-
resolve_const_param_from_outer_fn =
94-
const parameter from outer function
95-
9690
resolve_const_param_in_enum_discriminant =
9791
const parameters may not be used in enum discriminant values
9892
@@ -119,10 +113,19 @@ resolve_forward_declared_generic_param =
119113
generic parameters with a default cannot use forward declared identifiers
120114
.label = defaulted generic parameters cannot be forward declared
121115
122-
resolve_generic_params_from_outer_function =
123-
can't use generic parameters from outer function
124-
.label = use of generic parameter from outer function
125-
.suggestion = try using a local generic parameter instead
116+
resolve_generic_params_from_outer_item =
117+
can't use generic parameters from outer item
118+
.label = use of generic parameter from outer item
119+
.refer_to_type_directly = refer to the type directly here instead
120+
.suggestion = try introducing a local generic parameter here
121+
122+
resolve_generic_params_from_outer_item_const_param = const parameter from outer item
123+
124+
resolve_generic_params_from_outer_item_self_ty_alias = `Self` type implicitly declared here, by this `impl`
125+
126+
resolve_generic_params_from_outer_item_self_ty_param = can't use `Self` here
127+
128+
resolve_generic_params_from_outer_item_ty_param = type parameter from outer item
126129
127130
resolve_glob_import_doesnt_reexport =
128131
glob import doesn't reexport anything because no candidate is public enough
@@ -277,9 +280,6 @@ resolve_type_not_member_of_trait =
277280
type `{$type_}` is not a member of trait `{$trait_}`
278281
.label = not a member of trait `{$trait_}`
279282
280-
resolve_type_param_from_outer_fn =
281-
type parameter from outer function
282-
283283
resolve_type_param_in_enum_discriminant =
284284
type parameters may not be used in enum discriminant values
285285
@@ -315,9 +315,6 @@ resolve_unreachable_label_suggestion_use_similarly_named =
315315
resolve_unreachable_label_with_similar_name_exists =
316316
a label with a similar name exists but is unreachable
317317
318-
resolve_use_a_type_here_instead =
319-
use a type here instead
320-
321318
resolve_variable_bound_with_different_mode =
322319
variable `{$variable_name}` is bound inconsistently across alternatives separated by `|`
323320
.label = bound in different ways

compiler/rustc_resolve/src/diagnostics.rs

+20-27
Original file line numberDiff line numberDiff line change
@@ -553,53 +553,47 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
553553
resolution_error: ResolutionError<'a>,
554554
) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
555555
match resolution_error {
556-
ResolutionError::GenericParamsFromOuterFunction(outer_res, has_generic_params) => {
557-
let mut err = struct_span_err!(
558-
self.tcx.sess,
556+
ResolutionError::GenericParamsFromOuterItem(outer_res, has_generic_params) => {
557+
use errs::GenericParamsFromOuterItemLabel as Label;
558+
let mut err = errs::GenericParamsFromOuterItem {
559559
span,
560-
E0401,
561-
"can't use generic parameters from outer function",
562-
);
563-
err.span_label(span, "use of generic parameter from outer function");
560+
label: None,
561+
refer_to_type_directly: None,
562+
sugg: None,
563+
};
564564

565565
let sm = self.tcx.sess.source_map();
566566
let def_id = match outer_res {
567567
Res::SelfTyParam { .. } => {
568-
err.span_label(span, "can't use `Self` here");
569-
return err;
568+
err.label = Some(Label::SelfTyParam(span));
569+
return self.tcx.sess.create_err(err);
570570
}
571571
Res::SelfTyAlias { alias_to: def_id, .. } => {
572-
err.span_label(
573-
reduce_impl_span_to_impl_keyword(sm, self.def_span(def_id)),
574-
"`Self` type implicitly declared here, by this `impl`",
575-
);
576-
err.span_label(span, "use a type here instead");
577-
return err;
572+
err.label = Some(Label::SelfTyAlias(reduce_impl_span_to_impl_keyword(
573+
sm,
574+
self.def_span(def_id),
575+
)));
576+
err.refer_to_type_directly = Some(span);
577+
return self.tcx.sess.create_err(err);
578578
}
579579
Res::Def(DefKind::TyParam, def_id) => {
580-
err.span_label(self.def_span(def_id), "type parameter from outer function");
580+
err.label = Some(Label::TyParam(self.def_span(def_id)));
581581
def_id
582582
}
583583
Res::Def(DefKind::ConstParam, def_id) => {
584-
err.span_label(
585-
self.def_span(def_id),
586-
"const parameter from outer function",
587-
);
584+
err.label = Some(Label::ConstParam(self.def_span(def_id)));
588585
def_id
589586
}
590587
_ => {
591588
bug!(
592-
"GenericParamsFromOuterFunction should only be used with \
589+
"GenericParamsFromOuterItem should only be used with \
593590
Res::SelfTyParam, Res::SelfTyAlias, DefKind::TyParam or \
594591
DefKind::ConstParam"
595592
);
596593
}
597594
};
598595

599596
if let HasGenericParams::Yes(span) = has_generic_params {
600-
// Try to retrieve the span of the function signature and generate a new
601-
// message with a local type or const parameter.
602-
let sugg_msg = "try using a local generic parameter instead";
603597
let name = self.tcx.item_name(def_id);
604598
let (span, snippet) = if span.is_empty() {
605599
let snippet = format!("<{name}>");
@@ -609,11 +603,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
609603
let snippet = format!("{name}, ");
610604
(span, snippet)
611605
};
612-
// Suggest the modification to the user
613-
err.span_suggestion(span, sugg_msg, snippet, Applicability::MaybeIncorrect);
606+
err.sugg = Some(errs::GenericParamsFromOuterItemSugg { span, snippet });
614607
}
615608

616-
err
609+
self.tcx.sess.create_err(err)
617610
}
618611
ResolutionError::NameAlreadyUsedInParameterList(name, first_use_span) => self
619612
.tcx

compiler/rustc_resolve/src/errors.rs

+34
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,40 @@ pub(crate) struct CrateRootNamesMustBeNamedExplicitly(#[primary_span] pub(crate)
3232
#[diag(resolve_crate_root_imports_must_be_named_explicitly)]
3333
pub(crate) struct ResolutionError(#[primary_span] pub(crate) Span);
3434

35+
#[derive(Diagnostic)]
36+
#[diag(resolve_generic_params_from_outer_item, code = "E0401")]
37+
pub(crate) struct GenericParamsFromOuterItem {
38+
#[primary_span]
39+
#[label]
40+
pub(crate) span: Span,
41+
#[subdiagnostic]
42+
pub(crate) label: Option<GenericParamsFromOuterItemLabel>,
43+
#[label(resolve_refer_to_type_directly)]
44+
pub(crate) refer_to_type_directly: Option<Span>,
45+
#[subdiagnostic]
46+
pub(crate) sugg: Option<GenericParamsFromOuterItemSugg>,
47+
}
48+
49+
#[derive(Subdiagnostic)]
50+
pub(crate) enum GenericParamsFromOuterItemLabel {
51+
#[label(resolve_generic_params_from_outer_item_self_ty_param)]
52+
SelfTyParam(#[primary_span] Span),
53+
#[label(resolve_generic_params_from_outer_item_self_ty_alias)]
54+
SelfTyAlias(#[primary_span] Span),
55+
#[label(resolve_generic_params_from_outer_item_ty_param)]
56+
TyParam(#[primary_span] Span),
57+
#[label(resolve_generic_params_from_outer_item_const_param)]
58+
ConstParam(#[primary_span] Span),
59+
}
60+
61+
#[derive(Subdiagnostic)]
62+
#[suggestion(resolve_suggestion, code = "{snippet}", applicability = "maybe-incorrect")]
63+
pub(crate) struct GenericParamsFromOuterItemSugg {
64+
#[primary_span]
65+
pub(crate) span: Span,
66+
pub(crate) snippet: String,
67+
}
68+
3569
#[derive(Diagnostic)]
3670
#[diag(resolve_name_is_already_used_as_generic_parameter, code = "E0403")]
3771
pub(crate) struct NameAlreadyUsedInParameterList {

compiler/rustc_resolve/src/ident.rs

+2-8
Original file line numberDiff line numberDiff line change
@@ -1229,10 +1229,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
12291229
if let Some(span) = finalize {
12301230
self.report_error(
12311231
span,
1232-
ResolutionError::GenericParamsFromOuterFunction(
1233-
res,
1234-
has_generic_params,
1235-
),
1232+
ResolutionError::GenericParamsFromOuterItem(res, has_generic_params),
12361233
);
12371234
}
12381235
return Res::Err;
@@ -1296,10 +1293,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
12961293
if let Some(span) = finalize {
12971294
self.report_error(
12981295
span,
1299-
ResolutionError::GenericParamsFromOuterFunction(
1300-
res,
1301-
has_generic_params,
1302-
),
1296+
ResolutionError::GenericParamsFromOuterItem(res, has_generic_params),
13031297
);
13041298
}
13051299
return Res::Err;

compiler/rustc_resolve/src/late.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -2450,7 +2450,11 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
24502450
ItemKind::Const(box ast::ConstItem { ref generics, ref ty, ref expr, .. }) => {
24512451
self.with_generic_param_rib(
24522452
&generics.params,
2453-
RibKind::Item(HasGenericParams::Yes(generics.span)),
2453+
RibKind::Item(if self.r.tcx.features().generic_const_items {
2454+
HasGenericParams::Yes(generics.span)
2455+
} else {
2456+
HasGenericParams::No
2457+
}),
24542458
LifetimeRibKind::Generics {
24552459
binder: item.id,
24562460
kind: LifetimeBinderKind::ConstItem,

compiler/rustc_resolve/src/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -186,8 +186,8 @@ struct BindingError {
186186

187187
#[derive(Debug)]
188188
enum ResolutionError<'a> {
189-
/// Error E0401: can't use type or const parameters from outer function.
190-
GenericParamsFromOuterFunction(Res, HasGenericParams),
189+
/// Error E0401: can't use type or const parameters from outer item.
190+
GenericParamsFromOuterItem(Res, HasGenericParams),
191191
/// Error E0403: the name is already used for a type or const parameter in this generic
192192
/// parameter list.
193193
NameAlreadyUsedInParameterList(Symbol, Span),

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
fn foo<const X: u32>() {
22
fn bar() -> u32 {
3-
X //~ ERROR can't use generic parameters from outer function
3+
X //~ ERROR can't use generic parameters from outer item
44
}
55
}
66

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

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
error[E0401]: can't use generic parameters from outer function
1+
error[E0401]: can't use generic parameters from outer item
22
--> $DIR/const-param-from-outer-fn.rs:3:9
33
|
44
LL | fn foo<const X: u32>() {
5-
| - const parameter from outer function
5+
| - const parameter from outer item
66
LL | fn bar() -> u32 {
7-
| - help: try using a local generic parameter instead: `<X>`
7+
| - help: try introducing a local generic parameter here: `<X>`
88
LL | X
9-
| ^ use of generic parameter from outer function
9+
| ^ use of generic parameter from outer item
1010

1111
error: aborting due to previous error
1212

tests/ui/error-codes/E0401.stderr

+11-11
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,26 @@
1-
error[E0401]: can't use generic parameters from outer function
1+
error[E0401]: can't use generic parameters from outer item
22
--> $DIR/E0401.rs:4:39
33
|
44
LL | fn foo<T>(x: T) {
5-
| - type parameter from outer function
5+
| - type parameter from outer item
66
LL | fn bfnr<U, V: Baz<U>, W: Fn()>(y: T) {
7-
| - ^ use of generic parameter from outer function
7+
| - ^ use of generic parameter from outer item
88
| |
9-
| help: try using a local generic parameter instead: `T,`
9+
| help: try introducing a local generic parameter here: `T,`
1010

11-
error[E0401]: can't use generic parameters from outer function
11+
error[E0401]: can't use generic parameters from outer item
1212
--> $DIR/E0401.rs:9:16
1313
|
1414
LL | fn foo<T>(x: T) {
15-
| - type parameter from outer function
15+
| - type parameter from outer item
1616
...
1717
LL | fn baz<U,
18-
| - help: try using a local generic parameter instead: `T,`
18+
| - help: try introducing a local generic parameter here: `T,`
1919
...
2020
LL | (y: T) {
21-
| ^ use of generic parameter from outer function
21+
| ^ use of generic parameter from outer item
2222

23-
error[E0401]: can't use generic parameters from outer function
23+
error[E0401]: can't use generic parameters from outer item
2424
--> $DIR/E0401.rs:24:25
2525
|
2626
LL | impl<T> Iterator for A<T> {
@@ -29,8 +29,8 @@ LL | impl<T> Iterator for A<T> {
2929
LL | fn helper(sel: &Self) -> u8 {
3030
| ^^^^
3131
| |
32-
| use of generic parameter from outer function
33-
| use a type here instead
32+
| use of generic parameter from outer item
33+
| refer to the type directly here instead
3434

3535
error[E0282]: type annotations needed
3636
--> $DIR/E0401.rs:11:5

tests/ui/generics/issue-94432-garbage-ice.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
fna<e>(){fnp(){e}} //~ ERROR unknown start of token: \u{fffd}
66
//~^ ERROR unknown start of token: \u{fffd}
7-
//~^^ ERROR can't use generic parameters from outer function [E0401]
7+
//~^^ ERROR can't use generic parameters from outer item [E0401]
88
//~^^^ WARN type parameter `e` should have an upper camel case name
99

1010
fn main(){}

tests/ui/generics/issue-98432.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ struct Struct<T>(T);
22

33
impl<T> Struct<T> {
44
const CONST: fn() = || {
5-
struct _Obligation where T:; //~ ERROR can't use generic parameters from outer function
5+
struct _Obligation where T:; //~ ERROR can't use generic parameters from outer item
66
};
77
}
88

tests/ui/generics/issue-98432.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
error[E0401]: can't use generic parameters from outer function
1+
error[E0401]: can't use generic parameters from outer item
22
--> $DIR/issue-98432.rs:5:34
33
|
44
LL | impl<T> Struct<T> {
5-
| - type parameter from outer function
5+
| - type parameter from outer item
66
LL | const CONST: fn() = || {
77
LL | struct _Obligation where T:;
8-
| - ^ use of generic parameter from outer function
8+
| - ^ use of generic parameter from outer item
99
| |
10-
| help: try using a local generic parameter instead: `<T>`
10+
| help: try introducing a local generic parameter here: `<T>`
1111

1212
error: aborting due to previous error
1313

tests/ui/inner-static-type-parameter.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ enum Bar<T> { What } //~ ERROR parameter `T` is never used
44

55
fn foo<T>() {
66
static a: Bar<T> = Bar::What;
7-
//~^ ERROR can't use generic parameters from outer function
7+
//~^ ERROR can't use generic parameters from outer item
88
}
99

1010
fn main() {

tests/ui/inner-static-type-parameter.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
error[E0401]: can't use generic parameters from outer function
1+
error[E0401]: can't use generic parameters from outer item
22
--> $DIR/inner-static-type-parameter.rs:6:19
33
|
44
LL | fn foo<T>() {
5-
| - type parameter from outer function
5+
| - type parameter from outer item
66
LL | static a: Bar<T> = Bar::What;
7-
| ^ use of generic parameter from outer function
7+
| ^ use of generic parameter from outer item
88

99
error[E0392]: parameter `T` is never used
1010
--> $DIR/inner-static-type-parameter.rs:3:10

tests/ui/issues/issue-3214.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
fn foo<T>() {
22
struct Foo {
3-
x: T, //~ ERROR can't use generic parameters from outer function
3+
x: T, //~ ERROR can't use generic parameters from outer item
44
}
55

66
impl<T> Drop for Foo<T> {

0 commit comments

Comments
 (0)