1use hir_def::LifetimeParamId;
4use intern::{Interned, InternedRef, impl_internable};
5use macros::GenericTypeVisitable;
6use rustc_type_ir::{
7 BoundVarIndexKind, DebruijnIndex, Flags, GenericTypeVisitable, INNERMOST, RegionVid, TypeFlags,
8 TypeFoldable, TypeVisitable,
9 inherent::{IntoKind, SliceLike},
10 relate::Relate,
11};
12
13use crate::next_solver::{
14 GenericArg, OutlivesPredicate, impl_foldable_for_interned_slice, impl_stored_interned,
15 interned_slice,
16};
17
18use super::{SolverDefId, interner::DbInterner};
19
20pub type RegionKind<'db> = rustc_type_ir::RegionKind<DbInterner<'db>>;
21pub type RegionConstraint<'db> = rustc_type_ir::RegionConstraint<DbInterner<'db>>;
22
23#[derive(Clone, Copy, PartialEq, Eq, Hash)]
24pub struct Region<'db> {
25 pub(super) interned: InternedRef<'db, RegionInterned>,
26}
27
28#[derive(PartialEq, Eq, Hash, GenericTypeVisitable)]
29#[repr(align(4))] pub(super) struct RegionInterned(RegionKind<'static>);
31
32impl_internable!(gc; RegionInterned);
33impl_stored_interned!(RegionInterned, Region, StoredRegion);
34
35const _: () = {
36 const fn is_copy<T: Copy>() {}
37 is_copy::<Region<'static>>();
38};
39
40impl<'db> Region<'db> {
41 pub fn new_without_interner(kind: RegionKind<'db>) -> Self {
44 let kind = unsafe { std::mem::transmute::<RegionKind<'db>, RegionKind<'static>>(kind) };
45 Self { interned: Interned::new_gc(RegionInterned(kind)) }
46 }
47
48 pub fn new(_interner: DbInterner<'db>, kind: RegionKind<'db>) -> Self {
49 Self::new_without_interner(kind)
50 }
51
52 pub fn inner(&self) -> &RegionKind<'db> {
53 let inner = &self.interned.0;
54 unsafe { std::mem::transmute::<&RegionKind<'static>, &RegionKind<'db>>(inner) }
55 }
56
57 pub fn new_early_param(
58 interner: DbInterner<'db>,
59 early_bound_region: EarlyParamRegion,
60 ) -> Self {
61 Region::new(interner, RegionKind::ReEarlyParam(early_bound_region))
62 }
63
64 pub fn new_placeholder(interner: DbInterner<'db>, placeholder: PlaceholderRegion<'db>) -> Self {
65 Region::new(interner, RegionKind::RePlaceholder(placeholder))
66 }
67
68 pub fn new_var(interner: DbInterner<'db>, v: RegionVid) -> Region<'db> {
69 Region::new(interner, RegionKind::ReVar(v))
70 }
71
72 pub fn new_erased(interner: DbInterner<'db>) -> Region<'db> {
73 interner.default_types().regions.erased
74 }
75
76 pub fn new_bound(
77 interner: DbInterner<'db>,
78 index: DebruijnIndex,
79 bound: BoundRegion<'db>,
80 ) -> Region<'db> {
81 Region::new(interner, RegionKind::ReBound(BoundVarIndexKind::Bound(index), bound))
82 }
83
84 pub fn new_late_param(
85 interner: DbInterner<'db>,
86 scope: SolverDefId<'db>,
87 bound_region: BoundRegion<'db>,
88 ) -> Region<'db> {
89 let late_bound_region = LateParamRegion { scope, bound_region };
90 Region::new(interner, RegionKind::ReLateParam(late_bound_region))
91 }
92
93 pub fn is_placeholder(&self) -> bool {
94 matches!(self.inner(), RegionKind::RePlaceholder(..))
95 }
96
97 pub fn is_static(&self) -> bool {
98 matches!(self.inner(), RegionKind::ReStatic)
99 }
100
101 pub fn is_erased(&self) -> bool {
102 matches!(self.inner(), RegionKind::ReErased)
103 }
104
105 pub fn is_var(&self) -> bool {
106 matches!(self.inner(), RegionKind::ReVar(_))
107 }
108
109 pub fn is_error(&self) -> bool {
110 matches!(self.inner(), RegionKind::ReError(_))
111 }
112
113 pub fn error(interner: DbInterner<'db>) -> Self {
114 interner.default_types().regions.error
115 }
116
117 pub fn type_flags(&self) -> TypeFlags {
118 let mut flags = TypeFlags::empty();
119
120 match &self.inner() {
121 RegionKind::ReVar(..) => {
122 flags |= TypeFlags::HAS_FREE_REGIONS;
123 flags |= TypeFlags::HAS_FREE_LOCAL_REGIONS;
124 flags |= TypeFlags::HAS_RE_INFER;
125 }
126 RegionKind::RePlaceholder(..) => {
127 flags |= TypeFlags::HAS_FREE_REGIONS;
128 flags |= TypeFlags::HAS_FREE_LOCAL_REGIONS;
129 flags |= TypeFlags::HAS_RE_PLACEHOLDER;
130 }
131 RegionKind::ReEarlyParam(..) => {
132 flags |= TypeFlags::HAS_FREE_REGIONS;
133 flags |= TypeFlags::HAS_FREE_LOCAL_REGIONS;
134 flags |= TypeFlags::HAS_RE_PARAM;
135 }
136 RegionKind::ReLateParam(..) => {
137 flags |= TypeFlags::HAS_FREE_REGIONS;
138 flags |= TypeFlags::HAS_FREE_LOCAL_REGIONS;
139 }
140 RegionKind::ReStatic => {
141 flags |= TypeFlags::HAS_FREE_REGIONS;
142 }
143 RegionKind::ReBound(BoundVarIndexKind::Canonical, ..) => {
144 flags |= TypeFlags::HAS_RE_BOUND;
145 flags |= TypeFlags::HAS_CANONICAL_BOUND;
146 }
147 RegionKind::ReBound(BoundVarIndexKind::Bound(..), ..) => {
148 flags |= TypeFlags::HAS_RE_BOUND;
149 }
150 RegionKind::ReErased => {
151 flags |= TypeFlags::HAS_RE_ERASED;
152 }
153 RegionKind::ReError(..) => {
154 flags |= TypeFlags::HAS_FREE_REGIONS;
155 flags |= TypeFlags::HAS_RE_ERROR;
156 }
157 }
158
159 flags
160 }
161}
162
163pub type PlaceholderRegion<'db> = rustc_type_ir::PlaceholderRegion<DbInterner<'db>>;
164
165#[derive(Copy, Clone, PartialEq, Eq, Hash)]
166pub struct EarlyParamRegion {
167 pub id: LifetimeParamId,
169 pub index: u32,
170}
171
172#[derive(Copy, Clone, PartialEq, Eq, Hash, GenericTypeVisitable)]
173pub struct LateParamRegion<'db> {
178 pub scope: SolverDefId<'db>,
179 pub bound_region: BoundRegion<'db>,
180}
181
182impl std::fmt::Debug for LateParamRegion<'_> {
183 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
184 write!(f, "ReLateParam({:?}, {:?})", self.scope, self.bound_region)
185 }
186}
187
188pub type BoundRegion<'db> = rustc_type_ir::BoundRegion<DbInterner<'db>>;
189pub type BoundRegionKind<'db> = rustc_type_ir::BoundRegionKind<DbInterner<'db>>;
190
191impl rustc_type_ir::inherent::ParamLike for EarlyParamRegion {
192 fn index(self) -> u32 {
193 self.index
194 }
195}
196
197impl std::fmt::Debug for EarlyParamRegion {
198 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
199 write!(f, "#{}", self.index)
200 }
202}
203
204impl std::fmt::Debug for Region<'_> {
205 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
206 self.kind().fmt(f)
207 }
208}
209
210impl<'db> IntoKind for Region<'db> {
211 type Kind = RegionKind<'db>;
212
213 fn kind(self) -> Self::Kind {
214 *self.inner()
215 }
216}
217
218impl<'db> TypeVisitable<DbInterner<'db>> for Region<'db> {
219 fn visit_with<V: rustc_type_ir::TypeVisitor<DbInterner<'db>>>(
220 &self,
221 visitor: &mut V,
222 ) -> V::Result {
223 visitor.visit_region(*self)
224 }
225}
226
227impl<'db> TypeFoldable<DbInterner<'db>> for Region<'db> {
228 fn try_fold_with<F: rustc_type_ir::FallibleTypeFolder<DbInterner<'db>>>(
229 self,
230 folder: &mut F,
231 ) -> Result<Self, F::Error> {
232 folder.try_fold_region(self)
233 }
234 fn fold_with<F: rustc_type_ir::TypeFolder<DbInterner<'db>>>(self, folder: &mut F) -> Self {
235 folder.fold_region(self)
236 }
237}
238
239impl<'db> Relate<DbInterner<'db>> for Region<'db> {
240 fn relate<R: rustc_type_ir::relate::TypeRelation<DbInterner<'db>>>(
241 relation: &mut R,
242 a: Self,
243 b: Self,
244 ) -> rustc_type_ir::relate::RelateResult<DbInterner<'db>, Self> {
245 relation.regions(a, b)
246 }
247}
248
249impl<'db> Flags for Region<'db> {
250 fn flags(&self) -> rustc_type_ir::TypeFlags {
251 self.type_flags()
252 }
253
254 fn outer_exclusive_binder(&self) -> rustc_type_ir::DebruijnIndex {
255 match &self.inner() {
256 RegionKind::ReBound(BoundVarIndexKind::Bound(debruijn), _) => debruijn.shifted_in(1),
257 _ => INNERMOST,
258 }
259 }
260}
261
262impl<'db> rustc_type_ir::inherent::Region<DbInterner<'db>> for Region<'db> {
263 fn new_bound(
264 interner: DbInterner<'db>,
265 debruijn: DebruijnIndex,
266 var: BoundRegion<'db>,
267 ) -> Self {
268 Region::new(interner, RegionKind::ReBound(BoundVarIndexKind::Bound(debruijn), var))
269 }
270
271 fn new_anon_bound(
272 interner: DbInterner<'db>,
273 debruijn: DebruijnIndex,
274 var: rustc_type_ir::BoundVar,
275 ) -> Self {
276 Region::new(
277 interner,
278 RegionKind::ReBound(
279 BoundVarIndexKind::Bound(debruijn),
280 BoundRegion { var, kind: BoundRegionKind::Anon },
281 ),
282 )
283 }
284
285 fn new_canonical_bound(interner: DbInterner<'db>, var: rustc_type_ir::BoundVar) -> Self {
286 Region::new(
287 interner,
288 RegionKind::ReBound(
289 BoundVarIndexKind::Canonical,
290 BoundRegion { var, kind: BoundRegionKind::Anon },
291 ),
292 )
293 }
294
295 fn new_static(interner: DbInterner<'db>) -> Self {
296 interner.default_types().regions.statik
297 }
298
299 fn new_placeholder(interner: DbInterner<'db>, var: PlaceholderRegion<'db>) -> Self {
300 Region::new(interner, RegionKind::RePlaceholder(var))
301 }
302}
303
304impl<'db, V: super::WorldExposer> GenericTypeVisitable<V> for Region<'db> {
305 fn generic_visit_with(&self, visitor: &mut V) {
306 if visitor.on_interned(self.interned).is_continue() {
307 self.kind().generic_visit_with(visitor);
308 }
309 }
310}
311
312type GenericArgOutlivesPredicate<'db> = OutlivesPredicate<'db, GenericArg<'db>>;
313
314interned_slice!(
315 RegionAssumptionsStorage,
316 RegionAssumptions,
317 StoredRegionAssumptions,
318 region_assumptions,
319 GenericArgOutlivesPredicate<'db>,
320 GenericArgOutlivesPredicate<'static>,
321);
322impl_foldable_for_interned_slice!(RegionAssumptions);