From 66203adcea6eefa57caaf6e65ecf03fdfa164f98 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Fri, 4 Jul 2025 12:43:49 +0000 Subject: [PATCH] Lower extra lifetimes before normal generic params. --- compiler/rustc_ast_lowering/src/lib.rs | 29 +++++++++----- .../elided-lifetime-in-const-param-type.rs | 13 ++++++ ...elided-lifetime-in-const-param-type.stderr | 40 +++++++++++++++++++ 3 files changed, 71 insertions(+), 11 deletions(-) create mode 100644 tests/ui/lifetimes/elided-lifetime-in-const-param-type.rs create mode 100644 tests/ui/lifetimes/elided-lifetime-in-const-param-type.stderr diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 0706bdb119f01..c71021ccdda46 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -851,25 +851,32 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { /// name resolver owing to lifetime elision; this also populates the resolver's node-id->def-id /// map, so that later calls to `opt_node_id_to_def_id` that refer to these extra lifetime /// parameters will be successful. - #[instrument(level = "debug", skip(self))] + #[instrument(level = "debug", skip(self), ret)] #[inline] fn lower_lifetime_binder( &mut self, binder: NodeId, generic_params: &[GenericParam], ) -> &'hir [hir::GenericParam<'hir>] { - let mut generic_params: Vec<_> = self - .lower_generic_params_mut(generic_params, hir::GenericParamSource::Binder) - .collect(); + // Start by creating params for extra lifetimes params, as this creates the definitions + // that may be referred to by the AST inside `generic_params`. let extra_lifetimes = self.resolver.extra_lifetime_params(binder); debug!(?extra_lifetimes); - generic_params.extend(extra_lifetimes.into_iter().filter_map(|(ident, node_id, res)| { - self.lifetime_res_to_generic_param(ident, node_id, res, hir::GenericParamSource::Binder) - })); - let generic_params = self.arena.alloc_from_iter(generic_params); - debug!(?generic_params); - - generic_params + let extra_lifetimes: Vec<_> = extra_lifetimes + .into_iter() + .filter_map(|(ident, node_id, res)| { + self.lifetime_res_to_generic_param( + ident, + node_id, + res, + hir::GenericParamSource::Binder, + ) + }) + .collect(); + let arena = self.arena; + let explicit_generic_params = + self.lower_generic_params_mut(generic_params, hir::GenericParamSource::Binder); + arena.alloc_from_iter(explicit_generic_params.chain(extra_lifetimes.into_iter())) } fn with_dyn_type_scope(&mut self, in_scope: bool, f: impl FnOnce(&mut Self) -> T) -> T { diff --git a/tests/ui/lifetimes/elided-lifetime-in-const-param-type.rs b/tests/ui/lifetimes/elided-lifetime-in-const-param-type.rs new file mode 100644 index 0000000000000..3ae2ffc11df58 --- /dev/null +++ b/tests/ui/lifetimes/elided-lifetime-in-const-param-type.rs @@ -0,0 +1,13 @@ +//! Regression test for +//! The anonymous lifetime in `c(&())` is desugared by the resolver as an extra lifetime parameter +//! at the end of the `for` binder. Verify that lowering creates the definition for that extra +//! lifetime parameter before lowering `c(&())`. + +type A = for D; +//~^ ERROR cannot find type `c` in this scope +//~| ERROR cannot find trait `D` in this scope +//~| ERROR only lifetime parameters can be used in this context +//~| WARN trait objects without an explicit `dyn` are deprecated +//~| WARN this is accepted in the current edition + +fn main() {} diff --git a/tests/ui/lifetimes/elided-lifetime-in-const-param-type.stderr b/tests/ui/lifetimes/elided-lifetime-in-const-param-type.stderr new file mode 100644 index 0000000000000..3ccbb07014b8c --- /dev/null +++ b/tests/ui/lifetimes/elided-lifetime-in-const-param-type.stderr @@ -0,0 +1,40 @@ +error[E0412]: cannot find type `c` in this scope + --> $DIR/elided-lifetime-in-const-param-type.rs:6:23 + | +LL | type A = for D; + | ^ not found in this scope + +error[E0405]: cannot find trait `D` in this scope + --> $DIR/elided-lifetime-in-const-param-type.rs:6:31 + | +LL | type A = for D; + | ^ not found in this scope + +error[E0658]: only lifetime parameters can be used in this context + --> $DIR/elided-lifetime-in-const-param-type.rs:6:20 + | +LL | type A = for D; + | ^ + | + = note: see issue #108185 for more information + = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/elided-lifetime-in-const-param-type.rs:6:10 + | +LL | type A = for D; + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + = note: `#[warn(bare_trait_objects)]` on by default +help: if this is a dyn-compatible trait, use `dyn` + | +LL | type A = dyn for D; + | +++ + +error: aborting due to 3 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0405, E0412, E0658. +For more information about an error, try `rustc --explain E0405`.