diff options
Diffstat (limited to 'crates/hir_ty/src/autoderef.rs')
-rw-r--r-- | crates/hir_ty/src/autoderef.rs | 64 |
1 files changed, 52 insertions, 12 deletions
diff --git a/crates/hir_ty/src/autoderef.rs b/crates/hir_ty/src/autoderef.rs index 7ca4af80e..71bc436e6 100644 --- a/crates/hir_ty/src/autoderef.rs +++ b/crates/hir_ty/src/autoderef.rs | |||
@@ -6,14 +6,15 @@ | |||
6 | use std::iter::successors; | 6 | use std::iter::successors; |
7 | 7 | ||
8 | use base_db::CrateId; | 8 | use base_db::CrateId; |
9 | use chalk_ir::cast::Cast; | 9 | use chalk_ir::{cast::Cast, fold::Fold, interner::HasInterner, VariableKind}; |
10 | use hir_def::lang_item::LangItemTarget; | 10 | use hir_def::lang_item::LangItemTarget; |
11 | use hir_expand::name::name; | 11 | use hir_expand::name::name; |
12 | use log::{info, warn}; | 12 | use log::{info, warn}; |
13 | 13 | ||
14 | use crate::{ | 14 | use crate::{ |
15 | db::HirDatabase, AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds, DebruijnIndex, | 15 | db::HirDatabase, static_lifetime, AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds, |
16 | InEnvironment, Interner, Solution, Ty, TyBuilder, TyKind, | 16 | DebruijnIndex, InEnvironment, Interner, ProjectionTyExt, Solution, Substitution, Ty, TyBuilder, |
17 | TyKind, | ||
17 | }; | 18 | }; |
18 | 19 | ||
19 | const AUTODEREF_RECURSION_LIMIT: usize = 10; | 20 | const AUTODEREF_RECURSION_LIMIT: usize = 10; |
@@ -35,13 +36,21 @@ pub(crate) fn deref( | |||
35 | krate: CrateId, | 36 | krate: CrateId, |
36 | ty: InEnvironment<&Canonical<Ty>>, | 37 | ty: InEnvironment<&Canonical<Ty>>, |
37 | ) -> Option<Canonical<Ty>> { | 38 | ) -> Option<Canonical<Ty>> { |
38 | if let Some(derefed) = ty.goal.value.builtin_deref() { | 39 | if let Some(derefed) = builtin_deref(&ty.goal.value) { |
39 | Some(Canonical { value: derefed, binders: ty.goal.binders.clone() }) | 40 | Some(Canonical { value: derefed, binders: ty.goal.binders.clone() }) |
40 | } else { | 41 | } else { |
41 | deref_by_trait(db, krate, ty) | 42 | deref_by_trait(db, krate, ty) |
42 | } | 43 | } |
43 | } | 44 | } |
44 | 45 | ||
46 | fn builtin_deref(ty: &Ty) -> Option<Ty> { | ||
47 | match ty.kind(&Interner) { | ||
48 | TyKind::Ref(.., ty) => Some(ty.clone()), | ||
49 | TyKind::Raw(.., ty) => Some(ty.clone()), | ||
50 | _ => None, | ||
51 | } | ||
52 | } | ||
53 | |||
45 | fn deref_by_trait( | 54 | fn deref_by_trait( |
46 | db: &dyn HirDatabase, | 55 | db: &dyn HirDatabase, |
47 | krate: CrateId, | 56 | krate: CrateId, |
@@ -95,7 +104,7 @@ fn deref_by_trait( | |||
95 | binders: CanonicalVarKinds::from_iter( | 104 | binders: CanonicalVarKinds::from_iter( |
96 | &Interner, | 105 | &Interner, |
97 | ty.goal.binders.iter(&Interner).cloned().chain(Some(chalk_ir::WithKind::new( | 106 | ty.goal.binders.iter(&Interner).cloned().chain(Some(chalk_ir::WithKind::new( |
98 | chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General), | 107 | VariableKind::Ty(chalk_ir::TyVariableKind::General), |
99 | chalk_ir::UniverseIndex::ROOT, | 108 | chalk_ir::UniverseIndex::ROOT, |
100 | ))), | 109 | ))), |
101 | ), | 110 | ), |
@@ -120,23 +129,25 @@ fn deref_by_trait( | |||
120 | // assumptions will be broken. We would need to properly introduce | 129 | // assumptions will be broken. We would need to properly introduce |
121 | // new variables in that case | 130 | // new variables in that case |
122 | 131 | ||
123 | for i in 1..vars.0.binders.len(&Interner) { | 132 | for i in 1..vars.binders.len(&Interner) { |
124 | if vars.0.value.at(&Interner, i - 1).assert_ty_ref(&Interner).kind(&Interner) | 133 | if vars.value.subst.at(&Interner, i - 1).assert_ty_ref(&Interner).kind(&Interner) |
125 | != &TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i - 1)) | 134 | != &TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i - 1)) |
126 | { | 135 | { |
127 | warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.goal, solution); | 136 | warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.goal, solution); |
128 | return None; | 137 | return None; |
129 | } | 138 | } |
130 | } | 139 | } |
131 | Some(Canonical { | 140 | // FIXME: we remove lifetime variables here since they can confuse |
141 | // the method resolution code later | ||
142 | Some(fixup_lifetime_variables(Canonical { | ||
132 | value: vars | 143 | value: vars |
133 | .0 | ||
134 | .value | 144 | .value |
135 | .at(&Interner, vars.0.value.len(&Interner) - 1) | 145 | .subst |
146 | .at(&Interner, vars.value.subst.len(&Interner) - 1) | ||
136 | .assert_ty_ref(&Interner) | 147 | .assert_ty_ref(&Interner) |
137 | .clone(), | 148 | .clone(), |
138 | binders: vars.0.binders.clone(), | 149 | binders: vars.binders.clone(), |
139 | }) | 150 | })) |
140 | } | 151 | } |
141 | Solution::Ambig(_) => { | 152 | Solution::Ambig(_) => { |
142 | info!("Ambiguous solution for derefing {:?}: {:?}", ty.goal, solution); | 153 | info!("Ambiguous solution for derefing {:?}: {:?}", ty.goal, solution); |
@@ -144,3 +155,32 @@ fn deref_by_trait( | |||
144 | } | 155 | } |
145 | } | 156 | } |
146 | } | 157 | } |
158 | |||
159 | fn fixup_lifetime_variables<T: Fold<Interner, Result = T> + HasInterner<Interner = Interner>>( | ||
160 | c: Canonical<T>, | ||
161 | ) -> Canonical<T> { | ||
162 | // Removes lifetime variables from the Canonical, replacing them by static lifetimes. | ||
163 | let mut i = 0; | ||
164 | let subst = Substitution::from_iter( | ||
165 | &Interner, | ||
166 | c.binders.iter(&Interner).map(|vk| match vk.kind { | ||
167 | VariableKind::Ty(_) => { | ||
168 | let index = i; | ||
169 | i += 1; | ||
170 | BoundVar::new(DebruijnIndex::INNERMOST, index).to_ty(&Interner).cast(&Interner) | ||
171 | } | ||
172 | VariableKind::Lifetime => static_lifetime().cast(&Interner), | ||
173 | VariableKind::Const(_) => unimplemented!(), | ||
174 | }), | ||
175 | ); | ||
176 | let binders = CanonicalVarKinds::from_iter( | ||
177 | &Interner, | ||
178 | c.binders.iter(&Interner).filter(|vk| match vk.kind { | ||
179 | VariableKind::Ty(_) => true, | ||
180 | VariableKind::Lifetime => false, | ||
181 | VariableKind::Const(_) => true, | ||
182 | }), | ||
183 | ); | ||
184 | let value = subst.apply(c.value, &Interner); | ||
185 | Canonical { binders, value } | ||
186 | } | ||