aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh Mcguigan <[email protected]>2021-03-16 15:45:46 +0000
committerJosh Mcguigan <[email protected]>2021-03-26 16:11:50 +0000
commit957939292ec9038f139bd10e093e9673609eea04 (patch)
tree5babed3a488b43ea561874be3bda36198ccb421b
parent20e32fc946010f8c46728d6cb8bab1b96b3f48b9 (diff)
completion relevance consider if types can be unified
-rw-r--r--crates/hir/src/lib.rs6
-rw-r--r--crates/hir_ty/src/infer.rs5
-rw-r--r--crates/hir_ty/src/infer/unify.rs4
-rw-r--r--crates/hir_ty/src/lib.rs2
-rw-r--r--crates/ide_completion/src/render.rs33
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};
52use hir_expand::{diagnostics::DiagnosticSink, name::name, MacroDefKind}; 52use hir_expand::{diagnostics::DiagnosticSink, name::name, MacroDefKind};
53use hir_ty::{ 53use 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)]
52pub use unify::could_unify;
48pub(crate) use unify::unify; 53pub(crate) use unify::unify;
49 54
50mod unify; 55mod 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
160pub fn could_unify(t1: &Ty, t2: &Ty) -> bool {
161 InferenceTable::new().unify(t1, t2)
162}
163
160pub(crate) fn unify(tys: &Canonical<(Ty, Ty)>) -> Option<Substitution> { 164pub(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
43pub use autoderef::autoderef; 43pub use autoderef::autoderef;
44pub use infer::{InferenceResult, InferenceVar}; 44pub use infer::{could_unify, InferenceResult, InferenceVar};
45pub use lower::{ 45pub 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#"
1362enum Foo<T> { A(T), B }
1363// bar() should not be an exact type match
1364// because the generic parameters are different
1365fn 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.
1370fn baz<T>() -> Foo<T> { Foo::B }
1371fn 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}