From e0814742f0a54dd07726a58f3e29a51d4d478f67 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 7 Feb 2025 14:56:36 +0100 Subject: [PATCH] fix: Do not show safety hints for extern items lacking semantics --- crates/hir-def/src/dyn_map.rs | 7 ++-- crates/hir-def/src/item_scope.rs | 18 ++++++++-- crates/hir-def/src/nameres/collector.rs | 24 +++++++------ crates/hir/src/from_id.rs | 1 + crates/hir/src/lib.rs | 39 ++++++++++++++++++--- crates/hir/src/semantics.rs | 1 + crates/hir/src/semantics/child_by_source.rs | 3 ++ crates/hir/src/semantics/source_to_def.rs | 14 +++++--- crates/ide-db/src/defs.rs | 2 +- crates/ide/src/inlay_hints/extern_block.rs | 19 ++++++---- 10 files changed, 97 insertions(+), 31 deletions(-) diff --git a/crates/hir-def/src/dyn_map.rs b/crates/hir-def/src/dyn_map.rs index 0f73595347..e9318d146d 100644 --- a/crates/hir-def/src/dyn_map.rs +++ b/crates/hir-def/src/dyn_map.rs @@ -31,9 +31,9 @@ pub mod keys { use crate::{ dyn_map::{DynMap, Policy}, - BlockId, ConstId, EnumId, EnumVariantId, ExternCrateId, FieldId, FunctionId, ImplId, - LifetimeParamId, Macro2Id, MacroRulesId, ProcMacroId, StaticId, StructId, TraitAliasId, - TraitId, TypeAliasId, TypeOrConstParamId, UnionId, UseId, + BlockId, ConstId, EnumId, EnumVariantId, ExternBlockId, ExternCrateId, FieldId, FunctionId, + ImplId, LifetimeParamId, Macro2Id, MacroRulesId, ProcMacroId, StaticId, StructId, + TraitAliasId, TraitId, TypeAliasId, TypeOrConstParamId, UnionId, UseId, }; pub type Key = crate::dyn_map::Key, V, AstPtrPolicy>; @@ -44,6 +44,7 @@ pub mod keys { pub const STATIC: Key = Key::new(); pub const TYPE_ALIAS: Key = Key::new(); pub const IMPL: Key = Key::new(); + pub const EXTERN_BLOCK: Key = Key::new(); pub const TRAIT: Key = Key::new(); pub const TRAIT_ALIAS: Key = Key::new(); pub const STRUCT: Key = Key::new(); diff --git a/crates/hir-def/src/item_scope.rs b/crates/hir-def/src/item_scope.rs index 65a39c5656..0ca1eb9bcf 100644 --- a/crates/hir-def/src/item_scope.rs +++ b/crates/hir-def/src/item_scope.rs @@ -18,8 +18,8 @@ use crate::{ db::DefDatabase, per_ns::{Item, MacrosItem, PerNs, TypesItem, ValuesItem}, visibility::{Visibility, VisibilityExplicitness}, - AdtId, BuiltinType, ConstId, ExternCrateId, FxIndexMap, HasModule, ImplId, LocalModuleId, - Lookup, MacroId, ModuleDefId, ModuleId, TraitId, UseId, + AdtId, BuiltinType, ConstId, ExternBlockId, ExternCrateId, FxIndexMap, HasModule, ImplId, + LocalModuleId, Lookup, MacroId, ModuleDefId, ModuleId, TraitId, UseId, }; #[derive(Debug, Default)] @@ -158,6 +158,8 @@ pub struct ItemScope { declarations: Vec, impls: Vec, + #[allow(clippy::box_collection)] + extern_blocks: Option>>, unnamed_consts: Vec, /// Traits imported via `use Trait as _;`. unnamed_trait_imports: FxHashMap>, @@ -319,6 +321,10 @@ impl ItemScope { self.extern_crate_decls.iter().copied() } + pub fn extern_blocks(&self) -> impl Iterator + '_ { + self.extern_blocks.iter().flat_map(|it| it.iter()).copied() + } + pub fn use_decls(&self) -> impl ExactSizeIterator + '_ { self.use_decls.iter().copied() } @@ -469,6 +475,10 @@ impl ItemScope { self.impls.push(imp); } + pub(crate) fn define_extern_block(&mut self, extern_block: ExternBlockId) { + self.extern_blocks.get_or_insert_default().push(extern_block); + } + pub(crate) fn define_extern_crate_decl(&mut self, extern_crate: ExternCrateId) { self.extern_crate_decls.push(extern_crate); } @@ -806,7 +816,11 @@ impl ItemScope { use_imports_types, use_imports_macros, macro_invocations, + extern_blocks, } = self; + if let Some(it) = extern_blocks { + it.shrink_to_fit(); + } types.shrink_to_fit(); values.shrink_to_fit(); macros.shrink_to_fit(); diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs index 06276335b7..254c137991 100644 --- a/crates/hir-def/src/nameres/collector.rs +++ b/crates/hir-def/src/nameres/collector.rs @@ -1759,16 +1759,20 @@ impl ModCollector<'_, '_> { ); } } - ModItem::ExternBlock(block) => self.collect( - &self.item_tree[block].children, - ItemContainerId::ExternBlockId( - ExternBlockLoc { - container: module, - id: ItemTreeId::new(self.tree_id, block), - } - .intern(db), - ), - ), + ModItem::ExternBlock(block) => { + let extern_block_id = ExternBlockLoc { + container: module, + id: ItemTreeId::new(self.tree_id, block), + } + .intern(db); + self.def_collector.def_map.modules[self.module_id] + .scope + .define_extern_block(extern_block_id); + self.collect( + &self.item_tree[block].children, + ItemContainerId::ExternBlockId(extern_block_id), + ) + } ModItem::MacroCall(mac) => self.collect_macro_call(&self.item_tree[mac], container), ModItem::MacroRules(id) => self.collect_macro_rules(id, module), ModItem::Macro2(id) => self.collect_macro_def(id, module), diff --git a/crates/hir/src/from_id.rs b/crates/hir/src/from_id.rs index 537401afdc..72df07ef8c 100644 --- a/crates/hir/src/from_id.rs +++ b/crates/hir/src/from_id.rs @@ -49,6 +49,7 @@ from_id![ (hir_def::LifetimeParamId, crate::LifetimeParam), (hir_def::MacroId, crate::Macro), (hir_def::ExternCrateId, crate::ExternCrateDecl), + (hir_def::ExternBlockId, crate::ExternBlock), ]; impl From for Adt { diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 56090bc6b6..3c17ddb7b7 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -55,8 +55,8 @@ use hir_def::{ resolver::{HasResolver, Resolver}, type_ref::TypesSourceMap, AdtId, AssocItemId, AssocItemLoc, AttrDefId, CallableDefId, ConstId, ConstParamId, - CrateRootModuleId, DefWithBodyId, EnumId, EnumVariantId, ExternCrateId, FunctionId, - GenericDefId, GenericParamId, HasModule, ImplId, InTypeConstId, ItemContainerId, + CrateRootModuleId, DefWithBodyId, EnumId, EnumVariantId, ExternBlockId, ExternCrateId, + FunctionId, GenericDefId, GenericParamId, HasModule, ImplId, InTypeConstId, ItemContainerId, LifetimeParamId, LocalFieldId, Lookup, MacroExpander, MacroId, ModuleId, StaticId, StructId, SyntheticSyntax, TraitAliasId, TupleId, TypeAliasId, TypeOrConstParamId, TypeParamId, UnionId, }; @@ -2327,6 +2327,13 @@ impl Function { db.function_data(self.id).is_async() } + pub fn extern_block(self, db: &dyn HirDatabase) -> Option { + match self.id.lookup(db.upcast()).container { + ItemContainerId::ExternBlockId(id) => Some(ExternBlock { id }), + _ => None, + } + } + pub fn returns_impl_future(self, db: &dyn HirDatabase) -> bool { if self.is_async(db) { return true; @@ -2761,6 +2768,13 @@ impl Static { Type::from_value_def(db, self.id) } + pub fn extern_block(self, db: &dyn HirDatabase) -> Option { + match self.id.lookup(db.upcast()).container { + ItemContainerId::ExternBlockId(id) => Some(ExternBlock { id }), + _ => None, + } + } + /// Evaluate the static initializer. pub fn eval(self, db: &dyn HirDatabase) -> Result { db.const_eval(self.id.into(), Substitution::empty(Interner), None) @@ -2928,6 +2942,17 @@ impl HasVisibility for TypeAlias { } } +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct ExternBlock { + pub(crate) id: ExternBlockId, +} + +impl ExternBlock { + pub fn module(self, db: &dyn HirDatabase) -> Module { + Module { id: self.id.module(db.upcast()) } + } +} + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct StaticLifetime; @@ -6180,9 +6205,15 @@ impl HasContainer for TraitAlias { } } +impl HasContainer for ExternBlock { + fn container(&self, db: &dyn HirDatabase) -> ItemContainer { + ItemContainer::Module(Module { id: self.id.lookup(db.upcast()).container }) + } +} + fn container_id_to_hir(c: ItemContainerId) -> ItemContainer { match c { - ItemContainerId::ExternBlockId(_id) => ItemContainer::ExternBlock(), + ItemContainerId::ExternBlockId(id) => ItemContainer::ExternBlock(ExternBlock { id }), ItemContainerId::ModuleId(id) => ItemContainer::Module(Module { id }), ItemContainerId::ImplId(id) => ItemContainer::Impl(Impl { id }), ItemContainerId::TraitId(id) => ItemContainer::Trait(Trait { id }), @@ -6194,7 +6225,7 @@ pub enum ItemContainer { Trait(Trait), Impl(Impl), Module(Module), - ExternBlock(), + ExternBlock(ExternBlock), Crate(CrateId), } diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index 882a27182f..c9145f7d21 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs @@ -1998,6 +1998,7 @@ to_def_impls![ (crate::Adt, ast::Adt, adt_to_def), (crate::ExternCrateDecl, ast::ExternCrate, extern_crate_to_def), (crate::InlineAsmOperand, ast::AsmOperandNamed, asm_operand_to_def), + (crate::ExternBlock, ast::ExternBlock, extern_block_to_def), (MacroCallId, ast::MacroCall, macro_call_to_macro_call), ]; diff --git a/crates/hir/src/semantics/child_by_source.rs b/crates/hir/src/semantics/child_by_source.rs index d5dfb98571..d0fdf5cbdf 100644 --- a/crates/hir/src/semantics/child_by_source.rs +++ b/crates/hir/src/semantics/child_by_source.rs @@ -74,6 +74,9 @@ impl ChildBySource for ItemScope { fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) { self.declarations().for_each(|item| add_module_def(db, res, file_id, item)); self.impls().for_each(|imp| insert_item_loc(db, res, file_id, imp, keys::IMPL)); + self.extern_blocks().for_each(|extern_block| { + insert_item_loc(db, res, file_id, extern_block, keys::EXTERN_BLOCK) + }); self.extern_crate_decls() .for_each(|ext| insert_item_loc(db, res, file_id, ext, keys::EXTERN_CRATE)); self.use_decls().for_each(|ext| insert_item_loc(db, res, file_id, ext, keys::USE)); diff --git a/crates/hir/src/semantics/source_to_def.rs b/crates/hir/src/semantics/source_to_def.rs index 3c9e7065c4..4e61f5b5a3 100644 --- a/crates/hir/src/semantics/source_to_def.rs +++ b/crates/hir/src/semantics/source_to_def.rs @@ -92,10 +92,10 @@ use hir_def::{ DynMap, }, hir::{BindingId, Expr, LabelId}, - AdtId, BlockId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId, ExternCrateId, - FieldId, FunctionId, GenericDefId, GenericParamId, ImplId, LifetimeParamId, Lookup, MacroId, - ModuleId, StaticId, StructId, TraitAliasId, TraitId, TypeAliasId, TypeParamId, UnionId, UseId, - VariantId, + AdtId, BlockId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId, ExternBlockId, + ExternCrateId, FieldId, FunctionId, GenericDefId, GenericParamId, ImplId, LifetimeParamId, + Lookup, MacroId, ModuleId, StaticId, StructId, TraitAliasId, TraitId, TypeAliasId, TypeParamId, + UnionId, UseId, VariantId, }; use hir_expand::{ attrs::AttrId, name::AsName, ExpansionInfo, HirFileId, HirFileIdExt, InMacroFile, MacroCallId, @@ -308,6 +308,12 @@ impl SourceToDefCtx<'_, '_> { ) -> Option { self.to_def(src, keys::EXTERN_CRATE) } + pub(super) fn extern_block_to_def( + &mut self, + src: InFile<&ast::ExternBlock>, + ) -> Option { + self.to_def(src, keys::EXTERN_BLOCK) + } #[allow(dead_code)] pub(super) fn use_to_def(&mut self, src: InFile<&ast::Use>) -> Option { self.to_def(src, keys::USE) diff --git a/crates/ide-db/src/defs.rs b/crates/ide-db/src/defs.rs index bad5360805..6f71c3d9bd 100644 --- a/crates/ide-db/src/defs.rs +++ b/crates/ide-db/src/defs.rs @@ -108,7 +108,7 @@ impl Definition { ItemContainer::Trait(it) => Some(it.into()), ItemContainer::Impl(it) => Some(it.into()), ItemContainer::Module(it) => Some(it.into()), - ItemContainer::ExternBlock() | ItemContainer::Crate(_) => None, + ItemContainer::ExternBlock(_) | ItemContainer::Crate(_) => None, } } match self { diff --git a/crates/ide/src/inlay_hints/extern_block.rs b/crates/ide/src/inlay_hints/extern_block.rs index 2bc91b68ed..652dff0bc5 100644 --- a/crates/ide/src/inlay_hints/extern_block.rs +++ b/crates/ide/src/inlay_hints/extern_block.rs @@ -7,7 +7,7 @@ use crate::{InlayHint, InlayHintsConfig}; pub(super) fn extern_block_hints( acc: &mut Vec, - FamousDefs(_sema, _): &FamousDefs<'_, '_>, + FamousDefs(sema, _): &FamousDefs<'_, '_>, config: &InlayHintsConfig, _file_id: EditionedFileId, extern_block: ast::ExternBlock, @@ -16,6 +16,7 @@ pub(super) fn extern_block_hints( return None; } let abi = extern_block.abi()?; + sema.to_def(&extern_block)?; acc.push(InlayHint { range: abi.syntax().text_range(), position: crate::InlayHintPosition::Before, @@ -33,7 +34,7 @@ pub(super) fn extern_block_hints( pub(super) fn fn_hints( acc: &mut Vec, - FamousDefs(_sema, _): &FamousDefs<'_, '_>, + FamousDefs(sema, _): &FamousDefs<'_, '_>, config: &InlayHintsConfig, _file_id: EditionedFileId, fn_: &ast::Fn, @@ -43,14 +44,16 @@ pub(super) fn fn_hints( if !implicit_unsafe { return None; } - let fn_ = fn_.fn_token()?; - acc.push(item_hint(config, extern_block, fn_)); + let fn_token = fn_.fn_token()?; + if sema.to_def(fn_).is_some_and(|def| def.extern_block(sema.db).is_some()) { + acc.push(item_hint(config, extern_block, fn_token)); + } Some(()) } pub(super) fn static_hints( acc: &mut Vec, - FamousDefs(_sema, _): &FamousDefs<'_, '_>, + FamousDefs(sema, _): &FamousDefs<'_, '_>, config: &InlayHintsConfig, _file_id: EditionedFileId, static_: &ast::Static, @@ -60,8 +63,10 @@ pub(super) fn static_hints( if !implicit_unsafe { return None; } - let static_ = static_.static_token()?; - acc.push(item_hint(config, extern_block, static_)); + let static_token = static_.static_token()?; + if sema.to_def(static_).is_some_and(|def| def.extern_block(sema.db).is_some()) { + acc.push(item_hint(config, extern_block, static_token)); + } Some(()) }