diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2021-05-23 22:55:51 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2021-05-23 22:55:51 +0100 |
commit | 495c9586ec51e0cf9b06397d99ec4f65c55e7a28 (patch) | |
tree | c18eb1b1568ab0f0251339f7995b6ea177b3285f /crates/hir_ty | |
parent | a2ce091fd7e149f809bdf0ee0d960d9e185ee5fb (diff) | |
parent | b8262099cc51065259daf10b4b23ff49ce74434f (diff) |
Merge #8945
8945: fix: Make expected type work in more situations r=flodiebold a=flodiebold
Also makes call info show the correct types for generic methods.
![2021-05-23-182952_1134x616_scrot](https://user-images.githubusercontent.com/906069/119269023-dd5a5b00-bbf5-11eb-993a-b6e122c3b9a6.png)
![2021-05-23-183117_922x696_scrot](https://user-images.githubusercontent.com/906069/119269025-dfbcb500-bbf5-11eb-983c-fc415b8428e0.png)
Co-authored-by: Florian Diebold <[email protected]>
Diffstat (limited to 'crates/hir_ty')
-rw-r--r-- | crates/hir_ty/src/diagnostics/expr.rs | 12 | ||||
-rw-r--r-- | crates/hir_ty/src/diagnostics/unsafe_check.rs | 2 | ||||
-rw-r--r-- | crates/hir_ty/src/infer.rs | 25 | ||||
-rw-r--r-- | crates/hir_ty/src/infer/expr.rs | 34 | ||||
-rw-r--r-- | crates/hir_ty/src/infer/unify.rs | 7 |
5 files changed, 42 insertions, 38 deletions
diff --git a/crates/hir_ty/src/diagnostics/expr.rs b/crates/hir_ty/src/diagnostics/expr.rs index 53c4ee9da..d1f113e7f 100644 --- a/crates/hir_ty/src/diagnostics/expr.rs +++ b/crates/hir_ty/src/diagnostics/expr.rs | |||
@@ -181,7 +181,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> { | |||
181 | for (id, expr) in body.exprs.iter() { | 181 | for (id, expr) in body.exprs.iter() { |
182 | if let Expr::MethodCall { receiver, .. } = expr { | 182 | if let Expr::MethodCall { receiver, .. } = expr { |
183 | let function_id = match self.infer.method_resolution(id) { | 183 | let function_id = match self.infer.method_resolution(id) { |
184 | Some(id) => id, | 184 | Some((id, _)) => id, |
185 | None => continue, | 185 | None => continue, |
186 | }; | 186 | }; |
187 | 187 | ||
@@ -239,15 +239,11 @@ impl<'a, 'b> ExprValidator<'a, 'b> { | |||
239 | return; | 239 | return; |
240 | } | 240 | } |
241 | 241 | ||
242 | // FIXME: note that we erase information about substs here. This | 242 | let (callee, subst) = match self.infer.method_resolution(call_id) { |
243 | // is not right, but, luckily, doesn't matter as we care only | 243 | Some(it) => it, |
244 | // about the number of params | ||
245 | let callee = match self.infer.method_resolution(call_id) { | ||
246 | Some(callee) => callee, | ||
247 | None => return, | 244 | None => return, |
248 | }; | 245 | }; |
249 | let sig = | 246 | let sig = db.callable_item_signature(callee.into()).substitute(&Interner, &subst); |
250 | db.callable_item_signature(callee.into()).into_value_and_skipped_binders().0; | ||
251 | 247 | ||
252 | (sig, args) | 248 | (sig, args) |
253 | } | 249 | } |
diff --git a/crates/hir_ty/src/diagnostics/unsafe_check.rs b/crates/hir_ty/src/diagnostics/unsafe_check.rs index ed97dc0e3..5d13bddea 100644 --- a/crates/hir_ty/src/diagnostics/unsafe_check.rs +++ b/crates/hir_ty/src/diagnostics/unsafe_check.rs | |||
@@ -105,7 +105,7 @@ fn walk_unsafe( | |||
105 | Expr::MethodCall { .. } => { | 105 | Expr::MethodCall { .. } => { |
106 | if infer | 106 | if infer |
107 | .method_resolution(current) | 107 | .method_resolution(current) |
108 | .map(|func| db.function_data(func).is_unsafe()) | 108 | .map(|(func, _)| db.function_data(func).is_unsafe()) |
109 | .unwrap_or(false) | 109 | .unwrap_or(false) |
110 | { | 110 | { |
111 | unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block }); | 111 | unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block }); |
diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs index f1cebbdb9..db3c937ff 100644 --- a/crates/hir_ty/src/infer.rs +++ b/crates/hir_ty/src/infer.rs | |||
@@ -37,8 +37,8 @@ use syntax::SmolStr; | |||
37 | use super::{DomainGoal, InEnvironment, ProjectionTy, TraitEnvironment, TraitRef, Ty}; | 37 | use super::{DomainGoal, InEnvironment, ProjectionTy, TraitEnvironment, TraitRef, Ty}; |
38 | use crate::{ | 38 | use crate::{ |
39 | db::HirDatabase, fold_tys, infer::diagnostics::InferenceDiagnostic, | 39 | db::HirDatabase, fold_tys, infer::diagnostics::InferenceDiagnostic, |
40 | lower::ImplTraitLoweringMode, to_assoc_type_id, AliasEq, AliasTy, Goal, Interner, TyBuilder, | 40 | lower::ImplTraitLoweringMode, to_assoc_type_id, AliasEq, AliasTy, Goal, Interner, Substitution, |
41 | TyExt, TyKind, | 41 | TyBuilder, TyExt, TyKind, |
42 | }; | 42 | }; |
43 | 43 | ||
44 | // This lint has a false positive here. See the link below for details. | 44 | // This lint has a false positive here. See the link below for details. |
@@ -132,7 +132,7 @@ impl Default for InternedStandardTypes { | |||
132 | #[derive(Clone, PartialEq, Eq, Debug, Default)] | 132 | #[derive(Clone, PartialEq, Eq, Debug, Default)] |
133 | pub struct InferenceResult { | 133 | pub struct InferenceResult { |
134 | /// For each method call expr, records the function it resolves to. | 134 | /// For each method call expr, records the function it resolves to. |
135 | method_resolutions: FxHashMap<ExprId, FunctionId>, | 135 | method_resolutions: FxHashMap<ExprId, (FunctionId, Substitution)>, |
136 | /// For each field access expr, records the field it resolves to. | 136 | /// For each field access expr, records the field it resolves to. |
137 | field_resolutions: FxHashMap<ExprId, FieldId>, | 137 | field_resolutions: FxHashMap<ExprId, FieldId>, |
138 | /// For each struct literal or pattern, records the variant it resolves to. | 138 | /// For each struct literal or pattern, records the variant it resolves to. |
@@ -152,8 +152,8 @@ pub struct InferenceResult { | |||
152 | } | 152 | } |
153 | 153 | ||
154 | impl InferenceResult { | 154 | impl InferenceResult { |
155 | pub fn method_resolution(&self, expr: ExprId) -> Option<FunctionId> { | 155 | pub fn method_resolution(&self, expr: ExprId) -> Option<(FunctionId, Substitution)> { |
156 | self.method_resolutions.get(&expr).copied() | 156 | self.method_resolutions.get(&expr).cloned() |
157 | } | 157 | } |
158 | pub fn field_resolution(&self, expr: ExprId) -> Option<FieldId> { | 158 | pub fn field_resolution(&self, expr: ExprId) -> Option<FieldId> { |
159 | self.field_resolutions.get(&expr).copied() | 159 | self.field_resolutions.get(&expr).copied() |
@@ -284,14 +284,17 @@ impl<'a> InferenceContext<'a> { | |||
284 | self.table.propagate_diverging_flag(); | 284 | self.table.propagate_diverging_flag(); |
285 | let mut result = std::mem::take(&mut self.result); | 285 | let mut result = std::mem::take(&mut self.result); |
286 | for ty in result.type_of_expr.values_mut() { | 286 | for ty in result.type_of_expr.values_mut() { |
287 | *ty = self.table.resolve_ty_completely(ty.clone()); | 287 | *ty = self.table.resolve_completely(ty.clone()); |
288 | } | 288 | } |
289 | for ty in result.type_of_pat.values_mut() { | 289 | for ty in result.type_of_pat.values_mut() { |
290 | *ty = self.table.resolve_ty_completely(ty.clone()); | 290 | *ty = self.table.resolve_completely(ty.clone()); |
291 | } | 291 | } |
292 | for mismatch in result.type_mismatches.values_mut() { | 292 | for mismatch in result.type_mismatches.values_mut() { |
293 | mismatch.expected = self.table.resolve_ty_completely(mismatch.expected.clone()); | 293 | mismatch.expected = self.table.resolve_completely(mismatch.expected.clone()); |
294 | mismatch.actual = self.table.resolve_ty_completely(mismatch.actual.clone()); | 294 | mismatch.actual = self.table.resolve_completely(mismatch.actual.clone()); |
295 | } | ||
296 | for (_, subst) in result.method_resolutions.values_mut() { | ||
297 | *subst = self.table.resolve_completely(subst.clone()); | ||
295 | } | 298 | } |
296 | result | 299 | result |
297 | } | 300 | } |
@@ -300,8 +303,8 @@ impl<'a> InferenceContext<'a> { | |||
300 | self.result.type_of_expr.insert(expr, ty); | 303 | self.result.type_of_expr.insert(expr, ty); |
301 | } | 304 | } |
302 | 305 | ||
303 | fn write_method_resolution(&mut self, expr: ExprId, func: FunctionId) { | 306 | fn write_method_resolution(&mut self, expr: ExprId, func: FunctionId, subst: Substitution) { |
304 | self.result.method_resolutions.insert(expr, func); | 307 | self.result.method_resolutions.insert(expr, (func, subst)); |
305 | } | 308 | } |
306 | 309 | ||
307 | fn write_field_resolution(&mut self, expr: ExprId, field: FieldId) { | 310 | fn write_field_resolution(&mut self, expr: ExprId, field: FieldId) { |
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index 08c05c67c..eab8fac91 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs | |||
@@ -891,17 +891,21 @@ impl<'a> InferenceContext<'a> { | |||
891 | method_name, | 891 | method_name, |
892 | ) | 892 | ) |
893 | }); | 893 | }); |
894 | let (derefed_receiver_ty, method_ty, def_generics) = match resolved { | 894 | let (derefed_receiver_ty, method_ty, substs) = match resolved { |
895 | Some((ty, func)) => { | 895 | Some((ty, func)) => { |
896 | let ty = canonicalized_receiver.decanonicalize_ty(ty); | 896 | let ty = canonicalized_receiver.decanonicalize_ty(ty); |
897 | self.write_method_resolution(tgt_expr, func); | 897 | let generics = generics(self.db.upcast(), func.into()); |
898 | (ty, self.db.value_ty(func.into()), Some(generics(self.db.upcast(), func.into()))) | 898 | let substs = self.substs_for_method_call(generics, generic_args, &ty); |
899 | self.write_method_resolution(tgt_expr, func, substs.clone()); | ||
900 | (ty, self.db.value_ty(func.into()), substs) | ||
899 | } | 901 | } |
900 | None => (receiver_ty, Binders::empty(&Interner, self.err_ty()), None), | 902 | None => ( |
903 | receiver_ty, | ||
904 | Binders::empty(&Interner, self.err_ty()), | ||
905 | Substitution::empty(&Interner), | ||
906 | ), | ||
901 | }; | 907 | }; |
902 | let substs = self.substs_for_method_call(def_generics, generic_args, &derefed_receiver_ty); | ||
903 | let method_ty = method_ty.substitute(&Interner, &substs); | 908 | let method_ty = method_ty.substitute(&Interner, &substs); |
904 | let method_ty = self.insert_type_vars(method_ty); | ||
905 | self.register_obligations_for_call(&method_ty); | 909 | self.register_obligations_for_call(&method_ty); |
906 | let (expected_receiver_ty, param_tys, ret_ty) = match method_ty.callable_sig(self.db) { | 910 | let (expected_receiver_ty, param_tys, ret_ty) = match method_ty.callable_sig(self.db) { |
907 | Some(sig) => { | 911 | Some(sig) => { |
@@ -950,23 +954,21 @@ impl<'a> InferenceContext<'a> { | |||
950 | 954 | ||
951 | fn substs_for_method_call( | 955 | fn substs_for_method_call( |
952 | &mut self, | 956 | &mut self, |
953 | def_generics: Option<Generics>, | 957 | def_generics: Generics, |
954 | generic_args: Option<&GenericArgs>, | 958 | generic_args: Option<&GenericArgs>, |
955 | receiver_ty: &Ty, | 959 | receiver_ty: &Ty, |
956 | ) -> Substitution { | 960 | ) -> Substitution { |
957 | let (parent_params, self_params, type_params, impl_trait_params) = | 961 | let (parent_params, self_params, type_params, impl_trait_params) = |
958 | def_generics.as_ref().map_or((0, 0, 0, 0), |g| g.provenance_split()); | 962 | def_generics.provenance_split(); |
959 | assert_eq!(self_params, 0); // method shouldn't have another Self param | 963 | assert_eq!(self_params, 0); // method shouldn't have another Self param |
960 | let total_len = parent_params + type_params + impl_trait_params; | 964 | let total_len = parent_params + type_params + impl_trait_params; |
961 | let mut substs = Vec::with_capacity(total_len); | 965 | let mut substs = Vec::with_capacity(total_len); |
962 | // Parent arguments are unknown, except for the receiver type | 966 | // Parent arguments are unknown, except for the receiver type |
963 | if let Some(parent_generics) = def_generics.as_ref().map(|p| p.iter_parent()) { | 967 | for (_id, param) in def_generics.iter_parent() { |
964 | for (_id, param) in parent_generics { | 968 | if param.provenance == hir_def::generics::TypeParamProvenance::TraitSelf { |
965 | if param.provenance == hir_def::generics::TypeParamProvenance::TraitSelf { | 969 | substs.push(receiver_ty.clone()); |
966 | substs.push(receiver_ty.clone()); | 970 | } else { |
967 | } else { | 971 | substs.push(self.table.new_type_var()); |
968 | substs.push(self.err_ty()); | ||
969 | } | ||
970 | } | 972 | } |
971 | } | 973 | } |
972 | // handle provided type arguments | 974 | // handle provided type arguments |
@@ -989,7 +991,7 @@ impl<'a> InferenceContext<'a> { | |||
989 | }; | 991 | }; |
990 | let supplied_params = substs.len(); | 992 | let supplied_params = substs.len(); |
991 | for _ in supplied_params..total_len { | 993 | for _ in supplied_params..total_len { |
992 | substs.push(self.err_ty()); | 994 | substs.push(self.table.new_type_var()); |
993 | } | 995 | } |
994 | assert_eq!(substs.len(), total_len); | 996 | assert_eq!(substs.len(), total_len); |
995 | Substitution::from_iter(&Interner, substs) | 997 | Substitution::from_iter(&Interner, substs) |
diff --git a/crates/hir_ty/src/infer/unify.rs b/crates/hir_ty/src/infer/unify.rs index f8233cac3..ea5684229 100644 --- a/crates/hir_ty/src/infer/unify.rs +++ b/crates/hir_ty/src/infer/unify.rs | |||
@@ -295,8 +295,11 @@ impl<'a> InferenceTable<'a> { | |||
295 | .expect("fold failed unexpectedly") | 295 | .expect("fold failed unexpectedly") |
296 | } | 296 | } |
297 | 297 | ||
298 | pub(crate) fn resolve_ty_completely(&mut self, ty: Ty) -> Ty { | 298 | pub(crate) fn resolve_completely<T>(&mut self, t: T) -> T::Result |
299 | self.resolve_with_fallback(ty, |_, _, d, _| d) | 299 | where |
300 | T: HasInterner<Interner = Interner> + Fold<Interner>, | ||
301 | { | ||
302 | self.resolve_with_fallback(t, |_, _, d, _| d) | ||
300 | } | 303 | } |
301 | 304 | ||
302 | /// Unify two types and register new trait goals that arise from that. | 305 | /// Unify two types and register new trait goals that arise from that. |