]> git.lizzy.rs Git - rust.git/commitdiff
Merge #11393
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>
Tue, 1 Feb 2022 22:48:34 +0000 (22:48 +0000)
committerGitHub <noreply@github.com>
Tue, 1 Feb 2022 22:48:34 +0000 (22:48 +0000)
11393: fix: Complete functions and methods from block level impls r=Veykril a=Veykril

Fixes https://github.com/rust-analyzer/rust-analyzer/issues/11372

Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
19 files changed:
crates/hir/src/lib.rs
crates/hir_ty/src/infer/expr.rs
crates/hir_ty/src/infer/path.rs
crates/hir_ty/src/method_resolution.rs
crates/ide_assists/src/handlers/convert_iter_for_each_to_for.rs
crates/ide_assists/src/handlers/generate_is_empty_from_len.rs
crates/ide_completion/src/completions.rs
crates/ide_completion/src/completions/attribute/derive.rs
crates/ide_completion/src/completions/dot.rs
crates/ide_completion/src/completions/flyimport.rs
crates/ide_completion/src/completions/mod_.rs
crates/ide_completion/src/completions/qualified_path.rs
crates/ide_completion/src/completions/record.rs
crates/ide_completion/src/context.rs
crates/ide_completion/src/render/pattern.rs
crates/ide_completion/src/render/struct_literal.rs
crates/ide_completion/src/snippet.rs
crates/ide_db/src/helpers/import_assets.rs
crates/ide_ssr/src/resolving.rs

index fe518c8642924c3df8c33d422f88cafa06d2572d..e091af4bf8cdaa3b1f4ff9bd26334904ae0d0985 100644 (file)
@@ -2787,6 +2787,7 @@ pub fn iterate_method_candidates<T>(
         db: &dyn HirDatabase,
         krate: Crate,
         traits_in_scope: &FxHashSet<TraitId>,
+        with_local_impls: Option<Module>,
         name: Option<&Name>,
         mut callback: impl FnMut(Type, Function) -> Option<T>,
     ) -> Option<T> {
@@ -2797,6 +2798,7 @@ pub fn iterate_method_candidates<T>(
             db,
             krate,
             traits_in_scope,
+            with_local_impls,
             name,
             &mut |ty, assoc_item_id| {
                 if let AssocItemId::FunctionId(func) = assoc_item_id {
@@ -2816,6 +2818,7 @@ fn iterate_method_candidates_dyn(
         db: &dyn HirDatabase,
         krate: Crate,
         traits_in_scope: &FxHashSet<TraitId>,
+        with_local_impls: Option<Module>,
         name: Option<&Name>,
         callback: &mut dyn FnMut(&Ty, AssocItemId) -> ControlFlow<()>,
     ) {
@@ -2831,7 +2834,7 @@ fn iterate_method_candidates_dyn(
             env,
             krate,
             traits_in_scope,
-            None,
+            with_local_impls.and_then(|b| b.id.containing_block()).into(),
             name,
             method_resolution::LookupMode::MethodCall,
             &mut |ty, id| callback(&ty.value, id),
@@ -2843,6 +2846,7 @@ pub fn iterate_path_candidates<T>(
         db: &dyn HirDatabase,
         krate: Crate,
         traits_in_scope: &FxHashSet<TraitId>,
+        with_local_impls: Option<Module>,
         name: Option<&Name>,
         mut callback: impl FnMut(Type, AssocItem) -> Option<T>,
     ) -> Option<T> {
@@ -2852,6 +2856,7 @@ pub fn iterate_path_candidates<T>(
             db,
             krate,
             traits_in_scope,
+            with_local_impls,
             name,
             &mut |ty, assoc_item_id| {
                 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,
         krate: Crate,
         traits_in_scope: &FxHashSet<TraitId>,
+        with_local_impls: Option<Module>,
         name: Option<&Name>,
         callback: &mut dyn FnMut(&Ty, AssocItemId) -> ControlFlow<()>,
     ) {
@@ -2883,7 +2889,7 @@ fn iterate_path_candidates_dyn(
             env,
             krate,
             traits_in_scope,
-            None,
+            with_local_impls.and_then(|b| b.id.containing_block()).into(),
             name,
             method_resolution::LookupMode::Path,
             &mut |ty, id| callback(&ty.value, id),
index 54b1680214e9faeb8fc2ed989c29139d533492e2..4f1bdee705ddb5a5fcd7ca9a0983c05c08976cda 100644 (file)
@@ -996,7 +996,7 @@ fn infer_method_call(
                 self.trait_env.clone(),
                 krate,
                 &traits_in_scope,
-                self.resolver.module(),
+                self.resolver.module().into(),
                 method_name,
             )
         });
index c33a697f05af40b9606c533604d0ae4c2f409152..b63ef2ffdc8a7c80fcb8b455bd8a74e51a4a9864 100644 (file)
@@ -227,7 +227,7 @@ fn resolve_ty_assoc_item(
             self.table.trait_env.clone(),
             krate,
             &traits_in_scope,
-            self.resolver.module(),
+            self.resolver.module().into(),
             Some(name),
             method_resolution::LookupMode::Path,
             move |_ty, item| {
index 1a451ae79f513cf77e6f2679bfd3fdf0ada6e47d..c91b6f2e82d10d336df3182840932723e26d2be7 100644 (file)
@@ -437,7 +437,7 @@ pub(crate) fn lookup_method(
     env: Arc<TraitEnvironment>,
     krate: CrateId,
     traits_in_scope: &FxHashSet<TraitId>,
-    visible_from_module: Option<ModuleId>,
+    visible_from_module: VisibleFromModule,
     name: &Name,
 ) -> Option<(Canonical<Ty>, FunctionId)> {
     iterate_method_candidates(
@@ -468,6 +468,34 @@ pub enum LookupMode {
     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
 // lifetime problems, because we need to borrow temp `CrateImplDefs`.
 // FIXME add a context type here?
@@ -477,7 +505,7 @@ pub fn iterate_method_candidates<T>(
     env: Arc<TraitEnvironment>,
     krate: CrateId,
     traits_in_scope: &FxHashSet<TraitId>,
-    visible_from_module: Option<ModuleId>,
+    visible_from_module: VisibleFromModule,
     name: Option<&Name>,
     mode: LookupMode,
     mut callback: impl FnMut(&Canonical<Ty>, AssocItemId) -> Option<T>,
@@ -510,7 +538,7 @@ pub fn iterate_method_candidates_dyn(
     env: Arc<TraitEnvironment>,
     krate: CrateId,
     traits_in_scope: &FxHashSet<TraitId>,
-    visible_from_module: Option<ModuleId>,
+    visible_from_module: VisibleFromModule,
     name: Option<&Name>,
     mode: LookupMode,
     callback: &mut dyn FnMut(&Canonical<Ty>, AssocItemId) -> ControlFlow<()>,
@@ -578,7 +606,7 @@ fn iterate_method_candidates_with_autoref(
     env: Arc<TraitEnvironment>,
     krate: CrateId,
     traits_in_scope: &FxHashSet<TraitId>,
-    visible_from_module: Option<ModuleId>,
+    visible_from_module: VisibleFromModule,
     name: Option<&Name>,
     mut callback: &mut dyn FnMut(&Canonical<Ty>, AssocItemId) -> ControlFlow<()>,
 ) -> ControlFlow<()> {
@@ -644,7 +672,7 @@ fn iterate_method_candidates_by_receiver(
     env: Arc<TraitEnvironment>,
     krate: CrateId,
     traits_in_scope: &FxHashSet<TraitId>,
-    visible_from_module: Option<ModuleId>,
+    visible_from_module: VisibleFromModule,
     name: Option<&Name>,
     mut callback: &mut dyn FnMut(&Canonical<Ty>, AssocItemId) -> ControlFlow<()>,
 ) -> ControlFlow<()> {
@@ -686,7 +714,7 @@ fn iterate_method_candidates_for_self_ty(
     env: Arc<TraitEnvironment>,
     krate: CrateId,
     traits_in_scope: &FxHashSet<TraitId>,
-    visible_from_module: Option<ModuleId>,
+    visible_from_module: VisibleFromModule,
     name: Option<&Name>,
     mut callback: &mut dyn FnMut(&Canonical<Ty>, AssocItemId) -> ControlFlow<()>,
 ) -> ControlFlow<()> {
@@ -797,7 +825,7 @@ fn iterate_inherent_methods(
     name: Option<&Name>,
     receiver_ty: Option<&Canonical<Ty>>,
     krate: CrateId,
-    visible_from_module: Option<ModuleId>,
+    visible_from_module: VisibleFromModule,
     callback: &mut dyn FnMut(&Canonical<Ty>, AssocItemId) -> ControlFlow<()>,
 ) -> ControlFlow<()> {
     let def_crates = match def_crates(db, &self_ty.value, krate) {
@@ -805,35 +833,30 @@ fn iterate_inherent_methods(
         None => return ControlFlow::Continue(()),
     };
 
-    if let Some(module_id) = visible_from_module {
-        if let Some(block_id) = module_id.containing_block() {
-            if let Some(impls) = db.inherent_impls_in_block(block_id) {
-                impls_for_self_ty(
-                    &impls,
-                    self_ty,
-                    db,
-                    env.clone(),
-                    name,
-                    receiver_ty,
-                    visible_from_module,
-                    callback,
-                )?;
-            }
+    let (module, block) = match visible_from_module {
+        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) {
+            impls_for_self_ty(
+                &impls,
+                self_ty,
+                db,
+                env.clone(),
+                name,
+                receiver_ty,
+                module,
+                callback,
+            )?;
         }
     }
 
     for krate in def_crates {
         let impls = db.inherent_impls_in_crate(krate);
-        impls_for_self_ty(
-            &impls,
-            self_ty,
-            db,
-            env.clone(),
-            name,
-            receiver_ty,
-            visible_from_module,
-            callback,
-        )?;
+        impls_for_self_ty(&impls, self_ty, db, env.clone(), name, receiver_ty, module, callback)?;
     }
     return ControlFlow::Continue(());
 
index 7fbbdb4f5eb1f15d591af6c5e5a70d6fd9380f4d..0d2daa8dc30c567ab17b9af90dec6a735a546bb5 100644 (file)
@@ -156,6 +156,7 @@ fn is_ref_and_impls_iter_method(
             sema.db,
             krate,
             &traits_in_scope,
+            None,
             Some(&wanted_method),
             |_, func| {
                 if func.ret_type(sema.db).impls_trait(sema.db, iter_trait, &[]) {
index 15025cf0d0e4600320fcd16ecaab097437317a6d..cb3fbed21995a74682d8c3a55fa8a096e7564a8a 100644 (file)
@@ -93,7 +93,9 @@ fn get_impl_method(
     let krate = impl_def.module(db).krate();
     let ty = impl_def.self_ty(db);
     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)]
index e399213731db84a87b25afb327056a35a6b69567..a072d223e0daf610cbcfe33f27342d5bfaeeaaa9 100644 (file)
@@ -253,7 +253,7 @@ fn enum_variants_with_paths(
 ) {
     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.
         module
     } else {
index 5b22408a2cb13831ee9687c66f85b1c38fb43ea3..29fe096e135608fd9c6817a000c5cb4aee92d7f3 100644 (file)
@@ -80,7 +80,7 @@ fn flyimport_derive(acc: &mut Completions, ctx: &CompletionContext) -> Option<()
         return None;
     };
     let potential_import_name = ctx.token.to_string();
-    let module = ctx.scope.module()?;
+    let module = ctx.module?;
     let parent = ctx.token.parent()?;
     let user_input_lowercased = potential_import_name.to_lowercase();
     let import_assets = ImportAssets::for_fuzzy_path(
index 539b423cb30f94e13a5c39567b1eb8c507874539..b8bab941706f8e4480da65b3316359c90ed3df4e 100644 (file)
@@ -84,12 +84,19 @@ fn complete_methods(
             traits_in_scope.remove(&drop_trait.into());
         }
 
-        receiver.iterate_method_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, func| {
-            if func.self_param(ctx.db).is_some() && seen_methods.insert(func.name(ctx.db)) {
-                f(func);
-            }
-            None::<()>
-        });
+        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)) {
+                    f(func);
+                }
+                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]
     fn test_doc_hidden_filtering() {
         check(
index 8994c25475b131cc4da5a994a3b1d31d3c9be7e6..782a119c9e7e7338a9451bbde9a780083263e441 100644 (file)
@@ -217,7 +217,7 @@ pub(crate) fn position_for_import(
 }
 
 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() {
         ImportAssets::for_fuzzy_method_call(
             current_module,
index beef834581b9a0cf5bdfb518a38251005fd7b1f9..64e992c2e6be6c651b104da4d5377029b9a43b11 100644 (file)
@@ -22,7 +22,7 @@ pub(crate) fn complete_mod(acc: &mut Completions, ctx: &CompletionContext) -> Op
 
     let _p = profile::span("completion::complete_mod");
 
-    let current_module = ctx.scope.module()?;
+    let current_module = ctx.module?;
 
     let module_definition_file =
         current_module.definition_source(ctx.db).file_id.original_file(ctx.db);
index 499791abc9a2dcb45657eae2aad8a9131eb6edf5..85df19f1dd49253830598131dbf17130ba27d3a5 100644 (file)
@@ -51,7 +51,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
         None => return,
     };
 
-    let context_module = ctx.scope.module();
+    let context_module = ctx.module;
 
     match ctx.completion_location {
         Some(ImmediateLocation::ItemList | ImmediateLocation::Trait | ImmediateLocation::Impl) => {
@@ -75,7 +75,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
     match kind {
         Some(PathKind::Vis { .. }) => {
             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
                         .path_to_root(ctx.db)
                         .into_iter()
@@ -189,7 +189,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
                     ty
                 }
                 hir::ModuleDef::BuiltinType(builtin) => {
-                    let module = match ctx.scope.module() {
+                    let module = match ctx.module {
                         Some(it) => it,
                         None => return,
                     };
@@ -205,10 +205,17 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
             let krate = ctx.krate;
             if let Some(krate) = krate {
                 let traits_in_scope = ctx.scope.visible_traits();
-                ty.iterate_path_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, item| {
-                    add_assoc_item(acc, ctx, item);
-                    None::<()>
-                });
+                ty.iterate_path_candidates(
+                    ctx.db,
+                    krate,
+                    &traits_in_scope,
+                    ctx.module,
+                    None,
+                    |_ty, item| {
+                        add_assoc_item(acc, ctx, item);
+                        None::<()>
+                    },
+                );
 
                 // Iterate assoc types separately
                 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 mut seen = FxHashSet::default();
-                ty.iterate_path_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, item| {
-                    // We might iterate candidates of a trait multiple times here, so deduplicate
-                    // them.
-                    if seen.insert(item) {
-                        add_assoc_item(acc, ctx, item);
-                    }
-                    None::<()>
-                });
+                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
+                        // them.
+                        if seen.insert(item) {
+                            add_assoc_item(acc, ctx, item);
+                        }
+                        None::<()>
+                    },
+                );
             }
         }
         hir::PathResolution::Macro(mac) => acc.add_macro(ctx, None, mac),
index b066a46065de0817178a5692d00a7a4d06d1af89..ec1ee292be41ab5381dbc70923d01830f3f9855f 100644 (file)
@@ -59,8 +59,7 @@ pub(crate) fn complete_record_literal(
     }
 
     if let hir::Adt::Struct(strukt) = ctx.expected_type.as_ref()?.as_adt()? {
-        let module =
-            if let Some(module) = ctx.scope.module() { module } else { strukt.module(ctx.db) };
+        let module = if let Some(module) = ctx.module { module } else { strukt.module(ctx.db) };
 
         let path = module.find_use_path(ctx.db, hir::ModuleDef::from(strukt));
 
index 59c16c08d6cec7ede97c183136e1ddb7fd00f750..a31a552dadb36277c4f69271fba120ae00dba3f0 100644 (file)
@@ -103,6 +103,8 @@ pub(crate) struct CompletionContext<'a> {
     pub(super) token: SyntaxToken,
     /// The crate of the current file.
     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_type: Option<Type>,
 
@@ -338,7 +340,7 @@ fn is_visible_impl(
         attrs: &hir::Attrs,
         defining_crate: hir::Crate,
     ) -> bool {
-        let module = match self.scope.module() {
+        let module = match self.module {
             Some(it) => it,
             None => return false,
         };
@@ -394,6 +396,7 @@ pub(super) fn new(
         let token = sema.descend_into_macros_single(original_token.clone());
         let scope = sema.scope_at_offset(&token.parent()?, offset);
         let krate = scope.krate();
+        let module = scope.module();
         let mut locals = vec![];
         scope.process_all_names(&mut |name, scope| {
             if let ScopeDef::Local(local) = scope {
@@ -410,6 +413,7 @@ pub(super) fn new(
             original_token,
             token,
             krate,
+            module,
             expected_name: None,
             expected_type: None,
             function_def: None,
index e486d9f2b91e497570ae14b808866df63156d012..641a15aa65db8ce234f32d121585d15b4a365ccb 100644 (file)
@@ -144,7 +144,7 @@ fn visible_fields(
     fields: &[hir::Field],
     item: impl HasAttrs,
 ) -> Option<(Vec<hir::Field>, bool)> {
-    let module = ctx.completion.scope.module()?;
+    let module = ctx.completion.module?;
     let n_fields = fields.len();
     let fields = fields
         .iter()
index bfbcc263b1deb5d53627504d4bf2fd608d0460c9..6be7b9d43bc87dc1872e13551fb29520a5f2a251 100644 (file)
@@ -119,7 +119,7 @@ fn visible_fields(
     fields: &[hir::Field],
     item: impl HasAttrs,
 ) -> Option<(Vec<hir::Field>, bool)> {
-    let module = ctx.completion.scope.module()?;
+    let module = ctx.completion.module?;
     let n_fields = fields.len();
     let fields = fields
         .iter()
index 98cd3f8f3370b586413f80d93ad2c591d63c29ad..3a4f713333baae7cc079eefdb3f77102f52e58f5 100644 (file)
@@ -185,11 +185,8 @@ fn import_edits(
             hir::PathResolution::Def(def) => def.into(),
             _ => return None,
         };
-        let path = ctx.scope.module()?.find_use_path_prefixed(
-            ctx.db,
-            item,
-            ctx.config.insert_use.prefix_kind,
-        )?;
+        let path =
+            ctx.module?.find_use_path_prefixed(ctx.db, item, ctx.config.insert_use.prefix_kind)?;
         Some((path.len() > 1).then(|| ImportEdit {
             import: LocatedImport::new(path.clone(), item, item, None),
             scope: import_scope.clone(),
index 2356750bceb86c16f1c4a3bcd53cf595ba56962d..c037c3e0f87638cf47c25016e703dc58fecb473e 100644 (file)
@@ -505,6 +505,7 @@ fn trait_applicable_items(
             current_crate,
             &trait_candidates,
             None,
+            None,
             |_, assoc| {
                 if required_assoc_items.contains(&assoc) {
                     if let AssocItem::Function(f) = assoc {
@@ -531,6 +532,7 @@ fn trait_applicable_items(
             current_crate,
             &trait_candidates,
             None,
+            None,
             |_, function| {
                 let assoc = function.as_assoc_item(db)?;
                 if required_assoc_items.contains(&assoc) {
index 7902295d2907a6256088c7f907365f64395a4a70..844b19779a8776ee2ac2ba252bba0a142f66c4f8 100644 (file)
@@ -219,10 +219,12 @@ fn resolve_path(&self, path: &ast::Path) -> Option<hir::PathResolution> {
         let resolved_qualifier = self.scope.speculative_resolve(&path.qualifier()?)?;
         if let hir::PathResolution::Def(hir::ModuleDef::Adt(adt)) = resolved_qualifier {
             let name = path.segment()?.name_ref()?;
+            let module = self.scope.module()?;
             adt.ty(self.scope.db).iterate_path_candidates(
                 self.scope.db,
-                self.scope.module()?.krate(),
+                module.krate(),
                 &self.scope.visible_traits(),
+                Some(module),
                 None,
                 |_ty, assoc_item| {
                     let item_name = assoc_item.name(self.scope.db)?;