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