about summary refs log tree commit diff
diff options
context:
space:
mode:
author许杰友 Jieyou Xu (Joe) <39484203+jieyouxu@users.noreply.github.com>2025-07-22 00:54:25 +0800
committerGitHub <noreply@github.com>2025-07-22 00:54:25 +0800
commita99f3af990d7fff74765f4b3cbf6f313a225e2ea (patch)
tree1fdfc00cf2a11dea47eaa34bc363a9dc8a932013
parent5e3eb2512591df0cef52404f0ea4202f58935a54 (diff)
parent7da6fd1221636354139fb92297788b0b5d6b9ca2 (diff)
downloadrust-a99f3af990d7fff74765f4b3cbf6f313a225e2ea.tar.gz
rust-a99f3af990d7fff74765f4b3cbf6f313a225e2ea.zip
Rollup merge of #143430 - cjgillot:extra-lifetime-swap, r=oli-obk
Lower extra lifetimes before normal generic params.

Fixes https://github.com/rust-lang/rust/issues/143413
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs29
-rw-r--r--tests/ui/lifetimes/elided-lifetime-in-const-param-type.rs12
-rw-r--r--tests/ui/lifetimes/elided-lifetime-in-const-param-type.stderr20
3 files changed, 50 insertions, 11 deletions
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 533ee9bff54..9aef189a29d 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -874,25 +874,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<T>(&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 00000000000..cdfd1327eae
--- /dev/null
+++ b/tests/ui/lifetimes/elided-lifetime-in-const-param-type.rs
@@ -0,0 +1,12 @@
+//! Regression test for <https://github.com/rust-lang/rust/issues/143413>
+//! 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(&())`.
+
+trait D {}
+
+type A = dyn for<const B: c(&())> D;
+//~^ ERROR cannot find type `c` in this scope
+//~| ERROR only lifetime parameters can be used in this context
+
+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 00000000000..c7f3c0cc0cd
--- /dev/null
+++ b/tests/ui/lifetimes/elided-lifetime-in-const-param-type.stderr
@@ -0,0 +1,20 @@
+error[E0412]: cannot find type `c` in this scope
+  --> $DIR/elided-lifetime-in-const-param-type.rs:8:27
+   |
+LL | type A = dyn for<const B: c(&())> 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:8:24
+   |
+LL | type A = dyn for<const B: c(&())> D;
+   |                        ^
+   |
+   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/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
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0412, E0658.
+For more information about an error, try `rustc --explain E0412`.