aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_ty/src/lib.rs')
-rw-r--r--crates/hir_ty/src/lib.rs91
1 files changed, 34 insertions, 57 deletions
diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs
index 484652073..503910dde 100644
--- a/crates/hir_ty/src/lib.rs
+++ b/crates/hir_ty/src/lib.rs
@@ -151,17 +151,17 @@ pub enum TyKind {
151 Tuple(usize, Substs), 151 Tuple(usize, Substs),
152 152
153 /// An array with the given length. Written as `[T; n]`. 153 /// An array with the given length. Written as `[T; n]`.
154 Array(Substs), 154 Array(Ty),
155 155
156 /// The pointee of an array slice. Written as `[T]`. 156 /// The pointee of an array slice. Written as `[T]`.
157 Slice(Substs), 157 Slice(Ty),
158 158
159 /// A raw pointer. Written as `*mut T` or `*const T` 159 /// A raw pointer. Written as `*mut T` or `*const T`
160 Raw(Mutability, Substs), 160 Raw(Mutability, Ty),
161 161
162 /// A reference; a pointer with an associated lifetime. Written as 162 /// A reference; a pointer with an associated lifetime. Written as
163 /// `&'a mut T` or `&'a T`. 163 /// `&'a mut T` or `&'a T`.
164 Ref(Mutability, Substs), 164 Ref(Mutability, Ty),
165 165
166 /// This represents a placeholder for an opaque type in situations where we 166 /// This represents a placeholder for an opaque type in situations where we
167 /// don't know the hidden type (i.e. currently almost always). This is 167 /// don't know the hidden type (i.e. currently almost always). This is
@@ -248,11 +248,11 @@ pub enum TyKind {
248} 248}
249 249
250#[derive(Clone, PartialEq, Eq, Debug, Hash)] 250#[derive(Clone, PartialEq, Eq, Debug, Hash)]
251pub struct Ty(TyKind); 251pub struct Ty(Arc<TyKind>);
252 252
253impl TyKind { 253impl TyKind {
254 pub fn intern(self, _interner: &Interner) -> Ty { 254 pub fn intern(self, _interner: &Interner) -> Ty {
255 Ty(self) 255 Ty(Arc::new(self))
256 } 256 }
257} 257}
258 258
@@ -260,6 +260,14 @@ impl Ty {
260 pub fn interned(&self, _interner: &Interner) -> &TyKind { 260 pub fn interned(&self, _interner: &Interner) -> &TyKind {
261 &self.0 261 &self.0
262 } 262 }
263
264 pub fn interned_mut(&mut self) -> &mut TyKind {
265 Arc::make_mut(&mut self.0)
266 }
267
268 pub fn into_inner(self) -> TyKind {
269 Arc::try_unwrap(self.0).unwrap_or_else(|a| (*a).clone())
270 }
263} 271}
264 272
265/// A list of substitutions for generic parameters. 273/// A list of substitutions for generic parameters.
@@ -665,19 +673,15 @@ impl Ty {
665 673
666 pub fn as_reference(&self) -> Option<(&Ty, Mutability)> { 674 pub fn as_reference(&self) -> Option<(&Ty, Mutability)> {
667 match self.interned(&Interner) { 675 match self.interned(&Interner) {
668 TyKind::Ref(mutability, parameters) => Some((parameters.as_single(), *mutability)), 676 TyKind::Ref(mutability, ty) => Some((ty, *mutability)),
669 _ => None, 677 _ => None,
670 } 678 }
671 } 679 }
672 680
673 pub fn as_reference_or_ptr(&self) -> Option<(&Ty, Rawness, Mutability)> { 681 pub fn as_reference_or_ptr(&self) -> Option<(&Ty, Rawness, Mutability)> {
674 match self.interned(&Interner) { 682 match self.interned(&Interner) {
675 TyKind::Ref(mutability, parameters) => { 683 TyKind::Ref(mutability, ty) => Some((ty, Rawness::Ref, *mutability)),
676 Some((parameters.as_single(), Rawness::Ref, *mutability)) 684 TyKind::Raw(mutability, ty) => Some((ty, Rawness::RawPtr, *mutability)),
677 }
678 TyKind::Raw(mutability, parameters) => {
679 Some((parameters.as_single(), Rawness::RawPtr, *mutability))
680 }
681 _ => None, 685 _ => None,
682 } 686 }
683 } 687 }
@@ -685,8 +689,8 @@ impl Ty {
685 pub fn strip_references(&self) -> &Ty { 689 pub fn strip_references(&self) -> &Ty {
686 let mut t: &Ty = self; 690 let mut t: &Ty = self;
687 691
688 while let TyKind::Ref(_mutability, parameters) = t.interned(&Interner) { 692 while let TyKind::Ref(_mutability, ty) = t.interned(&Interner) {
689 t = parameters.as_single(); 693 t = ty;
690 } 694 }
691 695
692 t 696 t
@@ -772,8 +776,8 @@ impl Ty {
772 776
773 fn builtin_deref(&self) -> Option<Ty> { 777 fn builtin_deref(&self) -> Option<Ty> {
774 match self.interned(&Interner) { 778 match self.interned(&Interner) {
775 TyKind::Ref(.., parameters) => Some(Ty::clone(parameters.as_single())), 779 TyKind::Ref(.., ty) => Some(ty.clone()),
776 TyKind::Raw(.., parameters) => Some(Ty::clone(parameters.as_single())), 780 TyKind::Raw(.., ty) => Some(ty.clone()),
777 _ => None, 781 _ => None,
778 } 782 }
779 } 783 }
@@ -809,40 +813,11 @@ impl Ty {
809 } 813 }
810 } 814 }
811 815
812 /// If this is a type with type parameters (an ADT or function), replaces
813 /// the `Substs` for these type parameters with the given ones. (So e.g. if
814 /// `self` is `Option<_>` and the substs contain `u32`, we'll have
815 /// `Option<u32>` afterwards.)
816 pub fn apply_substs(mut self, new_substs: Substs) -> Ty {
817 match &mut self.0 {
818 TyKind::Adt(_, substs)
819 | TyKind::Slice(substs)
820 | TyKind::Array(substs)
821 | TyKind::Raw(_, substs)
822 | TyKind::Ref(_, substs)
823 | TyKind::FnDef(_, substs)
824 | TyKind::Function(FnPointer { substs, .. })
825 | TyKind::Tuple(_, substs)
826 | TyKind::OpaqueType(_, substs)
827 | TyKind::AssociatedType(_, substs)
828 | TyKind::Closure(.., substs) => {
829 assert_eq!(substs.len(), new_substs.len());
830 *substs = new_substs;
831 }
832 _ => (),
833 }
834 self
835 }
836
837 /// Returns the type parameters of this type if it has some (i.e. is an ADT 816 /// Returns the type parameters of this type if it has some (i.e. is an ADT
838 /// or function); so if `self` is `Option<u32>`, this returns the `u32`. 817 /// or function); so if `self` is `Option<u32>`, this returns the `u32`.
839 pub fn substs(&self) -> Option<&Substs> { 818 pub fn substs(&self) -> Option<&Substs> {
840 match self.interned(&Interner) { 819 match self.interned(&Interner) {
841 TyKind::Adt(_, substs) 820 TyKind::Adt(_, substs)
842 | TyKind::Slice(substs)
843 | TyKind::Array(substs)
844 | TyKind::Raw(_, substs)
845 | TyKind::Ref(_, substs)
846 | TyKind::FnDef(_, substs) 821 | TyKind::FnDef(_, substs)
847 | TyKind::Function(FnPointer { substs, .. }) 822 | TyKind::Function(FnPointer { substs, .. })
848 | TyKind::Tuple(_, substs) 823 | TyKind::Tuple(_, substs)
@@ -853,13 +828,9 @@ impl Ty {
853 } 828 }
854 } 829 }
855 830
856 pub fn substs_mut(&mut self) -> Option<&mut Substs> { 831 fn substs_mut(&mut self) -> Option<&mut Substs> {
857 match &mut self.0 { 832 match self.interned_mut() {
858 TyKind::Adt(_, substs) 833 TyKind::Adt(_, substs)
859 | TyKind::Slice(substs)
860 | TyKind::Array(substs)
861 | TyKind::Raw(_, substs)
862 | TyKind::Ref(_, substs)
863 | TyKind::FnDef(_, substs) 834 | TyKind::FnDef(_, substs)
864 | TyKind::Function(FnPointer { substs, .. }) 835 | TyKind::Function(FnPointer { substs, .. })
865 | TyKind::Tuple(_, substs) 836 | TyKind::Tuple(_, substs)
@@ -988,7 +959,7 @@ pub trait TypeWalk {
988 { 959 {
989 self.walk_mut_binders( 960 self.walk_mut_binders(
990 &mut |ty_mut, binders| { 961 &mut |ty_mut, binders| {
991 let ty = mem::replace(ty_mut, Ty(TyKind::Unknown)); 962 let ty = mem::replace(ty_mut, TyKind::Unknown.intern(&Interner));
992 *ty_mut = f(ty, binders); 963 *ty_mut = f(ty, binders);
993 }, 964 },
994 binders, 965 binders,
@@ -1001,7 +972,7 @@ pub trait TypeWalk {
1001 Self: Sized, 972 Self: Sized,
1002 { 973 {
1003 self.walk_mut(&mut |ty_mut| { 974 self.walk_mut(&mut |ty_mut| {
1004 let ty = mem::replace(ty_mut, Ty(TyKind::Unknown)); 975 let ty = mem::replace(ty_mut, TyKind::Unknown.intern(&Interner));
1005 *ty_mut = f(ty); 976 *ty_mut = f(ty);
1006 }); 977 });
1007 self 978 self
@@ -1022,7 +993,7 @@ pub trait TypeWalk {
1022 { 993 {
1023 self.walk_mut_binders( 994 self.walk_mut_binders(
1024 &mut |ty, binders| { 995 &mut |ty, binders| {
1025 if let &mut TyKind::BoundVar(bound) = &mut ty.0 { 996 if let &mut TyKind::BoundVar(bound) = ty.interned_mut() {
1026 if bound.debruijn >= binders { 997 if bound.debruijn >= binders {
1027 *ty = substs.0[bound.index].clone().shift_bound_vars(binders); 998 *ty = substs.0[bound.index].clone().shift_bound_vars(binders);
1028 } 999 }
@@ -1039,7 +1010,7 @@ pub trait TypeWalk {
1039 Self: Sized, 1010 Self: Sized,
1040 { 1011 {
1041 self.fold_binders( 1012 self.fold_binders(
1042 &mut |ty, binders| match &ty.0 { 1013 &mut |ty, binders| match ty.interned(&Interner) {
1043 TyKind::BoundVar(bound) if bound.debruijn >= binders => { 1014 TyKind::BoundVar(bound) if bound.debruijn >= binders => {
1044 TyKind::BoundVar(bound.shifted_in_from(n)).intern(&Interner) 1015 TyKind::BoundVar(bound.shifted_in_from(n)).intern(&Interner)
1045 } 1016 }
@@ -1068,6 +1039,9 @@ impl TypeWalk for Ty {
1068 p.walk(f); 1039 p.walk(f);
1069 } 1040 }
1070 } 1041 }
1042 TyKind::Slice(ty) | TyKind::Array(ty) | TyKind::Ref(_, ty) | TyKind::Raw(_, ty) => {
1043 ty.walk(f);
1044 }
1071 _ => { 1045 _ => {
1072 if let Some(substs) = self.substs() { 1046 if let Some(substs) = self.substs() {
1073 for t in substs.iter() { 1047 for t in substs.iter() {
@@ -1084,7 +1058,7 @@ impl TypeWalk for Ty {
1084 f: &mut impl FnMut(&mut Ty, DebruijnIndex), 1058 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
1085 binders: DebruijnIndex, 1059 binders: DebruijnIndex,
1086 ) { 1060 ) {
1087 match &mut self.0 { 1061 match self.interned_mut() {
1088 TyKind::Alias(AliasTy::Projection(p_ty)) => { 1062 TyKind::Alias(AliasTy::Projection(p_ty)) => {
1089 p_ty.substitution.walk_mut_binders(f, binders); 1063 p_ty.substitution.walk_mut_binders(f, binders);
1090 } 1064 }
@@ -1096,6 +1070,9 @@ impl TypeWalk for Ty {
1096 TyKind::Alias(AliasTy::Opaque(o_ty)) => { 1070 TyKind::Alias(AliasTy::Opaque(o_ty)) => {
1097 o_ty.substitution.walk_mut_binders(f, binders); 1071 o_ty.substitution.walk_mut_binders(f, binders);
1098 } 1072 }
1073 TyKind::Slice(ty) | TyKind::Array(ty) | TyKind::Ref(_, ty) | TyKind::Raw(_, ty) => {
1074 ty.walk_mut_binders(f, binders);
1075 }
1099 _ => { 1076 _ => {
1100 if let Some(substs) = self.substs_mut() { 1077 if let Some(substs) = self.substs_mut() {
1101 substs.walk_mut_binders(f, binders); 1078 substs.walk_mut_binders(f, binders);