Skip to content

Commit 9d72b14

Browse files
committed
Normalize assoc types in more places
1 parent 11b9845 commit 9d72b14

File tree

2 files changed

+27
-12
lines changed

2 files changed

+27
-12
lines changed

crates/ra_hir/src/ty/infer.rs

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -412,11 +412,18 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
412412
ty
413413
}
414414

415+
/// Recurses through the given type, normalizing associated types mentioned
416+
/// in it by replacing them by type variables and registering obligations to
417+
/// resolve later. This should be done once for every type we get from some
418+
/// type annotation (e.g. from a let type annotation, field type or function
419+
/// call). `make_ty` handles this already, but e.g. for field types we need
420+
/// to do it as well.
415421
fn normalize_associated_types_in(&mut self, ty: Ty) -> Ty {
422+
let ty = self.resolve_ty_as_possible(&mut vec![], ty);
416423
ty.fold(&mut |ty| match ty {
417424
Ty::Projection(proj_ty) => self.normalize_projection_ty(proj_ty),
418425
Ty::UnselectedProjection(proj_ty) => {
419-
// FIXME
426+
// FIXME use Chalk's unselected projection support
420427
Ty::UnselectedProjection(proj_ty)
421428
}
422429
_ => ty,
@@ -569,6 +576,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
569576
let substs = Ty::substs_from_path(self.db, &self.resolver, path, typable);
570577
let ty = ty.subst(&substs);
571578
let ty = self.insert_type_vars(ty);
579+
let ty = self.normalize_associated_types_in(ty);
572580
Some(ty)
573581
}
574582
Resolution::LocalBinding(pat) => {
@@ -690,6 +698,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
690698
.and_then(|d| d.field(self.db, &Name::tuple_field_name(i)))
691699
.map_or(Ty::Unknown, |field| field.ty(self.db))
692700
.subst(&substs);
701+
let expected_ty = self.normalize_associated_types_in(expected_ty);
693702
self.infer_pat(subpat, &expected_ty, default_bm);
694703
}
695704

@@ -717,6 +726,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
717726
let matching_field = def.and_then(|it| it.field(self.db, &subpat.name));
718727
let expected_ty =
719728
matching_field.map_or(Ty::Unknown, |field| field.ty(self.db)).subst(&substs);
729+
let expected_ty = self.normalize_associated_types_in(expected_ty);
720730
self.infer_pat(subpat.pat, &expected_ty, default_bm);
721731
}
722732

@@ -947,9 +957,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
947957
self.unify(&expected_receiver_ty, &actual_receiver_ty);
948958

949959
let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown));
950-
for (arg, param) in args.iter().zip(param_iter) {
951-
self.infer_expr(*arg, &Expectation::has_type(param));
960+
for (arg, param_ty) in args.iter().zip(param_iter) {
961+
let param_ty = self.normalize_associated_types_in(param_ty);
962+
self.infer_expr(*arg, &Expectation::has_type(param_ty));
952963
}
964+
let ret_ty = self.normalize_associated_types_in(ret_ty);
953965
ret_ty
954966
}
955967

@@ -1040,9 +1052,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
10401052
};
10411053
self.register_obligations_for_call(&callee_ty);
10421054
let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown));
1043-
for (arg, param) in args.iter().zip(param_iter) {
1044-
self.infer_expr(*arg, &Expectation::has_type(param));
1055+
for (arg, param_ty) in args.iter().zip(param_iter) {
1056+
let param_ty = self.normalize_associated_types_in(param_ty);
1057+
self.infer_expr(*arg, &Expectation::has_type(param_ty));
10451058
}
1059+
let ret_ty = self.normalize_associated_types_in(ret_ty);
10461060
ret_ty
10471061
}
10481062
Expr::MethodCall { receiver, args, method_name, generic_args } => self
@@ -1140,7 +1154,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
11401154
_ => None,
11411155
})
11421156
.unwrap_or(Ty::Unknown);
1143-
self.insert_type_vars(ty)
1157+
let ty = self.insert_type_vars(ty);
1158+
self.normalize_associated_types_in(ty)
11441159
}
11451160
Expr::Await { expr } => {
11461161
let inner_ty = self.infer_expr(*expr, &Expectation::none());

crates/ra_hir/src/ty/tests.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2515,10 +2515,10 @@ fn test<T: Iterable>() {
25152515
@r###"
25162516
25172517
⋮[108; 227) '{ ...ter; }': ()
2518-
⋮[118; 119) 'x': <S as Iterable>::Item
2519-
⋮[145; 146) '1': <S as Iterable>::Item
2520-
⋮[156; 157) 'y': <T as Iterable>::Item
2521-
⋮[183; 192) 'no_matter': <T as Iterable>::Item
2518+
⋮[118; 119) 'x': u32
2519+
⋮[145; 146) '1': u32
2520+
⋮[156; 157) 'y': {unknown}
2521+
⋮[183; 192) 'no_matter': {unknown}
25222522
⋮[202; 203) 'z': {unknown}
25232523
⋮[215; 224) 'no_matter': {unknown}
25242524
"###
@@ -2552,9 +2552,9 @@ fn test() {
25522552
⋮[205; 209) 'foo1': fn foo1<S>(T) -> {unknown}
25532553
⋮[205; 212) 'foo1(S)': {unknown}
25542554
⋮[210; 211) 'S': S
2555-
⋮[222; 223) 'y': <S as Iterable>::Item
2555+
⋮[222; 223) 'y': u32
25562556
⋮[226; 230) 'foo2': fn foo2<S>(T) -> <T as Iterable>::Item
2557-
⋮[226; 233) 'foo2(S)': <S as Iterable>::Item
2557+
⋮[226; 233) 'foo2(S)': u32
25582558
⋮[231; 232) 'S': S
25592559
"###
25602560
);

0 commit comments

Comments
 (0)