Skip to content

Commit f4b5f58

Browse files
authored
Rollup merge of #73320 - estebank:type-param-sugg-more, r=davidtwco
Make new type param suggestion more targetted Do not suggest new type param when encountering a missing type in an ADT field with generic parameters. Fix #72640.
2 parents ed92b6a + 8d1a380 commit f4b5f58

File tree

6 files changed

+80
-15
lines changed

6 files changed

+80
-15
lines changed

src/librustc_resolve/build_reduced_graph.rs

+1
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
485485
module_path.push(Segment {
486486
ident: Ident { name: kw::PathRoot, span: source.ident.span },
487487
id: Some(self.r.next_node_id()),
488+
has_generic_args: false,
488489
});
489490
source.ident.name = crate_name;
490491
}

src/librustc_resolve/late/diagnostics.rs

+35-8
Original file line numberDiff line numberDiff line change
@@ -920,20 +920,47 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
920920
&self,
921921
path: &[Segment],
922922
) -> Option<(Span, &'static str, String, Applicability)> {
923-
let ident = match path {
924-
[segment] => segment.ident,
923+
let (ident, span) = match path {
924+
[segment] if !segment.has_generic_args => {
925+
(segment.ident.to_string(), segment.ident.span)
926+
}
925927
_ => return None,
926928
};
927-
match (
928-
self.diagnostic_metadata.current_item,
929-
self.diagnostic_metadata.currently_processing_generics,
930-
) {
931-
(Some(Item { kind: ItemKind::Fn(..), ident, .. }), true) if ident.name == sym::main => {
929+
let mut iter = ident.chars().map(|c| c.is_uppercase());
930+
let single_uppercase_char =
931+
matches!(iter.next(), Some(true)) && matches!(iter.next(), None);
932+
if !self.diagnostic_metadata.currently_processing_generics && !single_uppercase_char {
933+
return None;
934+
}
935+
match (self.diagnostic_metadata.current_item, single_uppercase_char) {
936+
(Some(Item { kind: ItemKind::Fn(..), ident, .. }), _) if ident.name == sym::main => {
932937
// Ignore `fn main()` as we don't want to suggest `fn main<T>()`
933938
}
934-
(Some(Item { kind, .. }), true) => {
939+
(
940+
Some(Item {
941+
kind:
942+
kind @ ItemKind::Fn(..)
943+
| kind @ ItemKind::Enum(..)
944+
| kind @ ItemKind::Struct(..)
945+
| kind @ ItemKind::Union(..),
946+
..
947+
}),
948+
true,
949+
)
950+
| (Some(Item { kind, .. }), false) => {
935951
// Likely missing type parameter.
936952
if let Some(generics) = kind.generics() {
953+
if span.overlaps(generics.span) {
954+
// Avoid the following:
955+
// error[E0405]: cannot find trait `A` in this scope
956+
// --> $DIR/typo-suggestion-named-underscore.rs:CC:LL
957+
// |
958+
// L | fn foo<T: A>(x: T) {} // Shouldn't suggest underscore
959+
// | ^- help: you might be missing a type parameter: `, A`
960+
// | |
961+
// | not found in this scope
962+
return None;
963+
}
937964
let msg = "you might be missing a type parameter";
938965
let (span, sugg) = if let [.., param] = &generics.params[..] {
939966
let span = if let [.., bound] = &param.bounds[..] {

src/librustc_resolve/lib.rs

+8-6
Original file line numberDiff line numberDiff line change
@@ -225,13 +225,15 @@ enum VisResolutionError<'a> {
225225
ModuleOnly(Span),
226226
}
227227

228-
// A minimal representation of a path segment. We use this in resolve because
229-
// we synthesize 'path segments' which don't have the rest of an AST or HIR
230-
// `PathSegment`.
228+
/// A minimal representation of a path segment. We use this in resolve because we synthesize 'path
229+
/// segments' which don't have the rest of an AST or HIR `PathSegment`.
231230
#[derive(Clone, Copy, Debug)]
232231
pub struct Segment {
233232
ident: Ident,
234233
id: Option<NodeId>,
234+
/// Signals whether this `PathSegment` has generic arguments. Used to avoid providing
235+
/// nonsensical suggestions.
236+
has_generic_args: bool,
235237
}
236238

237239
impl Segment {
@@ -240,7 +242,7 @@ impl Segment {
240242
}
241243

242244
fn from_ident(ident: Ident) -> Segment {
243-
Segment { ident, id: None }
245+
Segment { ident, id: None, has_generic_args: false }
244246
}
245247

246248
fn names_to_string(segments: &[Segment]) -> String {
@@ -250,7 +252,7 @@ impl Segment {
250252

251253
impl<'a> From<&'a ast::PathSegment> for Segment {
252254
fn from(seg: &'a ast::PathSegment) -> Segment {
253-
Segment { ident: seg.ident, id: Some(seg.id) }
255+
Segment { ident: seg.ident, id: Some(seg.id), has_generic_args: seg.args.is_some() }
254256
}
255257
}
256258

@@ -2017,7 +2019,7 @@ impl<'a> Resolver<'a> {
20172019
path, opt_ns, record_used, path_span, crate_lint,
20182020
);
20192021

2020-
for (i, &Segment { ident, id }) in path.iter().enumerate() {
2022+
for (i, &Segment { ident, id, has_generic_args: _ }) in path.iter().enumerate() {
20212023
debug!("resolve_path ident {} {:?} {:?}", i, ident, id);
20222024
let record_segment_res = |this: &mut Self, res| {
20232025
if record_used {

src/test/ui/associated-types/associated-types-eq-1.stderr

+10-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,16 @@ error[E0412]: cannot find type `A` in this scope
44
LL | fn foo2<I: Foo>(x: I) {
55
| - similarly named type parameter `I` defined here
66
LL | let _: A = x.boo();
7-
| ^ help: a type parameter with a similar name exists: `I`
7+
| ^
8+
|
9+
help: a type parameter with a similar name exists
10+
|
11+
LL | let _: I = x.boo();
12+
| ^
13+
help: you might be missing a type parameter
14+
|
15+
LL | fn foo2<I: Foo, A>(x: I) {
16+
| ^^^
817

918
error: aborting due to previous error
1019

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
struct Struct {
2+
m: Vec<Someunknownname<String, ()>>, //~ ERROR cannot find type `Someunknownname` in this scope
3+
//~^ NOTE not found in this scope
4+
}
5+
struct OtherStruct { //~ HELP you might be missing a type parameter
6+
m: K, //~ ERROR cannot find type `K` in this scope
7+
//~^ NOTE not found in this scope
8+
}
9+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
error[E0412]: cannot find type `Someunknownname` in this scope
2+
--> $DIR/type-not-found-in-adt-field.rs:2:12
3+
|
4+
LL | m: Vec<Someunknownname<String, ()>>,
5+
| ^^^^^^^^^^^^^^^ not found in this scope
6+
7+
error[E0412]: cannot find type `K` in this scope
8+
--> $DIR/type-not-found-in-adt-field.rs:6:8
9+
|
10+
LL | struct OtherStruct {
11+
| - help: you might be missing a type parameter: `<K>`
12+
LL | m: K,
13+
| ^ not found in this scope
14+
15+
error: aborting due to 2 previous errors
16+
17+
For more information about this error, try `rustc --explain E0412`.

0 commit comments

Comments
 (0)