Handle Path<> better in error messages.

`Path<>` needs to be distinguished from `Path<T>`. This commit does
that, improving some error messages.
This commit is contained in:
Nicholas Nethercote
2025-04-28 19:24:45 +10:00
parent b2bf951dd6
commit d42edee451
4 changed files with 50 additions and 37 deletions

View File

@@ -54,8 +54,8 @@ use rustc_errors::{DiagArgFromDisplay, DiagCtxtHandle, StashKey};
use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res};
use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId};
use rustc_hir::{
self as hir, ConstArg, GenericArg, HirId, ItemLocalMap, LangItem, LifetimeSource,
LifetimeSyntax, ParamName, TraitCandidate,
self as hir, AngleBrackets, ConstArg, GenericArg, HirId, ItemLocalMap, LangItem,
LifetimeSource, LifetimeSyntax, ParamName, TraitCandidate,
};
use rustc_index::{Idx, IndexSlice, IndexVec};
use rustc_macros::extension;
@@ -1081,7 +1081,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
match arg {
ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(
lt,
LifetimeSource::Path { with_angle_brackets: true },
LifetimeSource::Path { angle_brackets: hir::AngleBrackets::Full },
lt.ident.into(),
)),
ast::GenericArg::Type(ty) => {
@@ -1773,13 +1773,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
&mut self,
id: NodeId,
span: Span,
with_angle_brackets: bool,
angle_brackets: AngleBrackets,
) -> &'hir hir::Lifetime {
self.new_named_lifetime(
id,
id,
Ident::new(kw::UnderscoreLifetime, span),
LifetimeSource::Path { with_angle_brackets },
LifetimeSource::Path { angle_brackets },
LifetimeSyntax::Hidden,
)
}

View File

@@ -432,27 +432,31 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// Note: these spans are used for diagnostics when they can't be inferred.
// See rustc_resolve::late::lifetimes::LifetimeContext::add_missing_lifetime_specifiers_label
let (elided_lifetime_span, with_angle_brackets) = if generic_args.span.is_empty() {
// If there are no brackets, use the identifier span.
let (elided_lifetime_span, angle_brackets) = if generic_args.span.is_empty() {
// No brackets, e.g. `Path`: use an empty span just past the end of the identifier.
// 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), false)
} 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)), true)
(
segment_ident_span.find_ancestor_inside(path_span).unwrap_or(path_span),
hir::AngleBrackets::Missing,
)
} else {
// Else use an empty span right after the opening bracket.
(generic_args.span.with_lo(generic_args.span.lo() + BytePos(1)).shrink_to_lo(), true)
// Brackets, e.g. `Path<>` or `Path<T>`: use an empty span just after the `<`.
(
generic_args.span.with_lo(generic_args.span.lo() + BytePos(1)).shrink_to_lo(),
if generic_args.is_empty() {
hir::AngleBrackets::Empty
} else {
hir::AngleBrackets::Full
},
)
};
generic_args.args.insert_many(
0,
(start..end).map(|id| {
let l = self.lower_lifetime_hidden_in_path(
id,
elided_lifetime_span,
with_angle_brackets,
);
let l =
self.lower_lifetime_hidden_in_path(id, elided_lifetime_span, angle_brackets);
GenericArg::Lifetime(l)
}),
);

View File

@@ -35,18 +35,24 @@ use crate::def_id::{DefId, LocalDefIdMap};
pub(crate) use crate::hir_id::{HirId, ItemLocalId, ItemLocalMap, OwnerId};
use crate::intravisit::{FnKind, VisitorExt};
#[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable_Generic)]
pub enum AngleBrackets {
/// E.g. `Path`.
Missing,
/// E.g. `Path<>`.
Empty,
/// E.g. `Path<T>`.
Full,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable_Generic)]
pub enum LifetimeSource {
/// E.g. `&Type`, `&'_ Type`, `&'a Type`, `&mut Type`, `&'_ mut Type`, `&'a mut Type`
Reference,
/// E.g. `ContainsLifetime`, `ContainsLifetime<'_>`, `ContainsLifetime<'a>`
Path {
/// - true for `ContainsLifetime<'_>`, `ContainsLifetime<'a>`,
/// `ContainsLifetime<'_, T>`, `ContainsLifetime<'a, T>`
/// - false for `ContainsLifetime`
with_angle_brackets: bool,
},
/// E.g. `ContainsLifetime`, `ContainsLifetime<>`, `ContainsLifetime<'_>`,
/// `ContainsLifetime<'a>`
Path { angle_brackets: AngleBrackets },
/// E.g. `impl Trait + '_`, `impl Trait + 'a`
OutlivesBound,
@@ -304,12 +310,17 @@ impl Lifetime {
(Named | Anonymous, _) => (self.ident.span, format!("{new_lifetime}")),
// The user wrote `Path<T>`, and omitted the `'_,`.
(Hidden, Path { with_angle_brackets: true }) => {
(Hidden, Path { angle_brackets: AngleBrackets::Full }) => {
(self.ident.span, format!("{new_lifetime}, "))
}
// The user wrote `Path<>`, and omitted the `'_`..
(Hidden, Path { angle_brackets: AngleBrackets::Empty }) => {
(self.ident.span, format!("{new_lifetime}"))
}
// The user wrote `Path` and omitted the `<'_>`.
(Hidden, Path { with_angle_brackets: false }) => {
(Hidden, Path { angle_brackets: AngleBrackets::Missing }) => {
(self.ident.span.shrink_to_hi(), format!("<{new_lifetime}>"))
}

View File

@@ -238,32 +238,30 @@ LL | fn g<'a>(mut x: impl Foo<'a>) -> Option<&()> { x.next() }
| ++++ ++++
error[E0658]: anonymous lifetimes in `impl Trait` are unstable
--> $DIR/impl-trait-missing-lifetime-gated.rs:55:21
--> $DIR/impl-trait-missing-lifetime-gated.rs:55:22
|
LL | fn f(_: impl Foo<>) {}
| ^ expected named lifetime parameter
| ^ expected named lifetime parameter
|
= help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
help: consider introducing a named lifetime parameter
|
LL - fn f(_: impl Foo<>) {}
LL + fn f<'a>(_: impl Foo'a, >) {}
|
LL | fn f<'a>(_: impl Foo<'a>) {}
| ++++ ++
error[E0658]: anonymous lifetimes in `impl Trait` are unstable
--> $DIR/impl-trait-missing-lifetime-gated.rs:58:25
--> $DIR/impl-trait-missing-lifetime-gated.rs:58:26
|
LL | fn g(mut x: impl Foo<>) -> Option<&()> { x.next() }
| ^ expected named lifetime parameter
| ^ expected named lifetime parameter
|
= help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
help: consider introducing a named lifetime parameter
|
LL - fn g(mut x: impl Foo<>) -> Option<&()> { x.next() }
LL + fn g<'a>(mut x: impl Foo'a, >) -> Option<&()> { x.next() }
|
LL | fn g<'a>(mut x: impl Foo<'a>) -> Option<&()> { x.next() }
| ++++ ++
error[E0658]: anonymous lifetimes in `impl Trait` are unstable
--> $DIR/impl-trait-missing-lifetime-gated.rs:66:22