aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/ty.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/ty.rs')
-rw-r--r--crates/ra_hir/src/ty.rs93
1 files changed, 59 insertions, 34 deletions
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index ff6030ac4..b7f50b714 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -79,7 +79,7 @@ pub enum TypeCtor {
79 /// 79 ///
80 /// For example the type of `bar` here: 80 /// For example the type of `bar` here:
81 /// 81 ///
82 /// ```rust 82 /// ```
83 /// fn foo() -> i32 { 1 } 83 /// fn foo() -> i32 { 1 }
84 /// let bar = foo; // bar: fn() -> i32 {foo} 84 /// let bar = foo; // bar: fn() -> i32 {foo}
85 /// ``` 85 /// ```
@@ -89,7 +89,7 @@ pub enum TypeCtor {
89 /// 89 ///
90 /// For example the type of `bar` here: 90 /// For example the type of `bar` here:
91 /// 91 ///
92 /// ```rust 92 /// ```
93 /// fn foo() -> i32 { 1 } 93 /// fn foo() -> i32 { 1 }
94 /// let bar: fn() -> i32 = foo; 94 /// let bar: fn() -> i32 = foo;
95 /// ``` 95 /// ```
@@ -224,8 +224,8 @@ impl TypeWalk for ProjectionTy {
224 self.parameters.walk(f); 224 self.parameters.walk(f);
225 } 225 }
226 226
227 fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { 227 fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize) {
228 self.parameters.walk_mut(f); 228 self.parameters.walk_mut_binders(f, binders);
229 } 229 }
230} 230}
231 231
@@ -291,6 +291,20 @@ pub enum Ty {
291#[derive(Clone, PartialEq, Eq, Debug, Hash)] 291#[derive(Clone, PartialEq, Eq, Debug, Hash)]
292pub struct Substs(Arc<[Ty]>); 292pub struct Substs(Arc<[Ty]>);
293 293
294impl TypeWalk for Substs {
295 fn walk(&self, f: &mut impl FnMut(&Ty)) {
296 for t in self.0.iter() {
297 t.walk(f);
298 }
299 }
300
301 fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize) {
302 for t in make_mut_slice(&mut self.0) {
303 t.walk_mut_binders(f, binders);
304 }
305 }
306}
307
294impl Substs { 308impl Substs {
295 pub fn empty() -> Substs { 309 pub fn empty() -> Substs {
296 Substs(Arc::new([])) 310 Substs(Arc::new([]))
@@ -304,18 +318,6 @@ impl Substs {
304 Substs(self.0[..std::cmp::min(self.0.len(), n)].into()) 318 Substs(self.0[..std::cmp::min(self.0.len(), n)].into())
305 } 319 }
306 320
307 pub fn walk(&self, f: &mut impl FnMut(&Ty)) {
308 for t in self.0.iter() {
309 t.walk(f);
310 }
311 }
312
313 pub fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) {
314 for t in make_mut_slice(&mut self.0) {
315 t.walk_mut(f);
316 }
317 }
318
319 pub fn as_single(&self) -> &Ty { 321 pub fn as_single(&self) -> &Ty {
320 if self.0.len() != 1 { 322 if self.0.len() != 1 {
321 panic!("expected substs of len 1, got {:?}", self); 323 panic!("expected substs of len 1, got {:?}", self);
@@ -440,8 +442,8 @@ impl TypeWalk for TraitRef {
440 self.substs.walk(f); 442 self.substs.walk(f);
441 } 443 }
442 444
443 fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { 445 fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize) {
444 self.substs.walk_mut(f); 446 self.substs.walk_mut_binders(f, binders);
445 } 447 }
446} 448}
447 449
@@ -491,10 +493,12 @@ impl TypeWalk for GenericPredicate {
491 } 493 }
492 } 494 }
493 495
494 fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { 496 fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize) {
495 match self { 497 match self {
496 GenericPredicate::Implemented(trait_ref) => trait_ref.walk_mut(f), 498 GenericPredicate::Implemented(trait_ref) => trait_ref.walk_mut_binders(f, binders),
497 GenericPredicate::Projection(projection_pred) => projection_pred.walk_mut(f), 499 GenericPredicate::Projection(projection_pred) => {
500 projection_pred.walk_mut_binders(f, binders)
501 }
498 GenericPredicate::Error => {} 502 GenericPredicate::Error => {}
499 } 503 }
500 } 504 }
@@ -544,9 +548,9 @@ impl TypeWalk for FnSig {
544 } 548 }
545 } 549 }
546 550
547 fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { 551 fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize) {
548 for t in make_mut_slice(&mut self.params_and_return) { 552 for t in make_mut_slice(&mut self.params_and_return) {
549 t.walk_mut(f); 553 t.walk_mut_binders(f, binders);
550 } 554 }
551 } 555 }
552} 556}
@@ -671,7 +675,20 @@ impl Ty {
671/// types, similar to Chalk's `Fold` trait. 675/// types, similar to Chalk's `Fold` trait.
672pub trait TypeWalk { 676pub trait TypeWalk {
673 fn walk(&self, f: &mut impl FnMut(&Ty)); 677 fn walk(&self, f: &mut impl FnMut(&Ty));
674 fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)); 678 fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) {
679 self.walk_mut_binders(&mut |ty, _binders| f(ty), 0);
680 }
681 /// Walk the type, counting entered binders.
682 ///
683 /// `Ty::Bound` variables use DeBruijn indexing, which means that 0 refers
684 /// to the innermost binder, 1 to the next, etc.. So when we want to
685 /// substitute a certain bound variable, we can't just walk the whole type
686 /// and blindly replace each instance of a certain index; when we 'enter'
687 /// things that introduce new bound variables, we have to keep track of
688 /// that. Currently, the only thing that introduces bound variables on our
689 /// side are `Ty::Dyn` and `Ty::Opaque`, which each introduce a bound
690 /// variable for the self type.
691 fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize);
675 692
676 fn fold(mut self, f: &mut impl FnMut(Ty) -> Ty) -> Self 693 fn fold(mut self, f: &mut impl FnMut(Ty) -> Ty) -> Self
677 where 694 where
@@ -700,14 +717,22 @@ pub trait TypeWalk {
700 } 717 }
701 718
702 /// Substitutes `Ty::Bound` vars (as opposed to type parameters). 719 /// Substitutes `Ty::Bound` vars (as opposed to type parameters).
703 fn subst_bound_vars(self, substs: &Substs) -> Self 720 fn subst_bound_vars(mut self, substs: &Substs) -> Self
704 where 721 where
705 Self: Sized, 722 Self: Sized,
706 { 723 {
707 self.fold(&mut |ty| match ty { 724 self.walk_mut_binders(
708 Ty::Bound(idx) => substs.get(idx as usize).cloned().unwrap_or_else(|| Ty::Bound(idx)), 725 &mut |ty, binders| match ty {
709 ty => ty, 726 &mut Ty::Bound(idx) => {
710 }) 727 if idx as usize >= binders && (idx as usize - binders) < substs.len() {
728 *ty = substs.0[idx as usize - binders].clone();
729 }
730 }
731 _ => {}
732 },
733 0,
734 );
735 self
711 } 736 }
712 737
713 /// Shifts up `Ty::Bound` vars by `n`. 738 /// Shifts up `Ty::Bound` vars by `n`.
@@ -748,22 +773,22 @@ impl TypeWalk for Ty {
748 f(self); 773 f(self);
749 } 774 }
750 775
751 fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { 776 fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize) {
752 match self { 777 match self {
753 Ty::Apply(a_ty) => { 778 Ty::Apply(a_ty) => {
754 a_ty.parameters.walk_mut(f); 779 a_ty.parameters.walk_mut_binders(f, binders);
755 } 780 }
756 Ty::Projection(p_ty) => { 781 Ty::Projection(p_ty) => {
757 p_ty.parameters.walk_mut(f); 782 p_ty.parameters.walk_mut_binders(f, binders);
758 } 783 }
759 Ty::Dyn(predicates) | Ty::Opaque(predicates) => { 784 Ty::Dyn(predicates) | Ty::Opaque(predicates) => {
760 for p in make_mut_slice(predicates) { 785 for p in make_mut_slice(predicates) {
761 p.walk_mut(f); 786 p.walk_mut_binders(f, binders + 1);
762 } 787 }
763 } 788 }
764 Ty::Param { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {} 789 Ty::Param { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {}
765 } 790 }
766 f(self); 791 f(self, binders);
767 } 792 }
768} 793}
769 794