diff options
author | Josh Mcguigan <[email protected]> | 2021-03-16 15:45:46 +0000 |
---|---|---|
committer | Josh Mcguigan <[email protected]> | 2021-03-26 16:11:50 +0000 |
commit | 957939292ec9038f139bd10e093e9673609eea04 (patch) | |
tree | 5babed3a488b43ea561874be3bda36198ccb421b | |
parent | 20e32fc946010f8c46728d6cb8bab1b96b3f48b9 (diff) |
completion relevance consider if types can be unified
-rw-r--r-- | crates/hir/src/lib.rs | 6 | ||||
-rw-r--r-- | crates/hir_ty/src/infer.rs | 5 | ||||
-rw-r--r-- | crates/hir_ty/src/infer/unify.rs | 4 | ||||
-rw-r--r-- | crates/hir_ty/src/lib.rs | 2 | ||||
-rw-r--r-- | crates/ide_completion/src/render.rs | 33 |
5 files changed, 47 insertions, 3 deletions
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 05a60e158..4ee08ef21 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs | |||
@@ -51,7 +51,7 @@ use hir_def::{ | |||
51 | }; | 51 | }; |
52 | use hir_expand::{diagnostics::DiagnosticSink, name::name, MacroDefKind}; | 52 | use hir_expand::{diagnostics::DiagnosticSink, name::name, MacroDefKind}; |
53 | use hir_ty::{ | 53 | use hir_ty::{ |
54 | autoderef, | 54 | autoderef, could_unify, |
55 | method_resolution::{self, TyFingerprint}, | 55 | method_resolution::{self, TyFingerprint}, |
56 | primitive::UintTy, | 56 | primitive::UintTy, |
57 | to_assoc_type_id, | 57 | to_assoc_type_id, |
@@ -2154,6 +2154,10 @@ impl Type { | |||
2154 | 2154 | ||
2155 | walk_type(db, self, &mut cb); | 2155 | walk_type(db, self, &mut cb); |
2156 | } | 2156 | } |
2157 | |||
2158 | pub fn could_unify_with(&self, other: &Type) -> bool { | ||
2159 | could_unify(&self.ty, &other.ty) | ||
2160 | } | ||
2157 | } | 2161 | } |
2158 | 2162 | ||
2159 | // FIXME: closures | 2163 | // FIXME: closures |
diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs index 8f9cf7480..e4407ff50 100644 --- a/crates/hir_ty/src/infer.rs +++ b/crates/hir_ty/src/infer.rs | |||
@@ -45,6 +45,11 @@ use crate::{ | |||
45 | to_assoc_type_id, to_chalk_trait_id, AliasEq, AliasTy, Interner, TyKind, | 45 | to_assoc_type_id, to_chalk_trait_id, AliasEq, AliasTy, Interner, TyKind, |
46 | }; | 46 | }; |
47 | 47 | ||
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; | ||
48 | pub(crate) use unify::unify; | 53 | pub(crate) use unify::unify; |
49 | 54 | ||
50 | mod unify; | 55 | mod unify; |
diff --git a/crates/hir_ty/src/infer/unify.rs b/crates/hir_ty/src/infer/unify.rs index 75250a369..6e7b0f5a6 100644 --- a/crates/hir_ty/src/infer/unify.rs +++ b/crates/hir_ty/src/infer/unify.rs | |||
@@ -157,6 +157,10 @@ impl<T> Canonicalized<T> { | |||
157 | } | 157 | } |
158 | } | 158 | } |
159 | 159 | ||
160 | pub fn could_unify(t1: &Ty, t2: &Ty) -> bool { | ||
161 | InferenceTable::new().unify(t1, t2) | ||
162 | } | ||
163 | |||
160 | pub(crate) fn unify(tys: &Canonical<(Ty, Ty)>) -> Option<Substitution> { | 164 | pub(crate) fn unify(tys: &Canonical<(Ty, Ty)>) -> Option<Substitution> { |
161 | let mut table = InferenceTable::new(); | 165 | let mut table = InferenceTable::new(); |
162 | let vars = Substitution( | 166 | let vars = Substitution( |
diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs index 69265286f..6f9c698e6 100644 --- a/crates/hir_ty/src/lib.rs +++ b/crates/hir_ty/src/lib.rs | |||
@@ -41,7 +41,7 @@ use crate::{ | |||
41 | }; | 41 | }; |
42 | 42 | ||
43 | pub use autoderef::autoderef; | 43 | pub use autoderef::autoderef; |
44 | pub use infer::{InferenceResult, InferenceVar}; | 44 | pub use infer::{could_unify, InferenceResult, InferenceVar}; |
45 | pub use lower::{ | 45 | pub use lower::{ |
46 | associated_type_shorthand_candidates, callable_item_sig, CallableDefId, ImplTraitLoweringMode, | 46 | associated_type_shorthand_candidates, callable_item_sig, CallableDefId, ImplTraitLoweringMode, |
47 | TyDefId, TyLoweringContext, ValueTyDefId, | 47 | TyDefId, TyLoweringContext, ValueTyDefId, |
diff --git a/crates/ide_completion/src/render.rs b/crates/ide_completion/src/render.rs index 9ce49074f..12453f889 100644 --- a/crates/ide_completion/src/render.rs +++ b/crates/ide_completion/src/render.rs | |||
@@ -314,7 +314,8 @@ fn compute_exact_type_match(ctx: &CompletionContext, completion_ty: &hir::Type) | |||
314 | Some(expected_type) => { | 314 | Some(expected_type) => { |
315 | // We don't ever consider unit type to be an exact type match, since | 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. | 316 | // 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() | ||
318 | } | 319 | } |
319 | None => false, | 320 | None => false, |
320 | } | 321 | } |
@@ -1353,4 +1354,34 @@ fn foo(f: Foo) { let _: &u32 = f.b$0 } | |||
1353 | "#]], | 1354 | "#]], |
1354 | ); | 1355 | ); |
1355 | } | 1356 | } |
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 | } | ||
1356 | } | 1387 | } |