aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_ty/src/lib.rs
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2020-02-22 12:31:30 +0000
committerGitHub <[email protected]>2020-02-22 12:31:30 +0000
commit2cbe8a4c4be2a69b27c248ab96341c2336f983cd (patch)
treeee1a32b47f889ed132a314286cd90a07f3700216 /crates/ra_hir_ty/src/lib.rs
parent7836720f2e9a7fa01ae09ff9d51413ecd5877139 (diff)
parent5a6e770f99d1549432c1e8a1abb1aada09ad2590 (diff)
Merge #3263
3263: Implement unsizing coercions using Chalk r=matklad a=flodiebold These are coercions like `&[T; n] -> &[T]`, which are handled by the `Unsize` and `CoerceUnsized` traits. The impls for `Unsize` are all built in to the compiler and require special handling, so we need to provide them to Chalk. This adds the following `Unsize` impls: - `Unsize<[T]> for [T; _]` - `Unsize<dyn Trait> for T where T: Trait` - `Unsize<dyn SuperTrait> for dyn SubTrait` Hence we are still missing the 'unsizing the last field of a generic struct' case. Co-authored-by: Florian Diebold <[email protected]> Co-authored-by: Florian Diebold <[email protected]>
Diffstat (limited to 'crates/ra_hir_ty/src/lib.rs')
-rw-r--r--crates/ra_hir_ty/src/lib.rs48
1 files changed, 41 insertions, 7 deletions
diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs
index 13c5e6c6b..0009c426c 100644
--- a/crates/ra_hir_ty/src/lib.rs
+++ b/crates/ra_hir_ty/src/lib.rs
@@ -461,6 +461,12 @@ impl<T> Binders<T> {
461 } 461 }
462} 462}
463 463
464impl<T: Clone> Binders<&T> {
465 pub fn cloned(&self) -> Binders<T> {
466 Binders { num_binders: self.num_binders, value: self.value.clone() }
467 }
468}
469
464impl<T: TypeWalk> Binders<T> { 470impl<T: TypeWalk> Binders<T> {
465 /// Substitutes all variables. 471 /// Substitutes all variables.
466 pub fn subst(self, subst: &Substs) -> T { 472 pub fn subst(self, subst: &Substs) -> T {
@@ -661,6 +667,17 @@ impl Ty {
661 } 667 }
662 } 668 }
663 669
670 /// If this is a `dyn Trait` type, this returns the `Trait` part.
671 pub fn dyn_trait_ref(&self) -> Option<&TraitRef> {
672 match self {
673 Ty::Dyn(bounds) => bounds.get(0).and_then(|b| match b {
674 GenericPredicate::Implemented(trait_ref) => Some(trait_ref),
675 _ => None,
676 }),
677 _ => None,
678 }
679 }
680
664 fn builtin_deref(&self) -> Option<Ty> { 681 fn builtin_deref(&self) -> Option<Ty> {
665 match self { 682 match self {
666 Ty::Apply(a_ty) => match a_ty.ctor { 683 Ty::Apply(a_ty) => match a_ty.ctor {
@@ -746,6 +763,20 @@ pub trait TypeWalk {
746 /// variable for the self type. 763 /// variable for the self type.
747 fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize); 764 fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize);
748 765
766 fn fold_binders(mut self, f: &mut impl FnMut(Ty, usize) -> Ty, binders: usize) -> Self
767 where
768 Self: Sized,
769 {
770 self.walk_mut_binders(
771 &mut |ty_mut, binders| {
772 let ty = mem::replace(ty_mut, Ty::Unknown);
773 *ty_mut = f(ty, binders);
774 },
775 binders,
776 );
777 self
778 }
779
749 fn fold(mut self, f: &mut impl FnMut(Ty) -> Ty) -> Self 780 fn fold(mut self, f: &mut impl FnMut(Ty) -> Ty) -> Self
750 where 781 where
751 Self: Sized, 782 Self: Sized,
@@ -783,13 +814,16 @@ pub trait TypeWalk {
783 where 814 where
784 Self: Sized, 815 Self: Sized,
785 { 816 {
786 self.fold(&mut |ty| match ty { 817 self.fold_binders(
787 Ty::Bound(idx) => { 818 &mut |ty, binders| match ty {
788 assert!(idx as i32 >= -n); 819 Ty::Bound(idx) if idx as usize >= binders => {
789 Ty::Bound((idx as i32 + n) as u32) 820 assert!(idx as i32 >= -n);
790 } 821 Ty::Bound((idx as i32 + n) as u32)
791 ty => ty, 822 }
792 }) 823 ty => ty,
824 },
825 0,
826 )
793 } 827 }
794} 828}
795 829