Skip to content

Commit 613dc22

Browse files
committed
Improve local generic parameter suggestions.
1 parent d7d701a commit 613dc22

16 files changed

+90
-81
lines changed

compiler/rustc_resolve/src/diagnostics.rs

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -511,7 +511,7 @@ impl<'a> Resolver<'a> {
511511
err.span_label(span, "use of generic parameter from outer function");
512512

513513
let sm = self.session.source_map();
514-
match outer_res {
514+
let def_id = match outer_res {
515515
Res::SelfTy { trait_: maybe_trait_defid, alias_to: maybe_impl_defid } => {
516516
if let Some(impl_span) =
517517
maybe_impl_defid.and_then(|(def_id, _)| self.opt_span(def_id))
@@ -536,40 +536,37 @@ impl<'a> Resolver<'a> {
536536
if let Some(span) = self.opt_span(def_id) {
537537
err.span_label(span, "type parameter from outer function");
538538
}
539+
def_id
539540
}
540541
Res::Def(DefKind::ConstParam, def_id) => {
541542
if let Some(span) = self.opt_span(def_id) {
542543
err.span_label(span, "const parameter from outer function");
543544
}
545+
def_id
544546
}
545547
_ => {
546548
bug!(
547549
"GenericParamsFromOuterFunction should only be used with Res::SelfTy, \
548550
DefKind::TyParam or DefKind::ConstParam"
549551
);
550552
}
551-
}
553+
};
552554

553-
if let HasGenericParams::Yes = has_generic_params {
555+
if let HasGenericParams::Yes(span) = has_generic_params {
554556
// Try to retrieve the span of the function signature and generate a new
555557
// message with a local type or const parameter.
556558
let sugg_msg = "try using a local generic parameter instead";
557-
if let Some((sugg_span, snippet)) = sm.generate_local_type_param_snippet(span) {
558-
// Suggest the modification to the user
559-
err.span_suggestion(
560-
sugg_span,
561-
sugg_msg,
562-
snippet,
563-
Applicability::MachineApplicable,
564-
);
565-
} else if let Some(sp) = sm.generate_fn_name_span(span) {
566-
err.span_label(
567-
sp,
568-
"try adding a local generic parameter in this method instead",
569-
);
559+
let name = self.opt_name(def_id).unwrap_or(sym::T);
560+
let (span, snippet) = if span.is_empty() {
561+
let snippet = format!("<{}>", name);
562+
(span, snippet)
570563
} else {
571-
err.help("try using a local generic parameter instead");
572-
}
564+
let span = sm.span_through_char(span, '<').shrink_to_hi();
565+
let snippet = format!("{}, ", name);
566+
(span, snippet)
567+
};
568+
// Suggest the modification to the user
569+
err.span_suggestion(span, sugg_msg, snippet, Applicability::MachineApplicable);
573570
}
574571

575572
err

compiler/rustc_resolve/src/ident.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1170,10 +1170,11 @@ impl<'a> Resolver<'a> {
11701170
let has_generic_params: HasGenericParams = match rib.kind {
11711171
NormalRibKind
11721172
| ClosureOrAsyncRibKind
1173-
| AssocItemRibKind
11741173
| ModuleRibKind(..)
11751174
| MacroDefinition(..)
11761175
| InlineAsmSymRibKind
1176+
| FnItemRibKind
1177+
| AssocItemRibKind
11771178
| ForwardGenericParamBanRibKind => {
11781179
// Nothing to do. Continue.
11791180
continue;
@@ -1211,7 +1212,6 @@ impl<'a> Resolver<'a> {
12111212

12121213
// This was an attempt to use a type parameter outside its scope.
12131214
ItemRibKind(has_generic_params) => has_generic_params,
1214-
FnItemRibKind => HasGenericParams::Yes,
12151215
ConstParamTyRibKind => {
12161216
if let Some(span) = finalize {
12171217
self.report_error(
@@ -1248,10 +1248,11 @@ impl<'a> Resolver<'a> {
12481248
let has_generic_params = match rib.kind {
12491249
NormalRibKind
12501250
| ClosureOrAsyncRibKind
1251-
| AssocItemRibKind
12521251
| ModuleRibKind(..)
12531252
| MacroDefinition(..)
12541253
| InlineAsmSymRibKind
1254+
| FnItemRibKind
1255+
| AssocItemRibKind
12551256
| ForwardGenericParamBanRibKind => continue,
12561257

12571258
ConstantItemRibKind(trivial, _) => {
@@ -1278,7 +1279,6 @@ impl<'a> Resolver<'a> {
12781279
}
12791280

12801281
ItemRibKind(has_generic_params) => has_generic_params,
1281-
FnItemRibKind => HasGenericParams::Yes,
12821282
ConstParamTyRibKind => {
12831283
if let Some(span) = finalize {
12841284
self.report_error(

compiler/rustc_resolve/src/late.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ enum PatBoundCtx {
9393
/// Does this the item (from the item rib scope) allow generic parameters?
9494
#[derive(Copy, Clone, Debug)]
9595
pub(crate) enum HasGenericParams {
96-
Yes,
96+
Yes(Span),
9797
No,
9898
}
9999

@@ -758,7 +758,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
758758
self.with_lifetime_rib(LifetimeRibKind::Item, |this| {
759759
this.with_generic_param_rib(
760760
&generics.params,
761-
ItemRibKind(HasGenericParams::Yes),
761+
ItemRibKind(HasGenericParams::Yes(generics.span)),
762762
LifetimeRibKind::Generics {
763763
binder: foreign_item.id,
764764
kind: LifetimeBinderKind::Item,
@@ -772,7 +772,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
772772
self.with_lifetime_rib(LifetimeRibKind::Item, |this| {
773773
this.with_generic_param_rib(
774774
&generics.params,
775-
ItemRibKind(HasGenericParams::Yes),
775+
ItemRibKind(HasGenericParams::Yes(generics.span)),
776776
LifetimeRibKind::Generics {
777777
binder: foreign_item.id,
778778
kind: LifetimeBinderKind::Function,
@@ -2078,7 +2078,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
20782078
self.with_current_self_item(item, |this| {
20792079
this.with_generic_param_rib(
20802080
&generics.params,
2081-
ItemRibKind(HasGenericParams::Yes),
2081+
ItemRibKind(HasGenericParams::Yes(generics.span)),
20822082
LifetimeRibKind::Generics {
20832083
binder: item.id,
20842084
kind: LifetimeBinderKind::Item,
@@ -2148,7 +2148,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
21482148
ItemKind::TyAlias(box TyAlias { ref generics, .. }) => {
21492149
self.with_generic_param_rib(
21502150
&generics.params,
2151-
ItemRibKind(HasGenericParams::Yes),
2151+
ItemRibKind(HasGenericParams::Yes(generics.span)),
21522152
LifetimeRibKind::Generics {
21532153
binder: item.id,
21542154
kind: LifetimeBinderKind::Item,
@@ -2161,7 +2161,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
21612161
ItemKind::Fn(box Fn { ref generics, .. }) => {
21622162
self.with_generic_param_rib(
21632163
&generics.params,
2164-
ItemRibKind(HasGenericParams::Yes),
2164+
ItemRibKind(HasGenericParams::Yes(generics.span)),
21652165
LifetimeRibKind::Generics {
21662166
binder: item.id,
21672167
kind: LifetimeBinderKind::Function,
@@ -2193,7 +2193,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
21932193
// Create a new rib for the trait-wide type parameters.
21942194
self.with_generic_param_rib(
21952195
&generics.params,
2196-
ItemRibKind(HasGenericParams::Yes),
2196+
ItemRibKind(HasGenericParams::Yes(generics.span)),
21972197
LifetimeRibKind::Generics {
21982198
binder: item.id,
21992199
kind: LifetimeBinderKind::Item,
@@ -2217,7 +2217,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
22172217
// Create a new rib for the trait-wide type parameters.
22182218
self.with_generic_param_rib(
22192219
&generics.params,
2220-
ItemRibKind(HasGenericParams::Yes),
2220+
ItemRibKind(HasGenericParams::Yes(generics.span)),
22212221
LifetimeRibKind::Generics {
22222222
binder: item.id,
22232223
kind: LifetimeBinderKind::Item,
@@ -2605,7 +2605,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
26052605
// If applicable, create a rib for the type parameters.
26062606
self.with_generic_param_rib(
26072607
&generics.params,
2608-
ItemRibKind(HasGenericParams::Yes),
2608+
ItemRibKind(HasGenericParams::Yes(generics.span)),
26092609
LifetimeRibKind::Generics {
26102610
span: generics.span,
26112611
binder: item_id,

compiler/rustc_resolve/src/lib.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1945,6 +1945,16 @@ impl<'a> Resolver<'a> {
19451945
def_id.as_local().map(|def_id| self.source_span[def_id])
19461946
}
19471947

1948+
/// Retrieves the name of the given `DefId`.
1949+
#[inline]
1950+
pub fn opt_name(&self, def_id: DefId) -> Option<Symbol> {
1951+
let def_key = match def_id.as_local() {
1952+
Some(def_id) => self.definitions.def_key(def_id),
1953+
None => self.cstore().def_key(def_id),
1954+
};
1955+
def_key.get_opt_name()
1956+
}
1957+
19481958
/// Checks if an expression refers to a function marked with
19491959
/// `#[rustc_legacy_const_generics]` and returns the argument index list
19501960
/// from the attribute.

compiler/rustc_span/src/symbol.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,7 @@ symbols! {
280280
StructuralPartialEq,
281281
SubdiagnosticMessage,
282282
Sync,
283+
T,
283284
Target,
284285
ToOwned,
285286
ToString,

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error[E0401]: can't use generic parameters from outer function
44
LL | fn foo<const X: u32>() {
55
| - const parameter from outer function
66
LL | fn bar() -> u32 {
7-
| --- try adding a local generic parameter in this method instead
7+
| - help: try using a local generic parameter instead: `<X>`
88
LL | X
99
| ^ use of generic parameter from outer function
1010

src/test/ui/error-codes/E0401.stderr

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ error[E0401]: can't use generic parameters from outer function
44
LL | fn foo<T>(x: T) {
55
| - type parameter from outer function
66
LL | fn bfnr<U, V: Baz<U>, W: Fn()>(y: T) {
7-
| --------------------------- ^ use of generic parameter from outer function
8-
| |
9-
| help: try using a local generic parameter instead: `bfnr<U, V: Baz<U>, W: Fn(), T>`
7+
| - ^ use of generic parameter from outer function
8+
| |
9+
| help: try using a local generic parameter instead: `T,`
1010

1111
error[E0401]: can't use generic parameters from outer function
1212
--> $DIR/E0401.rs:9:16
@@ -15,7 +15,7 @@ LL | fn foo<T>(x: T) {
1515
| - type parameter from outer function
1616
...
1717
LL | fn baz<U,
18-
| --- try adding a local generic parameter in this method instead
18+
| - help: try using a local generic parameter instead: `T,`
1919
...
2020
LL | (y: T) {
2121
| ^ use of generic parameter from outer function

src/test/ui/generics/issue-98432.stderr

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ LL | impl<T> Struct<T> {
55
| - type parameter from outer function
66
LL | const CONST: fn() = || {
77
LL | struct _Obligation where T:;
8-
| ^ use of generic parameter from outer function
9-
|
10-
= help: try using a local generic parameter instead
8+
| - ^ use of generic parameter from outer function
9+
| |
10+
| help: try using a local generic parameter instead: `<T>`
1111

1212
error: aborting due to previous error
1313

src/test/ui/issues/issue-3214.stderr

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,9 @@ error[E0401]: can't use generic parameters from outer function
22
--> $DIR/issue-3214.rs:3:12
33
|
44
LL | fn foo<T>() {
5-
| --- - type parameter from outer function
6-
| |
7-
| try adding a local generic parameter in this method instead
5+
| - type parameter from outer function
86
LL | struct Foo {
7+
| - help: try using a local generic parameter instead: `<T>`
98
LL | x: T,
109
| ^ use of generic parameter from outer function
1110

src/test/ui/issues/issue-5997-enum.stderr

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ error[E0401]: can't use generic parameters from outer function
22
--> $DIR/issue-5997-enum.rs:2:16
33
|
44
LL | fn f<Z>() -> bool {
5-
| - - type parameter from outer function
6-
| |
7-
| try adding a local generic parameter in this method instead
5+
| - type parameter from outer function
86
LL | enum E { V(Z) }
9-
| ^ use of generic parameter from outer function
7+
| - ^ use of generic parameter from outer function
8+
| |
9+
| help: try using a local generic parameter instead: `<Z>`
1010

1111
error: aborting due to previous error
1212

src/test/ui/issues/issue-5997-struct.stderr

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ error[E0401]: can't use generic parameters from outer function
22
--> $DIR/issue-5997-struct.rs:2:14
33
|
44
LL | fn f<T>() -> bool {
5-
| - - type parameter from outer function
6-
| |
7-
| try adding a local generic parameter in this method instead
5+
| - type parameter from outer function
86
LL | struct S(T);
9-
| ^ use of generic parameter from outer function
7+
| -^ use of generic parameter from outer function
8+
| |
9+
| help: try using a local generic parameter instead: `<T>`
1010

1111
error: aborting due to previous error
1212

src/test/ui/nested-ty-params.stderr

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,19 @@ error[E0401]: can't use generic parameters from outer function
44
LL | fn hd<U>(v: Vec<U> ) -> U {
55
| - type parameter from outer function
66
LL | fn hd1(w: [U]) -> U { return w[0]; }
7-
| --- ^ use of generic parameter from outer function
8-
| |
9-
| help: try using a local generic parameter instead: `hd1<U>`
7+
| - ^ use of generic parameter from outer function
8+
| |
9+
| help: try using a local generic parameter instead: `<U>`
1010

1111
error[E0401]: can't use generic parameters from outer function
1212
--> $DIR/nested-ty-params.rs:3:23
1313
|
1414
LL | fn hd<U>(v: Vec<U> ) -> U {
1515
| - type parameter from outer function
1616
LL | fn hd1(w: [U]) -> U { return w[0]; }
17-
| --- ^ use of generic parameter from outer function
18-
| |
19-
| help: try using a local generic parameter instead: `hd1<U>`
17+
| - ^ use of generic parameter from outer function
18+
| |
19+
| help: try using a local generic parameter instead: `<U>`
2020

2121
error: aborting due to 2 previous errors
2222

src/test/ui/resolve/bad-type-env-capture.stderr

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ error[E0401]: can't use generic parameters from outer function
44
LL | fn foo<T>() {
55
| - type parameter from outer function
66
LL | fn bar(b: T) { }
7-
| --- ^ use of generic parameter from outer function
8-
| |
9-
| help: try using a local generic parameter instead: `bar<T>`
7+
| - ^ use of generic parameter from outer function
8+
| |
9+
| help: try using a local generic parameter instead: `<T>`
1010

1111
error: aborting due to previous error
1212

src/test/ui/resolve/issue-3021-c.stderr

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,22 @@ error[E0401]: can't use generic parameters from outer function
33
|
44
LL | fn siphash<T>() {
55
| - type parameter from outer function
6-
...
6+
LL |
7+
LL | trait U {
8+
| - help: try using a local generic parameter instead: `<T>`
79
LL | fn g(&self, x: T) -> T;
8-
| - ^ use of generic parameter from outer function
9-
| |
10-
| help: try using a local generic parameter instead: `g<T>`
10+
| ^ use of generic parameter from outer function
1111

1212
error[E0401]: can't use generic parameters from outer function
1313
--> $DIR/issue-3021-c.rs:4:30
1414
|
1515
LL | fn siphash<T>() {
1616
| - type parameter from outer function
17-
...
17+
LL |
18+
LL | trait U {
19+
| - help: try using a local generic parameter instead: `<T>`
1820
LL | fn g(&self, x: T) -> T;
19-
| - ^ use of generic parameter from outer function
20-
| |
21-
| help: try using a local generic parameter instead: `g<T>`
21+
| ^ use of generic parameter from outer function
2222

2323
error: aborting due to 2 previous errors
2424

0 commit comments

Comments
 (0)