Change:
I tried this code: I expected this to compile without error, since it is implementing the trait correctly. Instead, the following error was shown: It suggests replacing the code with the code I already have, which doesn't make much sense, as well as complaining that two things which appear identical are not. . : <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
label +T-compiler +requires-nightly +F-returnpositionimpltraitin_trait +D-invalid-suggestion
claim

Discussion:
let ocx = ObligationCtxt::new(infcx); let norm_cause = ObligationCause::misc(return_span, impl_m_hir_id); <del> let impl_return_ty = ocx.normalize( </del> <ins> let impl_sig = ocx.normalize( </ins> norm_cause.clone(), param_env, <del> infcx .replace_bound_vars_with_fresh_vars( return_span, infer::HigherRankedType, tcx.fn_sig(impl_m.def_id), ) .output(), </del> <ins> infcx.replace_bound_vars_with_fresh_vars( return_span, infer::HigherRankedType, tcx.fn_sig(impl_m.def_id), ), </ins> ); <ins> let impl_return_ty = impl_sig.output(); </ins> let mut collector = ImplTraitInTraitCollector::new(&ocx, return_span, param_env, impl_m_hir_id); <del> let unnormalized_trait_return_ty = tcx </del> <ins> let unnormalized_trait_sig = tcx </ins> .liberate_late_bound_regions( impl_m.def_id, tcx.bound_fn_sig(trait_m.def_id).subst(tcx, trait_to_placeholder_substs), ) <del> .output() </del> .fold_with(&mut collector); <del> let trait_return_ty = ocx.normalize(norm_cause.clone(), param_env, unnormalized_trait_return_ty); </del> <ins> let trait_sig = ocx.normalize(norm_cause.clone(), param_env, unnormalized_trait_sig); let trait_return_ty = trait_sig.output(); </ins> <del> let wf_tys = FxHashSet::from_iter([unnormalized_trait_return_ty, trait_return_ty]); </del> <ins> let wf_tys = FxHashSet::from_iter( unnormalized_trait_sig.inputs_and_output.iter().chain(trait_sig.inputs_and_output.iter()), ); </ins> match infcx.at(&cause, param_env).eq(trait_return_ty, impl_return_ty) { Ok(infer::InferOk { value: (), obligations }) => {

} } <ins> // Unify the whole function signature. We need to do this to fully infer // the lifetimes of the return type, but do this after unifying just the // return types, since we want to avoid duplicating errors from // `compare_predicate_entailment`. match infcx .at(&cause, param_env) .eq(tcx.mk_fn_ptr(ty::Binder::dummy(trait_sig)), tcx.mk_fn_ptr(ty::Binder::dummy(impl_sig))) { Ok(infer::InferOk { value: (), obligations }) => { ocx.register_obligations(obligations); } Err(terr) => { let guar = tcx.sess.delay_span_bug( return_span, format!("could not unify `{trait_sig}` and `{impl_sig}`: {terr:?}"), ); return Err(guar); } } </ins> // Check that all obligations are satisfied by the implementation's // RPITs. let errors = ocx.select_all_or_error();

let id_substs = InternalSubsts::identity_for_item(tcx, def_id); debug!(?id_substs, ?substs); let map: FxHashMap<ty::GenericArg<'tcx>, ty::GenericArg<'tcx>> = <del> substs.iter().enumerate().map(|(index, arg)| (arg, id_substs[index])).collect(); </del> <ins> std::iter::zip(substs, id_substs).collect(); </ins> debug!(?map); <ins> // NOTE(compiler-errors): RPITITs, like all other RPITs, have early-bound // region substs that are synthesized during AST lowering. These are substs // that are appended to the parent substs (trait and trait method). However, // we're trying to infer the unsubstituted type value of the RPITIT inside // the *impl*, so we can later use the impl's method substs to normalize // an RPITIT to a concrete type (`confirm_impl_trait_in_trait_candidate`). // // Due to the design of RPITITs, during AST lowering, we have no idea that // an impl method corresponds to a trait method with RPITITs in it. Therefore, // we don't have a list of early-bound region substs for the RPITIT in the impl. // Since early region parameters are index-based, we can't just rebase these // (trait method) early-bound region substs onto the impl, and there's no // guarantee that the indices from the trait substs and impl substs line up. // So to fix this, we subtract the number of trait substs and add the number of // impl substs to *renumber* these early-bound regions to their corresponding // indices in the impl's substitutions list. // // Also, we only need to account for a difference in trait and impl substs, // since we previously enforce that the trait method and impl method have the // same generics. let num_trait_substs = trait_to_impl_substs.len(); let num_impl_substs = tcx.generics_of(impl_m.container_id(tcx)).params.len(); </ins> let ty = tcx.fold_regions(ty, |region, _| { <del> if let ty::ReFree(_) = region.kind() { map[&region.into()].expect_region() } else { region } </del> <ins> let ty::ReFree(_) = region.kind() else { return region; }; let ty::ReEarlyBound(e) = map[&region.into()].expect_region().kind() else { bug!("expected ReFree to map to ReEarlyBound"); }; tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion { def_id: e.def_id, name: e.name, index: (e.index as usize - num_trait_substs + num_impl_substs) as u32, })) </ins> }); debug!(%ty); collected_tys.insert(def_id, ty);

fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { #[cold] #[inline(never)] <del> fn region_param_out_of_range(data: ty::EarlyBoundRegion) -> ! { </del> <ins> fn region_param_out_of_range(data: ty::EarlyBoundRegion, substs: &[GenericArg<'_>]) -> ! { </ins> bug!( <del> "Region parameter out of range when substituting in region {} (index={})", </del> <ins> "Region parameter out of range when substituting in region {} (index={}, substs = {:?})", data.name, data.index, substs, ) } #[cold] #[inline(never)] fn region_param_invalid(data: ty::EarlyBoundRegion, other: GenericArgKind<'_>) -> ! { bug!( "Unexpected parameter {:?} when substituting in region {} (index={})", other, </ins> data.name, data.index )

let rk = self.substs.get(data.index as usize).map(|k| k.unpack()); match rk { Some(GenericArgKind::Lifetime(lt)) => self.shift_region_through_binders(lt), <del> _ => region_param_out_of_range(data), </del> <ins> Some(other) => region_param_invalid(data, other), None => region_param_out_of_range(data, self.substs), </ins> } } _ => r,

} let impl_fn_def_id = leaf_def.item.def_id; <del> let impl_fn_substs = obligation.predicate.substs.rebase_onto(tcx, trait_fn_def_id, data.substs); </del> <ins> // Rebase from {trait}::{fn}::{opaque} to {impl}::{fn}::{opaque}, // since `data.substs` are the impl substs. let impl_fn_substs = obligation.predicate.substs.rebase_onto(tcx, tcx.parent(trait_fn_def_id), data.substs); </ins> let cause = ObligationCause::new( obligation.cause.span,

<ins> // check-pass // edition:2021 #![feature(async_fn_in_trait)] #![allow(incomplete_features)] pub trait SpiDevice { async fn transaction<F, R>(&mut self); } impl SpiDevice for () { async fn transaction<F, R>(&mut self) {} } fn main() {} </ins>

<ins> // check-pass #![feature(return_position_impl_trait_in_trait)] #![allow(incomplete_features)] trait Foo<T> { fn foo<F2: Foo<T>>(self) -> impl Foo<T>; } struct Bar; impl Foo<u8> for Bar { fn foo<F2: Foo<u8>>(self) -> impl Foo<u8> { self } } fn main() {} </ins>