ty
}
+ /// Recurses through the given type, normalizing associated types mentioned
+ /// in it by replacing them by type variables and registering obligations to
+ /// resolve later. This should be done once for every type we get from some
+ /// type annotation (e.g. from a let type annotation, field type or function
+ /// call). `make_ty` handles this already, but e.g. for field types we need
+ /// to do it as well.
fn normalize_associated_types_in(&mut self, ty: Ty) -> Ty {
+ let ty = self.resolve_ty_as_possible(&mut vec![], ty);
ty.fold(&mut |ty| match ty {
Ty::Projection(proj_ty) => self.normalize_projection_ty(proj_ty),
Ty::UnselectedProjection(proj_ty) => {
- // FIXME
+ // FIXME use Chalk's unselected projection support
Ty::UnselectedProjection(proj_ty)
}
_ => ty,
let substs = Ty::substs_from_path(self.db, &self.resolver, path, typable);
let ty = ty.subst(&substs);
let ty = self.insert_type_vars(ty);
+ let ty = self.normalize_associated_types_in(ty);
Some(ty)
}
Resolution::LocalBinding(pat) => {
.and_then(|d| d.field(self.db, &Name::tuple_field_name(i)))
.map_or(Ty::Unknown, |field| field.ty(self.db))
.subst(&substs);
+ let expected_ty = self.normalize_associated_types_in(expected_ty);
self.infer_pat(subpat, &expected_ty, default_bm);
}
let matching_field = def.and_then(|it| it.field(self.db, &subpat.name));
let expected_ty =
matching_field.map_or(Ty::Unknown, |field| field.ty(self.db)).subst(&substs);
+ let expected_ty = self.normalize_associated_types_in(expected_ty);
self.infer_pat(subpat.pat, &expected_ty, default_bm);
}
self.unify(&expected_receiver_ty, &actual_receiver_ty);
let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown));
- for (arg, param) in args.iter().zip(param_iter) {
- self.infer_expr(*arg, &Expectation::has_type(param));
+ for (arg, param_ty) in args.iter().zip(param_iter) {
+ let param_ty = self.normalize_associated_types_in(param_ty);
+ self.infer_expr(*arg, &Expectation::has_type(param_ty));
}
+ let ret_ty = self.normalize_associated_types_in(ret_ty);
ret_ty
}
};
self.register_obligations_for_call(&callee_ty);
let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown));
- for (arg, param) in args.iter().zip(param_iter) {
- self.infer_expr(*arg, &Expectation::has_type(param));
+ for (arg, param_ty) in args.iter().zip(param_iter) {
+ let param_ty = self.normalize_associated_types_in(param_ty);
+ self.infer_expr(*arg, &Expectation::has_type(param_ty));
}
+ let ret_ty = self.normalize_associated_types_in(ret_ty);
ret_ty
}
Expr::MethodCall { receiver, args, method_name, generic_args } => self
_ => None,
})
.unwrap_or(Ty::Unknown);
- self.insert_type_vars(ty)
+ let ty = self.insert_type_vars(ty);
+ self.normalize_associated_types_in(ty)
}
Expr::Await { expr } => {
let inner_ty = self.infer_expr(*expr, &Expectation::none());
@r###"
⋮
⋮[108; 227) '{ ...ter; }': ()
- ⋮[118; 119) 'x': <S as Iterable>::Item
- ⋮[145; 146) '1': <S as Iterable>::Item
- ⋮[156; 157) 'y': <T as Iterable>::Item
- ⋮[183; 192) 'no_matter': <T as Iterable>::Item
+ ⋮[118; 119) 'x': u32
+ ⋮[145; 146) '1': u32
+ ⋮[156; 157) 'y': {unknown}
+ ⋮[183; 192) 'no_matter': {unknown}
⋮[202; 203) 'z': {unknown}
⋮[215; 224) 'no_matter': {unknown}
"###
⋮[205; 209) 'foo1': fn foo1<S>(T) -> {unknown}
⋮[205; 212) 'foo1(S)': {unknown}
⋮[210; 211) 'S': S
- ⋮[222; 223) 'y': <S as Iterable>::Item
+ ⋮[222; 223) 'y': u32
⋮[226; 230) 'foo2': fn foo2<S>(T) -> <T as Iterable>::Item
- ⋮[226; 233) 'foo2(S)': <S as Iterable>::Item
+ ⋮[226; 233) 'foo2(S)': u32
⋮[231; 232) 'S': S
"###
);