Skip to content

Commit 15f143f

Browse files
Merge #2468
2468: Fix #2467 r=flodiebold a=flodiebold 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)... Co-authored-by: Florian Diebold <flodiebold@gmail.com>
2 parents ba4f7fa + e4add45 commit 15f143f

File tree

4 files changed

+65
-7
lines changed

4 files changed

+65
-7
lines changed

crates/ra_hir_ty/src/infer/path.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
//! Path expression resolution.
22
3+
use std::iter;
4+
35
use hir_def::{
46
path::{Path, PathKind, PathSegment},
57
resolver::{ResolveValueResult, Resolver, TypeNs, ValueNs},
@@ -207,7 +209,16 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
207209
};
208210
let substs = match container {
209211
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)
211222
}
212223
ContainerId::TraitId(trait_) => {
213224
// we're picking this method

crates/ra_hir_ty/src/infer/unify.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,12 +167,12 @@ impl<T> Canonicalized<T> {
167167
}
168168
}
169169

170-
pub fn unify(ty1: Canonical<&Ty>, ty2: &Ty) -> Option<Substs> {
170+
pub fn unify(ty1: &Canonical<Ty>, ty2: &Canonical<Ty>) -> Option<Substs> {
171171
let mut table = InferenceTable::new();
172172
let vars =
173173
Substs::builder(ty1.num_vars).fill(std::iter::repeat_with(|| table.new_type_var())).build();
174174
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) {
176176
return None;
177177
}
178178
Some(

crates/ra_hir_ty/src/method_resolution.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -437,12 +437,12 @@ fn is_valid_candidate(
437437
pub(crate) fn inherent_impl_substs(
438438
db: &impl HirDatabase,
439439
impl_id: ImplId,
440-
self_ty: &Ty,
440+
self_ty: &Canonical<Ty>,
441441
) -> Option<Substs> {
442442
let vars = Substs::build_for_def(db, impl_id).fill_with_bound_vars(0).build();
443443
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 };
445-
super::infer::unify(self_ty_with_vars, self_ty)
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)
446446
}
447447

448448
fn transform_receiver_ty(
@@ -455,7 +455,7 @@ fn transform_receiver_ty(
455455
.push(self_ty.value.clone())
456456
.fill_with_unknown()
457457
.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)?,
459459
hir_def::ContainerId::ModuleId(_) => unreachable!(),
460460
};
461461
let sig = db.callable_item_signature(function_id.into());

crates/ra_hir_ty/src/tests.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4820,6 +4820,53 @@ fn test<T, U>() where T: Trait<U::Item>, U: Trait<T::Item> {
48204820
assert_eq!(t, "{unknown}");
48214821
}
48224822

4823+
#[test]
4824+
fn bug_2467() {
4825+
assert_snapshot!(
4826+
infer(r#"
4827+
struct S<T>(T);
4828+
impl<T> S<T> {
4829+
fn foo(self) -> T;
4830+
}
4831+
fn 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+
48234870
fn type_at_pos(db: &TestDB, pos: FilePosition) -> String {
48244871
let file = db.parse(pos.file_id).ok().unwrap();
48254872
let expr = algo::find_node_at_offset::<ast::Expr>(file.syntax(), pos.offset).unwrap();

0 commit comments

Comments
 (0)