diff options
author | Florian Diebold <[email protected]> | 2021-05-23 17:10:40 +0100 |
---|---|---|
committer | Florian Diebold <[email protected]> | 2021-05-23 17:45:44 +0100 |
commit | 7a0c93c58ac17b089edd8c9763fef303b7a81414 (patch) | |
tree | 49cb56219cd7aea41376c49252601264ebabcf1a /crates/ide_completion/src | |
parent | 4a6cdd776d403bacce0a5471d77e8c76695c5bc5 (diff) |
Infer correct expected type for generic struct fields
Diffstat (limited to 'crates/ide_completion/src')
-rw-r--r-- | crates/ide_completion/src/context.rs | 32 | ||||
-rw-r--r-- | crates/ide_completion/src/render.rs | 7 |
2 files changed, 23 insertions, 16 deletions
diff --git a/crates/ide_completion/src/context.rs b/crates/ide_completion/src/context.rs index c929d7394..4a88a6e88 100644 --- a/crates/ide_completion/src/context.rs +++ b/crates/ide_completion/src/context.rs | |||
@@ -337,25 +337,25 @@ impl<'a> CompletionContext<'a> { | |||
337 | }, | 337 | }, |
338 | ast::RecordExprFieldList(_it) => { | 338 | ast::RecordExprFieldList(_it) => { |
339 | cov_mark::hit!(expected_type_struct_field_without_leading_char); | 339 | cov_mark::hit!(expected_type_struct_field_without_leading_char); |
340 | self.token.prev_sibling_or_token() | 340 | // wouldn't try {} be nice... |
341 | .and_then(|se| se.into_node()) | 341 | (|| { |
342 | .and_then(|node| ast::RecordExprField::cast(node)) | 342 | let record_ty = self.sema.type_of_expr(&ast::Expr::cast(node.parent()?)?)?; |
343 | .and_then(|rf| self.sema.resolve_record_field(&rf).zip(Some(rf))) | 343 | let expr_field = self.token.prev_sibling_or_token()? |
344 | .map(|(f, rf)|( | 344 | .into_node() |
345 | Some(f.0.ty(self.db)), | 345 | .and_then(|node| ast::RecordExprField::cast(node))?; |
346 | rf.field_name().map(NameOrNameRef::NameRef), | 346 | let field = self.sema.resolve_record_field(&expr_field)?.0; |
347 | Some(( | ||
348 | record_ty.field_type(self.db, field), | ||
349 | expr_field.field_name().map(NameOrNameRef::NameRef), | ||
347 | )) | 350 | )) |
348 | .unwrap_or((None, None)) | 351 | })().unwrap_or((None, None)) |
349 | }, | 352 | }, |
350 | ast::RecordExprField(it) => { | 353 | ast::RecordExprField(it) => { |
351 | cov_mark::hit!(expected_type_struct_field_with_leading_char); | 354 | cov_mark::hit!(expected_type_struct_field_with_leading_char); |
352 | self.sema | 355 | ( |
353 | .resolve_record_field(&it) | 356 | it.expr().as_ref().and_then(|e| self.sema.type_of_expr(e)), |
354 | .map(|f|( | 357 | it.field_name().map(NameOrNameRef::NameRef), |
355 | Some(f.0.ty(self.db)), | 358 | ) |
356 | it.field_name().map(NameOrNameRef::NameRef), | ||
357 | )) | ||
358 | .unwrap_or((None, None)) | ||
359 | }, | 359 | }, |
360 | ast::MatchExpr(it) => { | 360 | ast::MatchExpr(it) => { |
361 | cov_mark::hit!(expected_type_match_arm_without_leading_char); | 361 | cov_mark::hit!(expected_type_match_arm_without_leading_char); |
@@ -910,7 +910,7 @@ fn foo() -> u32 { | |||
910 | } | 910 | } |
911 | 911 | ||
912 | #[test] | 912 | #[test] |
913 | fn expected_type_closure_param() { | 913 | fn expected_type_closure_param_return() { |
914 | check_expected_type_and_name( | 914 | check_expected_type_and_name( |
915 | r#" | 915 | r#" |
916 | fn foo() { | 916 | fn foo() { |
diff --git a/crates/ide_completion/src/render.rs b/crates/ide_completion/src/render.rs index 6b04ee164..d7f96b864 100644 --- a/crates/ide_completion/src/render.rs +++ b/crates/ide_completion/src/render.rs | |||
@@ -667,6 +667,13 @@ fn foo() { A { the$0 } } | |||
667 | ), | 667 | ), |
668 | detail: "u32", | 668 | detail: "u32", |
669 | deprecated: true, | 669 | deprecated: true, |
670 | relevance: CompletionRelevance { | ||
671 | exact_name_match: false, | ||
672 | type_match: Some( | ||
673 | CouldUnify, | ||
674 | ), | ||
675 | is_local: false, | ||
676 | }, | ||
670 | }, | 677 | }, |
671 | ] | 678 | ] |
672 | "#]], | 679 | "#]], |