mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-28 05:53:45 +00:00
Auto merge of #17270 - davidbarsky:david/fix-completions-from-associated-types, r=Veykril
fix: ensure implied bounds from associated types are considered in autocomplete closes: #16989 rust-analyzer needs to consider implied bounds from associated types in order to get all methods suggestions people expect. A pretty easy way to do that is to keep the `candidate_trait_id`'s receiver if it matches `TyFingerprint::Unnameable`. When benchmarking this change, I didn't notice a meaningful difference in autocomplete latency. (`TyFingerprint::Unnameable` corresponds to `TyKind::AssociatedType`, `TyKind::OpaqueType`, `TyKind::FnDef`, `TyKind::Closure`, `TyKind::Coroutine`, and `TyKind::CoroutineWitness`.)
This commit is contained in:
commit
653b69eb42
3 changed files with 53 additions and 2 deletions
|
@ -68,7 +68,7 @@ use hir_ty::{
|
|||
diagnostics::BodyValidationDiagnostic,
|
||||
error_lifetime, known_const_to_ast,
|
||||
layout::{Layout as TyLayout, RustcEnumVariantIdx, RustcFieldIdx, TagEncoding},
|
||||
method_resolution::{self, TyFingerprint},
|
||||
method_resolution::{self},
|
||||
mir::{interpret_mir, MutBorrowKind},
|
||||
primitive::UintTy,
|
||||
traits::FnTrait,
|
||||
|
@ -99,6 +99,7 @@ pub use crate::{
|
|||
VisibleTraits,
|
||||
},
|
||||
};
|
||||
pub use hir_ty::method_resolution::TyFingerprint;
|
||||
|
||||
// Be careful with these re-exports.
|
||||
//
|
||||
|
|
|
@ -472,6 +472,47 @@ fn main() {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn trait_completions_handle_associated_types() {
|
||||
let fixture = r#"
|
||||
//- /foo.rs crate:foo
|
||||
pub trait NotInScope {
|
||||
fn not_in_scope(&self);
|
||||
}
|
||||
|
||||
pub trait Wrapper {
|
||||
type Inner: NotInScope;
|
||||
fn inner(&self) -> Self::Inner;
|
||||
}
|
||||
|
||||
//- /main.rs crate:main deps:foo
|
||||
use foo::Wrapper;
|
||||
|
||||
fn completion<T: Wrapper>(whatever: T) {
|
||||
whatever.inner().$0
|
||||
}
|
||||
"#;
|
||||
|
||||
check(
|
||||
fixture,
|
||||
expect![[r#"
|
||||
me not_in_scope() (use foo::NotInScope) fn(&self)
|
||||
"#]],
|
||||
);
|
||||
|
||||
check_edit(
|
||||
"not_in_scope",
|
||||
fixture,
|
||||
r#"
|
||||
use foo::{NotInScope, Wrapper};
|
||||
|
||||
fn completion<T: Wrapper>(whatever: T) {
|
||||
whatever.inner().not_in_scope()$0
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn trait_method_fuzzy_completion_aware_of_unit_type() {
|
||||
let fixture = r#"
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
use hir::{
|
||||
db::HirDatabase, AsAssocItem, AssocItem, AssocItemContainer, Crate, HasCrate, ImportPathConfig,
|
||||
ItemInNs, ModPath, Module, ModuleDef, Name, PathResolution, PrefixKind, ScopeDef, Semantics,
|
||||
SemanticsScope, Trait, Type,
|
||||
SemanticsScope, Trait, TyFingerprint, Type,
|
||||
};
|
||||
use itertools::{EitherOrBoth, Itertools};
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
|
@ -545,6 +545,15 @@ fn trait_applicable_items(
|
|||
let Some(receiver) = trait_candidate.receiver_ty.fingerprint_for_trait_impl() else {
|
||||
return false;
|
||||
};
|
||||
|
||||
// in order to handle implied bounds through an associated type, keep any
|
||||
// method receiver that matches `TyFingerprint::Unnameable`. this receiver
|
||||
// won't be in `TraitImpls` anyways, as `TraitImpls` only contains actual
|
||||
// implementations.
|
||||
if matches!(receiver, TyFingerprint::Unnameable) {
|
||||
return true;
|
||||
}
|
||||
|
||||
let definitions_exist_in_trait_crate = db
|
||||
.trait_impls_in_crate(defining_crate_for_trait.into())
|
||||
.has_impls_for_trait_and_self_ty(candidate_trait_id, receiver);
|
||||
|
|
Loading…
Reference in a new issue