fix: Complete functions and methods from block level impls

This commit is contained in:
Lukas Wirth 2022-02-01 23:29:40 +01:00
parent dbd5a70ea3
commit d7a544e69a
19 changed files with 160 additions and 72 deletions

View File

@ -2787,6 +2787,7 @@ pub fn iterate_method_candidates<T>(
db: &dyn HirDatabase, db: &dyn HirDatabase,
krate: Crate, krate: Crate,
traits_in_scope: &FxHashSet<TraitId>, traits_in_scope: &FxHashSet<TraitId>,
with_local_impls: Option<Module>,
name: Option<&Name>, name: Option<&Name>,
mut callback: impl FnMut(Type, Function) -> Option<T>, mut callback: impl FnMut(Type, Function) -> Option<T>,
) -> Option<T> { ) -> Option<T> {
@ -2797,6 +2798,7 @@ pub fn iterate_method_candidates<T>(
db, db,
krate, krate,
traits_in_scope, traits_in_scope,
with_local_impls,
name, name,
&mut |ty, assoc_item_id| { &mut |ty, assoc_item_id| {
if let AssocItemId::FunctionId(func) = assoc_item_id { if let AssocItemId::FunctionId(func) = assoc_item_id {
@ -2816,6 +2818,7 @@ fn iterate_method_candidates_dyn(
db: &dyn HirDatabase, db: &dyn HirDatabase,
krate: Crate, krate: Crate,
traits_in_scope: &FxHashSet<TraitId>, traits_in_scope: &FxHashSet<TraitId>,
with_local_impls: Option<Module>,
name: Option<&Name>, name: Option<&Name>,
callback: &mut dyn FnMut(&Ty, AssocItemId) -> ControlFlow<()>, callback: &mut dyn FnMut(&Ty, AssocItemId) -> ControlFlow<()>,
) { ) {
@ -2831,7 +2834,7 @@ fn iterate_method_candidates_dyn(
env, env,
krate, krate,
traits_in_scope, traits_in_scope,
None, with_local_impls.and_then(|b| b.id.containing_block()).into(),
name, name,
method_resolution::LookupMode::MethodCall, method_resolution::LookupMode::MethodCall,
&mut |ty, id| callback(&ty.value, id), &mut |ty, id| callback(&ty.value, id),
@ -2843,6 +2846,7 @@ pub fn iterate_path_candidates<T>(
db: &dyn HirDatabase, db: &dyn HirDatabase,
krate: Crate, krate: Crate,
traits_in_scope: &FxHashSet<TraitId>, traits_in_scope: &FxHashSet<TraitId>,
with_local_impls: Option<Module>,
name: Option<&Name>, name: Option<&Name>,
mut callback: impl FnMut(Type, AssocItem) -> Option<T>, mut callback: impl FnMut(Type, AssocItem) -> Option<T>,
) -> Option<T> { ) -> Option<T> {
@ -2852,6 +2856,7 @@ pub fn iterate_path_candidates<T>(
db, db,
krate, krate,
traits_in_scope, traits_in_scope,
with_local_impls,
name, name,
&mut |ty, assoc_item_id| { &mut |ty, assoc_item_id| {
if let Some(res) = callback(self.derived(ty.clone()), assoc_item_id.into()) { if let Some(res) = callback(self.derived(ty.clone()), assoc_item_id.into()) {
@ -2869,6 +2874,7 @@ fn iterate_path_candidates_dyn(
db: &dyn HirDatabase, db: &dyn HirDatabase,
krate: Crate, krate: Crate,
traits_in_scope: &FxHashSet<TraitId>, traits_in_scope: &FxHashSet<TraitId>,
with_local_impls: Option<Module>,
name: Option<&Name>, name: Option<&Name>,
callback: &mut dyn FnMut(&Ty, AssocItemId) -> ControlFlow<()>, callback: &mut dyn FnMut(&Ty, AssocItemId) -> ControlFlow<()>,
) { ) {
@ -2883,7 +2889,7 @@ fn iterate_path_candidates_dyn(
env, env,
krate, krate,
traits_in_scope, traits_in_scope,
None, with_local_impls.and_then(|b| b.id.containing_block()).into(),
name, name,
method_resolution::LookupMode::Path, method_resolution::LookupMode::Path,
&mut |ty, id| callback(&ty.value, id), &mut |ty, id| callback(&ty.value, id),

View File

@ -996,7 +996,7 @@ fn infer_method_call(
self.trait_env.clone(), self.trait_env.clone(),
krate, krate,
&traits_in_scope, &traits_in_scope,
self.resolver.module(), self.resolver.module().into(),
method_name, method_name,
) )
}); });

View File

@ -227,7 +227,7 @@ fn resolve_ty_assoc_item(
self.table.trait_env.clone(), self.table.trait_env.clone(),
krate, krate,
&traits_in_scope, &traits_in_scope,
self.resolver.module(), self.resolver.module().into(),
Some(name), Some(name),
method_resolution::LookupMode::Path, method_resolution::LookupMode::Path,
move |_ty, item| { move |_ty, item| {

View File

@ -437,7 +437,7 @@ pub(crate) fn lookup_method(
env: Arc<TraitEnvironment>, env: Arc<TraitEnvironment>,
krate: CrateId, krate: CrateId,
traits_in_scope: &FxHashSet<TraitId>, traits_in_scope: &FxHashSet<TraitId>,
visible_from_module: Option<ModuleId>, visible_from_module: VisibleFromModule,
name: &Name, name: &Name,
) -> Option<(Canonical<Ty>, FunctionId)> { ) -> Option<(Canonical<Ty>, FunctionId)> {
iterate_method_candidates( iterate_method_candidates(
@ -468,6 +468,34 @@ pub enum LookupMode {
Path, Path,
} }
#[derive(Clone, Copy)]
pub enum VisibleFromModule {
/// Filter for results that are visible from the given module
Filter(ModuleId),
/// Include impls from the given block.
IncludeBlock(BlockId),
/// Do nothing special in regards visibility
None,
}
impl From<Option<ModuleId>> for VisibleFromModule {
fn from(module: Option<ModuleId>) -> Self {
match module {
Some(module) => Self::Filter(module),
None => Self::None,
}
}
}
impl From<Option<BlockId>> for VisibleFromModule {
fn from(block: Option<BlockId>) -> Self {
match block {
Some(block) => Self::IncludeBlock(block),
None => Self::None,
}
}
}
// This would be nicer if it just returned an iterator, but that runs into // This would be nicer if it just returned an iterator, but that runs into
// lifetime problems, because we need to borrow temp `CrateImplDefs`. // lifetime problems, because we need to borrow temp `CrateImplDefs`.
// FIXME add a context type here? // FIXME add a context type here?
@ -477,7 +505,7 @@ pub fn iterate_method_candidates<T>(
env: Arc<TraitEnvironment>, env: Arc<TraitEnvironment>,
krate: CrateId, krate: CrateId,
traits_in_scope: &FxHashSet<TraitId>, traits_in_scope: &FxHashSet<TraitId>,
visible_from_module: Option<ModuleId>, visible_from_module: VisibleFromModule,
name: Option<&Name>, name: Option<&Name>,
mode: LookupMode, mode: LookupMode,
mut callback: impl FnMut(&Canonical<Ty>, AssocItemId) -> Option<T>, mut callback: impl FnMut(&Canonical<Ty>, AssocItemId) -> Option<T>,
@ -510,7 +538,7 @@ pub fn iterate_method_candidates_dyn(
env: Arc<TraitEnvironment>, env: Arc<TraitEnvironment>,
krate: CrateId, krate: CrateId,
traits_in_scope: &FxHashSet<TraitId>, traits_in_scope: &FxHashSet<TraitId>,
visible_from_module: Option<ModuleId>, visible_from_module: VisibleFromModule,
name: Option<&Name>, name: Option<&Name>,
mode: LookupMode, mode: LookupMode,
callback: &mut dyn FnMut(&Canonical<Ty>, AssocItemId) -> ControlFlow<()>, callback: &mut dyn FnMut(&Canonical<Ty>, AssocItemId) -> ControlFlow<()>,
@ -578,7 +606,7 @@ fn iterate_method_candidates_with_autoref(
env: Arc<TraitEnvironment>, env: Arc<TraitEnvironment>,
krate: CrateId, krate: CrateId,
traits_in_scope: &FxHashSet<TraitId>, traits_in_scope: &FxHashSet<TraitId>,
visible_from_module: Option<ModuleId>, visible_from_module: VisibleFromModule,
name: Option<&Name>, name: Option<&Name>,
mut callback: &mut dyn FnMut(&Canonical<Ty>, AssocItemId) -> ControlFlow<()>, mut callback: &mut dyn FnMut(&Canonical<Ty>, AssocItemId) -> ControlFlow<()>,
) -> ControlFlow<()> { ) -> ControlFlow<()> {
@ -644,7 +672,7 @@ fn iterate_method_candidates_by_receiver(
env: Arc<TraitEnvironment>, env: Arc<TraitEnvironment>,
krate: CrateId, krate: CrateId,
traits_in_scope: &FxHashSet<TraitId>, traits_in_scope: &FxHashSet<TraitId>,
visible_from_module: Option<ModuleId>, visible_from_module: VisibleFromModule,
name: Option<&Name>, name: Option<&Name>,
mut callback: &mut dyn FnMut(&Canonical<Ty>, AssocItemId) -> ControlFlow<()>, mut callback: &mut dyn FnMut(&Canonical<Ty>, AssocItemId) -> ControlFlow<()>,
) -> ControlFlow<()> { ) -> ControlFlow<()> {
@ -686,7 +714,7 @@ fn iterate_method_candidates_for_self_ty(
env: Arc<TraitEnvironment>, env: Arc<TraitEnvironment>,
krate: CrateId, krate: CrateId,
traits_in_scope: &FxHashSet<TraitId>, traits_in_scope: &FxHashSet<TraitId>,
visible_from_module: Option<ModuleId>, visible_from_module: VisibleFromModule,
name: Option<&Name>, name: Option<&Name>,
mut callback: &mut dyn FnMut(&Canonical<Ty>, AssocItemId) -> ControlFlow<()>, mut callback: &mut dyn FnMut(&Canonical<Ty>, AssocItemId) -> ControlFlow<()>,
) -> ControlFlow<()> { ) -> ControlFlow<()> {
@ -797,7 +825,7 @@ fn iterate_inherent_methods(
name: Option<&Name>, name: Option<&Name>,
receiver_ty: Option<&Canonical<Ty>>, receiver_ty: Option<&Canonical<Ty>>,
krate: CrateId, krate: CrateId,
visible_from_module: Option<ModuleId>, visible_from_module: VisibleFromModule,
callback: &mut dyn FnMut(&Canonical<Ty>, AssocItemId) -> ControlFlow<()>, callback: &mut dyn FnMut(&Canonical<Ty>, AssocItemId) -> ControlFlow<()>,
) -> ControlFlow<()> { ) -> ControlFlow<()> {
let def_crates = match def_crates(db, &self_ty.value, krate) { let def_crates = match def_crates(db, &self_ty.value, krate) {
@ -805,8 +833,13 @@ fn iterate_inherent_methods(
None => return ControlFlow::Continue(()), None => return ControlFlow::Continue(()),
}; };
if let Some(module_id) = visible_from_module { let (module, block) = match visible_from_module {
if let Some(block_id) = module_id.containing_block() { VisibleFromModule::Filter(module) => (Some(module), module.containing_block()),
VisibleFromModule::IncludeBlock(block) => (None, Some(block)),
VisibleFromModule::None => (None, None),
};
if let Some(block_id) = block {
if let Some(impls) = db.inherent_impls_in_block(block_id) { if let Some(impls) = db.inherent_impls_in_block(block_id) {
impls_for_self_ty( impls_for_self_ty(
&impls, &impls,
@ -815,25 +848,15 @@ fn iterate_inherent_methods(
env.clone(), env.clone(),
name, name,
receiver_ty, receiver_ty,
visible_from_module, module,
callback, callback,
)?; )?;
} }
} }
}
for krate in def_crates { for krate in def_crates {
let impls = db.inherent_impls_in_crate(krate); let impls = db.inherent_impls_in_crate(krate);
impls_for_self_ty( impls_for_self_ty(&impls, self_ty, db, env.clone(), name, receiver_ty, module, callback)?;
&impls,
self_ty,
db,
env.clone(),
name,
receiver_ty,
visible_from_module,
callback,
)?;
} }
return ControlFlow::Continue(()); return ControlFlow::Continue(());

View File

@ -156,6 +156,7 @@ fn is_ref_and_impls_iter_method(
sema.db, sema.db,
krate, krate,
&traits_in_scope, &traits_in_scope,
None,
Some(&wanted_method), Some(&wanted_method),
|_, func| { |_, func| {
if func.ret_type(sema.db).impls_trait(sema.db, iter_trait, &[]) { if func.ret_type(sema.db).impls_trait(sema.db, iter_trait, &[]) {

View File

@ -93,7 +93,9 @@ fn get_impl_method(
let krate = impl_def.module(db).krate(); let krate = impl_def.module(db).krate();
let ty = impl_def.self_ty(db); let ty = impl_def.self_ty(db);
let traits_in_scope = scope.visible_traits(); let traits_in_scope = scope.visible_traits();
ty.iterate_method_candidates(db, krate, &traits_in_scope, Some(fn_name), |_, func| Some(func)) ty.iterate_method_candidates(db, krate, &traits_in_scope, None, Some(fn_name), |_, func| {
Some(func)
})
} }
#[cfg(test)] #[cfg(test)]

View File

@ -253,7 +253,7 @@ fn enum_variants_with_paths(
) { ) {
let variants = enum_.variants(ctx.db); let variants = enum_.variants(ctx.db);
let module = if let Some(module) = ctx.scope.module() { let module = if let Some(module) = ctx.module {
// Compute path from the completion site if available. // Compute path from the completion site if available.
module module
} else { } else {

View File

@ -80,7 +80,7 @@ fn flyimport_derive(acc: &mut Completions, ctx: &CompletionContext) -> Option<()
return None; return None;
}; };
let potential_import_name = ctx.token.to_string(); let potential_import_name = ctx.token.to_string();
let module = ctx.scope.module()?; let module = ctx.module?;
let parent = ctx.token.parent()?; let parent = ctx.token.parent()?;
let user_input_lowercased = potential_import_name.to_lowercase(); let user_input_lowercased = potential_import_name.to_lowercase();
let import_assets = ImportAssets::for_fuzzy_path( let import_assets = ImportAssets::for_fuzzy_path(

View File

@ -84,12 +84,19 @@ fn complete_methods(
traits_in_scope.remove(&drop_trait.into()); traits_in_scope.remove(&drop_trait.into());
} }
receiver.iterate_method_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, func| { receiver.iterate_method_candidates(
ctx.db,
krate,
&traits_in_scope,
ctx.module,
None,
|_ty, func| {
if func.self_param(ctx.db).is_some() && seen_methods.insert(func.name(ctx.db)) { if func.self_param(ctx.db).is_some() && seen_methods.insert(func.name(ctx.db)) {
f(func); f(func);
} }
None::<()> None::<()>
}); },
);
} }
} }
@ -265,6 +272,37 @@ fn foo(a: lib::A) { a.$0 }
); );
} }
#[test]
fn test_local_impls() {
check(
r#"
//- /lib.rs crate:lib
pub struct A {}
mod m {
impl super::A {
pub fn pub_module_method(&self) {}
}
fn f() {
impl super::A {
pub fn pub_foreign_local_method(&self) {}
}
}
}
//- /main.rs crate:main deps:lib
fn foo(a: lib::A) {
impl lib::A {
fn local_method(&self) {}
}
a.$0
}
"#,
expect![[r#"
me local_method() fn(&self)
me pub_module_method() fn(&self)
"#]],
);
}
#[test] #[test]
fn test_doc_hidden_filtering() { fn test_doc_hidden_filtering() {
check( check(

View File

@ -217,7 +217,7 @@ pub(crate) fn position_for_import(
} }
fn import_assets(ctx: &CompletionContext, fuzzy_name: String) -> Option<ImportAssets> { fn import_assets(ctx: &CompletionContext, fuzzy_name: String) -> Option<ImportAssets> {
let current_module = ctx.scope.module()?; let current_module = ctx.module?;
if let Some(dot_receiver) = ctx.dot_receiver() { if let Some(dot_receiver) = ctx.dot_receiver() {
ImportAssets::for_fuzzy_method_call( ImportAssets::for_fuzzy_method_call(
current_module, current_module,

View File

@ -22,7 +22,7 @@ pub(crate) fn complete_mod(acc: &mut Completions, ctx: &CompletionContext) -> Op
let _p = profile::span("completion::complete_mod"); let _p = profile::span("completion::complete_mod");
let current_module = ctx.scope.module()?; let current_module = ctx.module?;
let module_definition_file = let module_definition_file =
current_module.definition_source(ctx.db).file_id.original_file(ctx.db); current_module.definition_source(ctx.db).file_id.original_file(ctx.db);

View File

@ -51,7 +51,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
None => return, None => return,
}; };
let context_module = ctx.scope.module(); let context_module = ctx.module;
match ctx.completion_location { match ctx.completion_location {
Some(ImmediateLocation::ItemList | ImmediateLocation::Trait | ImmediateLocation::Impl) => { Some(ImmediateLocation::ItemList | ImmediateLocation::Trait | ImmediateLocation::Impl) => {
@ -75,7 +75,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
match kind { match kind {
Some(PathKind::Vis { .. }) => { Some(PathKind::Vis { .. }) => {
if let hir::PathResolution::Def(hir::ModuleDef::Module(module)) = resolution { if let hir::PathResolution::Def(hir::ModuleDef::Module(module)) = resolution {
if let Some(current_module) = ctx.scope.module() { if let Some(current_module) = ctx.module {
if let Some(next) = current_module if let Some(next) = current_module
.path_to_root(ctx.db) .path_to_root(ctx.db)
.into_iter() .into_iter()
@ -189,7 +189,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
ty ty
} }
hir::ModuleDef::BuiltinType(builtin) => { hir::ModuleDef::BuiltinType(builtin) => {
let module = match ctx.scope.module() { let module = match ctx.module {
Some(it) => it, Some(it) => it,
None => return, None => return,
}; };
@ -205,10 +205,17 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
let krate = ctx.krate; let krate = ctx.krate;
if let Some(krate) = krate { if let Some(krate) = krate {
let traits_in_scope = ctx.scope.visible_traits(); let traits_in_scope = ctx.scope.visible_traits();
ty.iterate_path_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, item| { ty.iterate_path_candidates(
ctx.db,
krate,
&traits_in_scope,
ctx.module,
None,
|_ty, item| {
add_assoc_item(acc, ctx, item); add_assoc_item(acc, ctx, item);
None::<()> None::<()>
}); },
);
// Iterate assoc types separately // Iterate assoc types separately
ty.iterate_assoc_items(ctx.db, krate, |item| { ty.iterate_assoc_items(ctx.db, krate, |item| {
@ -239,14 +246,21 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
let traits_in_scope = ctx.scope.visible_traits(); let traits_in_scope = ctx.scope.visible_traits();
let mut seen = FxHashSet::default(); let mut seen = FxHashSet::default();
ty.iterate_path_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, item| { ty.iterate_path_candidates(
ctx.db,
krate,
&traits_in_scope,
ctx.module,
None,
|_ty, item| {
// We might iterate candidates of a trait multiple times here, so deduplicate // We might iterate candidates of a trait multiple times here, so deduplicate
// them. // them.
if seen.insert(item) { if seen.insert(item) {
add_assoc_item(acc, ctx, item); add_assoc_item(acc, ctx, item);
} }
None::<()> None::<()>
}); },
);
} }
} }
hir::PathResolution::Macro(mac) => acc.add_macro(ctx, None, mac), hir::PathResolution::Macro(mac) => acc.add_macro(ctx, None, mac),

View File

@ -59,8 +59,7 @@ pub(crate) fn complete_record_literal(
} }
if let hir::Adt::Struct(strukt) = ctx.expected_type.as_ref()?.as_adt()? { if let hir::Adt::Struct(strukt) = ctx.expected_type.as_ref()?.as_adt()? {
let module = let module = if let Some(module) = ctx.module { module } else { strukt.module(ctx.db) };
if let Some(module) = ctx.scope.module() { module } else { strukt.module(ctx.db) };
let path = module.find_use_path(ctx.db, hir::ModuleDef::from(strukt)); let path = module.find_use_path(ctx.db, hir::ModuleDef::from(strukt));

View File

@ -103,6 +103,8 @@ pub(crate) struct CompletionContext<'a> {
pub(super) token: SyntaxToken, pub(super) token: SyntaxToken,
/// The crate of the current file. /// The crate of the current file.
pub(super) krate: Option<hir::Crate>, pub(super) krate: Option<hir::Crate>,
/// The crate of the `scope`.
pub(super) module: Option<hir::Module>,
pub(super) expected_name: Option<NameOrNameRef>, pub(super) expected_name: Option<NameOrNameRef>,
pub(super) expected_type: Option<Type>, pub(super) expected_type: Option<Type>,
@ -338,7 +340,7 @@ fn is_visible_impl(
attrs: &hir::Attrs, attrs: &hir::Attrs,
defining_crate: hir::Crate, defining_crate: hir::Crate,
) -> bool { ) -> bool {
let module = match self.scope.module() { let module = match self.module {
Some(it) => it, Some(it) => it,
None => return false, None => return false,
}; };
@ -394,6 +396,7 @@ pub(super) fn new(
let token = sema.descend_into_macros_single(original_token.clone()); let token = sema.descend_into_macros_single(original_token.clone());
let scope = sema.scope_at_offset(&token.parent()?, offset); let scope = sema.scope_at_offset(&token.parent()?, offset);
let krate = scope.krate(); let krate = scope.krate();
let module = scope.module();
let mut locals = vec![]; let mut locals = vec![];
scope.process_all_names(&mut |name, scope| { scope.process_all_names(&mut |name, scope| {
if let ScopeDef::Local(local) = scope { if let ScopeDef::Local(local) = scope {
@ -410,6 +413,7 @@ pub(super) fn new(
original_token, original_token,
token, token,
krate, krate,
module,
expected_name: None, expected_name: None,
expected_type: None, expected_type: None,
function_def: None, function_def: None,

View File

@ -144,7 +144,7 @@ fn visible_fields(
fields: &[hir::Field], fields: &[hir::Field],
item: impl HasAttrs, item: impl HasAttrs,
) -> Option<(Vec<hir::Field>, bool)> { ) -> Option<(Vec<hir::Field>, bool)> {
let module = ctx.completion.scope.module()?; let module = ctx.completion.module?;
let n_fields = fields.len(); let n_fields = fields.len();
let fields = fields let fields = fields
.iter() .iter()

View File

@ -119,7 +119,7 @@ fn visible_fields(
fields: &[hir::Field], fields: &[hir::Field],
item: impl HasAttrs, item: impl HasAttrs,
) -> Option<(Vec<hir::Field>, bool)> { ) -> Option<(Vec<hir::Field>, bool)> {
let module = ctx.completion.scope.module()?; let module = ctx.completion.module?;
let n_fields = fields.len(); let n_fields = fields.len();
let fields = fields let fields = fields
.iter() .iter()

View File

@ -185,11 +185,8 @@ fn import_edits(
hir::PathResolution::Def(def) => def.into(), hir::PathResolution::Def(def) => def.into(),
_ => return None, _ => return None,
}; };
let path = ctx.scope.module()?.find_use_path_prefixed( let path =
ctx.db, ctx.module?.find_use_path_prefixed(ctx.db, item, ctx.config.insert_use.prefix_kind)?;
item,
ctx.config.insert_use.prefix_kind,
)?;
Some((path.len() > 1).then(|| ImportEdit { Some((path.len() > 1).then(|| ImportEdit {
import: LocatedImport::new(path.clone(), item, item, None), import: LocatedImport::new(path.clone(), item, item, None),
scope: import_scope.clone(), scope: import_scope.clone(),

View File

@ -505,6 +505,7 @@ fn trait_applicable_items(
current_crate, current_crate,
&trait_candidates, &trait_candidates,
None, None,
None,
|_, assoc| { |_, assoc| {
if required_assoc_items.contains(&assoc) { if required_assoc_items.contains(&assoc) {
if let AssocItem::Function(f) = assoc { if let AssocItem::Function(f) = assoc {
@ -531,6 +532,7 @@ fn trait_applicable_items(
current_crate, current_crate,
&trait_candidates, &trait_candidates,
None, None,
None,
|_, function| { |_, function| {
let assoc = function.as_assoc_item(db)?; let assoc = function.as_assoc_item(db)?;
if required_assoc_items.contains(&assoc) { if required_assoc_items.contains(&assoc) {

View File

@ -219,10 +219,12 @@ fn resolve_path(&self, path: &ast::Path) -> Option<hir::PathResolution> {
let resolved_qualifier = self.scope.speculative_resolve(&path.qualifier()?)?; let resolved_qualifier = self.scope.speculative_resolve(&path.qualifier()?)?;
if let hir::PathResolution::Def(hir::ModuleDef::Adt(adt)) = resolved_qualifier { if let hir::PathResolution::Def(hir::ModuleDef::Adt(adt)) = resolved_qualifier {
let name = path.segment()?.name_ref()?; let name = path.segment()?.name_ref()?;
let module = self.scope.module()?;
adt.ty(self.scope.db).iterate_path_candidates( adt.ty(self.scope.db).iterate_path_candidates(
self.scope.db, self.scope.db,
self.scope.module()?.krate(), module.krate(),
&self.scope.visible_traits(), &self.scope.visible_traits(),
Some(module),
None, None,
|_ty, assoc_item| { |_ty, assoc_item| {
let item_name = assoc_item.name(self.scope.db)?; let item_name = assoc_item.name(self.scope.db)?;