1use std::{
4 borrow::Borrow,
5 ops::{Deref, DerefMut, Index, IndexMut, RangeFrom},
6};
7
8use derive_generic_visitor::{Drive, DriveMut, DriveTwo};
9use index_vec::Idx;
10use macros::EnumIsA;
11use serde::{Deserialize, Serialize};
12use serde_state::{DeserializeState, SerializeState};
13
14use crate::{ast::*, impl_from_enum};
15
16#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
18#[derive(Serialize, Deserialize, Drive, DriveMut, DriveTwo)]
19#[serde(transparent)]
20#[cfg_attr(feature = "charon_on_charon", charon::transparent)]
21pub struct DeBruijnId {
22 pub index: usize,
23}
24
25impl DeBruijnId {
26 pub const ZERO: DeBruijnId = DeBruijnId { index: 0 };
27}
28
29#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
64#[derive(SerializeState, DeserializeState, Drive, DriveMut, DriveTwo)]
65pub enum DeBruijnVar<Id> {
66 Bound(#[serde_state(stateless)] DeBruijnId, Id),
68 Free(Id),
73}
74
75generate_index_type!(RegionId, "Region");
80generate_index_type!(TypeVarId, "T");
81generate_index_type!(ConstGenericVarId, "Const");
82generate_index_type!(TraitClauseId, "TraitClause");
83generate_index_type!(TraitTypeConstraintId, "TraitTypeConstraint");
84
85#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
87#[derive(Serialize, Deserialize, Drive, DriveMut, DriveTwo)]
88pub enum Variance {
89 Covariant,
90 Invariant,
91 Contravariant,
92 Bivariant,
94 #[cfg_attr(feature = "charon_on_charon", charon::rename("VaUnknown"))]
97 Unknown,
98}
99
100impl Variance {
101 pub fn compose(outer: Variance, inner: Variance) -> Variance {
102 match (outer, inner) {
103 (Variance::Unknown, _) | (_, Variance::Unknown) => Variance::Unknown,
104 (Variance::Bivariant, _) | (_, Variance::Bivariant) => Variance::Bivariant,
105 (Variance::Invariant, _) | (_, Variance::Invariant) => Variance::Invariant,
106 (Variance::Covariant, variance) => variance,
107 (Variance::Contravariant, Variance::Covariant) => Variance::Contravariant,
108 (Variance::Contravariant, Variance::Contravariant) => Variance::Covariant,
109 }
110 }
111}
112
113#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
115#[derive(Serialize, Deserialize, Drive, DriveMut, DriveTwo)]
116pub struct TypeParam {
117 pub index: TypeVarId,
119 pub name: String,
121 pub variance: Variance,
123}
124
125#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
127#[derive(Serialize, Deserialize, Drive, DriveMut, DriveTwo)]
128pub struct RegionParam {
129 pub index: RegionId,
131 pub name: Option<String>,
133 pub variance: Variance,
135 pub mutability: LifetimeMutability,
139 pub late_bound: bool,
142}
143
144#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
147#[derive(EnumIsA)]
148#[derive(Serialize, Deserialize)]
149#[cfg_attr(feature = "charon_on_charon", charon::variants_prefix("Lt"))]
150pub enum LifetimeMutability {
151 Mutable,
153 Shared,
155 Unknown,
157}
158
159#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
161#[derive(SerializeState, DeserializeState, Drive, DriveMut, DriveTwo)]
162pub struct ConstGenericParam {
163 pub index: ConstGenericVarId,
165 pub name: String,
167 pub ty: Ty,
169}
170
171#[derive(Debug, Clone)]
174#[derive(SerializeState, DeserializeState, Drive, DriveMut, DriveTwo)]
175pub struct TraitParam {
176 pub clause_id: TraitClauseId,
178 pub span: Option<Span>,
180 pub origin: PredicateOrigin,
182 #[cfg_attr(feature = "charon_on_charon", charon::rename("trait"))]
184 pub trait_: PolyTraitDeclRef,
185}
186
187#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
189#[derive(SerializeState, DeserializeState, Drive, DriveMut, DriveTwo)]
190pub enum PredicateOrigin {
191 WhereClauseOnFn,
198 WhereClauseOnType,
204 WhereClauseOnImpl,
211 TraitSelf,
217 WhereClauseOnTrait,
224 TraitItem(AssocTypeId),
230 #[cfg_attr(feature = "charon_on_charon", charon::rename("OriginDyn"))]
232 Dyn,
233}
234
235impl TypeParam {
236 pub fn new(index: TypeVarId, name: String, variance: Variance) -> Self {
237 Self {
238 index,
239 name,
240 variance,
241 }
242 }
243}
244
245impl RegionParam {
246 pub fn new(index: RegionId, name: Option<String>, variance: Variance) -> Self {
247 Self {
248 index,
249 name,
250 variance,
251 mutability: LifetimeMutability::Unknown,
252 late_bound: false,
253 }
254 }
255}
256
257impl ConstGenericParam {
258 pub fn new(index: ConstGenericVarId, name: String, ty: Ty) -> Self {
259 Self { index, name, ty }
260 }
261}
262
263impl TraitParam {
264 pub fn identity_tref(&self) -> PolyTraitRef {
266 self.identity_tref_at_depth(DeBruijnId::zero())
267 }
268
269 pub fn identity_tref_at_depth(&self, depth: DeBruijnId) -> PolyTraitRef {
271 let regions = self.trait_.identity_region_args();
272 PolyTraitRef(
273 self.trait_
274 .clone()
275 .move_under_binders(depth)
276 .map(|trait_decl_ref| {
277 TraitRef::new(
278 TraitRefKind::Clause(
279 DeBruijnVar::bound(depth.incr(), self.clause_id),
280 regions,
281 ),
282 trait_decl_ref,
283 )
284 }),
285 )
286 }
287}
288
289impl PartialEq for TraitParam {
290 fn eq(&self, other: &Self) -> bool {
291 self.clause_id == other.clause_id && self.trait_ == other.trait_
293 }
294}
295
296impl Eq for TraitParam {}
297
298impl PartialOrd for TraitParam {
299 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
300 Some(self.cmp(other))
301 }
302}
303
304impl Ord for TraitParam {
305 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
306 (&self.clause_id, &self.trait_).cmp(&(&other.clause_id, &other.trait_))
307 }
308}
309
310impl std::hash::Hash for TraitParam {
311 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
312 self.clause_id.hash(state);
313 self.trait_.hash(state);
314 }
315}
316
317pub type RegionDbVar = DeBruijnVar<RegionId>;
318pub type TypeDbVar = DeBruijnVar<TypeVarId>;
319pub type ConstGenericDbVar = DeBruijnVar<ConstGenericVarId>;
320pub type ClauseDbVar = DeBruijnVar<TraitClauseId>;
321
322impl_from_enum!(Region::Var(RegionDbVar));
323impl_from_enum!(TyKind::TypeVar(TypeDbVar));
324impl_from_enum!(ConstantExprKind::Var(ConstGenericDbVar));
325impl From<TypeDbVar> for Ty {
326 fn from(x: TypeDbVar) -> Self {
327 TyKind::TypeVar(x).into_ty()
328 }
329}
330
331impl DeBruijnId {
332 pub fn zero() -> Self {
333 DeBruijnId { index: 0 }
334 }
335
336 pub fn one() -> Self {
337 DeBruijnId { index: 1 }
338 }
339
340 pub fn new(index: usize) -> Self {
341 DeBruijnId { index }
342 }
343
344 pub fn is_zero(&self) -> bool {
345 self.index == 0
346 }
347
348 pub fn incr(&self) -> Self {
349 DeBruijnId {
350 index: self.index + 1,
351 }
352 }
353
354 pub fn decr(&self) -> Self {
355 DeBruijnId {
356 index: self.index - 1,
357 }
358 }
359
360 pub fn plus(&self, delta: Self) -> Self {
361 DeBruijnId {
362 index: self.index + delta.index,
363 }
364 }
365
366 pub fn sub(&self, delta: Self) -> Option<Self> {
367 Some(DeBruijnId {
368 index: self.index.checked_sub(delta.index)?,
369 })
370 }
371}
372
373impl<Id> DeBruijnVar<Id>
374where
375 Id: Copy,
376{
377 pub fn new_at_zero(id: Id) -> Self {
378 DeBruijnVar::Bound(DeBruijnId::new(0), id)
379 }
380
381 pub fn free(id: Id) -> Self {
382 DeBruijnVar::Free(id)
383 }
384
385 pub fn bound(index: DeBruijnId, id: Id) -> Self {
386 DeBruijnVar::Bound(index, id)
387 }
388
389 pub fn incr(&self) -> Self {
390 match *self {
391 DeBruijnVar::Bound(dbid, varid) => DeBruijnVar::Bound(dbid.incr(), varid),
392 DeBruijnVar::Free(varid) => DeBruijnVar::Free(varid),
393 }
394 }
395
396 pub fn decr(&self) -> Self {
397 match *self {
398 DeBruijnVar::Bound(dbid, varid) => DeBruijnVar::Bound(dbid.decr(), varid),
399 DeBruijnVar::Free(varid) => DeBruijnVar::Free(varid),
400 }
401 }
402
403 pub fn bound_at_depth(&self, depth: DeBruijnId) -> Option<Id> {
405 match *self {
406 DeBruijnVar::Bound(dbid, varid) if dbid == depth => Some(varid),
407 _ => None,
408 }
409 }
410 pub fn bound_at_depth_mut(&mut self, depth: DeBruijnId) -> Option<&mut Id> {
412 match self {
413 DeBruijnVar::Bound(dbid, varid) if *dbid == depth => Some(varid),
414 _ => None,
415 }
416 }
417
418 pub fn move_out_from_depth(&self, depth: DeBruijnId) -> Option<Self> {
421 Some(match *self {
422 DeBruijnVar::Bound(dbid, varid) => DeBruijnVar::Bound(dbid.sub(depth)?, varid),
423 DeBruijnVar::Free(_) => *self,
424 })
425 }
426
427 pub fn move_under_binders(&self, depth: DeBruijnId) -> Self {
429 match *self {
430 DeBruijnVar::Bound(dbid, varid) => DeBruijnVar::Bound(dbid.plus(depth), varid),
431 DeBruijnVar::Free(_) => *self,
432 }
433 }
434}
435
436impl Default for DeBruijnId {
437 fn default() -> Self {
438 Self::zero()
439 }
440}
441
442#[derive(Clone, Hash)]
447pub struct BindingStack<T> {
448 stack: Vec<T>,
451}
452
453impl<T> BindingStack<T> {
454 pub fn new(x: T) -> Self {
455 Self { stack: vec![x] }
456 }
457 pub fn empty() -> Self {
459 Self { stack: vec![] }
460 }
461
462 pub fn push(&mut self, x: T) {
463 self.stack.push(x);
464 }
465 pub fn pop(&mut self) -> Option<T> {
466 self.stack.pop()
467 }
468 pub fn into_iter(self) -> impl DoubleEndedIterator<Item = T> + ExactSizeIterator {
470 self.stack.into_iter().rev()
471 }
472}
473
474#[repr(transparent)]
476pub struct BinderSlice<T>([T]);
477
478impl<T> BinderSlice<T> {
479 fn from_slice(stack: &[T]) -> &Self {
480 unsafe { &*(stack as *const [T] as *const Self) }
482 }
483
484 fn from_slice_mut(stack: &mut [T]) -> &mut Self {
485 unsafe { &mut *(stack as *mut [T] as *mut Self) }
487 }
488
489 pub fn is_empty(&self) -> bool {
490 self.0.is_empty()
491 }
492 pub fn len(&self) -> usize {
493 self.0.len()
494 }
495 pub fn depth(&self) -> DeBruijnId {
496 DeBruijnId::new(self.0.len() - 1)
497 }
498
499 pub fn as_bound_var<Id>(&self, var: DeBruijnVar<Id>) -> (DeBruijnId, Id) {
502 match var {
503 DeBruijnVar::Bound(dbid, varid) => (dbid, varid),
504 DeBruijnVar::Free(varid) => (self.depth(), varid),
505 }
506 }
507 fn real_index(&self, id: DeBruijnId) -> Option<usize> {
509 self.0.len().checked_sub(id.index + 1)
510 }
511 pub fn get(&self, id: DeBruijnId) -> Option<&T> {
512 self.0.get(self.real_index(id)?)
513 }
514 pub fn get_var<'a, Id: Idx, Inner>(&'a self, var: DeBruijnVar<Id>) -> Option<&'a Inner::Output>
515 where
516 T: Borrow<Inner>,
517 Inner: HasIdxVecOf<Id> + 'a,
518 {
519 let (dbid, varid) = self.as_bound_var(var);
520 self.get(dbid)
521 .and_then(|x| x.borrow().get_idx_vec().get(varid))
522 }
523 pub fn get_mut(&mut self, id: DeBruijnId) -> Option<&mut T> {
524 let index = self.real_index(id)?;
525 self.0.get_mut(index)
526 }
527
528 pub fn iter(&self) -> impl DoubleEndedIterator<Item = &T> + ExactSizeIterator {
530 self.0.iter().rev()
531 }
532 pub fn iter_mut(&mut self) -> impl DoubleEndedIterator<Item = &mut T> + ExactSizeIterator {
534 self.0.iter_mut().rev()
535 }
536 pub fn indices(
538 &self,
539 ) -> impl DoubleEndedIterator<Item = DeBruijnId> + ExactSizeIterator + use<T> {
540 (0..self.0.len()).map(DeBruijnId::new)
541 }
542 pub fn iter_enumerated(
544 &self,
545 ) -> impl DoubleEndedIterator<Item = (DeBruijnId, &T)> + ExactSizeIterator {
546 self.iter()
547 .enumerate()
548 .map(|(i, x)| (DeBruijnId::new(i), x))
549 }
550 pub fn iter_mut_enumerated(
552 &mut self,
553 ) -> impl DoubleEndedIterator<Item = (DeBruijnId, &mut T)> + ExactSizeIterator {
554 self.iter_mut()
555 .enumerate()
556 .map(|(i, x)| (DeBruijnId::new(i), x))
557 }
558
559 pub fn map_ref<'a, U>(&'a self, f: impl FnMut(&'a T) -> U) -> BindingStack<U> {
560 BindingStack {
561 stack: self.0.iter().map(f).collect(),
562 }
563 }
564
565 pub fn place_at_outermost<U>(&mut self, val: &U) -> (U, &mut T)
567 where
568 U: TyVisitable + Clone,
569 {
570 for (depth, binder) in self.iter_mut_enumerated().rev() {
571 if let Some(val) = val.clone().move_from_under_binders(depth) {
572 return (val, binder);
573 }
574 }
575 unreachable!()
577 }
578
579 pub fn innermost(&self) -> &T {
580 self.0.last().unwrap()
581 }
582 pub fn innermost_mut(&mut self) -> &mut T {
583 self.0.last_mut().unwrap()
584 }
585 pub fn outermost(&self) -> &T {
586 self.0.first().unwrap()
587 }
588 pub fn outermost_mut(&mut self) -> &mut T {
589 self.0.first_mut().unwrap()
590 }
591}
592
593impl<T> Deref for BindingStack<T> {
594 type Target = BinderSlice<T>;
595 fn deref(&self) -> &Self::Target {
596 BinderSlice::from_slice(&self.stack)
597 }
598}
599impl<T> DerefMut for BindingStack<T> {
600 fn deref_mut(&mut self) -> &mut Self::Target {
601 BinderSlice::from_slice_mut(&mut self.stack)
602 }
603}
604
605impl<T> Default for BindingStack<T> {
606 fn default() -> Self {
607 Self {
608 stack: Default::default(),
609 }
610 }
611}
612
613impl<T: std::fmt::Debug> std::fmt::Debug for BindingStack<T> {
614 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
615 write!(f, "{:?}", self.stack)
616 }
617}
618
619impl<T> Index<DeBruijnId> for BinderSlice<T> {
620 type Output = T;
621 fn index(&self, id: DeBruijnId) -> &Self::Output {
622 self.get(id).unwrap()
623 }
624}
625impl<T> IndexMut<DeBruijnId> for BinderSlice<T> {
626 fn index_mut(&mut self, id: DeBruijnId) -> &mut Self::Output {
627 self.get_mut(id).unwrap()
628 }
629}
630
631impl<T> Index<RangeFrom<DeBruijnId>> for BinderSlice<T> {
633 type Output = BinderSlice<T>;
634 fn index(&self, range: RangeFrom<DeBruijnId>) -> &Self::Output {
635 let end = self.0.len() - range.start.index;
636 BinderSlice::from_slice(&self.0[..end])
637 }
638}
639impl<T> IndexMut<RangeFrom<DeBruijnId>> for BinderSlice<T> {
640 fn index_mut(&mut self, range: RangeFrom<DeBruijnId>) -> &mut Self::Output {
641 let end = self.0.len() - range.start.index;
642 BinderSlice::from_slice_mut(&mut self.0[..end])
643 }
644}