about summary refs log tree commit diff
path: root/compiler/rustc_resolve/src
diff options
context:
space:
mode:
authorLeón Orell Valerian Liehr <liehr.exchange@gmx.net>2022-08-10 14:06:27 +0200
committerLeón Orell Valerian Liehr <liehr.exchange@gmx.net>2022-08-11 23:09:39 +0200
commit0fb4ef6769dd2f5ccb3daf1e84c0afe75ca8c118 (patch)
tree2fe698e361932eccceca68e3c5b730db2ca9ba2b /compiler/rustc_resolve/src
parent20ffea6938b5839c390252e07940b99e3b6a889a (diff)
downloadrust-0fb4ef6769dd2f5ccb3daf1e84c0afe75ca8c118.tar.gz
rust-0fb4ef6769dd2f5ccb3daf1e84c0afe75ca8c118.zip
Suggest path separator when a dot is used on a trait
Diffstat (limited to 'compiler/rustc_resolve/src')
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs53
1 files changed, 37 insertions, 16 deletions
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index cb133841bca..09c1f44826f 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -985,27 +985,45 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
         let ns = source.namespace();
         let is_expected = &|res| source.is_expected(res);
 
-        let path_sep = |err: &mut Diagnostic, expr: &Expr| match expr.kind {
-            ExprKind::Field(_, ident) => {
+        let path_sep = |err: &mut Diagnostic, expr: &Expr, kind: DefKind| {
+            const MESSAGE: &str = "use the path separator to refer to an item";
+
+            let (lhs_span, rhs_span) = match &expr.kind {
+                ExprKind::Field(base, ident) => (base.span, ident.span),
+                ExprKind::MethodCall(_, receiver, _, span) => (receiver.span, *span),
+                _ => return false,
+            };
+
+            if lhs_span.eq_ctxt(rhs_span) {
                 err.span_suggestion(
-                    expr.span,
-                    "use the path separator to refer to an item",
-                    format!("{}::{}", path_str, ident),
+                    lhs_span.between(rhs_span),
+                    MESSAGE,
+                    "::",
                     Applicability::MaybeIncorrect,
                 );
                 true
-            }
-            ExprKind::MethodCall(ref segment, ..) => {
-                let span = expr.span.with_hi(segment.ident.span.hi());
-                err.span_suggestion(
-                    span,
-                    "use the path separator to refer to an item",
-                    format!("{}::{}", path_str, segment.ident),
+            } else if kind == DefKind::Struct
+            && let Some(lhs_source_span) = lhs_span.find_ancestor_inside(expr.span)
+            && let Ok(snippet) = self.r.session.source_map().span_to_snippet(lhs_source_span)
+            {
+                // The LHS is a type that originates from a macro call.
+                // We have to add angle brackets around it.
+
+                err.span_suggestion_verbose(
+                    lhs_source_span.until(rhs_span),
+                    MESSAGE,
+                    format!("<{snippet}>::"),
                     Applicability::MaybeIncorrect,
                 );
                 true
+            } else {
+                // Either we were unable to obtain the source span / the snippet or
+                // the LHS originates from a macro call and it is not a type and thus
+                // there is no way to replace `.` with `::` and still somehow suggest
+                // valid Rust code.
+
+                false
             }
-            _ => false,
         };
 
         let find_span = |source: &PathSource<'_>, err: &mut Diagnostic| {
@@ -1027,7 +1045,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
             match source {
                 PathSource::Expr(Some(
                     parent @ Expr { kind: ExprKind::Field(..) | ExprKind::MethodCall(..), .. },
-                )) if path_sep(err, &parent) => {}
+                )) if path_sep(err, &parent, DefKind::Struct) => {}
                 PathSource::Expr(
                     None
                     | Some(Expr {
@@ -1143,8 +1161,11 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
                     }
                 }
             }
-            (Res::Def(DefKind::Mod, _), PathSource::Expr(Some(parent))) => {
-                if !path_sep(err, &parent) {
+            (
+                Res::Def(kind @ (DefKind::Mod | DefKind::Trait), _),
+                PathSource::Expr(Some(parent)),
+            ) => {
+                if !path_sep(err, &parent, kind) {
                     return false;
                 }
             }