aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty/src/autoderef.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_ty/src/autoderef.rs')
-rw-r--r--crates/hir_ty/src/autoderef.rs46
1 files changed, 40 insertions, 6 deletions
diff --git a/crates/hir_ty/src/autoderef.rs b/crates/hir_ty/src/autoderef.rs
index f8e9db9ae..2c07494a9 100644
--- a/crates/hir_ty/src/autoderef.rs
+++ b/crates/hir_ty/src/autoderef.rs
@@ -6,14 +6,15 @@
6use std::iter::successors; 6use std::iter::successors;
7 7
8use base_db::CrateId; 8use base_db::CrateId;
9use chalk_ir::cast::Cast; 9use chalk_ir::{cast::Cast, fold::Fold, interner::HasInterner, VariableKind};
10use hir_def::lang_item::LangItemTarget; 10use hir_def::lang_item::LangItemTarget;
11use hir_expand::name::name; 11use hir_expand::name::name;
12use log::{info, warn}; 12use log::{info, warn};
13 13
14use crate::{ 14use crate::{
15 db::HirDatabase, AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds, DebruijnIndex, 15 db::HirDatabase, static_lifetime, AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds,
16 InEnvironment, Interner, ProjectionTyExt, Solution, Ty, TyBuilder, TyKind, 16 DebruijnIndex, InEnvironment, Interner, ProjectionTyExt, Solution, Substitution, Ty, TyBuilder,
17 TyKind,
17}; 18};
18 19
19const AUTODEREF_RECURSION_LIMIT: usize = 10; 20const AUTODEREF_RECURSION_LIMIT: usize = 10;
@@ -35,6 +36,7 @@ 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>> {
39 let _p = profile::span("deref");
38 if let Some(derefed) = builtin_deref(&ty.goal.value) { 40 if let Some(derefed) = builtin_deref(&ty.goal.value) {
39 Some(Canonical { value: derefed, binders: ty.goal.binders.clone() }) 41 Some(Canonical { value: derefed, binders: ty.goal.binders.clone() })
40 } else { 42 } else {
@@ -55,6 +57,7 @@ fn deref_by_trait(
55 krate: CrateId, 57 krate: CrateId,
56 ty: InEnvironment<&Canonical<Ty>>, 58 ty: InEnvironment<&Canonical<Ty>>,
57) -> Option<Canonical<Ty>> { 59) -> Option<Canonical<Ty>> {
60 let _p = profile::span("deref_by_trait");
58 let deref_trait = match db.lang_item(krate, "deref".into())? { 61 let deref_trait = match db.lang_item(krate, "deref".into())? {
59 LangItemTarget::TraitId(it) => it, 62 LangItemTarget::TraitId(it) => it,
60 _ => return None, 63 _ => return None,
@@ -103,7 +106,7 @@ fn deref_by_trait(
103 binders: CanonicalVarKinds::from_iter( 106 binders: CanonicalVarKinds::from_iter(
104 &Interner, 107 &Interner,
105 ty.goal.binders.iter(&Interner).cloned().chain(Some(chalk_ir::WithKind::new( 108 ty.goal.binders.iter(&Interner).cloned().chain(Some(chalk_ir::WithKind::new(
106 chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General), 109 VariableKind::Ty(chalk_ir::TyVariableKind::General),
107 chalk_ir::UniverseIndex::ROOT, 110 chalk_ir::UniverseIndex::ROOT,
108 ))), 111 ))),
109 ), 112 ),
@@ -136,7 +139,9 @@ fn deref_by_trait(
136 return None; 139 return None;
137 } 140 }
138 } 141 }
139 Some(Canonical { 142 // FIXME: we remove lifetime variables here since they can confuse
143 // the method resolution code later
144 Some(fixup_lifetime_variables(Canonical {
140 value: vars 145 value: vars
141 .value 146 .value
142 .subst 147 .subst
@@ -144,7 +149,7 @@ fn deref_by_trait(
144 .assert_ty_ref(&Interner) 149 .assert_ty_ref(&Interner)
145 .clone(), 150 .clone(),
146 binders: vars.binders.clone(), 151 binders: vars.binders.clone(),
147 }) 152 }))
148 } 153 }
149 Solution::Ambig(_) => { 154 Solution::Ambig(_) => {
150 info!("Ambiguous solution for derefing {:?}: {:?}", ty.goal, solution); 155 info!("Ambiguous solution for derefing {:?}: {:?}", ty.goal, solution);
@@ -152,3 +157,32 @@ fn deref_by_trait(
152 } 157 }
153 } 158 }
154} 159}
160
161fn fixup_lifetime_variables<T: Fold<Interner, Result = T> + HasInterner<Interner = Interner>>(
162 c: Canonical<T>,
163) -> Canonical<T> {
164 // Removes lifetime variables from the Canonical, replacing them by static lifetimes.
165 let mut i = 0;
166 let subst = Substitution::from_iter(
167 &Interner,
168 c.binders.iter(&Interner).map(|vk| match vk.kind {
169 VariableKind::Ty(_) => {
170 let index = i;
171 i += 1;
172 BoundVar::new(DebruijnIndex::INNERMOST, index).to_ty(&Interner).cast(&Interner)
173 }
174 VariableKind::Lifetime => static_lifetime().cast(&Interner),
175 VariableKind::Const(_) => unimplemented!(),
176 }),
177 );
178 let binders = CanonicalVarKinds::from_iter(
179 &Interner,
180 c.binders.iter(&Interner).filter(|vk| match vk.kind {
181 VariableKind::Ty(_) => true,
182 VariableKind::Lifetime => false,
183 VariableKind::Const(_) => true,
184 }),
185 );
186 let value = subst.apply(c.value, &Interner);
187 Canonical { binders, value }
188}