@@ -20,8 +20,8 @@ use ide_db::{
2020use syntax:: TextRange ;
2121
2222use crate :: {
23- item:: ImportEdit , CompletionContext , CompletionItem , CompletionItemKind , CompletionKind ,
24- CompletionRelevance ,
23+ item:: { CompletionRelevanceTypeMatch , ImportEdit } ,
24+ CompletionContext , CompletionItem , CompletionItemKind , CompletionKind , CompletionRelevance ,
2525} ;
2626
2727use crate :: render:: { enum_variant:: render_variant, function:: render_fn, macro_:: render_macro} ;
@@ -143,7 +143,7 @@ impl<'a> Render<'a> {
143143 . set_deprecated ( is_deprecated) ;
144144
145145 item. set_relevance ( CompletionRelevance {
146- exact_type_match : compute_exact_type_match ( self . ctx . completion , ty) ,
146+ type_match : compute_type_match ( self . ctx . completion , ty) ,
147147 exact_name_match : compute_exact_name_match ( self . ctx . completion , name. to_string ( ) ) ,
148148 ..CompletionRelevance :: default ( )
149149 } ) ;
@@ -245,7 +245,7 @@ impl<'a> Render<'a> {
245245 }
246246
247247 item. set_relevance ( CompletionRelevance {
248- exact_type_match : compute_exact_type_match ( self . ctx . completion , & ty) ,
248+ type_match : compute_type_match ( self . ctx . completion , & ty) ,
249249 exact_name_match : compute_exact_name_match ( self . ctx . completion , & local_name) ,
250250 is_local : true ,
251251 ..CompletionRelevance :: default ( )
@@ -309,14 +309,24 @@ impl<'a> Render<'a> {
309309 }
310310}
311311
312- fn compute_exact_type_match ( ctx : & CompletionContext , completion_ty : & hir:: Type ) -> bool {
313- match ctx. expected_type . as_ref ( ) {
314- Some ( expected_type) => {
315- // We don't ever consider unit type to be an exact type match, since
316- // nearly always this is not meaningful to the user.
317- completion_ty == expected_type && !expected_type. is_unit ( )
318- }
319- None => false ,
312+ fn compute_type_match (
313+ ctx : & CompletionContext ,
314+ completion_ty : & hir:: Type ,
315+ ) -> Option < CompletionRelevanceTypeMatch > {
316+ let expected_type = ctx. expected_type . as_ref ( ) ?;
317+
318+ // We don't ever consider unit type to be an exact type match, since
319+ // nearly always this is not meaningful to the user.
320+ if expected_type. is_unit ( ) {
321+ return None ;
322+ }
323+
324+ if completion_ty == expected_type {
325+ Some ( CompletionRelevanceTypeMatch :: Exact )
326+ } else if expected_type. could_unify_with ( completion_ty) {
327+ Some ( CompletionRelevanceTypeMatch :: CouldUnify )
328+ } else {
329+ None
320330 }
321331}
322332
@@ -348,6 +358,7 @@ mod tests {
348358 use itertools:: Itertools ;
349359
350360 use crate :: {
361+ item:: CompletionRelevanceTypeMatch ,
351362 test_utils:: { check_edit, do_completion, get_all_items, TEST_CONFIG } ,
352363 CompletionKind , CompletionRelevance ,
353364 } ;
@@ -360,7 +371,11 @@ mod tests {
360371 fn check_relevance ( ra_fixture : & str , expect : Expect ) {
361372 fn display_relevance ( relevance : CompletionRelevance ) -> String {
362373 let relevance_factors = vec ! [
363- ( relevance. exact_type_match, "type" ) ,
374+ ( relevance. type_match == Some ( CompletionRelevanceTypeMatch :: Exact ) , "type" ) ,
375+ (
376+ relevance. type_match == Some ( CompletionRelevanceTypeMatch :: CouldUnify ) ,
377+ "type_could_unify" ,
378+ ) ,
364379 ( relevance. exact_name_match, "name" ) ,
365380 ( relevance. is_local, "local" ) ,
366381 ]
@@ -533,7 +548,9 @@ fn main() { let _: m::Spam = S$0 }
533548 detail: "(i32)",
534549 relevance: CompletionRelevance {
535550 exact_name_match: false,
536- exact_type_match: true,
551+ type_match: Some(
552+ Exact,
553+ ),
537554 is_local: false,
538555 },
539556 trigger_call_info: true,
@@ -559,7 +576,9 @@ fn main() { let _: m::Spam = S$0 }
559576 detail: "()",
560577 relevance: CompletionRelevance {
561578 exact_name_match: false,
562- exact_type_match: true,
579+ type_match: Some(
580+ Exact,
581+ ),
563582 is_local: false,
564583 },
565584 },
@@ -1108,7 +1127,7 @@ fn main() {
11081127 detail: "S",
11091128 relevance: CompletionRelevance {
11101129 exact_name_match: true,
1111- exact_type_match: false ,
1130+ type_match: None ,
11121131 is_local: true,
11131132 },
11141133 ref_match: "&mut ",
@@ -1353,4 +1372,34 @@ fn foo(f: Foo) { let _: &u32 = f.b$0 }
13531372 "# ] ] ,
13541373 ) ;
13551374 }
1375+
1376+ #[ test]
1377+ fn generic_enum ( ) {
1378+ check_relevance (
1379+ r#"
1380+ enum Foo<T> { A(T), B }
1381+ // bar() should not be an exact type match
1382+ // because the generic parameters are different
1383+ fn bar() -> Foo<u8> { Foo::B }
1384+ // FIXME baz() should be an exact type match
1385+ // because the types could unify, but it currently
1386+ // is not. This is due to the T here being
1387+ // TyKind::Placeholder rather than TyKind::Missing.
1388+ fn baz<T>() -> Foo<T> { Foo::B }
1389+ fn foo() {
1390+ let foo: Foo<u32> = Foo::B;
1391+ let _: Foo<u32> = f$0;
1392+ }
1393+ "# ,
1394+ expect ! [ [ r#"
1395+ ev Foo::A(…) [type_could_unify]
1396+ ev Foo::B [type_could_unify]
1397+ lc foo [type+local]
1398+ en Foo []
1399+ fn baz() []
1400+ fn bar() []
1401+ fn foo() []
1402+ "# ] ] ,
1403+ ) ;
1404+ }
13561405}
0 commit comments