Repository: rust-lang/rust
Pull request: delegation: don't propagate synthetic params, remove lifetime hacks

Some small fixes after new delegation lowering was merged: remove lifetime hacks as now we get only early-bound lifetimes from generics, don't propagate synthetic generic params as now we know that they are synthetic. Fixes rust-lang/rust#143498. Part of rust-lang/rust#118212.

r? @petrochenkov

Changed files:
filename: compiler/rustc_ast_lowering/src/delegation/generics.rs
patch: @@ -337,7 +337,6 @@ impl<'hir, R: ResolverAstLoweringExt<'hir>> LoweringContext<'_, 'hir, R> {
         // HACK: for now we generate predicates such that all lifetimes are early bound,
         // we can not not generate early-bound lifetimes, but we can't know which of them
         // are late-bound at this level of compilation.
-        // FIXME(fn_delegation): proper support for late bound lifetimes.
         let predicates =
             self.arena.alloc_from_iter(params.iter().filter_map(|p| {
                 p.is_lifetime().then(|| self.generate_lifetime_predicate(p, span))
@@ -391,7 +390,7 @@ impl<'hir, R: ResolverAstLoweringExt<'hir>> LoweringContext<'_, 'hir, R> {
         self.arena.alloc(hir::GenericArgs {
             args: self.arena.alloc_from_iter(params.iter().filter_map(|p| {
                 // Skip self generic arg, we do not need to propagate it.
-                if p.name.ident().name == kw::SelfUpper {
+                if p.name.ident().name == kw::SelfUpper || p.is_impl_trait() {
                     return None;
                 }
 

filename: compiler/rustc_hir_analysis/src/delegation.rs
patch: @@ -138,7 +138,6 @@ fn create_mapping<'tcx>(
     tcx: TyCtxt<'tcx>,
     sig_id: DefId,
     def_id: LocalDefId,
-    args: &[ty::GenericArg<'tcx>],
 ) -> FxHashMap<u32, u32> {
     let mut mapping: FxHashMap<u32, u32> = Default::default();
 
@@ -176,13 +175,6 @@ fn create_mapping<'tcx>(
         }
     }
 
-    // If there are still unmapped lifetimes left and we are to map types and maybe self
-    // then skip them, now it is the case when we generated more lifetimes then needed.
-    // FIXME(fn_delegation): proper support for late bound lifetimes.
-    while args_index < args.len() && args[args_index].as_region().is_some() {
-        args_index += 1;
-    }
-
     // If self after lifetimes insert mapping, relying that self is at 0 in sig parent.
     if matches!(self_pos_kind, SelfPositionKind::AfterLifetimes) {
         mapping.insert(0, args_index as u32);
@@ -511,7 +503,7 @@ fn create_folder_and_args<'tcx>(
     child_args: &'tcx [ty::GenericArg<'tcx>],
 ) -> (ParamIndexRemapper<'tcx>, Vec<ty::GenericArg<'tcx>>) {
     let args = create_generic_args(tcx, sig_id, def_id, parent_args, child_args);
-    let remap_table = create_mapping(tcx, sig_id, def_id, &args);
+    let remap_table = create_mapping(tcx, sig_id, def_id);
 
     (ParamIndexRemapper { tcx, remap_table }, args)
 }

filename: tests/ui/delegation/generics/mapping/free-to-free-pass.rs
patch: @@ -78,18 +78,16 @@ mod test_6 {
     }
 }
 
-// FIXME(fn_delegation): Uncomment this test when impl Traits in function params are supported
-
-// mod test_7 {
-//     fn foo<T, U>(t: T, u: U, f: impl FnOnce(T, U) -> U) -> U {
-//         f(t, u)
-//     }
+mod test_7 {
+    fn foo<T, U>(t: T, u: U, f: impl FnOnce(T, U) -> U) -> U {
+        f(t, u)
+    }
 
-//     pub fn check() {
-//         reuse foo as bar;
-//         assert_eq!(bar::<i32, i32>(1, 2, |x, y| y), 2);
-//     }
-// }
+    pub fn check() {
+        reuse foo as bar;
+        assert_eq!(bar::<i32, i32>(1, 2, |_, y| y), 2);
+    }
+}
 
 // Testing reuse of local fn with delegation parent generic params specified,
 // late-bound lifetimes + types + consts, reusing with user args,
@@ -126,7 +124,7 @@ pub fn main() {
     test_4::check::<i32, String>();
     test_5::check::<i32, String>();
     test_6::check::<i32, String>();
-    // test_7::check();
+    test_7::check();
     test_8::check::<i32, String>();
     test_9::check::<String, i32>();
 }

filename: tests/ui/delegation/generics/synth-params-ice-143498.rs
patch: @@ -0,0 +1,27 @@
+//@ compile-flags: -Z deduplicate-diagnostics=yes
+//@ edition:2024
+
+#![feature(fn_delegation)]
+#![feature(iter_advance_by)]
+#![feature(iter_array_chunks)]
+#![feature(iterator_try_collect)]
+#![feature(iterator_try_reduce)]
+#![feature(iter_collect_into)]
+#![feature(iter_intersperse)]
+#![feature(iter_is_partitioned)]
+#![feature(iter_map_windows)]
+#![feature(iter_next_chunk)]
+#![feature(iter_order_by)]
+#![feature(iter_partition_in_place)]
+#![feature(trusted_random_access)]
+#![feature(try_find)]
+#![allow(incomplete_features)]
+
+impl X {
+//~^ ERROR: cannot find type `X` in this scope
+    reuse< std::fmt::Debug as Iterator >::*;
+    //~^ ERROR: expected method or associated constant, found associated type `Iterator::Item`
+    //~| ERROR: expected a type, found a trait
+}
+
+pub fn main() {}

filename: tests/ui/delegation/generics/synth-params-ice-143498.stderr
patch: @@ -0,0 +1,27 @@
+error[E0425]: cannot find type `X` in this scope
+  --> $DIR/synth-params-ice-143498.rs:20:6
+   |
+LL | impl X {
+   |      ^ not found in this scope
+
+error[E0575]: expected method or associated constant, found associated type `Iterator::Item`
+  --> $DIR/synth-params-ice-143498.rs:22:10
+   |
+LL |     reuse< std::fmt::Debug as Iterator >::*;
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a method or associated constant
+
+error[E0782]: expected a type, found a trait
+  --> $DIR/synth-params-ice-143498.rs:22:12
+   |
+LL |     reuse< std::fmt::Debug as Iterator >::*;
+   |            ^^^^^^^^^^^^^^^
+   |
+help: you can add the `dyn` keyword if you want a trait object
+   |
+LL |     reuse< dyn std::fmt::Debug as Iterator >::*;
+   |            +++
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0425, E0575, E0782.
+For more information about an error, try `rustc --explain E0425`.