Suggest new type param on single char ident

Suggest new type parameter on single char uppercase ident even if it
doesn't appear in a field's type parameter.

Address comment in #72641.
This commit is contained in:
Esteban Küber 2020-06-13 12:08:32 -07:00
parent 4606168dd5
commit af45d8a5bb
4 changed files with 61 additions and 15 deletions

View File

@ -919,20 +919,45 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
&self,
path: &[Segment],
) -> Option<(Span, &'static str, String, Applicability)> {
let ident = match path {
[segment] if !segment.has_args => segment.ident,
let (ident, span) = match path {
[segment] if !segment.has_args => (segment.ident.to_string(), segment.ident.span),
_ => return None,
};
match (
self.diagnostic_metadata.current_item,
self.diagnostic_metadata.currently_processing_generics,
) {
(Some(Item { kind: ItemKind::Fn(..), ident, .. }), true) if ident.name == sym::main => {
let mut iter = ident.chars().map(|c| c.is_uppercase());
let single_uppercase_char =
matches!(iter.next(), Some(true)) && matches!(iter.next(), None);
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 => {
// Ignore `fn main()` as we don't want to suggest `fn main<T>()`
}
(Some(Item { kind, .. }), true) => {
(
Some(Item {
kind:
kind @ ItemKind::Fn(..)
| kind @ ItemKind::Enum(..)
| kind @ ItemKind::Struct(..)
| kind @ ItemKind::Union(..),
..
}),
true,
)
| (Some(Item { kind, .. }), false) => {
// Likely missing type parameter.
if let Some(generics) = kind.generics() {
if span.overlaps(generics.span) {
// Avoid the following:
// error[E0405]: cannot find trait `A` in this scope
// --> $DIR/typo-suggestion-named-underscore.rs:CC:LL
// |
// L | fn foo<T: A>(x: T) {} // Shouldn't suggest underscore
// | ^- help: you might be missing a type parameter: `, A`
// | |
// | not found in this scope
return None;
}
let msg = "you might be missing a type parameter";
let (span, sugg) = if let [.., param] = &generics.params[..] {
let span = if let [.., bound] = &param.bounds[..] {

View File

@ -4,7 +4,16 @@ error[E0412]: cannot find type `A` in this scope
LL | fn foo2<I: Foo>(x: I) {
| - similarly named type parameter `I` defined here
LL | let _: A = x.boo();
| ^ help: a type parameter with a similar name exists: `I`
| ^
|
help: a type parameter with a similar name exists
|
LL | let _: I = x.boo();
| ^
help: you might be missing a type parameter
|
LL | fn foo2<I: Foo, A>(x: I) {
| ^^^
error: aborting due to previous error

View File

@ -1,5 +1,9 @@
struct S {
m: Vec<Hashmap<String, ()>>, //~ ERROR cannot find type `Hashmap` in this scope
struct Struct {
m: Vec<Someunknownname<String, ()>>, //~ ERROR cannot find type `Someunknownname` in this scope
//~^ NOTE not found in this scope
}
struct OtherStruct { //~ HELP you might be missing a type parameter
m: K, //~ ERROR cannot find type `K` in this scope
//~^ NOTE not found in this scope
}
fn main() {}

View File

@ -1,9 +1,17 @@
error[E0412]: cannot find type `Hashmap` in this scope
error[E0412]: cannot find type `Someunknownname` in this scope
--> $DIR/type-not-found-in-adt-field.rs:2:12
|
LL | m: Vec<Hashmap<String, ()>>,
| ^^^^^^^ not found in this scope
LL | m: Vec<Someunknownname<String, ()>>,
| ^^^^^^^^^^^^^^^ not found in this scope
error: aborting due to previous error
error[E0412]: cannot find type `K` in this scope
--> $DIR/type-not-found-in-adt-field.rs:6:8
|
LL | struct OtherStruct {
| - help: you might be missing a type parameter: `<K>`
LL | m: K,
| ^ not found in this scope
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0412`.