diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs
index 78afc33974826..46928a1846540 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 e74a7a9565080..4cd1b34bedc95 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 0000000000000..800f03302ed38
--- /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> = as Trait>::Foo;
+//~^ ERROR missing lifetime specifier
+//~| NOTE expected named lifetime parameter
+
+type C<'a, 'b> = 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 0000000000000..f1b951fc82632
--- /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> = as Trait>::Foo;
+ | ^^^^^ expected named lifetime parameter
+ |
+help: consider using the `'a` lifetime
+ |
+LL | type B<'a> = as Trait<'a>>::Foo;
+ | ~~~~~~~~~
+
+error[E0106]: missing lifetime specifier
+ --> $DIR/missing-lifetime-in-alias.rs:27:28
+ |
+LL | type C<'a, 'b> = 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> = 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> = 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> = 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 f797c89a03269..a692d6af703ea 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