about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2021-12-27 14:10:59 -0800
committerMichael Goulet <michael@errs.io>2021-12-27 23:34:52 -0800
commite37d012a0629a20ea9a79efc8434d636f37487d9 (patch)
tree2737a79d8a0ac80682f7f6311008c50e6d965ce8
parent51e8031e14a899477a5e2d78ce461cab31123354 (diff)
downloadrust-e37d012a0629a20ea9a79efc8434d636f37487d9.tar.gz
rust-e37d012a0629a20ea9a79efc8434d636f37487d9.zip
Tighten span when suggesting lifetime on path
-rw-r--r--compiler/rustc_ast_lowering/src/path.rs4
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs9
-rw-r--r--src/test/ui/in-band-lifetimes/missing-lifetime-in-alias.rs34
-rw-r--r--src/test/ui/in-band-lifetimes/missing-lifetime-in-alias.stderr43
-rw-r--r--src/test/ui/lint/reasons.stderr6
5 files changed, 89 insertions, 7 deletions
diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs
index 78afc339748..46928a18465 100644
--- a/compiler/rustc_ast_lowering/src/path.rs
+++ b/compiler/rustc_ast_lowering/src/path.rs
@@ -277,7 +277,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             // See rustc_resolve::late::lifetimes::LifetimeContext::add_missing_lifetime_specifiers_label
             let elided_lifetime_span = if generic_args.span.is_empty() {
                 // If there are no brackets, use the identifier span.
-                path_span
+                // HACK: we use find_ancestor_inside to properly suggest elided spans in paths
+                // originating from macros, since the segment's span might be from a macro arg.
+                segment.ident.span.find_ancestor_inside(path_span).unwrap_or(path_span)
             } else if generic_args.is_empty() {
                 // If there are brackets, but not generic arguments, then use the opening bracket
                 generic_args.span.with_hi(generic_args.span.lo() + BytePos(1))
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index e74a7a95650..4cd1b34bedc 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -2115,10 +2115,13 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
                 let spans_suggs: Vec<_> = formatters
                     .into_iter()
                     .zip(spans_with_counts.iter())
-                    .filter_map(|(fmt, (span, _))| {
-                        if let Some(formatter) = fmt { Some((formatter, span)) } else { None }
+                    .filter_map(|(formatter, (span, _))| {
+                        if let Some(formatter) = formatter {
+                            Some((*span, formatter(name)))
+                        } else {
+                            None
+                        }
                     })
-                    .map(|(formatter, span)| (*span, formatter(name)))
                     .collect();
                 if spans_suggs.is_empty() {
                     // If all the spans come from macros, we cannot extract snippets and then
diff --git a/src/test/ui/in-band-lifetimes/missing-lifetime-in-alias.rs b/src/test/ui/in-band-lifetimes/missing-lifetime-in-alias.rs
new file mode 100644
index 00000000000..800f03302ed
--- /dev/null
+++ b/src/test/ui/in-band-lifetimes/missing-lifetime-in-alias.rs
@@ -0,0 +1,34 @@
+#![feature(generic_associated_types)]
+#![allow(unused)]
+
+trait Trait<'a> {
+    type Foo;
+
+    type Bar<'b>
+    //~^ NOTE associated type defined here, with 1 lifetime parameter
+    //~| NOTE
+    where
+        Self: 'b;
+}
+
+struct Impl<'a>(&'a ());
+
+impl<'a> Trait<'a> for Impl<'a> {
+    type Foo = &'a ();
+    type Bar<'b> = &'b ();
+}
+
+type A<'a> = Impl<'a>;
+
+type B<'a> = <A<'a> as Trait>::Foo;
+//~^ ERROR missing lifetime specifier
+//~| NOTE expected named lifetime parameter
+
+type C<'a, 'b> = <A<'a> as Trait>::Bar;
+//~^ ERROR missing lifetime specifier
+//~| ERROR missing generics for associated type
+//~| NOTE expected named lifetime parameter
+//~| NOTE these named lifetimes are available to use
+//~| NOTE expected 1 lifetime argument
+
+fn main() {}
diff --git a/src/test/ui/in-band-lifetimes/missing-lifetime-in-alias.stderr b/src/test/ui/in-band-lifetimes/missing-lifetime-in-alias.stderr
new file mode 100644
index 00000000000..f1b951fc826
--- /dev/null
+++ b/src/test/ui/in-band-lifetimes/missing-lifetime-in-alias.stderr
@@ -0,0 +1,43 @@
+error[E0106]: missing lifetime specifier
+  --> $DIR/missing-lifetime-in-alias.rs:23:24
+   |
+LL | type B<'a> = <A<'a> as Trait>::Foo;
+   |                        ^^^^^ expected named lifetime parameter
+   |
+help: consider using the `'a` lifetime
+   |
+LL | type B<'a> = <A<'a> as Trait<'a>>::Foo;
+   |                        ~~~~~~~~~
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/missing-lifetime-in-alias.rs:27:28
+   |
+LL | type C<'a, 'b> = <A<'a> as Trait>::Bar;
+   |                            ^^^^^ expected named lifetime parameter
+   |
+note: these named lifetimes are available to use
+  --> $DIR/missing-lifetime-in-alias.rs:27:8
+   |
+LL | type C<'a, 'b> = <A<'a> as Trait>::Bar;
+   |        ^^  ^^
+
+error[E0107]: missing generics for associated type `Trait::Bar`
+  --> $DIR/missing-lifetime-in-alias.rs:27:36
+   |
+LL | type C<'a, 'b> = <A<'a> as Trait>::Bar;
+   |                                    ^^^ expected 1 lifetime argument
+   |
+note: associated type defined here, with 1 lifetime parameter: `'b`
+  --> $DIR/missing-lifetime-in-alias.rs:7:10
+   |
+LL |     type Bar<'b>
+   |          ^^^ --
+help: add missing lifetime argument
+   |
+LL | type C<'a, 'b> = <A<'a> as Trait>::Bar<'a>;
+   |                                    ~~~~~~~
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0106, E0107.
+For more information about an error, try `rustc --explain E0106`.
diff --git a/src/test/ui/lint/reasons.stderr b/src/test/ui/lint/reasons.stderr
index f797c89a032..a692d6af703 100644
--- a/src/test/ui/lint/reasons.stderr
+++ b/src/test/ui/lint/reasons.stderr
@@ -1,8 +1,8 @@
 warning: hidden lifetime parameters in types are deprecated
-  --> $DIR/reasons.rs:20:29
+  --> $DIR/reasons.rs:20:34
    |
 LL |     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
-   |                             ^^^^^^^^^^^^^^ expected named lifetime parameter
+   |                                  ^^^^^^^^^ expected named lifetime parameter
    |
    = note: explicit anonymous lifetimes aid reasoning about ownership
 note: the lint level is defined here
@@ -13,7 +13,7 @@ LL | #![warn(elided_lifetimes_in_paths,
 help: consider using the `'_` lifetime
    |
 LL |     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-   |                             ~~~~~~~~~~~~~~~~~~
+   |                                  ~~~~~~~~~~~~~
 
 warning: variable `Social_exchange_psychology` should have a snake case name
   --> $DIR/reasons.rs:30:9