Skip to content

Commit d42edee

Browse files
committed
Handle Path<> better in error messages.
`Path<>` needs to be distinguished from `Path<T>`. This commit does that, improving some error messages.
1 parent b2bf951 commit d42edee

File tree

4 files changed

+50
-37
lines changed

4 files changed

+50
-37
lines changed

compiler/rustc_ast_lowering/src/lib.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@ use rustc_errors::{DiagArgFromDisplay, DiagCtxtHandle, StashKey};
5454
use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res};
5555
use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId};
5656
use rustc_hir::{
57-
self as hir, ConstArg, GenericArg, HirId, ItemLocalMap, LangItem, LifetimeSource,
58-
LifetimeSyntax, ParamName, TraitCandidate,
57+
self as hir, AngleBrackets, ConstArg, GenericArg, HirId, ItemLocalMap, LangItem,
58+
LifetimeSource, LifetimeSyntax, ParamName, TraitCandidate,
5959
};
6060
use rustc_index::{Idx, IndexSlice, IndexVec};
6161
use rustc_macros::extension;
@@ -1081,7 +1081,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
10811081
match arg {
10821082
ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(
10831083
lt,
1084-
LifetimeSource::Path { with_angle_brackets: true },
1084+
LifetimeSource::Path { angle_brackets: hir::AngleBrackets::Full },
10851085
lt.ident.into(),
10861086
)),
10871087
ast::GenericArg::Type(ty) => {
@@ -1773,13 +1773,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
17731773
&mut self,
17741774
id: NodeId,
17751775
span: Span,
1776-
with_angle_brackets: bool,
1776+
angle_brackets: AngleBrackets,
17771777
) -> &'hir hir::Lifetime {
17781778
self.new_named_lifetime(
17791779
id,
17801780
id,
17811781
Ident::new(kw::UnderscoreLifetime, span),
1782-
LifetimeSource::Path { with_angle_brackets },
1782+
LifetimeSource::Path { angle_brackets },
17831783
LifetimeSyntax::Hidden,
17841784
)
17851785
}

compiler/rustc_ast_lowering/src/path.rs

+17-13
Original file line numberDiff line numberDiff line change
@@ -432,27 +432,31 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
432432

433433
// Note: these spans are used for diagnostics when they can't be inferred.
434434
// See rustc_resolve::late::lifetimes::LifetimeContext::add_missing_lifetime_specifiers_label
435-
let (elided_lifetime_span, with_angle_brackets) = if generic_args.span.is_empty() {
436-
// If there are no brackets, use the identifier span.
435+
let (elided_lifetime_span, angle_brackets) = if generic_args.span.is_empty() {
436+
// No brackets, e.g. `Path`: use an empty span just past the end of the identifier.
437437
// HACK: we use find_ancestor_inside to properly suggest elided spans in paths
438438
// originating from macros, since the segment's span might be from a macro arg.
439-
(segment_ident_span.find_ancestor_inside(path_span).unwrap_or(path_span), false)
440-
} else if generic_args.is_empty() {
441-
// If there are brackets, but not generic arguments, then use the opening bracket
442-
(generic_args.span.with_hi(generic_args.span.lo() + BytePos(1)), true)
439+
(
440+
segment_ident_span.find_ancestor_inside(path_span).unwrap_or(path_span),
441+
hir::AngleBrackets::Missing,
442+
)
443443
} else {
444-
// Else use an empty span right after the opening bracket.
445-
(generic_args.span.with_lo(generic_args.span.lo() + BytePos(1)).shrink_to_lo(), true)
444+
// Brackets, e.g. `Path<>` or `Path<T>`: use an empty span just after the `<`.
445+
(
446+
generic_args.span.with_lo(generic_args.span.lo() + BytePos(1)).shrink_to_lo(),
447+
if generic_args.is_empty() {
448+
hir::AngleBrackets::Empty
449+
} else {
450+
hir::AngleBrackets::Full
451+
},
452+
)
446453
};
447454

448455
generic_args.args.insert_many(
449456
0,
450457
(start..end).map(|id| {
451-
let l = self.lower_lifetime_hidden_in_path(
452-
id,
453-
elided_lifetime_span,
454-
with_angle_brackets,
455-
);
458+
let l =
459+
self.lower_lifetime_hidden_in_path(id, elided_lifetime_span, angle_brackets);
456460
GenericArg::Lifetime(l)
457461
}),
458462
);

compiler/rustc_hir/src/hir.rs

+20-9
Original file line numberDiff line numberDiff line change
@@ -35,18 +35,24 @@ use crate::def_id::{DefId, LocalDefIdMap};
3535
pub(crate) use crate::hir_id::{HirId, ItemLocalId, ItemLocalMap, OwnerId};
3636
use crate::intravisit::{FnKind, VisitorExt};
3737

38+
#[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable_Generic)]
39+
pub enum AngleBrackets {
40+
/// E.g. `Path`.
41+
Missing,
42+
/// E.g. `Path<>`.
43+
Empty,
44+
/// E.g. `Path<T>`.
45+
Full,
46+
}
47+
3848
#[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable_Generic)]
3949
pub enum LifetimeSource {
4050
/// E.g. `&Type`, `&'_ Type`, `&'a Type`, `&mut Type`, `&'_ mut Type`, `&'a mut Type`
4151
Reference,
4252

43-
/// E.g. `ContainsLifetime`, `ContainsLifetime<'_>`, `ContainsLifetime<'a>`
44-
Path {
45-
/// - true for `ContainsLifetime<'_>`, `ContainsLifetime<'a>`,
46-
/// `ContainsLifetime<'_, T>`, `ContainsLifetime<'a, T>`
47-
/// - false for `ContainsLifetime`
48-
with_angle_brackets: bool,
49-
},
53+
/// E.g. `ContainsLifetime`, `ContainsLifetime<>`, `ContainsLifetime<'_>`,
54+
/// `ContainsLifetime<'a>`
55+
Path { angle_brackets: AngleBrackets },
5056

5157
/// E.g. `impl Trait + '_`, `impl Trait + 'a`
5258
OutlivesBound,
@@ -304,12 +310,17 @@ impl Lifetime {
304310
(Named | Anonymous, _) => (self.ident.span, format!("{new_lifetime}")),
305311

306312
// The user wrote `Path<T>`, and omitted the `'_,`.
307-
(Hidden, Path { with_angle_brackets: true }) => {
313+
(Hidden, Path { angle_brackets: AngleBrackets::Full }) => {
308314
(self.ident.span, format!("{new_lifetime}, "))
309315
}
310316

317+
// The user wrote `Path<>`, and omitted the `'_`..
318+
(Hidden, Path { angle_brackets: AngleBrackets::Empty }) => {
319+
(self.ident.span, format!("{new_lifetime}"))
320+
}
321+
311322
// The user wrote `Path` and omitted the `<'_>`.
312-
(Hidden, Path { with_angle_brackets: false }) => {
323+
(Hidden, Path { angle_brackets: AngleBrackets::Missing }) => {
313324
(self.ident.span.shrink_to_hi(), format!("<{new_lifetime}>"))
314325
}
315326

tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr

+8-10
Original file line numberDiff line numberDiff line change
@@ -238,32 +238,30 @@ LL | fn g<'a>(mut x: impl Foo<'a>) -> Option<&()> { x.next() }
238238
| ++++ ++++
239239

240240
error[E0658]: anonymous lifetimes in `impl Trait` are unstable
241-
--> $DIR/impl-trait-missing-lifetime-gated.rs:55:21
241+
--> $DIR/impl-trait-missing-lifetime-gated.rs:55:22
242242
|
243243
LL | fn f(_: impl Foo<>) {}
244-
| ^ expected named lifetime parameter
244+
| ^ expected named lifetime parameter
245245
|
246246
= help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable
247247
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
248248
help: consider introducing a named lifetime parameter
249249
|
250-
LL - fn f(_: impl Foo<>) {}
251-
LL + fn f<'a>(_: impl Foo'a, >) {}
252-
|
250+
LL | fn f<'a>(_: impl Foo<'a>) {}
251+
| ++++ ++
253252

254253
error[E0658]: anonymous lifetimes in `impl Trait` are unstable
255-
--> $DIR/impl-trait-missing-lifetime-gated.rs:58:25
254+
--> $DIR/impl-trait-missing-lifetime-gated.rs:58:26
256255
|
257256
LL | fn g(mut x: impl Foo<>) -> Option<&()> { x.next() }
258-
| ^ expected named lifetime parameter
257+
| ^ expected named lifetime parameter
259258
|
260259
= help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable
261260
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
262261
help: consider introducing a named lifetime parameter
263262
|
264-
LL - fn g(mut x: impl Foo<>) -> Option<&()> { x.next() }
265-
LL + fn g<'a>(mut x: impl Foo'a, >) -> Option<&()> { x.next() }
266-
|
263+
LL | fn g<'a>(mut x: impl Foo<'a>) -> Option<&()> { x.next() }
264+
| ++++ ++
267265

268266
error[E0658]: anonymous lifetimes in `impl Trait` are unstable
269267
--> $DIR/impl-trait-missing-lifetime-gated.rs:66:22

0 commit comments

Comments
 (0)