diff options
Diffstat (limited to 'crates/hir_ty/src/infer/coerce.rs')
-rw-r--r-- | crates/hir_ty/src/infer/coerce.rs | 64 |
1 files changed, 35 insertions, 29 deletions
diff --git a/crates/hir_ty/src/infer/coerce.rs b/crates/hir_ty/src/infer/coerce.rs index 9c62932b1..1f463a425 100644 --- a/crates/hir_ty/src/infer/coerce.rs +++ b/crates/hir_ty/src/infer/coerce.rs | |||
@@ -7,9 +7,7 @@ | |||
7 | use chalk_ir::{cast::Cast, Mutability, TyVariableKind}; | 7 | use chalk_ir::{cast::Cast, Mutability, TyVariableKind}; |
8 | use hir_def::lang_item::LangItemTarget; | 8 | use hir_def::lang_item::LangItemTarget; |
9 | 9 | ||
10 | use crate::{ | 10 | use crate::{autoderef, Canonical, Interner, Solution, Ty, TyBuilder, TyExt, TyKind}; |
11 | autoderef, to_chalk_trait_id, traits::Solution, Interner, Substitution, TraitRef, Ty, TyKind, | ||
12 | }; | ||
13 | 11 | ||
14 | use super::{InEnvironment, InferenceContext}; | 12 | use super::{InEnvironment, InferenceContext}; |
15 | 13 | ||
@@ -36,7 +34,7 @@ impl<'a> InferenceContext<'a> { | |||
36 | ty1.clone() | 34 | ty1.clone() |
37 | } else { | 35 | } else { |
38 | if let (TyKind::FnDef(..), TyKind::FnDef(..)) = | 36 | if let (TyKind::FnDef(..), TyKind::FnDef(..)) = |
39 | (ty1.interned(&Interner), ty2.interned(&Interner)) | 37 | (ty1.kind(&Interner), ty2.kind(&Interner)) |
40 | { | 38 | { |
41 | cov_mark::hit!(coerce_fn_reification); | 39 | cov_mark::hit!(coerce_fn_reification); |
42 | // Special case: two function types. Try to coerce both to | 40 | // Special case: two function types. Try to coerce both to |
@@ -44,8 +42,8 @@ impl<'a> InferenceContext<'a> { | |||
44 | // https://github.com/rust-lang/rust/blob/7b805396bf46dce972692a6846ce2ad8481c5f85/src/librustc_typeck/check/coercion.rs#L877-L916 | 42 | // https://github.com/rust-lang/rust/blob/7b805396bf46dce972692a6846ce2ad8481c5f85/src/librustc_typeck/check/coercion.rs#L877-L916 |
45 | let sig1 = ty1.callable_sig(self.db).expect("FnDef without callable sig"); | 43 | let sig1 = ty1.callable_sig(self.db).expect("FnDef without callable sig"); |
46 | let sig2 = ty2.callable_sig(self.db).expect("FnDef without callable sig"); | 44 | let sig2 = ty2.callable_sig(self.db).expect("FnDef without callable sig"); |
47 | let ptr_ty1 = Ty::fn_ptr(sig1); | 45 | let ptr_ty1 = TyBuilder::fn_ptr(sig1); |
48 | let ptr_ty2 = Ty::fn_ptr(sig2); | 46 | let ptr_ty2 = TyBuilder::fn_ptr(sig2); |
49 | self.coerce_merge_branch(&ptr_ty1, &ptr_ty2) | 47 | self.coerce_merge_branch(&ptr_ty1, &ptr_ty2) |
50 | } else { | 48 | } else { |
51 | cov_mark::hit!(coerce_merge_fail_fallback); | 49 | cov_mark::hit!(coerce_merge_fail_fallback); |
@@ -55,7 +53,7 @@ impl<'a> InferenceContext<'a> { | |||
55 | } | 53 | } |
56 | 54 | ||
57 | fn coerce_inner(&mut self, mut from_ty: Ty, to_ty: &Ty) -> bool { | 55 | fn coerce_inner(&mut self, mut from_ty: Ty, to_ty: &Ty) -> bool { |
58 | match (from_ty.interned(&Interner), to_ty.interned(&Interner)) { | 56 | match (from_ty.kind(&Interner), to_ty.kind(&Interner)) { |
59 | // Never type will make type variable to fallback to Never Type instead of Unknown. | 57 | // Never type will make type variable to fallback to Never Type instead of Unknown. |
60 | (TyKind::Never, TyKind::InferenceVar(tv, TyVariableKind::General)) => { | 58 | (TyKind::Never, TyKind::InferenceVar(tv, TyVariableKind::General)) => { |
61 | self.table.type_variable_table.set_diverging(*tv, true); | 59 | self.table.type_variable_table.set_diverging(*tv, true); |
@@ -73,17 +71,19 @@ impl<'a> InferenceContext<'a> { | |||
73 | } | 71 | } |
74 | 72 | ||
75 | // Pointer weakening and function to pointer | 73 | // Pointer weakening and function to pointer |
76 | match (from_ty.interned_mut(), to_ty.interned(&Interner)) { | 74 | match (from_ty.kind(&Interner), to_ty.kind(&Interner)) { |
77 | // `*mut T` -> `*const T` | 75 | // `*mut T` -> `*const T` |
76 | (TyKind::Raw(_, inner), TyKind::Raw(m2 @ Mutability::Not, ..)) => { | ||
77 | from_ty = TyKind::Raw(*m2, inner.clone()).intern(&Interner); | ||
78 | } | ||
78 | // `&mut T` -> `&T` | 79 | // `&mut T` -> `&T` |
79 | (TyKind::Raw(m1, ..), TyKind::Raw(m2 @ Mutability::Not, ..)) | 80 | (TyKind::Ref(_, lt, inner), TyKind::Ref(m2 @ Mutability::Not, ..)) => { |
80 | | (TyKind::Ref(m1, ..), TyKind::Ref(m2 @ Mutability::Not, ..)) => { | 81 | from_ty = TyKind::Ref(*m2, lt.clone(), inner.clone()).intern(&Interner); |
81 | *m1 = *m2; | ||
82 | } | 82 | } |
83 | // `&T` -> `*const T` | 83 | // `&T` -> `*const T` |
84 | // `&mut T` -> `*mut T`/`*const T` | 84 | // `&mut T` -> `*mut T`/`*const T` |
85 | (TyKind::Ref(.., substs), &TyKind::Raw(m2 @ Mutability::Not, ..)) | 85 | (TyKind::Ref(.., substs), &TyKind::Raw(m2 @ Mutability::Not, ..)) |
86 | | (TyKind::Ref(Mutability::Mut, substs), &TyKind::Raw(m2, ..)) => { | 86 | | (TyKind::Ref(Mutability::Mut, _, substs), &TyKind::Raw(m2, ..)) => { |
87 | from_ty = TyKind::Raw(m2, substs.clone()).intern(&Interner); | 87 | from_ty = TyKind::Raw(m2, substs.clone()).intern(&Interner); |
88 | } | 88 | } |
89 | 89 | ||
@@ -95,12 +95,12 @@ impl<'a> InferenceContext<'a> { | |||
95 | (TyKind::FnDef(..), TyKind::Function { .. }) => match from_ty.callable_sig(self.db) { | 95 | (TyKind::FnDef(..), TyKind::Function { .. }) => match from_ty.callable_sig(self.db) { |
96 | None => return false, | 96 | None => return false, |
97 | Some(sig) => { | 97 | Some(sig) => { |
98 | from_ty = Ty::fn_ptr(sig); | 98 | from_ty = TyBuilder::fn_ptr(sig); |
99 | } | 99 | } |
100 | }, | 100 | }, |
101 | 101 | ||
102 | (TyKind::Closure(.., substs), TyKind::Function { .. }) => { | 102 | (TyKind::Closure(.., substs), TyKind::Function { .. }) => { |
103 | from_ty = substs[0].clone(); | 103 | from_ty = substs.at(&Interner, 0).assert_ty_ref(&Interner).clone(); |
104 | } | 104 | } |
105 | 105 | ||
106 | _ => {} | 106 | _ => {} |
@@ -111,9 +111,11 @@ impl<'a> InferenceContext<'a> { | |||
111 | } | 111 | } |
112 | 112 | ||
113 | // Auto Deref if cannot coerce | 113 | // Auto Deref if cannot coerce |
114 | match (from_ty.interned(&Interner), to_ty.interned(&Interner)) { | 114 | match (from_ty.kind(&Interner), to_ty.kind(&Interner)) { |
115 | // FIXME: DerefMut | 115 | // FIXME: DerefMut |
116 | (TyKind::Ref(_, st1), TyKind::Ref(_, st2)) => self.unify_autoderef_behind_ref(st1, st2), | 116 | (TyKind::Ref(.., st1), TyKind::Ref(.., st2)) => { |
117 | self.unify_autoderef_behind_ref(st1, st2) | ||
118 | } | ||
117 | 119 | ||
118 | // Otherwise, normal unify | 120 | // Otherwise, normal unify |
119 | _ => self.unify(&from_ty, to_ty), | 121 | _ => self.unify(&from_ty, to_ty), |
@@ -130,19 +132,16 @@ impl<'a> InferenceContext<'a> { | |||
130 | _ => return None, | 132 | _ => return None, |
131 | }; | 133 | }; |
132 | 134 | ||
133 | let generic_params = crate::utils::generics(self.db.upcast(), coerce_unsized_trait.into()); | 135 | let trait_ref = { |
134 | if generic_params.len() != 2 { | 136 | let b = TyBuilder::trait_ref(self.db, coerce_unsized_trait); |
135 | // The CoerceUnsized trait should have two generic params: Self and T. | 137 | if b.remaining() != 2 { |
136 | return None; | 138 | // The CoerceUnsized trait should have two generic params: Self and T. |
137 | } | 139 | return None; |
140 | } | ||
141 | b.push(from_ty.clone()).push(to_ty.clone()).build() | ||
142 | }; | ||
138 | 143 | ||
139 | let substs = Substitution::build_for_generics(&generic_params) | 144 | let goal = InEnvironment::new(&self.trait_env.env, trait_ref.cast(&Interner)); |
140 | .push(from_ty.clone()) | ||
141 | .push(to_ty.clone()) | ||
142 | .build(); | ||
143 | let trait_ref = | ||
144 | TraitRef { trait_id: to_chalk_trait_id(coerce_unsized_trait), substitution: substs }; | ||
145 | let goal = InEnvironment::new(self.trait_env.env.clone(), trait_ref.cast(&Interner)); | ||
146 | 145 | ||
147 | let canonicalizer = self.canonicalizer(); | 146 | let canonicalizer = self.canonicalizer(); |
148 | let canonicalized = canonicalizer.canonicalize_obligation(goal); | 147 | let canonicalized = canonicalizer.canonicalize_obligation(goal); |
@@ -151,7 +150,14 @@ impl<'a> InferenceContext<'a> { | |||
151 | 150 | ||
152 | match solution { | 151 | match solution { |
153 | Solution::Unique(v) => { | 152 | Solution::Unique(v) => { |
154 | canonicalized.apply_solution(self, v.0); | 153 | canonicalized.apply_solution( |
154 | self, | ||
155 | Canonical { | ||
156 | binders: v.binders, | ||
157 | // FIXME handle constraints | ||
158 | value: v.value.subst, | ||
159 | }, | ||
160 | ); | ||
155 | } | 161 | } |
156 | _ => return None, | 162 | _ => return None, |
157 | }; | 163 | }; |