diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs index 815550a49e1..7eb1042d2f8 100644 --- a/compiler/rustc_ty_utils/src/implied_bounds.rs +++ b/compiler/rustc_ty_utils/src/implied_bounds.rs @@ -11,7 +11,10 @@ use std::iter; pub fn provide(providers: &mut Providers) { *providers = Providers { assumed_wf_types, - assumed_wf_types_for_rpitit: |tcx, def_id| tcx.assumed_wf_types(def_id), + assumed_wf_types_for_rpitit: |tcx, def_id| { + assert!(tcx.is_impl_trait_in_trait(def_id.to_def_id())); + tcx.assumed_wf_types(def_id) + }, ..*providers }; } @@ -52,6 +55,15 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<' ty::ImplTraitInTraitData::Trait { fn_def_id, opaque_def_id } => { let hir::OpaqueTy { lifetime_mapping, .. } = *tcx.hir().expect_item(opaque_def_id.expect_local()).expect_opaque_ty(); + // We need to remap all of the late-bound lifetimes in theassumed wf types + // of the fn (which are represented as ReFree) to the early-bound lifetimes + // of the RPITIT (which are represented by ReEarlyBound owned by the opaque). + // Luckily, this is very easy to do because we already have that mapping + // stored in the HIR of this RPITIT. + // + // Side-note: We don't really need to do this remapping for early-bound + // lifetimes because they're already "linked" by the bidirectional outlives + // predicates we insert in the `explicit_predicates_of` query for RPITITs. let mut mapping = FxHashMap::default(); let generics = tcx.generics_of(def_id); for &(lifetime, new_early_bound_def_id) in @@ -81,14 +93,24 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<' ); } } - let a = tcx.fold_regions( + // FIXME: This could use a real folder, I guess. + let remapped_wf_tys = tcx.fold_regions( tcx.assumed_wf_types(fn_def_id.expect_local()).to_vec(), - |re, _| { - if let Some(re) = mapping.get(&re) { *re } else { re } + |region, _| { + // If `region` is a `ReFree` that is captured by the + // opaque, remap it to its corresponding the early- + // bound region. + if let Some(remapped_region) = mapping.get(®ion) { + *remapped_region + } else { + region + } }, ); - tcx.arena.alloc_from_iter(a) + tcx.arena.alloc_from_iter(remapped_wf_tys) } + // Assumed wf types for RPITITs in an impl just inherit (and instantiate) + // the assumed wf types of the trait's RPITIT GAT. ty::ImplTraitInTraitData::Impl { .. } => { let impl_def_id = tcx.local_parent(def_id); let rpitit_def_id = tcx.associated_item(def_id).trait_item_def_id.unwrap(); diff --git a/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit.rs b/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit.rs index 8b97336fe0c..ff7ad4bf389 100644 --- a/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit.rs +++ b/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit.rs @@ -17,7 +17,6 @@ impl<'a, I: 'a + Iterable> Iterable for &'a I { //~^ ERROR impl has stricter requirements than trait fn iter(&self) -> impl 'a + Iterator> { - //~^ ERROR the type `&'a I` does not fulfill the required lifetime (*self).iter() } } diff --git a/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit.stderr b/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit.stderr index 54a08c5b516..106b8a7c804 100644 --- a/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit.stderr +++ b/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit.stderr @@ -12,19 +12,6 @@ help: copy the `where` clause predicates from the trait LL | where Self: 'b; | ~~~~~~~~~~~~~~ -error[E0477]: the type `&'a I` does not fulfill the required lifetime - --> $DIR/bad-item-bound-within-rpitit.rs:19:23 - | -LL | fn iter(&self) -> impl 'a + Iterator> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: type must outlive the anonymous lifetime as defined here - --> $DIR/bad-item-bound-within-rpitit.rs:10:28 - | -LL | fn iter(&self) -> impl '_ + Iterator>; - | ^^ +error: aborting due to previous error -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0276, E0477. -For more information about an error, try `rustc --explain E0276`. +For more information about this error, try `rustc --explain E0276`.