diff options
Diffstat (limited to 'crates/ra_hir_ty/src/lib.rs')
-rw-r--r-- | crates/ra_hir_ty/src/lib.rs | 34 |
1 files changed, 32 insertions, 2 deletions
diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs index cb7a60352..79084bb3e 100644 --- a/crates/ra_hir_ty/src/lib.rs +++ b/crates/ra_hir_ty/src/lib.rs | |||
@@ -453,6 +453,30 @@ impl Deref for Substs { | |||
453 | } | 453 | } |
454 | } | 454 | } |
455 | 455 | ||
456 | #[derive(Copy, Clone, PartialEq, Eq, Debug)] | ||
457 | pub struct Binders<T> { | ||
458 | pub num_binders: usize, | ||
459 | pub value: T, | ||
460 | } | ||
461 | |||
462 | impl<T> Binders<T> { | ||
463 | pub fn new(num_binders: usize, value: T) -> Self { Self { num_binders, value } } | ||
464 | } | ||
465 | |||
466 | impl<T: TypeWalk> Binders<T> { | ||
467 | /// Substitutes all variables. | ||
468 | pub fn subst(self, subst: &Substs) -> T { | ||
469 | assert_eq!(subst.len(), self.num_binders); | ||
470 | self.value.subst_bound_vars(subst) | ||
471 | } | ||
472 | |||
473 | /// Substitutes just a prefix of the variables (shifting the rest). | ||
474 | pub fn subst_prefix(self, subst: &Substs) -> Binders<T> { | ||
475 | assert!(subst.len() < self.num_binders); | ||
476 | Binders::new(self.num_binders - subst.len(), self.value.subst_bound_vars(subst)) | ||
477 | } | ||
478 | } | ||
479 | |||
456 | /// A trait with type parameters. This includes the `Self`, so this represents a concrete type implementing the trait. | 480 | /// A trait with type parameters. This includes the `Self`, so this represents a concrete type implementing the trait. |
457 | /// Name to be bikeshedded: TraitBound? TraitImplements? | 481 | /// Name to be bikeshedded: TraitBound? TraitImplements? |
458 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | 482 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] |
@@ -553,6 +577,9 @@ pub struct FnSig { | |||
553 | params_and_return: Arc<[Ty]>, | 577 | params_and_return: Arc<[Ty]>, |
554 | } | 578 | } |
555 | 579 | ||
580 | /// A polymorphic function signature. | ||
581 | pub type PolyFnSig = Binders<FnSig>; | ||
582 | |||
556 | impl FnSig { | 583 | impl FnSig { |
557 | pub fn from_params_and_return(mut params: Vec<Ty>, ret: Ty) -> FnSig { | 584 | pub fn from_params_and_return(mut params: Vec<Ty>, ret: Ty) -> FnSig { |
558 | params.push(ret); | 585 | params.push(ret); |
@@ -757,6 +784,9 @@ pub trait TypeWalk { | |||
757 | &mut Ty::Bound(idx) => { | 784 | &mut Ty::Bound(idx) => { |
758 | if idx as usize >= binders && (idx as usize - binders) < substs.len() { | 785 | if idx as usize >= binders && (idx as usize - binders) < substs.len() { |
759 | *ty = substs.0[idx as usize - binders].clone(); | 786 | *ty = substs.0[idx as usize - binders].clone(); |
787 | } else if idx as usize >= binders + substs.len() { | ||
788 | // shift free binders | ||
789 | *ty = Ty::Bound(idx - substs.len() as u32); | ||
760 | } | 790 | } |
761 | } | 791 | } |
762 | _ => {} | 792 | _ => {} |
@@ -903,8 +933,8 @@ impl HirDisplay for ApplicationTy { | |||
903 | write!(f, ">")?; | 933 | write!(f, ">")?; |
904 | } | 934 | } |
905 | write!(f, "(")?; | 935 | write!(f, "(")?; |
906 | f.write_joined(sig.params(), ", ")?; | 936 | f.write_joined(sig.value.params(), ", ")?; |
907 | write!(f, ") -> {}", sig.ret().display(f.db))?; | 937 | write!(f, ") -> {}", sig.value.ret().display(f.db))?; |
908 | } | 938 | } |
909 | TypeCtor::Adt(def_id) => { | 939 | TypeCtor::Adt(def_id) => { |
910 | let name = match def_id { | 940 | let name = match def_id { |