diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2020-02-22 12:31:30 +0000 |
---|---|---|
committer | GitHub <[email protected]> | 2020-02-22 12:31:30 +0000 |
commit | 2cbe8a4c4be2a69b27c248ab96341c2336f983cd (patch) | |
tree | ee1a32b47f889ed132a314286cd90a07f3700216 /crates/ra_hir_ty/src/lib.rs | |
parent | 7836720f2e9a7fa01ae09ff9d51413ecd5877139 (diff) | |
parent | 5a6e770f99d1549432c1e8a1abb1aada09ad2590 (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.rs | 48 |
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 | ||
464 | impl<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 | |||
464 | impl<T: TypeWalk> Binders<T> { | 470 | impl<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 | ||