Skip to content

Commit 9579392

Browse files
committed
completion relevance consider if types can be unified
1 parent 20e32fc commit 9579392

File tree

5 files changed

+47
-3
lines changed

5 files changed

+47
-3
lines changed

crates/hir/src/lib.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ use hir_def::{
5151
};
5252
use hir_expand::{diagnostics::DiagnosticSink, name::name, MacroDefKind};
5353
use hir_ty::{
54-
autoderef,
54+
autoderef, could_unify,
5555
method_resolution::{self, TyFingerprint},
5656
primitive::UintTy,
5757
to_assoc_type_id,
@@ -2154,6 +2154,10 @@ impl Type {
21542154

21552155
walk_type(db, self, &mut cb);
21562156
}
2157+
2158+
pub fn could_unify_with(&self, other: &Type) -> bool {
2159+
could_unify(&self.ty, &other.ty)
2160+
}
21572161
}
21582162

21592163
// FIXME: closures

crates/hir_ty/src/infer.rs

+5
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,11 @@ use crate::{
4545
to_assoc_type_id, to_chalk_trait_id, AliasEq, AliasTy, Interner, TyKind,
4646
};
4747

48+
// This lint has a false positive here. See the link below for details.
49+
//
50+
// https://github.com/rust-lang/rust/issues/57411
51+
#[allow(unreachable_pub)]
52+
pub use unify::could_unify;
4853
pub(crate) use unify::unify;
4954

5055
mod unify;

crates/hir_ty/src/infer/unify.rs

+4
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,10 @@ impl<T> Canonicalized<T> {
157157
}
158158
}
159159

160+
pub fn could_unify(t1: &Ty, t2: &Ty) -> bool {
161+
InferenceTable::new().unify(t1, t2)
162+
}
163+
160164
pub(crate) fn unify(tys: &Canonical<(Ty, Ty)>) -> Option<Substitution> {
161165
let mut table = InferenceTable::new();
162166
let vars = Substitution(

crates/hir_ty/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ use crate::{
4141
};
4242

4343
pub use autoderef::autoderef;
44-
pub use infer::{InferenceResult, InferenceVar};
44+
pub use infer::{could_unify, InferenceResult, InferenceVar};
4545
pub use lower::{
4646
associated_type_shorthand_candidates, callable_item_sig, CallableDefId, ImplTraitLoweringMode,
4747
TyDefId, TyLoweringContext, ValueTyDefId,

crates/ide_completion/src/render.rs

+32-1
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,8 @@ fn compute_exact_type_match(ctx: &CompletionContext, completion_ty: &hir::Type)
314314
Some(expected_type) => {
315315
// We don't ever consider unit type to be an exact type match, since
316316
// nearly always this is not meaningful to the user.
317-
completion_ty == expected_type && !expected_type.is_unit()
317+
(completion_ty == expected_type || expected_type.could_unify_with(completion_ty))
318+
&& !expected_type.is_unit()
318319
}
319320
None => false,
320321
}
@@ -1353,4 +1354,34 @@ fn foo(f: Foo) { let _: &u32 = f.b$0 }
13531354
"#]],
13541355
);
13551356
}
1357+
1358+
#[test]
1359+
fn generic_enum() {
1360+
check_relevance(
1361+
r#"
1362+
enum Foo<T> { A(T), B }
1363+
// bar() should not be an exact type match
1364+
// because the generic parameters are different
1365+
fn bar() -> Foo<u8> { Foo::B }
1366+
// FIXME baz() should be an exact type match
1367+
// because the types could unify, but it currently
1368+
// is not. This is due to the T here being
1369+
// TyKind::Placeholder rather than TyKind::Missing.
1370+
fn baz<T>() -> Foo<T> { Foo::B }
1371+
fn foo() {
1372+
let foo: Foo<u32> = Foo::B;
1373+
let _: Foo<u32> = f$0;
1374+
}
1375+
"#,
1376+
expect![[r#"
1377+
ev Foo::A(…) [type]
1378+
ev Foo::B [type]
1379+
lc foo [type+local]
1380+
en Foo []
1381+
fn baz() []
1382+
fn bar() []
1383+
fn foo() []
1384+
"#]],
1385+
);
1386+
}
13561387
}

0 commit comments

Comments
 (0)