Skip to content

Commit ac2708a

Browse files
committed
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`.)
2 parents 0916e72 + f2c3ef7 commit ac2708a

3 files changed

Lines changed: 53 additions & 2 deletions

File tree

‎src/tools/rust-analyzer/crates/hir/src/lib.rs‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ use hir_ty::{
6868
diagnostics::BodyValidationDiagnostic,
6969
error_lifetime, known_const_to_ast,
7070
layout::{LayoutasTyLayout,RustcEnumVariantIdx,RustcFieldIdx,TagEncoding},
71-
method_resolution::{self,TyFingerprint},
71+
method_resolution::{self},
7272
mir::{interpret_mir,MutBorrowKind},
7373
primitive::UintTy,
7474
traits::FnTrait,
@@ -99,6 +99,7 @@ pub use crate::{
9999
VisibleTraits,
100100
},
101101
};
102+
pubuse hir_ty::method_resolution::TyFingerprint;
102103

103104
// Be careful with these re-exports.
104105
//

‎src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs‎

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,47 @@ fn main() {
472472
);
473473
}
474474

475+
#[test]
476+
fntrait_completions_handle_associated_types(){
477+
let fixture = r#"
478+
//- /foo.rs crate:foo
479+
pub trait NotInScope {
480+
fn not_in_scope(&self);
481+
}
482+
483+
pub trait Wrapper {
484+
type Inner: NotInScope;
485+
fn inner(&self) -> Self::Inner;
486+
}
487+
488+
//- /main.rs crate:main deps:foo
489+
use foo::Wrapper;
490+
491+
fn completion<T: Wrapper>(whatever: T) {
492+
whatever.inner().$0
493+
}
494+
"#;
495+
496+
check(
497+
fixture,
498+
expect![[r#"
499+
me not_in_scope() (use foo::NotInScope) fn(&self)
500+
"#]],
501+
);
502+
503+
check_edit(
504+
"not_in_scope",
505+
fixture,
506+
r#"
507+
use foo::{NotInScope, Wrapper};
508+
509+
fn completion<T: Wrapper>(whatever: T) {
510+
whatever.inner().not_in_scope()$0
511+
}
512+
"#,
513+
);
514+
}
515+
475516
#[test]
476517
fntrait_method_fuzzy_completion_aware_of_unit_type(){
477518
let fixture = r#"

‎src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs‎

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
use hir::{
44
db::HirDatabase,AsAssocItem,AssocItem,AssocItemContainer,Crate,HasCrate,ImportPathConfig,
55
ItemInNs,ModPath,Module,ModuleDef,Name,PathResolution,PrefixKind,ScopeDef,Semantics,
6-
SemanticsScope,Trait,Type,
6+
SemanticsScope,Trait,TyFingerprint,Type,
77
};
88
use itertools::{EitherOrBoth,Itertools};
99
use rustc_hash::{FxHashMap,FxHashSet};
@@ -545,6 +545,15 @@ fn trait_applicable_items(
545545
letSome(receiver) = trait_candidate.receiver_ty.fingerprint_for_trait_impl()else{
546546
returnfalse;
547547
};
548+
549+
// in order to handle implied bounds through an associated type, keep any
550+
// method receiver that matches `TyFingerprint::Unnameable`. this receiver
551+
// won't be in `TraitImpls` anyways, as `TraitImpls` only contains actual
552+
// implementations.
553+
ifmatches!(receiver,TyFingerprint::Unnameable){
554+
returntrue;
555+
}
556+
548557
let definitions_exist_in_trait_crate = db
549558
.trait_impls_in_crate(defining_crate_for_trait.into())
550559
.has_impls_for_trait_and_self_ty(candidate_trait_id, receiver);

0 commit comments

Comments
 (0)