diff options
| author | Michael Goulet <michael@errs.io> | 2023-08-07 23:37:57 +0000 |
|---|---|---|
| committer | Michael Goulet <michael@errs.io> | 2023-08-08 09:39:42 +0000 |
| commit | 420ee167a8fbda2a078cb3a294fa1108c0180c98 (patch) | |
| tree | 73df2d1556dad567f9fa48bf1411b98483ec699d /compiler/rustc_middle/src | |
| parent | 8dcb8e0759ea48df925968557bd81e37c084e2d0 (diff) | |
| download | rust-420ee167a8fbda2a078cb3a294fa1108c0180c98.tar.gz rust-420ee167a8fbda2a078cb3a294fa1108c0180c98.zip | |
Install bidirectional outlives predicates for RPITITs (and RPITs) correctly
Diffstat (limited to 'compiler/rustc_middle/src')
| -rw-r--r-- | compiler/rustc_middle/src/ty/context.rs | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 5eef3e45f32..75a2c6cbd20 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1931,6 +1931,75 @@ impl<'tcx> TyCtxt<'tcx> { ) } + /// Given the def-id of an early-bound lifetime on an RPIT corresponding to + /// a duplicated captured lifetime, map it back to the early- or late-bound + /// lifetime of the function from which it originally as captured. If it is + /// a late-bound lifetime, this will represent the liberated (`ReFree`) lifetime + /// of the signature. + // FIXME(RPITIT): if we ever synthesize new lifetimes for RPITITs and not just + // re-use the generics of the opaque, this function will need to be tweaked slightly. + pub fn map_rpit_lifetime_to_fn_lifetime( + self, + mut rpit_lifetime_param_def_id: LocalDefId, + ) -> ty::Region<'tcx> { + debug_assert!( + matches!(self.def_kind(rpit_lifetime_param_def_id), DefKind::LifetimeParam), + "{rpit_lifetime_param_def_id:?} is a {}", + self.def_descr(rpit_lifetime_param_def_id.to_def_id()) + ); + + loop { + let parent = self.local_parent(rpit_lifetime_param_def_id); + let hir::OpaqueTy { lifetime_mapping, .. } = + self.hir().get_by_def_id(parent).expect_item().expect_opaque_ty(); + + let Some((lifetime, _)) = lifetime_mapping + .iter() + .find(|(_, duplicated_param)| *duplicated_param == rpit_lifetime_param_def_id) + else { + bug!("duplicated lifetime param should be present"); + }; + + match self.named_bound_var(lifetime.hir_id) { + Some(resolve_bound_vars::ResolvedArg::EarlyBound(ebv)) => { + let new_parent = self.parent(ebv); + + // If we map to another opaque, then it should be a parent + // of the opaque we mapped from. Continue mapping. + if matches!(self.def_kind(new_parent), DefKind::OpaqueTy) { + debug_assert_eq!(self.parent(parent.to_def_id()), new_parent); + rpit_lifetime_param_def_id = ebv.expect_local(); + continue; + } + + let generics = self.generics_of(new_parent); + return ty::Region::new_early_bound( + self, + ty::EarlyBoundRegion { + def_id: ebv, + index: generics + .param_def_id_to_index(self, ebv) + .expect("early-bound var should be present in fn generics"), + name: self.hir().name(self.local_def_id_to_hir_id(ebv.expect_local())), + }, + ); + } + Some(resolve_bound_vars::ResolvedArg::LateBound(_, _, lbv)) => { + let new_parent = self.parent(lbv); + return ty::Region::new_free( + self, + new_parent, + ty::BoundRegionKind::BrNamed( + lbv, + self.hir().name(self.local_def_id_to_hir_id(lbv.expect_local())), + ), + ); + } + _ => bug!(), + } + } + } + /// Whether the `def_id` counts as const fn in the current crate, considering all active /// feature gates pub fn is_const_fn(self, def_id: DefId) -> bool { |
