aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/hir_ty/src/autoderef.rs44
-rw-r--r--crates/hir_ty/src/method_resolution.rs1
-rw-r--r--crates/hir_ty/src/tests/regression.rs38
3 files changed, 77 insertions, 6 deletions
diff --git a/crates/hir_ty/src/autoderef.rs b/crates/hir_ty/src/autoderef.rs
index f8e9db9ae..71bc436e6 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;
@@ -103,7 +104,7 @@ fn deref_by_trait(
103 binders: CanonicalVarKinds::from_iter( 104 binders: CanonicalVarKinds::from_iter(
104 &Interner, 105 &Interner,
105 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(
106 chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General), 107 VariableKind::Ty(chalk_ir::TyVariableKind::General),
107 chalk_ir::UniverseIndex::ROOT, 108 chalk_ir::UniverseIndex::ROOT,
108 ))), 109 ))),
109 ), 110 ),
@@ -136,7 +137,9 @@ fn deref_by_trait(
136 return None; 137 return None;
137 } 138 }
138 } 139 }
139 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 {
140 value: vars 143 value: vars
141 .value 144 .value
142 .subst 145 .subst
@@ -144,7 +147,7 @@ fn deref_by_trait(
144 .assert_ty_ref(&Interner) 147 .assert_ty_ref(&Interner)
145 .clone(), 148 .clone(),
146 binders: vars.binders.clone(), 149 binders: vars.binders.clone(),
147 }) 150 }))
148 } 151 }
149 Solution::Ambig(_) => { 152 Solution::Ambig(_) => {
150 info!("Ambiguous solution for derefing {:?}: {:?}", ty.goal, solution); 153 info!("Ambiguous solution for derefing {:?}: {:?}", ty.goal, solution);
@@ -152,3 +155,32 @@ fn deref_by_trait(
152 } 155 }
153 } 156 }
154} 157}
158
159fn 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}
diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs
index be3e4f09a..1b60cb727 100644
--- a/crates/hir_ty/src/method_resolution.rs
+++ b/crates/hir_ty/src/method_resolution.rs
@@ -609,6 +609,7 @@ fn iterate_trait_method_candidates(
609 } 609 }
610 } 610 }
611 known_implemented = true; 611 known_implemented = true;
612 // FIXME: we shouldn't be ignoring the binders here
612 if callback(&self_ty.value, *item) { 613 if callback(&self_ty.value, *item) {
613 return true; 614 return true;
614 } 615 }
diff --git a/crates/hir_ty/src/tests/regression.rs b/crates/hir_ty/src/tests/regression.rs
index b69f86050..9cd9f473d 100644
--- a/crates/hir_ty/src/tests/regression.rs
+++ b/crates/hir_ty/src/tests/regression.rs
@@ -974,3 +974,41 @@ fn param_overrides_fn() {
974 "#, 974 "#,
975 ) 975 )
976} 976}
977
978#[test]
979fn lifetime_from_chalk_during_deref() {
980 check_types(
981 r#"
982 #[lang = "deref"]
983 pub trait Deref {
984 type Target;
985 }
986
987 struct Box<T: ?Sized> {}
988 impl<T> Deref for Box<T> {
989 type Target = T;
990
991 fn deref(&self) -> &Self::Target {
992 loop {}
993 }
994 }
995
996 trait Iterator {
997 type Item;
998 }
999
1000 pub struct Iter<'a, T: 'a> {
1001 inner: Box<dyn IterTrait<'a, T, Item = &'a T> + 'a>,
1002 }
1003
1004 trait IterTrait<'a, T: 'a>: Iterator<Item = &'a T> {
1005 fn clone_box(&self);
1006 }
1007
1008 fn clone_iter<T>(s: Iter<T>) {
1009 s.inner.clone_box();
1010 //^^^^^^^^^^^^^^^^^^^ ()
1011 }
1012 "#,
1013 )
1014}