From 693e9579bc796e5a8f38f58563e20d3cc1c21ce3 Mon Sep 17 00:00:00 2001 From: mibac138 <5672750+mibac138@users.noreply.github.com> Date: Wed, 5 May 2021 18:59:37 +0200 Subject: [PATCH 1/3] Suggest adding a type parameter for impls --- .../rustc_resolve/src/late/diagnostics.rs | 10 +++++---- src/test/ui/const-generics/diagnostics.stderr | 22 +++++++++++++++++-- src/test/ui/traits/issue-75627.stderr | 4 +++- src/test/ui/traits/issue-78372.stderr | 11 +++++++++- 4 files changed, 39 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 7561b3df3af..a4bf19aab95 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1600,8 +1600,8 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { if !self.diagnostic_metadata.currently_processing_generics && !single_uppercase_char { return None; } - match (self.diagnostic_metadata.current_item, single_uppercase_char) { - (Some(Item { kind: ItemKind::Fn(..), ident, .. }), _) if ident.name == sym::main => { + match (self.diagnostic_metadata.current_item, single_uppercase_char, self.diagnostic_metadata.currently_processing_generics) { + (Some(Item { kind: ItemKind::Fn(..), ident, .. }), _, _) if ident.name == sym::main => { // Ignore `fn main()` as we don't want to suggest `fn main()` } ( @@ -1613,9 +1613,11 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { | kind @ ItemKind::Union(..), .. }), - true, + true, _ ) - | (Some(Item { kind, .. }), false) => { + // Without the 2nd `true`, we'd suggest `impl ` for `impl T` when a type `T` isn't found + | (Some(Item { kind: kind @ ItemKind::Impl(..), .. }), true, true) + | (Some(Item { kind, .. }), false, _) => { // Likely missing type parameter. if let Some(generics) = kind.generics() { if span.overlaps(generics.span) { diff --git a/src/test/ui/const-generics/diagnostics.stderr b/src/test/ui/const-generics/diagnostics.stderr index c8ee6ad61ec..983cb52f3ff 100644 --- a/src/test/ui/const-generics/diagnostics.stderr +++ b/src/test/ui/const-generics/diagnostics.stderr @@ -5,7 +5,16 @@ LL | struct A; | ---------------------- similarly named struct `A` defined here LL | trait Foo {} LL | impl Foo for A {} - | ^ help: a struct with a similar name exists: `A` + | ^ + | +help: a struct with a similar name exists + | +LL | impl Foo for A {} + | ^ +help: you might be missing a type parameter + | +LL | impl Foo for A {} + | ^^^ error[E0412]: cannot find type `T` in this scope --> $DIR/diagnostics.rs:16:32 @@ -14,7 +23,16 @@ LL | struct A; | ---------------------- similarly named struct `A` defined here ... LL | impl Foo for C {} - | ^ help: a struct with a similar name exists: `A` + | ^ + | +help: a struct with a similar name exists + | +LL | impl Foo for C {} + | ^ +help: you might be missing a type parameter + | +LL | impl Foo for C {} + | ^^^ error[E0747]: unresolved item provided when a constant was expected --> $DIR/diagnostics.rs:7:16 diff --git a/src/test/ui/traits/issue-75627.stderr b/src/test/ui/traits/issue-75627.stderr index 92d9ac0f84c..432ddf2dcdb 100644 --- a/src/test/ui/traits/issue-75627.stderr +++ b/src/test/ui/traits/issue-75627.stderr @@ -2,7 +2,9 @@ error[E0412]: cannot find type `T` in this scope --> $DIR/issue-75627.rs:3:26 | LL | unsafe impl Send for Foo {} - | ^ not found in this scope + | - ^ not found in this scope + | | + | help: you might be missing a type parameter: `` error: aborting due to previous error diff --git a/src/test/ui/traits/issue-78372.stderr b/src/test/ui/traits/issue-78372.stderr index 9267e838cea..e63740c4ea9 100644 --- a/src/test/ui/traits/issue-78372.stderr +++ b/src/test/ui/traits/issue-78372.stderr @@ -13,9 +13,18 @@ error[E0412]: cannot find type `U` in this scope --> $DIR/issue-78372.rs:3:31 | LL | impl DispatchFromDyn> for T {} - | - ^ help: a type parameter with a similar name exists: `T` + | - ^ | | | similarly named type parameter `T` defined here + | +help: a type parameter with a similar name exists + | +LL | impl DispatchFromDyn> for T {} + | ^ +help: you might be missing a type parameter + | +LL | impl DispatchFromDyn> for T {} + | ^^^ error[E0412]: cannot find type `MISC` in this scope --> $DIR/issue-78372.rs:3:34 From 1bb94fbbeb703806817a09806365e26a18f5daa4 Mon Sep 17 00:00:00 2001 From: mibac138 <5672750+mibac138@users.noreply.github.com> Date: Thu, 6 May 2021 14:33:02 +0200 Subject: [PATCH 2/3] Expand impl type parameter suggestion tests --- .../missing-items/missing-type-parameter2.rs | 18 ++++ .../missing-type-parameter2.stderr | 85 +++++++++++++++++++ 2 files changed, 103 insertions(+) create mode 100644 src/test/ui/missing/missing-items/missing-type-parameter2.rs create mode 100644 src/test/ui/missing/missing-items/missing-type-parameter2.stderr diff --git a/src/test/ui/missing/missing-items/missing-type-parameter2.rs b/src/test/ui/missing/missing-items/missing-type-parameter2.rs new file mode 100644 index 00000000000..e5d90bb6ff0 --- /dev/null +++ b/src/test/ui/missing/missing-items/missing-type-parameter2.rs @@ -0,0 +1,18 @@ +#![allow(incomplete_features)] +#![feature(const_generics_defaults)] + +struct X(); + +impl X {} +//~^ ERROR cannot find type `N` in this scope +//~| ERROR unresolved item provided when a constant was expected +impl X {} +//~^ ERROR cannot find type `N` in this scope +//~| ERROR defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions +//~| ERROR unresolved item provided when a constant was expected + +fn bar(a: A) {} +//~^ ERROR cannot find type `A` in this scope + +fn main() { +} diff --git a/src/test/ui/missing/missing-items/missing-type-parameter2.stderr b/src/test/ui/missing/missing-items/missing-type-parameter2.stderr new file mode 100644 index 00000000000..545be1c34fb --- /dev/null +++ b/src/test/ui/missing/missing-items/missing-type-parameter2.stderr @@ -0,0 +1,85 @@ +error[E0412]: cannot find type `N` in this scope + --> $DIR/missing-type-parameter2.rs:6:8 + | +LL | struct X(); + | ------------------------ similarly named struct `X` defined here +LL | +LL | impl X {} + | ^ + | +help: a struct with a similar name exists + | +LL | impl X {} + | ^ +help: you might be missing a type parameter + | +LL | impl X {} + | ^^^ + +error[E0412]: cannot find type `N` in this scope + --> $DIR/missing-type-parameter2.rs:9:28 + | +LL | impl X {} + | - ^ + | | + | similarly named type parameter `T` defined here + | +help: a type parameter with a similar name exists + | +LL | impl X {} + | ^ +help: you might be missing a type parameter + | +LL | impl X {} + | ^^^ + +error[E0412]: cannot find type `A` in this scope + --> $DIR/missing-type-parameter2.rs:14:24 + | +LL | struct X(); + | ------------------------ similarly named struct `X` defined here +... +LL | fn bar(a: A) {} + | ^ + | +help: a struct with a similar name exists + | +LL | fn bar(a: X) {} + | ^ +help: you might be missing a type parameter + | +LL | fn bar(a: A) {} + | ^^^ + +error[E0747]: unresolved item provided when a constant was expected + --> $DIR/missing-type-parameter2.rs:6:8 + | +LL | impl X {} + | ^ + | +help: if this generic argument was intended as a const parameter, surround it with braces + | +LL | impl X<{ N }> {} + | ^ ^ + +error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/missing-type-parameter2.rs:9:15 + | +LL | impl X {} + | ^ + +error[E0747]: unresolved item provided when a constant was expected + --> $DIR/missing-type-parameter2.rs:9:28 + | +LL | impl X {} + | ^ + | +help: if this generic argument was intended as a const parameter, surround it with braces + | +LL | impl X<{ N }> {} + | ^ ^ + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0412, E0747. +For more information about an error, try `rustc --explain E0412`. From 4c72efc8167405ca1cc3002266a9bf15f70dafb3 Mon Sep 17 00:00:00 2001 From: mibac138 <5672750+mibac138@users.noreply.github.com> Date: Thu, 6 May 2021 14:33:23 +0200 Subject: [PATCH 3/3] Fix impl type parameter suggestion involving consts --- .../rustc_resolve/src/late/diagnostics.rs | 9 +++- src/test/ui/const-generics/diagnostics.stderr | 4 +- .../missing-items/missing-type-parameter2.rs | 6 ++- .../missing-type-parameter2.stderr | 54 +++++++++++++++---- 4 files changed, 60 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index a4bf19aab95..28d636ef1b2 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -6,7 +6,10 @@ use crate::{CrateLint, Module, ModuleKind, ModuleOrUniformRoot}; use crate::{PathResult, PathSource, Segment}; use rustc_ast::visit::FnKind; -use rustc_ast::{self as ast, Expr, ExprKind, Item, ItemKind, NodeId, Path, Ty, TyKind}; +use rustc_ast::{ + self as ast, Expr, ExprKind, GenericParam, GenericParamKind, Item, ItemKind, NodeId, Path, Ty, + TyKind, +}; use rustc_ast_pretty::pprust::path_segment_to_string; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder}; @@ -1635,6 +1638,10 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { let (span, sugg) = if let [.., param] = &generics.params[..] { let span = if let [.., bound] = ¶m.bounds[..] { bound.span() + } else if let GenericParam { + kind: GenericParamKind::Const { ty, kw_span: _, default }, .. + } = param { + default.as_ref().map(|def| def.value.span).unwrap_or(ty.span) } else { param.ident.span }; diff --git a/src/test/ui/const-generics/diagnostics.stderr b/src/test/ui/const-generics/diagnostics.stderr index 983cb52f3ff..2e3132c2eb7 100644 --- a/src/test/ui/const-generics/diagnostics.stderr +++ b/src/test/ui/const-generics/diagnostics.stderr @@ -31,8 +31,8 @@ LL | impl Foo for C {} | ^ help: you might be missing a type parameter | -LL | impl Foo for C {} - | ^^^ +LL | impl Foo for C {} + | ^^^ error[E0747]: unresolved item provided when a constant was expected --> $DIR/diagnostics.rs:7:16 diff --git a/src/test/ui/missing/missing-items/missing-type-parameter2.rs b/src/test/ui/missing/missing-items/missing-type-parameter2.rs index e5d90bb6ff0..15dc5ef797b 100644 --- a/src/test/ui/missing/missing-items/missing-type-parameter2.rs +++ b/src/test/ui/missing/missing-items/missing-type-parameter2.rs @@ -11,7 +11,11 @@ impl X {} //~| ERROR defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions //~| ERROR unresolved item provided when a constant was expected -fn bar(a: A) {} +fn foo(_: T) where T: Send {} +//~^ ERROR cannot find type `T` in this scope +//~| ERROR cannot find type `T` in this scope + +fn bar(_: A) {} //~^ ERROR cannot find type `A` in this scope fn main() { diff --git a/src/test/ui/missing/missing-items/missing-type-parameter2.stderr b/src/test/ui/missing/missing-items/missing-type-parameter2.stderr index 545be1c34fb..985a9bb2a3f 100644 --- a/src/test/ui/missing/missing-items/missing-type-parameter2.stderr +++ b/src/test/ui/missing/missing-items/missing-type-parameter2.stderr @@ -30,26 +30,62 @@ LL | impl X {} | ^ help: you might be missing a type parameter | -LL | impl X {} - | ^^^ +LL | impl X {} + | ^^^ -error[E0412]: cannot find type `A` in this scope - --> $DIR/missing-type-parameter2.rs:14:24 +error[E0412]: cannot find type `T` in this scope + --> $DIR/missing-type-parameter2.rs:14:20 | LL | struct X(); | ------------------------ similarly named struct `X` defined here ... -LL | fn bar(a: A) {} +LL | fn foo(_: T) where T: Send {} + | ^ + | +help: a struct with a similar name exists + | +LL | fn foo(_: T) where X: Send {} + | ^ +help: you might be missing a type parameter + | +LL | fn foo(_: T) where T: Send {} + | ^^^ + +error[E0412]: cannot find type `T` in this scope + --> $DIR/missing-type-parameter2.rs:14:11 + | +LL | struct X(); + | ------------------------ similarly named struct `X` defined here +... +LL | fn foo(_: T) where T: Send {} + | ^ + | +help: a struct with a similar name exists + | +LL | fn foo(_: X) where T: Send {} + | ^ +help: you might be missing a type parameter + | +LL | fn foo(_: T) where T: Send {} + | ^^^ + +error[E0412]: cannot find type `A` in this scope + --> $DIR/missing-type-parameter2.rs:18:24 + | +LL | struct X(); + | ------------------------ similarly named struct `X` defined here +... +LL | fn bar(_: A) {} | ^ | help: a struct with a similar name exists | -LL | fn bar(a: X) {} +LL | fn bar(_: X) {} | ^ help: you might be missing a type parameter | -LL | fn bar(a: A) {} - | ^^^ +LL | fn bar(_: A) {} + | ^^^ error[E0747]: unresolved item provided when a constant was expected --> $DIR/missing-type-parameter2.rs:6:8 @@ -79,7 +115,7 @@ help: if this generic argument was intended as a const parameter, surround it wi LL | impl X<{ N }> {} | ^ ^ -error: aborting due to 6 previous errors +error: aborting due to 8 previous errors Some errors have detailed explanations: E0412, E0747. For more information about an error, try `rustc --explain E0412`.