aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_ty
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2019-12-03 13:59:29 +0000
committerFlorian Diebold <[email protected]>2019-12-03 14:01:23 +0000
commite4add45951511f9afe348bf6066a724deb0d3ccf (patch)
tree0a357e2d3333a06e37f5cb8d6613733c1c0c78ac /crates/ra_hir_ty
parentba4f7fa02f746e5bb3efdaa06c2b35beaa4e3440 (diff)
Fix #2467
The stand-alone `unify` requires that the type doesn't contain any type variables. So we can't share the code here for now (without more refactoring)...
Diffstat (limited to 'crates/ra_hir_ty')
-rw-r--r--crates/ra_hir_ty/src/infer/path.rs13
-rw-r--r--crates/ra_hir_ty/src/infer/unify.rs4
-rw-r--r--crates/ra_hir_ty/src/method_resolution.rs8
-rw-r--r--crates/ra_hir_ty/src/tests.rs47
4 files changed, 65 insertions, 7 deletions
diff --git a/crates/ra_hir_ty/src/infer/path.rs b/crates/ra_hir_ty/src/infer/path.rs
index b0024c6e1..37db005ea 100644
--- a/crates/ra_hir_ty/src/infer/path.rs
+++ b/crates/ra_hir_ty/src/infer/path.rs
@@ -1,5 +1,7 @@
1//! Path expression resolution. 1//! Path expression resolution.
2 2
3use std::iter;
4
3use hir_def::{ 5use hir_def::{
4 path::{Path, PathKind, PathSegment}, 6 path::{Path, PathKind, PathSegment},
5 resolver::{ResolveValueResult, Resolver, TypeNs, ValueNs}, 7 resolver::{ResolveValueResult, Resolver, TypeNs, ValueNs},
@@ -207,7 +209,16 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
207 }; 209 };
208 let substs = match container { 210 let substs = match container {
209 ContainerId::ImplId(impl_id) => { 211 ContainerId::ImplId(impl_id) => {
210 method_resolution::inherent_impl_substs(self.db, impl_id, &ty) 212 let impl_substs = Substs::build_for_def(self.db, impl_id)
213 .fill(iter::repeat_with(|| self.table.new_type_var()))
214 .build();
215 let impl_self_ty = self.db.impl_self_ty(impl_id).subst(&impl_substs);
216 let substs = Substs::build_for_def(self.db, item)
217 .use_parent_substs(&impl_substs)
218 .fill_with_params()
219 .build();
220 self.unify(&impl_self_ty, &ty);
221 Some(substs)
211 } 222 }
212 ContainerId::TraitId(trait_) => { 223 ContainerId::TraitId(trait_) => {
213 // we're picking this method 224 // we're picking this method
diff --git a/crates/ra_hir_ty/src/infer/unify.rs b/crates/ra_hir_ty/src/infer/unify.rs
index 8ed2a6090..fe05642ae 100644
--- a/crates/ra_hir_ty/src/infer/unify.rs
+++ b/crates/ra_hir_ty/src/infer/unify.rs
@@ -167,12 +167,12 @@ impl<T> Canonicalized<T> {
167 } 167 }
168} 168}
169 169
170pub fn unify(ty1: Canonical<&Ty>, ty2: &Ty) -> Option<Substs> { 170pub fn unify(ty1: &Canonical<Ty>, ty2: &Canonical<Ty>) -> Option<Substs> {
171 let mut table = InferenceTable::new(); 171 let mut table = InferenceTable::new();
172 let vars = 172 let vars =
173 Substs::builder(ty1.num_vars).fill(std::iter::repeat_with(|| table.new_type_var())).build(); 173 Substs::builder(ty1.num_vars).fill(std::iter::repeat_with(|| table.new_type_var())).build();
174 let ty_with_vars = ty1.value.clone().subst_bound_vars(&vars); 174 let ty_with_vars = ty1.value.clone().subst_bound_vars(&vars);
175 if !table.unify(&ty_with_vars, ty2) { 175 if !table.unify(&ty_with_vars, &ty2.value) {
176 return None; 176 return None;
177 } 177 }
178 Some( 178 Some(
diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs
index 21efb196a..7220d6e0a 100644
--- a/crates/ra_hir_ty/src/method_resolution.rs
+++ b/crates/ra_hir_ty/src/method_resolution.rs
@@ -437,12 +437,12 @@ fn is_valid_candidate(
437pub(crate) fn inherent_impl_substs( 437pub(crate) fn inherent_impl_substs(
438 db: &impl HirDatabase, 438 db: &impl HirDatabase,
439 impl_id: ImplId, 439 impl_id: ImplId,
440 self_ty: &Ty, 440 self_ty: &Canonical<Ty>,
441) -> Option<Substs> { 441) -> Option<Substs> {
442 let vars = Substs::build_for_def(db, impl_id).fill_with_bound_vars(0).build(); 442 let vars = Substs::build_for_def(db, impl_id).fill_with_bound_vars(0).build();
443 let self_ty_with_vars = db.impl_self_ty(impl_id).subst(&vars); 443 let self_ty_with_vars = db.impl_self_ty(impl_id).subst(&vars);
444 let self_ty_with_vars = Canonical { num_vars: vars.len(), value: &self_ty_with_vars }; 444 let self_ty_with_vars = Canonical { num_vars: vars.len(), value: self_ty_with_vars };
445 super::infer::unify(self_ty_with_vars, self_ty) 445 super::infer::unify(&self_ty_with_vars, self_ty)
446} 446}
447 447
448fn transform_receiver_ty( 448fn transform_receiver_ty(
@@ -455,7 +455,7 @@ fn transform_receiver_ty(
455 .push(self_ty.value.clone()) 455 .push(self_ty.value.clone())
456 .fill_with_unknown() 456 .fill_with_unknown()
457 .build(), 457 .build(),
458 hir_def::ContainerId::ImplId(impl_id) => inherent_impl_substs(db, impl_id, &self_ty.value)?, 458 hir_def::ContainerId::ImplId(impl_id) => inherent_impl_substs(db, impl_id, &self_ty)?,
459 hir_def::ContainerId::ModuleId(_) => unreachable!(), 459 hir_def::ContainerId::ModuleId(_) => unreachable!(),
460 }; 460 };
461 let sig = db.callable_item_signature(function_id.into()); 461 let sig = db.callable_item_signature(function_id.into());
diff --git a/crates/ra_hir_ty/src/tests.rs b/crates/ra_hir_ty/src/tests.rs
index d5b8d10e2..2ea9e261c 100644
--- a/crates/ra_hir_ty/src/tests.rs
+++ b/crates/ra_hir_ty/src/tests.rs
@@ -4820,6 +4820,53 @@ fn test<T, U>() where T: Trait<U::Item>, U: Trait<T::Item> {
4820 assert_eq!(t, "{unknown}"); 4820 assert_eq!(t, "{unknown}");
4821} 4821}
4822 4822
4823#[test]
4824fn bug_2467() {
4825 assert_snapshot!(
4826 infer(r#"
4827struct S<T>(T);
4828impl<T> S<T> {
4829 fn foo(self) -> T;
4830}
4831fn test() {
4832 // needs to nest multiple times for variable indices to get high enough
4833 let a = S::foo(S(1));
4834 let b = S::foo(S(a));
4835 let c = S::foo(S(b));
4836 let d: u32 = S::foo(S(c));
4837}
4838"#),
4839 @r###"
4840 [43; 47) 'self': S<T>
4841 [67; 255) '{ ...c)); }': ()
4842 [153; 154) 'a': u32
4843 [157; 163) 'S::foo': fn foo<u32>(S<T>) -> T
4844 [157; 169) 'S::foo(S(1))': u32
4845 [164; 165) 'S': S<u32>(T) -> S<T>
4846 [164; 168) 'S(1)': S<u32>
4847 [166; 167) '1': u32
4848 [179; 180) 'b': u32
4849 [183; 189) 'S::foo': fn foo<u32>(S<T>) -> T
4850 [183; 195) 'S::foo(S(a))': u32
4851 [190; 191) 'S': S<u32>(T) -> S<T>
4852 [190; 194) 'S(a)': S<u32>
4853 [192; 193) 'a': u32
4854 [205; 206) 'c': u32
4855 [209; 215) 'S::foo': fn foo<u32>(S<T>) -> T
4856 [209; 221) 'S::foo(S(b))': u32
4857 [216; 217) 'S': S<u32>(T) -> S<T>
4858 [216; 220) 'S(b)': S<u32>
4859 [218; 219) 'b': u32
4860 [231; 232) 'd': u32
4861 [240; 246) 'S::foo': fn foo<u32>(S<T>) -> T
4862 [240; 252) 'S::foo(S(c))': u32
4863 [247; 248) 'S': S<u32>(T) -> S<T>
4864 [247; 251) 'S(c)': S<u32>
4865 [249; 250) 'c': u32
4866 "###
4867 );
4868}
4869
4823fn type_at_pos(db: &TestDB, pos: FilePosition) -> String { 4870fn type_at_pos(db: &TestDB, pos: FilePosition) -> String {
4824 let file = db.parse(pos.file_id).ok().unwrap(); 4871 let file = db.parse(pos.file_id).ok().unwrap();
4825 let expr = algo::find_node_at_offset::<ast::Expr>(file.syntax(), pos.offset).unwrap(); 4872 let expr = algo::find_node_at_offset::<ast::Expr>(file.syntax(), pos.offset).unwrap();