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:
@@ -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,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -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}>"))
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user