aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_ty')
-rw-r--r--crates/hir_ty/src/display.rs9
-rw-r--r--crates/hir_ty/src/infer.rs30
-rw-r--r--crates/hir_ty/src/infer/coerce.rs12
-rw-r--r--crates/hir_ty/src/infer/expr.rs21
-rw-r--r--crates/hir_ty/src/infer/pat.rs22
-rw-r--r--crates/hir_ty/src/infer/unify.rs28
-rw-r--r--crates/hir_ty/src/lib.rs91
-rw-r--r--crates/hir_ty/src/lower.rs12
-rw-r--r--crates/hir_ty/src/method_resolution.rs6
-rw-r--r--crates/hir_ty/src/traits/chalk/mapping.rs32
10 files changed, 126 insertions, 137 deletions
diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs
index 378c951c5..c1062387e 100644
--- a/crates/hir_ty/src/display.rs
+++ b/crates/hir_ty/src/display.rs
@@ -276,20 +276,17 @@ impl HirDisplay for Ty {
276 &TyKind::Scalar(Scalar::Float(t)) => write!(f, "{}", primitive::float_ty_to_string(t))?, 276 &TyKind::Scalar(Scalar::Float(t)) => write!(f, "{}", primitive::float_ty_to_string(t))?,
277 &TyKind::Scalar(Scalar::Int(t)) => write!(f, "{}", primitive::int_ty_to_string(t))?, 277 &TyKind::Scalar(Scalar::Int(t)) => write!(f, "{}", primitive::int_ty_to_string(t))?,
278 &TyKind::Scalar(Scalar::Uint(t)) => write!(f, "{}", primitive::uint_ty_to_string(t))?, 278 &TyKind::Scalar(Scalar::Uint(t)) => write!(f, "{}", primitive::uint_ty_to_string(t))?,
279 TyKind::Slice(parameters) => { 279 TyKind::Slice(t) => {
280 let t = parameters.as_single();
281 write!(f, "[")?; 280 write!(f, "[")?;
282 t.hir_fmt(f)?; 281 t.hir_fmt(f)?;
283 write!(f, "]")?; 282 write!(f, "]")?;
284 } 283 }
285 TyKind::Array(parameters) => { 284 TyKind::Array(t) => {
286 let t = parameters.as_single();
287 write!(f, "[")?; 285 write!(f, "[")?;
288 t.hir_fmt(f)?; 286 t.hir_fmt(f)?;
289 write!(f, "; _]")?; 287 write!(f, "; _]")?;
290 } 288 }
291 TyKind::Raw(m, parameters) | TyKind::Ref(m, parameters) => { 289 TyKind::Raw(m, t) | TyKind::Ref(m, t) => {
292 let t = parameters.as_single();
293 let ty_display = 290 let ty_display =
294 t.into_displayable(f.db, f.max_size, f.omit_verbose_types, f.display_target); 291 t.into_displayable(f.db, f.max_size, f.omit_verbose_types, f.display_target);
295 292
diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs
index 9f29098ee..9c385b845 100644
--- a/crates/hir_ty/src/infer.rs
+++ b/crates/hir_ty/src/infer.rs
@@ -108,6 +108,17 @@ pub struct TypeMismatch {
108 pub actual: Ty, 108 pub actual: Ty,
109} 109}
110 110
111#[derive(Clone, PartialEq, Eq, Debug)]
112struct InternedStandardTypes {
113 unknown: Ty,
114}
115
116impl Default for InternedStandardTypes {
117 fn default() -> Self {
118 InternedStandardTypes { unknown: TyKind::Unknown.intern(&Interner) }
119 }
120}
121
111/// The result of type inference: A mapping from expressions and patterns to types. 122/// The result of type inference: A mapping from expressions and patterns to types.
112#[derive(Clone, PartialEq, Eq, Debug, Default)] 123#[derive(Clone, PartialEq, Eq, Debug, Default)]
113pub struct InferenceResult { 124pub struct InferenceResult {
@@ -126,6 +137,8 @@ pub struct InferenceResult {
126 pub type_of_expr: ArenaMap<ExprId, Ty>, 137 pub type_of_expr: ArenaMap<ExprId, Ty>,
127 pub type_of_pat: ArenaMap<PatId, Ty>, 138 pub type_of_pat: ArenaMap<PatId, Ty>,
128 pub(super) type_mismatches: ArenaMap<ExprId, TypeMismatch>, 139 pub(super) type_mismatches: ArenaMap<ExprId, TypeMismatch>,
140 /// Interned Unknown to return references to.
141 standard_types: InternedStandardTypes,
129} 142}
130 143
131impl InferenceResult { 144impl InferenceResult {
@@ -170,7 +183,7 @@ impl Index<ExprId> for InferenceResult {
170 type Output = Ty; 183 type Output = Ty;
171 184
172 fn index(&self, expr: ExprId) -> &Ty { 185 fn index(&self, expr: ExprId) -> &Ty {
173 self.type_of_expr.get(expr).unwrap_or(&Ty(TyKind::Unknown)) 186 self.type_of_expr.get(expr).unwrap_or(&self.standard_types.unknown)
174 } 187 }
175} 188}
176 189
@@ -178,7 +191,7 @@ impl Index<PatId> for InferenceResult {
178 type Output = Ty; 191 type Output = Ty;
179 192
180 fn index(&self, pat: PatId) -> &Ty { 193 fn index(&self, pat: PatId) -> &Ty {
181 self.type_of_pat.get(pat).unwrap_or(&Ty(TyKind::Unknown)) 194 self.type_of_pat.get(pat).unwrap_or(&self.standard_types.unknown)
182 } 195 }
183} 196}
184 197
@@ -723,14 +736,19 @@ impl Expectation {
723 736
724 /// This expresses no expectation on the type. 737 /// This expresses no expectation on the type.
725 fn none() -> Self { 738 fn none() -> Self {
726 Expectation { ty: TyKind::Unknown.intern(&Interner), rvalue_hint: false } 739 Expectation {
740 // FIXME
741 ty: TyKind::Unknown.intern(&Interner),
742 rvalue_hint: false,
743 }
727 } 744 }
728 745
729 fn coercion_target(&self) -> &Ty { 746 fn coercion_target(&self) -> Ty {
730 if self.rvalue_hint { 747 if self.rvalue_hint {
731 &Ty(TyKind::Unknown) 748 // FIXME
749 TyKind::Unknown.intern(&Interner)
732 } else { 750 } else {
733 &self.ty 751 self.ty.clone()
734 } 752 }
735 } 753 }
736} 754}
diff --git a/crates/hir_ty/src/infer/coerce.rs b/crates/hir_ty/src/infer/coerce.rs
index 36670043a..137419264 100644
--- a/crates/hir_ty/src/infer/coerce.rs
+++ b/crates/hir_ty/src/infer/coerce.rs
@@ -71,7 +71,7 @@ impl<'a> InferenceContext<'a> {
71 } 71 }
72 72
73 // Pointer weakening and function to pointer 73 // Pointer weakening and function to pointer
74 match (&mut from_ty.0, to_ty.interned(&Interner)) { 74 match (from_ty.interned_mut(), to_ty.interned(&Interner)) {
75 // `*mut T` -> `*const T` 75 // `*mut T` -> `*const T`
76 // `&mut T` -> `&T` 76 // `&mut T` -> `&T`
77 (TyKind::Raw(m1, ..), TyKind::Raw(m2 @ Mutability::Not, ..)) 77 (TyKind::Raw(m1, ..), TyKind::Raw(m2 @ Mutability::Not, ..))
@@ -111,9 +111,7 @@ impl<'a> InferenceContext<'a> {
111 // Auto Deref if cannot coerce 111 // Auto Deref if cannot coerce
112 match (from_ty.interned(&Interner), to_ty.interned(&Interner)) { 112 match (from_ty.interned(&Interner), to_ty.interned(&Interner)) {
113 // FIXME: DerefMut 113 // FIXME: DerefMut
114 (TyKind::Ref(_, st1), TyKind::Ref(_, st2)) => { 114 (TyKind::Ref(_, st1), TyKind::Ref(_, st2)) => self.unify_autoderef_behind_ref(st1, st2),
115 self.unify_autoderef_behind_ref(&st1[0], &st2[0])
116 }
117 115
118 // Otherwise, normal unify 116 // Otherwise, normal unify
119 _ => self.unify(&from_ty, to_ty), 117 _ => self.unify(&from_ty, to_ty),
@@ -178,11 +176,7 @@ impl<'a> InferenceContext<'a> {
178 // Stop when constructor matches. 176 // Stop when constructor matches.
179 if from_ty.equals_ctor(&to_ty) { 177 if from_ty.equals_ctor(&to_ty) {
180 // It will not recurse to `coerce`. 178 // It will not recurse to `coerce`.
181 return match (from_ty.substs(), to_ty.substs()) { 179 return self.table.unify(&from_ty, &to_ty);
182 (Some(st1), Some(st2)) => self.table.unify_substs(st1, st2, 0),
183 (None, None) => true,
184 _ => false,
185 };
186 } else if self.table.unify_inner_trivial(&derefed_ty, &to_ty, 0) { 180 } else if self.table.unify_inner_trivial(&derefed_ty, &to_ty, 0) {
187 return true; 181 return true;
188 } 182 }
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs
index 1a11b146a..f40dec17f 100644
--- a/crates/hir_ty/src/infer/expr.rs
+++ b/crates/hir_ty/src/infer/expr.rs
@@ -503,8 +503,8 @@ impl<'a> InferenceContext<'a> {
503 }; 503 };
504 let inner_ty = self.infer_expr_inner(*expr, &expectation); 504 let inner_ty = self.infer_expr_inner(*expr, &expectation);
505 match rawness { 505 match rawness {
506 Rawness::RawPtr => TyKind::Raw(mutability, Substs::single(inner_ty)), 506 Rawness::RawPtr => TyKind::Raw(mutability, inner_ty),
507 Rawness::Ref => TyKind::Ref(mutability, Substs::single(inner_ty)), 507 Rawness::Ref => TyKind::Ref(mutability, inner_ty),
508 } 508 }
509 .intern(&Interner) 509 .intern(&Interner)
510 } 510 }
@@ -685,7 +685,7 @@ impl<'a> InferenceContext<'a> {
685 } 685 }
686 Expr::Array(array) => { 686 Expr::Array(array) => {
687 let elem_ty = match expected.ty.interned(&Interner) { 687 let elem_ty = match expected.ty.interned(&Interner) {
688 TyKind::Array(st) | TyKind::Slice(st) => st.as_single().clone(), 688 TyKind::Array(st) | TyKind::Slice(st) => st.clone(),
689 _ => self.table.new_type_var(), 689 _ => self.table.new_type_var(),
690 }; 690 };
691 691
@@ -709,18 +709,17 @@ impl<'a> InferenceContext<'a> {
709 } 709 }
710 } 710 }
711 711
712 TyKind::Array(Substs::single(elem_ty)).intern(&Interner) 712 TyKind::Array(elem_ty).intern(&Interner)
713 } 713 }
714 Expr::Literal(lit) => match lit { 714 Expr::Literal(lit) => match lit {
715 Literal::Bool(..) => TyKind::Scalar(Scalar::Bool).intern(&Interner), 715 Literal::Bool(..) => TyKind::Scalar(Scalar::Bool).intern(&Interner),
716 Literal::String(..) => { 716 Literal::String(..) => {
717 TyKind::Ref(Mutability::Not, Substs::single(TyKind::Str.intern(&Interner))) 717 TyKind::Ref(Mutability::Not, TyKind::Str.intern(&Interner)).intern(&Interner)
718 .intern(&Interner)
719 } 718 }
720 Literal::ByteString(..) => { 719 Literal::ByteString(..) => {
721 let byte_type = TyKind::Scalar(Scalar::Uint(UintTy::U8)).intern(&Interner); 720 let byte_type = TyKind::Scalar(Scalar::Uint(UintTy::U8)).intern(&Interner);
722 let array_type = TyKind::Array(Substs::single(byte_type)).intern(&Interner); 721 let array_type = TyKind::Array(byte_type).intern(&Interner);
723 TyKind::Ref(Mutability::Not, Substs::single(array_type)).intern(&Interner) 722 TyKind::Ref(Mutability::Not, array_type).intern(&Interner)
724 } 723 }
725 Literal::Char(..) => TyKind::Scalar(Scalar::Char).intern(&Interner), 724 Literal::Char(..) => TyKind::Scalar(Scalar::Char).intern(&Interner),
726 Literal::Int(_v, ty) => match ty { 725 Literal::Int(_v, ty) => match ty {
@@ -799,7 +798,7 @@ impl<'a> InferenceContext<'a> {
799 // we don't even make an attempt at coercion 798 // we don't even make an attempt at coercion
800 self.table.new_maybe_never_var() 799 self.table.new_maybe_never_var()
801 } else { 800 } else {
802 self.coerce(&Ty::unit(), expected.coercion_target()); 801 self.coerce(&Ty::unit(), &expected.coercion_target());
803 Ty::unit() 802 Ty::unit()
804 } 803 }
805 }; 804 };
@@ -854,9 +853,7 @@ impl<'a> InferenceContext<'a> {
854 // Apply autoref so the below unification works correctly 853 // Apply autoref so the below unification works correctly
855 // FIXME: return correct autorefs from lookup_method 854 // FIXME: return correct autorefs from lookup_method
856 let actual_receiver_ty = match expected_receiver_ty.as_reference() { 855 let actual_receiver_ty = match expected_receiver_ty.as_reference() {
857 Some((_, mutability)) => { 856 Some((_, mutability)) => TyKind::Ref(mutability, derefed_receiver_ty).intern(&Interner),
858 TyKind::Ref(mutability, Substs::single(derefed_receiver_ty)).intern(&Interner)
859 }
860 _ => derefed_receiver_ty, 857 _ => derefed_receiver_ty,
861 }; 858 };
862 self.unify(&expected_receiver_ty, &actual_receiver_ty); 859 self.unify(&expected_receiver_ty, &actual_receiver_ty);
diff --git a/crates/hir_ty/src/infer/pat.rs b/crates/hir_ty/src/infer/pat.rs
index a16755cda..9e8ca18ef 100644
--- a/crates/hir_ty/src/infer/pat.rs
+++ b/crates/hir_ty/src/infer/pat.rs
@@ -158,12 +158,12 @@ impl<'a> InferenceContext<'a> {
158 if mutability != exp_mut { 158 if mutability != exp_mut {
159 // FIXME: emit type error? 159 // FIXME: emit type error?
160 } 160 }
161 inner_ty 161 inner_ty.clone()
162 } 162 }
163 _ => &Ty(TyKind::Unknown), 163 _ => self.result.standard_types.unknown.clone(),
164 }; 164 };
165 let subty = self.infer_pat(*pat, expectation, default_bm); 165 let subty = self.infer_pat(*pat, &expectation, default_bm);
166 TyKind::Ref(mutability, Substs::single(subty)).intern(&Interner) 166 TyKind::Ref(mutability, subty).intern(&Interner)
167 } 167 }
168 Pat::TupleStruct { path: p, args: subpats, ellipsis } => self.infer_tuple_struct_pat( 168 Pat::TupleStruct { path: p, args: subpats, ellipsis } => self.infer_tuple_struct_pat(
169 p.as_ref(), 169 p.as_ref(),
@@ -196,7 +196,7 @@ impl<'a> InferenceContext<'a> {
196 196
197 let bound_ty = match mode { 197 let bound_ty = match mode {
198 BindingMode::Ref(mutability) => { 198 BindingMode::Ref(mutability) => {
199 TyKind::Ref(mutability, Substs::single(inner_ty.clone())).intern(&Interner) 199 TyKind::Ref(mutability, inner_ty.clone()).intern(&Interner)
200 } 200 }
201 BindingMode::Move => inner_ty.clone(), 201 BindingMode::Move => inner_ty.clone(),
202 }; 202 };
@@ -206,8 +206,8 @@ impl<'a> InferenceContext<'a> {
206 } 206 }
207 Pat::Slice { prefix, slice, suffix } => { 207 Pat::Slice { prefix, slice, suffix } => {
208 let (container_ty, elem_ty): (fn(_) -> _, _) = match expected.interned(&Interner) { 208 let (container_ty, elem_ty): (fn(_) -> _, _) = match expected.interned(&Interner) {
209 TyKind::Array(st) => (TyKind::Array, st.as_single().clone()), 209 TyKind::Array(st) => (TyKind::Array, st.clone()),
210 TyKind::Slice(st) => (TyKind::Slice, st.as_single().clone()), 210 TyKind::Slice(st) => (TyKind::Slice, st.clone()),
211 _ => (TyKind::Slice, self.err_ty()), 211 _ => (TyKind::Slice, self.err_ty()),
212 }; 212 };
213 213
@@ -215,7 +215,7 @@ impl<'a> InferenceContext<'a> {
215 self.infer_pat(*pat_id, &elem_ty, default_bm); 215 self.infer_pat(*pat_id, &elem_ty, default_bm);
216 } 216 }
217 217
218 let pat_ty = container_ty(Substs::single(elem_ty)).intern(&Interner); 218 let pat_ty = container_ty(elem_ty).intern(&Interner);
219 if let Some(slice_pat_id) = slice { 219 if let Some(slice_pat_id) = slice {
220 self.infer_pat(*slice_pat_id, &pat_ty, default_bm); 220 self.infer_pat(*slice_pat_id, &pat_ty, default_bm);
221 } 221 }
@@ -232,11 +232,11 @@ impl<'a> InferenceContext<'a> {
232 Pat::Box { inner } => match self.resolve_boxed_box() { 232 Pat::Box { inner } => match self.resolve_boxed_box() {
233 Some(box_adt) => { 233 Some(box_adt) => {
234 let inner_expected = match expected.as_adt() { 234 let inner_expected = match expected.as_adt() {
235 Some((adt, substs)) if adt == box_adt => substs.as_single(), 235 Some((adt, substs)) if adt == box_adt => substs.as_single().clone(),
236 _ => &Ty(TyKind::Unknown), 236 _ => self.result.standard_types.unknown.clone(),
237 }; 237 };
238 238
239 let inner_ty = self.infer_pat(*inner, inner_expected, default_bm); 239 let inner_ty = self.infer_pat(*inner, &inner_expected, default_bm);
240 Ty::adt_ty(box_adt, Substs::single(inner_ty)) 240 Ty::adt_ty(box_adt, Substs::single(inner_ty))
241 } 241 }
242 None => self.err_ty(), 242 None => self.err_ty(),
diff --git a/crates/hir_ty/src/infer/unify.rs b/crates/hir_ty/src/infer/unify.rs
index ebc612ca9..66f8fe8a3 100644
--- a/crates/hir_ty/src/infer/unify.rs
+++ b/crates/hir_ty/src/infer/unify.rs
@@ -7,8 +7,8 @@ use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue};
7 7
8use super::{InferenceContext, Obligation}; 8use super::{InferenceContext, Obligation};
9use crate::{ 9use crate::{
10 BoundVar, Canonical, DebruijnIndex, GenericPredicate, InEnvironment, InferenceVar, Interner, 10 BoundVar, Canonical, DebruijnIndex, FnPointer, GenericPredicate, InEnvironment, InferenceVar,
11 Scalar, Substs, Ty, TyKind, TypeWalk, 11 Interner, Scalar, Substs, Ty, TyKind, TypeWalk,
12}; 12};
13 13
14impl<'a> InferenceContext<'a> { 14impl<'a> InferenceContext<'a> {
@@ -108,7 +108,7 @@ impl<T> Canonicalized<T> {
108 pub(super) fn decanonicalize_ty(&self, mut ty: Ty) -> Ty { 108 pub(super) fn decanonicalize_ty(&self, mut ty: Ty) -> Ty {
109 ty.walk_mut_binders( 109 ty.walk_mut_binders(
110 &mut |ty, binders| { 110 &mut |ty, binders| {
111 if let &mut TyKind::BoundVar(bound) = &mut ty.0 { 111 if let &mut TyKind::BoundVar(bound) = ty.interned_mut() {
112 if bound.debruijn >= binders { 112 if bound.debruijn >= binders {
113 let (v, k) = self.free_vars[bound.index]; 113 let (v, k) = self.free_vars[bound.index];
114 *ty = TyKind::InferenceVar(v, k).intern(&Interner); 114 *ty = TyKind::InferenceVar(v, k).intern(&Interner);
@@ -283,9 +283,23 @@ impl InferenceTable {
283 let ty1 = self.resolve_ty_shallow(ty1); 283 let ty1 = self.resolve_ty_shallow(ty1);
284 let ty2 = self.resolve_ty_shallow(ty2); 284 let ty2 = self.resolve_ty_shallow(ty2);
285 if ty1.equals_ctor(&ty2) { 285 if ty1.equals_ctor(&ty2) {
286 match (ty1.substs(), ty2.substs()) { 286 match (ty1.interned(&Interner), ty2.interned(&Interner)) {
287 (Some(st1), Some(st2)) => self.unify_substs(st1, st2, depth + 1), 287 (TyKind::Adt(_, substs1), TyKind::Adt(_, substs2))
288 (None, None) => true, 288 | (TyKind::FnDef(_, substs1), TyKind::FnDef(_, substs2))
289 | (
290 TyKind::Function(FnPointer { substs: substs1, .. }),
291 TyKind::Function(FnPointer { substs: substs2, .. }),
292 )
293 | (TyKind::Tuple(_, substs1), TyKind::Tuple(_, substs2))
294 | (TyKind::OpaqueType(_, substs1), TyKind::OpaqueType(_, substs2))
295 | (TyKind::AssociatedType(_, substs1), TyKind::AssociatedType(_, substs2))
296 | (TyKind::Closure(.., substs1), TyKind::Closure(.., substs2)) => {
297 self.unify_substs(substs1, substs2, depth + 1)
298 }
299 (TyKind::Ref(_, ty1), TyKind::Ref(_, ty2))
300 | (TyKind::Raw(_, ty1), TyKind::Raw(_, ty2))
301 | (TyKind::Array(ty1), TyKind::Array(ty2))
302 | (TyKind::Slice(ty1), TyKind::Slice(ty2)) => self.unify_inner(ty1, ty2, depth + 1),
289 _ => false, 303 _ => false,
290 } 304 }
291 } else { 305 } else {
@@ -404,7 +418,7 @@ impl InferenceTable {
404 if i > 0 { 418 if i > 0 {
405 cov_mark::hit!(type_var_resolves_to_int_var); 419 cov_mark::hit!(type_var_resolves_to_int_var);
406 } 420 }
407 match &ty.0 { 421 match ty.interned(&Interner) {
408 TyKind::InferenceVar(tv, _) => { 422 TyKind::InferenceVar(tv, _) => {
409 let inner = tv.to_inner(); 423 let inner = tv.to_inner();
410 match self.var_unification_table.inlined_probe_value(inner).known() { 424 match self.var_unification_table.inlined_probe_value(inner).known() {
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);
diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs
index d026310f4..b4c650fa1 100644
--- a/crates/hir_ty/src/lower.rs
+++ b/crates/hir_ty/src/lower.rs
@@ -160,21 +160,19 @@ impl<'a> TyLoweringContext<'a> {
160 } 160 }
161 TypeRef::RawPtr(inner, mutability) => { 161 TypeRef::RawPtr(inner, mutability) => {
162 let inner_ty = self.lower_ty(inner); 162 let inner_ty = self.lower_ty(inner);
163 TyKind::Raw(lower_to_chalk_mutability(*mutability), Substs::single(inner_ty)) 163 TyKind::Raw(lower_to_chalk_mutability(*mutability), inner_ty).intern(&Interner)
164 .intern(&Interner)
165 } 164 }
166 TypeRef::Array(inner) => { 165 TypeRef::Array(inner) => {
167 let inner_ty = self.lower_ty(inner); 166 let inner_ty = self.lower_ty(inner);
168 TyKind::Array(Substs::single(inner_ty)).intern(&Interner) 167 TyKind::Array(inner_ty).intern(&Interner)
169 } 168 }
170 TypeRef::Slice(inner) => { 169 TypeRef::Slice(inner) => {
171 let inner_ty = self.lower_ty(inner); 170 let inner_ty = self.lower_ty(inner);
172 TyKind::Slice(Substs::single(inner_ty)).intern(&Interner) 171 TyKind::Slice(inner_ty).intern(&Interner)
173 } 172 }
174 TypeRef::Reference(inner, _, mutability) => { 173 TypeRef::Reference(inner, _, mutability) => {
175 let inner_ty = self.lower_ty(inner); 174 let inner_ty = self.lower_ty(inner);
176 TyKind::Ref(lower_to_chalk_mutability(*mutability), Substs::single(inner_ty)) 175 TyKind::Ref(lower_to_chalk_mutability(*mutability), inner_ty).intern(&Interner)
177 .intern(&Interner)
178 } 176 }
179 TypeRef::Placeholder => TyKind::Unknown.intern(&Interner), 177 TypeRef::Placeholder => TyKind::Unknown.intern(&Interner),
180 TypeRef::Fn(params, is_varargs) => { 178 TypeRef::Fn(params, is_varargs) => {
@@ -993,7 +991,7 @@ pub(crate) fn generic_defaults_query(
993 991
994 // Each default can only refer to previous parameters. 992 // Each default can only refer to previous parameters.
995 ty.walk_mut_binders( 993 ty.walk_mut_binders(
996 &mut |ty, binders| match &mut ty.0 { 994 &mut |ty, binders| match ty.interned_mut() {
997 TyKind::BoundVar(BoundVar { debruijn, index }) if *debruijn == binders => { 995 TyKind::BoundVar(BoundVar { debruijn, index }) if *debruijn == binders => {
998 if *index >= idx { 996 if *index >= idx {
999 // type variable default referring to parameter coming 997 // type variable default referring to parameter coming
diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs
index c7055bee5..741440006 100644
--- a/crates/hir_ty/src/method_resolution.rs
+++ b/crates/hir_ty/src/method_resolution.rs
@@ -435,8 +435,7 @@ fn iterate_method_candidates_with_autoref(
435 } 435 }
436 let refed = Canonical { 436 let refed = Canonical {
437 kinds: deref_chain[0].kinds.clone(), 437 kinds: deref_chain[0].kinds.clone(),
438 value: TyKind::Ref(Mutability::Not, Substs::single(deref_chain[0].value.clone())) 438 value: TyKind::Ref(Mutability::Not, deref_chain[0].value.clone()).intern(&Interner),
439 .intern(&Interner),
440 }; 439 };
441 if iterate_method_candidates_by_receiver( 440 if iterate_method_candidates_by_receiver(
442 &refed, 441 &refed,
@@ -452,8 +451,7 @@ fn iterate_method_candidates_with_autoref(
452 } 451 }
453 let ref_muted = Canonical { 452 let ref_muted = Canonical {
454 kinds: deref_chain[0].kinds.clone(), 453 kinds: deref_chain[0].kinds.clone(),
455 value: TyKind::Ref(Mutability::Mut, Substs::single(deref_chain[0].value.clone())) 454 value: TyKind::Ref(Mutability::Mut, deref_chain[0].value.clone()).intern(&Interner),
456 .intern(&Interner),
457 }; 455 };
458 if iterate_method_candidates_by_receiver( 456 if iterate_method_candidates_by_receiver(
459 &ref_muted, 457 &ref_muted,
diff --git a/crates/hir_ty/src/traits/chalk/mapping.rs b/crates/hir_ty/src/traits/chalk/mapping.rs
index 05a4bf0df..6a8b6752e 100644
--- a/crates/hir_ty/src/traits/chalk/mapping.rs
+++ b/crates/hir_ty/src/traits/chalk/mapping.rs
@@ -24,9 +24,9 @@ use super::*;
24impl ToChalk for Ty { 24impl ToChalk for Ty {
25 type Chalk = chalk_ir::Ty<Interner>; 25 type Chalk = chalk_ir::Ty<Interner>;
26 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Ty<Interner> { 26 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Ty<Interner> {
27 match self.0 { 27 match self.into_inner() {
28 TyKind::Ref(m, parameters) => ref_to_chalk(db, m, parameters), 28 TyKind::Ref(m, ty) => ref_to_chalk(db, m, ty),
29 TyKind::Array(parameters) => array_to_chalk(db, parameters), 29 TyKind::Array(ty) => array_to_chalk(db, ty),
30 TyKind::Function(FnPointer { sig, substs, .. }) => { 30 TyKind::Function(FnPointer { sig, substs, .. }) => {
31 let substitution = chalk_ir::FnSubst(substs.to_chalk(db).shifted_in(&Interner)); 31 let substitution = chalk_ir::FnSubst(substs.to_chalk(db).shifted_in(&Interner));
32 chalk_ir::TyKind::Function(chalk_ir::FnPointer { 32 chalk_ir::TyKind::Function(chalk_ir::FnPointer {
@@ -54,13 +54,11 @@ impl ToChalk for Ty {
54 let substitution = substs.to_chalk(db); 54 let substitution = substs.to_chalk(db);
55 chalk_ir::TyKind::Tuple(cardinality.into(), substitution).intern(&Interner) 55 chalk_ir::TyKind::Tuple(cardinality.into(), substitution).intern(&Interner)
56 } 56 }
57 TyKind::Raw(mutability, substs) => { 57 TyKind::Raw(mutability, ty) => {
58 let ty = substs[0].clone().to_chalk(db); 58 let ty = ty.to_chalk(db);
59 chalk_ir::TyKind::Raw(mutability, ty).intern(&Interner) 59 chalk_ir::TyKind::Raw(mutability, ty).intern(&Interner)
60 } 60 }
61 TyKind::Slice(substs) => { 61 TyKind::Slice(ty) => chalk_ir::TyKind::Slice(ty.to_chalk(db)).intern(&Interner),
62 chalk_ir::TyKind::Slice(substs[0].clone().to_chalk(db)).intern(&Interner)
63 }
64 TyKind::Str => chalk_ir::TyKind::Str.intern(&Interner), 62 TyKind::Str => chalk_ir::TyKind::Str.intern(&Interner),
65 TyKind::FnDef(id, substs) => { 63 TyKind::FnDef(id, substs) => {
66 let substitution = substs.to_chalk(db); 64 let substitution = substs.to_chalk(db);
@@ -114,7 +112,7 @@ impl ToChalk for Ty {
114 fn from_chalk(db: &dyn HirDatabase, chalk: chalk_ir::Ty<Interner>) -> Self { 112 fn from_chalk(db: &dyn HirDatabase, chalk: chalk_ir::Ty<Interner>) -> Self {
115 match chalk.data(&Interner).kind.clone() { 113 match chalk.data(&Interner).kind.clone() {
116 chalk_ir::TyKind::Error => TyKind::Unknown, 114 chalk_ir::TyKind::Error => TyKind::Unknown,
117 chalk_ir::TyKind::Array(ty, _size) => TyKind::Array(Substs::single(from_chalk(db, ty))), 115 chalk_ir::TyKind::Array(ty, _size) => TyKind::Array(from_chalk(db, ty)),
118 chalk_ir::TyKind::Placeholder(idx) => TyKind::Placeholder(idx), 116 chalk_ir::TyKind::Placeholder(idx) => TyKind::Placeholder(idx),
119 chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Projection(proj)) => { 117 chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Projection(proj)) => {
120 let associated_ty = proj.associated_ty_id; 118 let associated_ty = proj.associated_ty_id;
@@ -168,12 +166,10 @@ impl ToChalk for Ty {
168 chalk_ir::TyKind::Tuple(cardinality, subst) => { 166 chalk_ir::TyKind::Tuple(cardinality, subst) => {
169 TyKind::Tuple(cardinality, from_chalk(db, subst)) 167 TyKind::Tuple(cardinality, from_chalk(db, subst))
170 } 168 }
171 chalk_ir::TyKind::Raw(mutability, ty) => { 169 chalk_ir::TyKind::Raw(mutability, ty) => TyKind::Raw(mutability, from_chalk(db, ty)),
172 TyKind::Raw(mutability, Substs::single(from_chalk(db, ty))) 170 chalk_ir::TyKind::Slice(ty) => TyKind::Slice(from_chalk(db, ty)),
173 }
174 chalk_ir::TyKind::Slice(ty) => TyKind::Slice(Substs::single(from_chalk(db, ty))),
175 chalk_ir::TyKind::Ref(mutability, _lifetime, ty) => { 171 chalk_ir::TyKind::Ref(mutability, _lifetime, ty) => {
176 TyKind::Ref(mutability, Substs::single(from_chalk(db, ty))) 172 TyKind::Ref(mutability, from_chalk(db, ty))
177 } 173 }
178 chalk_ir::TyKind::Str => TyKind::Str, 174 chalk_ir::TyKind::Str => TyKind::Str,
179 chalk_ir::TyKind::Never => TyKind::Never, 175 chalk_ir::TyKind::Never => TyKind::Never,
@@ -197,17 +193,17 @@ impl ToChalk for Ty {
197fn ref_to_chalk( 193fn ref_to_chalk(
198 db: &dyn HirDatabase, 194 db: &dyn HirDatabase,
199 mutability: chalk_ir::Mutability, 195 mutability: chalk_ir::Mutability,
200 subst: Substs, 196 ty: Ty,
201) -> chalk_ir::Ty<Interner> { 197) -> chalk_ir::Ty<Interner> {
202 let arg = subst[0].clone().to_chalk(db); 198 let arg = ty.to_chalk(db);
203 let lifetime = LifetimeData::Static.intern(&Interner); 199 let lifetime = LifetimeData::Static.intern(&Interner);
204 chalk_ir::TyKind::Ref(mutability, lifetime, arg).intern(&Interner) 200 chalk_ir::TyKind::Ref(mutability, lifetime, arg).intern(&Interner)
205} 201}
206 202
207/// We currently don't model constants, but Chalk does. So, we have to insert a 203/// We currently don't model constants, but Chalk does. So, we have to insert a
208/// fake constant here, because Chalks built-in logic may expect it to be there. 204/// fake constant here, because Chalks built-in logic may expect it to be there.
209fn array_to_chalk(db: &dyn HirDatabase, subst: Substs) -> chalk_ir::Ty<Interner> { 205fn array_to_chalk(db: &dyn HirDatabase, ty: Ty) -> chalk_ir::Ty<Interner> {
210 let arg = subst[0].clone().to_chalk(db); 206 let arg = ty.to_chalk(db);
211 let usize_ty = chalk_ir::TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(&Interner); 207 let usize_ty = chalk_ir::TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(&Interner);
212 let const_ = chalk_ir::ConstData { 208 let const_ = chalk_ir::ConstData {
213 ty: usize_ty, 209 ty: usize_ty,