From 957939292ec9038f139bd10e093e9673609eea04 Mon Sep 17 00:00:00 2001 From: Josh Mcguigan Date: Tue, 16 Mar 2021 08:45:46 -0700 Subject: completion relevance consider if types can be unified --- crates/hir/src/lib.rs | 6 +++++- crates/hir_ty/src/infer.rs | 5 +++++ crates/hir_ty/src/infer/unify.rs | 4 ++++ crates/hir_ty/src/lib.rs | 2 +- crates/ide_completion/src/render.rs | 33 ++++++++++++++++++++++++++++++++- 5 files changed, 47 insertions(+), 3 deletions(-) (limited to 'crates') 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::{ }; use hir_expand::{diagnostics::DiagnosticSink, name::name, MacroDefKind}; use hir_ty::{ - autoderef, + autoderef, could_unify, method_resolution::{self, TyFingerprint}, primitive::UintTy, to_assoc_type_id, @@ -2154,6 +2154,10 @@ impl Type { walk_type(db, self, &mut cb); } + + pub fn could_unify_with(&self, other: &Type) -> bool { + could_unify(&self.ty, &other.ty) + } } // 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::{ to_assoc_type_id, to_chalk_trait_id, AliasEq, AliasTy, Interner, TyKind, }; +// This lint has a false positive here. See the link below for details. +// +// https://github.com/rust-lang/rust/issues/57411 +#[allow(unreachable_pub)] +pub use unify::could_unify; pub(crate) use unify::unify; 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 Canonicalized { } } +pub fn could_unify(t1: &Ty, t2: &Ty) -> bool { + InferenceTable::new().unify(t1, t2) +} + pub(crate) fn unify(tys: &Canonical<(Ty, Ty)>) -> Option { let mut table = InferenceTable::new(); 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::{ }; pub use autoderef::autoderef; -pub use infer::{InferenceResult, InferenceVar}; +pub use infer::{could_unify, InferenceResult, InferenceVar}; pub use lower::{ associated_type_shorthand_candidates, callable_item_sig, CallableDefId, ImplTraitLoweringMode, 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) Some(expected_type) => { // We don't ever consider unit type to be an exact type match, since // nearly always this is not meaningful to the user. - completion_ty == expected_type && !expected_type.is_unit() + (completion_ty == expected_type || expected_type.could_unify_with(completion_ty)) + && !expected_type.is_unit() } None => false, } @@ -1353,4 +1354,34 @@ fn foo(f: Foo) { let _: &u32 = f.b$0 } "#]], ); } + + #[test] + fn generic_enum() { + check_relevance( + r#" +enum Foo { A(T), B } +// bar() should not be an exact type match +// because the generic parameters are different +fn bar() -> Foo { Foo::B } +// FIXME baz() should be an exact type match +// because the types could unify, but it currently +// is not. This is due to the T here being +// TyKind::Placeholder rather than TyKind::Missing. +fn baz() -> Foo { Foo::B } +fn foo() { + let foo: Foo = Foo::B; + let _: Foo = f$0; +} +"#, + expect![[r#" + ev Foo::A(…) [type] + ev Foo::B [type] + lc foo [type+local] + en Foo [] + fn baz() [] + fn bar() [] + fn foo() [] + "#]], + ); + } } -- cgit v1.2.3