From f2c3ef77b1976eee67ae88ac12cbd1eb4e2da398 Mon Sep 17 00:00:00 2001 From: David Barsky Date: Wed, 22 May 2024 16:16:19 -0400 Subject: [PATCH] fix: ensure implied bounds from associated types are considered in autocomplete --- src/tools/rust-analyzer/crates/hir/src/lib.rs | 3 +- .../ide-completion/src/tests/flyimport.rs | 41 +++++++++++++++++++ .../ide-db/src/imports/import_assets.rs | 11 ++++- 3 files changed, 53 insertions(+), 2 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index 0b68762e4f4c0..777be711a5e6e 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -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. // diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs index d2227d23cd77f..abffa73c3b4c6 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs @@ -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(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(whatever: T) { + whatever.inner().not_in_scope()$0 +} +"#, + ); +} + #[test] fn trait_method_fuzzy_completion_aware_of_unit_type() { let fixture = r#" diff --git a/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs b/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs index 6e708182d09f6..4caecb3f2fe10 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs @@ -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);