1use hir_def::LifetimeParamId;
4use intern::Symbol;
5use rustc_type_ir::{
6 BoundVar, BoundVarIndexKind, DebruijnIndex, Flags, INNERMOST, RegionVid, TypeFlags,
7 TypeFoldable, TypeVisitable,
8 inherent::{IntoKind, PlaceholderLike, SliceLike},
9 relate::Relate,
10};
11
12use crate::next_solver::{GenericArg, OutlivesPredicate};
13
14use super::{
15 ErrorGuaranteed, SolverDefId, interned_vec_db,
16 interner::{BoundVarKind, DbInterner, Placeholder},
17};
18
19pub type RegionKind<'db> = rustc_type_ir::RegionKind<DbInterner<'db>>;
20
21#[salsa::interned(constructor = new_)]
22pub struct Region<'db> {
23 #[returns(ref)]
24 kind_: RegionKind<'db>,
25}
26
27impl std::fmt::Debug for Region<'_> {
28 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
29 self.kind().fmt(f)
30 }
31}
32
33impl<'db> Region<'db> {
34 pub fn new(interner: DbInterner<'db>, kind: RegionKind<'db>) -> Self {
35 Region::new_(interner.db(), kind)
36 }
37
38 pub fn inner(&self) -> &RegionKind<'db> {
39 crate::with_attached_db(|db| {
40 let inner = self.kind_(db);
41 unsafe { std::mem::transmute::<&RegionKind<'_>, &RegionKind<'db>>(inner) }
44 })
45 }
46
47 pub fn new_early_param(
48 interner: DbInterner<'db>,
49 early_bound_region: EarlyParamRegion,
50 ) -> Self {
51 Region::new(interner, RegionKind::ReEarlyParam(early_bound_region))
52 }
53
54 pub fn new_placeholder(interner: DbInterner<'db>, placeholder: PlaceholderRegion) -> Self {
55 Region::new(interner, RegionKind::RePlaceholder(placeholder))
56 }
57
58 pub fn new_var(interner: DbInterner<'db>, v: RegionVid) -> Region<'db> {
59 Region::new(interner, RegionKind::ReVar(v))
60 }
61
62 pub fn new_erased(interner: DbInterner<'db>) -> Region<'db> {
63 Region::new(interner, RegionKind::ReErased)
64 }
65
66 pub fn new_bound(
67 interner: DbInterner<'db>,
68 index: DebruijnIndex,
69 bound: BoundRegion,
70 ) -> Region<'db> {
71 Region::new(interner, RegionKind::ReBound(BoundVarIndexKind::Bound(index), bound))
72 }
73
74 pub fn is_placeholder(&self) -> bool {
75 matches!(self.inner(), RegionKind::RePlaceholder(..))
76 }
77
78 pub fn is_static(&self) -> bool {
79 matches!(self.inner(), RegionKind::ReStatic)
80 }
81
82 pub fn is_erased(&self) -> bool {
83 matches!(self.inner(), RegionKind::ReErased)
84 }
85
86 pub fn is_var(&self) -> bool {
87 matches!(self.inner(), RegionKind::ReVar(_))
88 }
89
90 pub fn is_error(&self) -> bool {
91 matches!(self.inner(), RegionKind::ReError(_))
92 }
93
94 pub fn error(interner: DbInterner<'db>) -> Self {
95 Region::new(interner, RegionKind::ReError(ErrorGuaranteed))
96 }
97
98 pub fn type_flags(&self) -> TypeFlags {
99 let mut flags = TypeFlags::empty();
100
101 match &self.inner() {
102 RegionKind::ReVar(..) => {
103 flags |= TypeFlags::HAS_FREE_REGIONS;
104 flags |= TypeFlags::HAS_FREE_LOCAL_REGIONS;
105 flags |= TypeFlags::HAS_RE_INFER;
106 }
107 RegionKind::RePlaceholder(..) => {
108 flags |= TypeFlags::HAS_FREE_REGIONS;
109 flags |= TypeFlags::HAS_FREE_LOCAL_REGIONS;
110 flags |= TypeFlags::HAS_RE_PLACEHOLDER;
111 }
112 RegionKind::ReEarlyParam(..) => {
113 flags |= TypeFlags::HAS_FREE_REGIONS;
114 flags |= TypeFlags::HAS_FREE_LOCAL_REGIONS;
115 flags |= TypeFlags::HAS_RE_PARAM;
116 }
117 RegionKind::ReLateParam(..) => {
118 flags |= TypeFlags::HAS_FREE_REGIONS;
119 flags |= TypeFlags::HAS_FREE_LOCAL_REGIONS;
120 }
121 RegionKind::ReStatic => {
122 flags |= TypeFlags::HAS_FREE_REGIONS;
123 }
124 RegionKind::ReBound(BoundVarIndexKind::Canonical, ..) => {
125 flags |= TypeFlags::HAS_RE_BOUND;
126 flags |= TypeFlags::HAS_CANONICAL_BOUND;
127 }
128 RegionKind::ReBound(BoundVarIndexKind::Bound(..), ..) => {
129 flags |= TypeFlags::HAS_RE_BOUND;
130 }
131 RegionKind::ReErased => {
132 flags |= TypeFlags::HAS_RE_ERASED;
133 }
134 RegionKind::ReError(..) => {
135 flags |= TypeFlags::HAS_FREE_REGIONS;
136 flags |= TypeFlags::HAS_ERROR;
137 }
138 }
139
140 flags
141 }
142}
143
144pub type PlaceholderRegion = Placeholder<BoundRegion>;
145
146#[derive(Copy, Clone, PartialEq, Eq, Hash)]
147pub struct EarlyParamRegion {
148 pub id: LifetimeParamId,
150 pub index: u32,
151}
152
153#[derive(Copy, Clone, PartialEq, Eq, Hash)]
154pub struct LateParamRegion {
163 pub scope: SolverDefId,
164 pub bound_region: BoundRegionKind,
165}
166
167impl std::fmt::Debug for LateParamRegion {
168 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
169 write!(f, "ReLateParam({:?}, {:?})", self.scope, self.bound_region)
170 }
171}
172
173#[derive(Copy, Clone, PartialEq, Eq, Hash)]
174pub enum BoundRegionKind {
175 Anon,
177
178 Named(SolverDefId),
183
184 ClosureEnv,
187}
188
189impl std::fmt::Debug for BoundRegionKind {
190 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
191 match *self {
192 BoundRegionKind::Anon => write!(f, "BrAnon"),
193 BoundRegionKind::Named(did) => {
194 write!(f, "BrNamed({did:?})")
195 }
196 BoundRegionKind::ClosureEnv => write!(f, "BrEnv"),
197 }
198 }
199}
200
201#[derive(Copy, Clone, PartialEq, Eq, Hash)]
202pub struct BoundRegion {
203 pub var: BoundVar,
204 pub kind: BoundRegionKind,
205}
206
207impl rustc_type_ir::inherent::ParamLike for EarlyParamRegion {
208 fn index(self) -> u32 {
209 self.index
210 }
211}
212
213impl std::fmt::Debug for EarlyParamRegion {
214 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
215 write!(f, "#{}", self.index)
216 }
218}
219
220impl<'db> rustc_type_ir::inherent::BoundVarLike<DbInterner<'db>> for BoundRegion {
221 fn var(self) -> BoundVar {
222 self.var
223 }
224
225 fn assert_eq(self, var: BoundVarKind) {
226 assert_eq!(self.kind, var.expect_region())
227 }
228}
229
230impl core::fmt::Debug for BoundRegion {
231 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
232 match &self.kind {
233 BoundRegionKind::Anon => write!(f, "{:?}", self.var),
234 BoundRegionKind::ClosureEnv => write!(f, "{:?}.Env", self.var),
235 BoundRegionKind::Named(def) => {
236 write!(f, "{:?}.Named({:?})", self.var, def)
237 }
238 }
239 }
240}
241
242impl BoundRegionKind {
243 pub fn is_named(&self) -> bool {
244 matches!(self, BoundRegionKind::Named(_))
245 }
246
247 pub fn get_name(&self) -> Option<Symbol> {
248 None
249 }
250
251 pub fn get_id(&self) -> Option<SolverDefId> {
252 match self {
253 BoundRegionKind::Named(id) => Some(*id),
254 _ => None,
255 }
256 }
257}
258
259impl<'db> IntoKind for Region<'db> {
260 type Kind = RegionKind<'db>;
261
262 fn kind(self) -> Self::Kind {
263 *self.inner()
264 }
265}
266
267impl<'db> TypeVisitable<DbInterner<'db>> for Region<'db> {
268 fn visit_with<V: rustc_type_ir::TypeVisitor<DbInterner<'db>>>(
269 &self,
270 visitor: &mut V,
271 ) -> V::Result {
272 visitor.visit_region(*self)
273 }
274}
275
276impl<'db> TypeFoldable<DbInterner<'db>> for Region<'db> {
277 fn try_fold_with<F: rustc_type_ir::FallibleTypeFolder<DbInterner<'db>>>(
278 self,
279 folder: &mut F,
280 ) -> Result<Self, F::Error> {
281 folder.try_fold_region(self)
282 }
283 fn fold_with<F: rustc_type_ir::TypeFolder<DbInterner<'db>>>(self, folder: &mut F) -> Self {
284 folder.fold_region(self)
285 }
286}
287
288impl<'db> Relate<DbInterner<'db>> for Region<'db> {
289 fn relate<R: rustc_type_ir::relate::TypeRelation<DbInterner<'db>>>(
290 relation: &mut R,
291 a: Self,
292 b: Self,
293 ) -> rustc_type_ir::relate::RelateResult<DbInterner<'db>, Self> {
294 relation.regions(a, b)
295 }
296}
297
298impl<'db> Flags for Region<'db> {
299 fn flags(&self) -> rustc_type_ir::TypeFlags {
300 self.type_flags()
301 }
302
303 fn outer_exclusive_binder(&self) -> rustc_type_ir::DebruijnIndex {
304 match &self.inner() {
305 RegionKind::ReBound(BoundVarIndexKind::Bound(debruijn), _) => debruijn.shifted_in(1),
306 _ => INNERMOST,
307 }
308 }
309}
310
311impl<'db> rustc_type_ir::inherent::Region<DbInterner<'db>> for Region<'db> {
312 fn new_bound(
313 interner: DbInterner<'db>,
314 debruijn: rustc_type_ir::DebruijnIndex,
315 var: BoundRegion,
316 ) -> Self {
317 Region::new(interner, RegionKind::ReBound(BoundVarIndexKind::Bound(debruijn), var))
318 }
319
320 fn new_anon_bound(
321 interner: DbInterner<'db>,
322 debruijn: rustc_type_ir::DebruijnIndex,
323 var: rustc_type_ir::BoundVar,
324 ) -> Self {
325 Region::new(
326 interner,
327 RegionKind::ReBound(
328 BoundVarIndexKind::Bound(debruijn),
329 BoundRegion { var, kind: BoundRegionKind::Anon },
330 ),
331 )
332 }
333
334 fn new_canonical_bound(interner: DbInterner<'db>, var: rustc_type_ir::BoundVar) -> Self {
335 Region::new(
336 interner,
337 RegionKind::ReBound(
338 BoundVarIndexKind::Canonical,
339 BoundRegion { var, kind: BoundRegionKind::Anon },
340 ),
341 )
342 }
343
344 fn new_static(interner: DbInterner<'db>) -> Self {
345 Region::new(interner, RegionKind::ReStatic)
346 }
347
348 fn new_placeholder(
349 interner: DbInterner<'db>,
350 var: <DbInterner<'db> as rustc_type_ir::Interner>::PlaceholderRegion,
351 ) -> Self {
352 Region::new(interner, RegionKind::RePlaceholder(var))
353 }
354}
355
356impl<'db> PlaceholderLike<DbInterner<'db>> for PlaceholderRegion {
357 type Bound = BoundRegion;
358
359 fn universe(self) -> rustc_type_ir::UniverseIndex {
360 self.universe
361 }
362
363 fn var(self) -> rustc_type_ir::BoundVar {
364 self.bound.var
365 }
366
367 fn with_updated_universe(self, ui: rustc_type_ir::UniverseIndex) -> Self {
368 Placeholder { universe: ui, bound: self.bound }
369 }
370
371 fn new(ui: rustc_type_ir::UniverseIndex, bound: Self::Bound) -> Self {
372 Placeholder { universe: ui, bound }
373 }
374
375 fn new_anon(ui: rustc_type_ir::UniverseIndex, var: rustc_type_ir::BoundVar) -> Self {
376 Placeholder { universe: ui, bound: BoundRegion { var, kind: BoundRegionKind::Anon } }
377 }
378}
379
380type GenericArgOutlivesPredicate<'db> = OutlivesPredicate<'db, GenericArg<'db>>;
381
382interned_vec_db!(RegionAssumptions, GenericArgOutlivesPredicate);