diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_hir_ty/src/infer/unify.rs | 15 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/lib.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/method_resolution.rs | 13 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/method_resolution.rs | 19 |
4 files changed, 45 insertions, 6 deletions
diff --git a/crates/ra_hir_ty/src/infer/unify.rs b/crates/ra_hir_ty/src/infer/unify.rs index aed527fe5..82b85d570 100644 --- a/crates/ra_hir_ty/src/infer/unify.rs +++ b/crates/ra_hir_ty/src/infer/unify.rs | |||
@@ -142,12 +142,21 @@ impl<T> Canonicalized<T> { | |||
142 | 142 | ||
143 | pub fn unify(ty1: &Canonical<Ty>, ty2: &Canonical<Ty>) -> Option<Substs> { | 143 | pub fn unify(ty1: &Canonical<Ty>, ty2: &Canonical<Ty>) -> Option<Substs> { |
144 | let mut table = InferenceTable::new(); | 144 | let mut table = InferenceTable::new(); |
145 | let num_vars = ty1.num_vars.max(ty2.num_vars); | ||
145 | let vars = | 146 | let vars = |
146 | Substs::builder(ty1.num_vars).fill(std::iter::repeat_with(|| table.new_type_var())).build(); | 147 | Substs::builder(num_vars).fill(std::iter::repeat_with(|| table.new_type_var())).build(); |
147 | let ty_with_vars = ty1.value.clone().subst_bound_vars(&vars); | 148 | let ty1_with_vars = ty1.value.clone().subst_bound_vars(&vars); |
148 | if !table.unify(&ty_with_vars, &ty2.value) { | 149 | let ty2_with_vars = ty2.value.clone().subst_bound_vars(&vars); |
150 | if !table.unify(&ty1_with_vars, &ty2_with_vars) { | ||
149 | return None; | 151 | return None; |
150 | } | 152 | } |
153 | // default any type vars that weren't unified back to their original bound vars | ||
154 | // (kind of hacky) | ||
155 | for (i, var) in vars.iter().enumerate() { | ||
156 | if &*table.resolve_ty_shallow(var) == var { | ||
157 | table.unify(var, &Ty::Bound(i as u32)); | ||
158 | } | ||
159 | } | ||
151 | Some( | 160 | Some( |
152 | Substs::builder(ty1.num_vars) | 161 | Substs::builder(ty1.num_vars) |
153 | .fill(vars.iter().map(|v| table.resolve_ty_completely(v.clone()))) | 162 | .fill(vars.iter().map(|v| table.resolve_ty_completely(v.clone()))) |
diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs index 0009c426c..ca194f806 100644 --- a/crates/ra_hir_ty/src/lib.rs +++ b/crates/ra_hir_ty/src/lib.rs | |||
@@ -355,6 +355,10 @@ impl Substs { | |||
355 | Substs(self.0[..std::cmp::min(self.0.len(), n)].into()) | 355 | Substs(self.0[..std::cmp::min(self.0.len(), n)].into()) |
356 | } | 356 | } |
357 | 357 | ||
358 | pub fn suffix(&self, n: usize) -> Substs { | ||
359 | Substs(self.0[self.0.len() - std::cmp::min(self.0.len(), n)..].into()) | ||
360 | } | ||
361 | |||
358 | pub fn as_single(&self) -> &Ty { | 362 | pub fn as_single(&self) -> &Ty { |
359 | if self.0.len() != 1 { | 363 | if self.0.len() != 1 { |
360 | panic!("expected substs of len 1, got {:?}", self); | 364 | panic!("expected substs of len 1, got {:?}", self); |
diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs index 74b908c2e..b7e8855fb 100644 --- a/crates/ra_hir_ty/src/method_resolution.rs +++ b/crates/ra_hir_ty/src/method_resolution.rs | |||
@@ -508,10 +508,17 @@ pub(crate) fn inherent_impl_substs( | |||
508 | impl_id: ImplId, | 508 | impl_id: ImplId, |
509 | self_ty: &Canonical<Ty>, | 509 | self_ty: &Canonical<Ty>, |
510 | ) -> Option<Substs> { | 510 | ) -> Option<Substs> { |
511 | let vars = Substs::build_for_def(db, impl_id).fill_with_bound_vars(0).build(); | 511 | // we create a var for each type parameter of the impl; we need to keep in |
512 | // mind here that `self_ty` might have vars of its own | ||
513 | let vars = | ||
514 | Substs::build_for_def(db, impl_id).fill_with_bound_vars(self_ty.num_vars as u32).build(); | ||
512 | let self_ty_with_vars = db.impl_self_ty(impl_id).subst(&vars); | 515 | let self_ty_with_vars = db.impl_self_ty(impl_id).subst(&vars); |
513 | let self_ty_with_vars = Canonical { num_vars: vars.len(), value: self_ty_with_vars }; | 516 | let self_ty_with_vars = |
514 | super::infer::unify(&self_ty_with_vars, self_ty) | 517 | Canonical { num_vars: vars.len() + self_ty.num_vars, value: self_ty_with_vars }; |
518 | let substs = super::infer::unify(&self_ty_with_vars, self_ty); | ||
519 | // we only want the substs for the vars we added, not the ones from self_ty | ||
520 | let result = substs.map(|s| s.suffix(vars.len())); | ||
521 | result | ||
515 | } | 522 | } |
516 | 523 | ||
517 | fn transform_receiver_ty( | 524 | fn transform_receiver_ty( |
diff --git a/crates/ra_hir_ty/src/tests/method_resolution.rs b/crates/ra_hir_ty/src/tests/method_resolution.rs index f9b394f05..af3e5b12c 100644 --- a/crates/ra_hir_ty/src/tests/method_resolution.rs +++ b/crates/ra_hir_ty/src/tests/method_resolution.rs | |||
@@ -1049,6 +1049,25 @@ where | |||
1049 | } | 1049 | } |
1050 | 1050 | ||
1051 | #[test] | 1051 | #[test] |
1052 | fn method_resolution_3373() { | ||
1053 | let t = type_at( | ||
1054 | r#" | ||
1055 | //- /main.rs | ||
1056 | struct A<T>(T); | ||
1057 | |||
1058 | impl A<i32> { | ||
1059 | fn from(v: i32) -> A<i32> { A(v) } | ||
1060 | } | ||
1061 | |||
1062 | fn main() { | ||
1063 | A::from(3)<|>; | ||
1064 | } | ||
1065 | "#, | ||
1066 | ); | ||
1067 | assert_eq!(t, "A<i32>"); | ||
1068 | } | ||
1069 | |||
1070 | #[test] | ||
1052 | fn method_resolution_slow() { | 1071 | fn method_resolution_slow() { |
1053 | // this can get quite slow if we set the solver size limit too high | 1072 | // this can get quite slow if we set the solver size limit too high |
1054 | let t = type_at( | 1073 | let t = type_at( |