@@ -20,8 +20,8 @@ use ide_db::{
20
20
use syntax:: TextRange ;
21
21
22
22
use crate :: {
23
- item:: ImportEdit , CompletionContext , CompletionItem , CompletionItemKind , CompletionKind ,
24
- CompletionRelevance ,
23
+ item:: { CompletionRelevanceTypeMatch , ImportEdit } ,
24
+ CompletionContext , CompletionItem , CompletionItemKind , CompletionKind , CompletionRelevance ,
25
25
} ;
26
26
27
27
use crate :: render:: { enum_variant:: render_variant, function:: render_fn, macro_:: render_macro} ;
@@ -143,7 +143,7 @@ impl<'a> Render<'a> {
143
143
. set_deprecated ( is_deprecated) ;
144
144
145
145
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) ,
147
147
exact_name_match : compute_exact_name_match ( self . ctx . completion , name. to_string ( ) ) ,
148
148
..CompletionRelevance :: default ( )
149
149
} ) ;
@@ -245,7 +245,7 @@ impl<'a> Render<'a> {
245
245
}
246
246
247
247
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) ,
249
249
exact_name_match : compute_exact_name_match ( self . ctx . completion , & local_name) ,
250
250
is_local : true ,
251
251
..CompletionRelevance :: default ( )
@@ -309,14 +309,24 @@ impl<'a> Render<'a> {
309
309
}
310
310
}
311
311
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
320
330
}
321
331
}
322
332
@@ -348,6 +358,7 @@ mod tests {
348
358
use itertools:: Itertools ;
349
359
350
360
use crate :: {
361
+ item:: CompletionRelevanceTypeMatch ,
351
362
test_utils:: { check_edit, do_completion, get_all_items, TEST_CONFIG } ,
352
363
CompletionKind , CompletionRelevance ,
353
364
} ;
@@ -360,7 +371,11 @@ mod tests {
360
371
fn check_relevance ( ra_fixture : & str , expect : Expect ) {
361
372
fn display_relevance ( relevance : CompletionRelevance ) -> String {
362
373
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
+ ) ,
364
379
( relevance. exact_name_match, "name" ) ,
365
380
( relevance. is_local, "local" ) ,
366
381
]
@@ -533,7 +548,9 @@ fn main() { let _: m::Spam = S$0 }
533
548
detail: "(i32)",
534
549
relevance: CompletionRelevance {
535
550
exact_name_match: false,
536
- exact_type_match: true,
551
+ type_match: Some(
552
+ Exact,
553
+ ),
537
554
is_local: false,
538
555
},
539
556
trigger_call_info: true,
@@ -559,7 +576,9 @@ fn main() { let _: m::Spam = S$0 }
559
576
detail: "()",
560
577
relevance: CompletionRelevance {
561
578
exact_name_match: false,
562
- exact_type_match: true,
579
+ type_match: Some(
580
+ Exact,
581
+ ),
563
582
is_local: false,
564
583
},
565
584
},
@@ -1108,7 +1127,7 @@ fn main() {
1108
1127
detail: "S",
1109
1128
relevance: CompletionRelevance {
1110
1129
exact_name_match: true,
1111
- exact_type_match: false ,
1130
+ type_match: None ,
1112
1131
is_local: true,
1113
1132
},
1114
1133
ref_match: "&mut ",
@@ -1353,4 +1372,34 @@ fn foo(f: Foo) { let _: &u32 = f.b$0 }
1353
1372
"# ] ] ,
1354
1373
) ;
1355
1374
}
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
+ }
1356
1405
}
0 commit comments