mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-30 13:51:31 +00:00
Normalize assoc types in more places
This commit is contained in:
parent
11b9845afd
commit
9d72b14cfe
2 changed files with 27 additions and 12 deletions
|
@ -412,11 +412,18 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||||
ty
|
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 {
|
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.fold(&mut |ty| match ty {
|
||||||
Ty::Projection(proj_ty) => self.normalize_projection_ty(proj_ty),
|
Ty::Projection(proj_ty) => self.normalize_projection_ty(proj_ty),
|
||||||
Ty::UnselectedProjection(proj_ty) => {
|
Ty::UnselectedProjection(proj_ty) => {
|
||||||
// FIXME
|
// FIXME use Chalk's unselected projection support
|
||||||
Ty::UnselectedProjection(proj_ty)
|
Ty::UnselectedProjection(proj_ty)
|
||||||
}
|
}
|
||||||
_ => ty,
|
_ => ty,
|
||||||
|
@ -569,6 +576,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||||
let substs = Ty::substs_from_path(self.db, &self.resolver, path, typable);
|
let substs = Ty::substs_from_path(self.db, &self.resolver, path, typable);
|
||||||
let ty = ty.subst(&substs);
|
let ty = ty.subst(&substs);
|
||||||
let ty = self.insert_type_vars(ty);
|
let ty = self.insert_type_vars(ty);
|
||||||
|
let ty = self.normalize_associated_types_in(ty);
|
||||||
Some(ty)
|
Some(ty)
|
||||||
}
|
}
|
||||||
Resolution::LocalBinding(pat) => {
|
Resolution::LocalBinding(pat) => {
|
||||||
|
@ -690,6 +698,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||||
.and_then(|d| d.field(self.db, &Name::tuple_field_name(i)))
|
.and_then(|d| d.field(self.db, &Name::tuple_field_name(i)))
|
||||||
.map_or(Ty::Unknown, |field| field.ty(self.db))
|
.map_or(Ty::Unknown, |field| field.ty(self.db))
|
||||||
.subst(&substs);
|
.subst(&substs);
|
||||||
|
let expected_ty = self.normalize_associated_types_in(expected_ty);
|
||||||
self.infer_pat(subpat, &expected_ty, default_bm);
|
self.infer_pat(subpat, &expected_ty, default_bm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -717,6 +726,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||||
let matching_field = def.and_then(|it| it.field(self.db, &subpat.name));
|
let matching_field = def.and_then(|it| it.field(self.db, &subpat.name));
|
||||||
let expected_ty =
|
let expected_ty =
|
||||||
matching_field.map_or(Ty::Unknown, |field| field.ty(self.db)).subst(&substs);
|
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.infer_pat(subpat.pat, &expected_ty, default_bm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -947,9 +957,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||||
self.unify(&expected_receiver_ty, &actual_receiver_ty);
|
self.unify(&expected_receiver_ty, &actual_receiver_ty);
|
||||||
|
|
||||||
let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown));
|
let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown));
|
||||||
for (arg, param) in args.iter().zip(param_iter) {
|
for (arg, param_ty) in args.iter().zip(param_iter) {
|
||||||
self.infer_expr(*arg, &Expectation::has_type(param));
|
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
|
ret_ty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1040,9 +1052,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||||
};
|
};
|
||||||
self.register_obligations_for_call(&callee_ty);
|
self.register_obligations_for_call(&callee_ty);
|
||||||
let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown));
|
let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown));
|
||||||
for (arg, param) in args.iter().zip(param_iter) {
|
for (arg, param_ty) in args.iter().zip(param_iter) {
|
||||||
self.infer_expr(*arg, &Expectation::has_type(param));
|
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
|
ret_ty
|
||||||
}
|
}
|
||||||
Expr::MethodCall { receiver, args, method_name, generic_args } => self
|
Expr::MethodCall { receiver, args, method_name, generic_args } => self
|
||||||
|
@ -1140,7 +1154,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
.unwrap_or(Ty::Unknown);
|
.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 } => {
|
Expr::Await { expr } => {
|
||||||
let inner_ty = self.infer_expr(*expr, &Expectation::none());
|
let inner_ty = self.infer_expr(*expr, &Expectation::none());
|
||||||
|
|
|
@ -2515,10 +2515,10 @@ fn test<T: Iterable>() {
|
||||||
@r###"
|
@r###"
|
||||||
⋮
|
⋮
|
||||||
⋮[108; 227) '{ ...ter; }': ()
|
⋮[108; 227) '{ ...ter; }': ()
|
||||||
⋮[118; 119) 'x': <S as Iterable>::Item
|
⋮[118; 119) 'x': u32
|
||||||
⋮[145; 146) '1': <S as Iterable>::Item
|
⋮[145; 146) '1': u32
|
||||||
⋮[156; 157) 'y': <T as Iterable>::Item
|
⋮[156; 157) 'y': {unknown}
|
||||||
⋮[183; 192) 'no_matter': <T as Iterable>::Item
|
⋮[183; 192) 'no_matter': {unknown}
|
||||||
⋮[202; 203) 'z': {unknown}
|
⋮[202; 203) 'z': {unknown}
|
||||||
⋮[215; 224) 'no_matter': {unknown}
|
⋮[215; 224) 'no_matter': {unknown}
|
||||||
"###
|
"###
|
||||||
|
@ -2552,9 +2552,9 @@ fn test() {
|
||||||
⋮[205; 209) 'foo1': fn foo1<S>(T) -> {unknown}
|
⋮[205; 209) 'foo1': fn foo1<S>(T) -> {unknown}
|
||||||
⋮[205; 212) 'foo1(S)': {unknown}
|
⋮[205; 212) 'foo1(S)': {unknown}
|
||||||
⋮[210; 211) 'S': S
|
⋮[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; 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
|
⋮[231; 232) 'S': S
|
||||||
"###
|
"###
|
||||||
);
|
);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue