From 4606168dd508007fb1014b6ab12b27e320e07038 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 13 Jun 2020 11:12:29 -0700 Subject: [PATCH] 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. --- src/librustc_resolve/build_reduced_graph.rs | 1 + src/librustc_resolve/late/diagnostics.rs | 2 +- src/librustc_resolve/lib.rs | 14 ++++++++------ .../ui/suggestions/type-not-found-in-adt-field.rs | 5 +++++ .../suggestions/type-not-found-in-adt-field.stderr | 9 +++++++++ 5 files changed, 24 insertions(+), 7 deletions(-) create mode 100644 src/test/ui/suggestions/type-not-found-in-adt-field.rs create mode 100644 src/test/ui/suggestions/type-not-found-in-adt-field.stderr diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 2ae063660e38..8661af6d7a1d 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -485,6 +485,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { module_path.push(Segment { ident: Ident { name: kw::PathRoot, span: source.ident.span }, id: Some(self.r.next_node_id()), + has_args: false, }); source.ident.name = crate_name; } diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs index b1a1f8725a18..28ff89f66925 100644 --- a/src/librustc_resolve/late/diagnostics.rs +++ b/src/librustc_resolve/late/diagnostics.rs @@ -920,7 +920,7 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> { path: &[Segment], ) -> Option<(Span, &'static str, String, Applicability)> { let ident = match path { - [segment] => segment.ident, + [segment] if !segment.has_args => segment.ident, _ => return None, }; match ( diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 6bd73877fab7..f7ec919fa04e 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -225,13 +225,15 @@ enum VisResolutionError<'a> { ModuleOnly(Span), } -// A minimal representation of a path segment. We use this in resolve because -// we synthesize 'path segments' which don't have the rest of an AST or HIR -// `PathSegment`. +/// A minimal representation of a path segment. We use this in resolve because we synthesize 'path +/// segments' which don't have the rest of an AST or HIR `PathSegment`. #[derive(Clone, Copy, Debug)] pub struct Segment { ident: Ident, id: Option, + /// Signals whether this `PathSegment` has generic arguments. Used to avoid providing + /// nonsensical suggestions. + has_args: bool, } impl Segment { @@ -240,7 +242,7 @@ impl Segment { } fn from_ident(ident: Ident) -> Segment { - Segment { ident, id: None } + Segment { ident, id: None, has_args: false } } fn names_to_string(segments: &[Segment]) -> String { @@ -250,7 +252,7 @@ impl Segment { impl<'a> From<&'a ast::PathSegment> for Segment { fn from(seg: &'a ast::PathSegment) -> Segment { - Segment { ident: seg.ident, id: Some(seg.id) } + Segment { ident: seg.ident, id: Some(seg.id), has_args: seg.args.is_some() } } } @@ -2017,7 +2019,7 @@ impl<'a> Resolver<'a> { path, opt_ns, record_used, path_span, crate_lint, ); - for (i, &Segment { ident, id }) in path.iter().enumerate() { + for (i, &Segment { ident, id, has_args: _ }) in path.iter().enumerate() { debug!("resolve_path ident {} {:?} {:?}", i, ident, id); let record_segment_res = |this: &mut Self, res| { if record_used { diff --git a/src/test/ui/suggestions/type-not-found-in-adt-field.rs b/src/test/ui/suggestions/type-not-found-in-adt-field.rs new file mode 100644 index 000000000000..6bd42472f5a5 --- /dev/null +++ b/src/test/ui/suggestions/type-not-found-in-adt-field.rs @@ -0,0 +1,5 @@ +struct S { + m: Vec>, //~ ERROR cannot find type `Hashmap` in this scope + //~^ NOTE not found in this scope +} +fn main() {} diff --git a/src/test/ui/suggestions/type-not-found-in-adt-field.stderr b/src/test/ui/suggestions/type-not-found-in-adt-field.stderr new file mode 100644 index 000000000000..cfad8c689d03 --- /dev/null +++ b/src/test/ui/suggestions/type-not-found-in-adt-field.stderr @@ -0,0 +1,9 @@ +error[E0412]: cannot find type `Hashmap` in this scope + --> $DIR/type-not-found-in-adt-field.rs:2:12 + | +LL | m: Vec>, + | ^^^^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`.