diff options
| author | Nicholas Nethercote <n.nethercote@gmail.com> | 2025-04-28 19:24:45 +1000 |
|---|---|---|
| committer | Nicholas Nethercote <n.nethercote@gmail.com> | 2025-05-02 08:26:39 +1000 |
| commit | d42edee451b87ce3d7b9de82f43c142592e1e661 (patch) | |
| tree | 399edbc4bbd8816e2ac4ebc4b7dfa9c16ed7ae57 | |
| parent | b2bf951dd60a57b423ab0a3f6b544ff580a08cd1 (diff) | |
| download | rust-d42edee451b87ce3d7b9de82f43c142592e1e661.tar.gz rust-d42edee451b87ce3d7b9de82f43c142592e1e661.zip | |
Handle `Path<>` better in error messages.
`Path<>` needs to be distinguished from `Path<T>`. This commit does that, improving some error messages.
| -rw-r--r-- | compiler/rustc_ast_lowering/src/lib.rs | 10 | ||||
| -rw-r--r-- | compiler/rustc_ast_lowering/src/path.rs | 30 | ||||
| -rw-r--r-- | compiler/rustc_hir/src/hir.rs | 29 | ||||
| -rw-r--r-- | tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr | 18 |
4 files changed, 50 insertions, 37 deletions
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 1e14b4d6723..1844cb2de6c 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -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, ) } diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index fabe40a9d04..5cda64ce7b4 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -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) }), ); diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index af587ee5bdc..58b776bdc6a 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -36,17 +36,23 @@ 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}>")) } diff --git a/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr b/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr index e7dbb06987a..92996ca8467 100644 --- a/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr +++ b/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr @@ -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 |
