about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLukas Wirth <lukastw97@gmail.com>2025-02-12 13:58:56 +0000
committerGitHub <noreply@github.com>2025-02-12 13:58:56 +0000
commit2de75297fc2f9ac91d26d51e5e5ff88be1986bd1 (patch)
tree55c00fa5a831823eec28cf72a6d532f0172d44b6
parent4a1559344f0413b9f52bb512ec5fd8e40f668d2d (diff)
parenta09ece29254cd06a1ee9529622e47c9a72645cb1 (diff)
downloadrust-2de75297fc2f9ac91d26d51e5e5ff88be1986bd1.tar.gz
rust-2de75297fc2f9ac91d26d51e5e5ff88be1986bd1.zip
Merge pull request #19109 from Veykril/push-nzpuuqommpnq
fix: Do not show safety hints for extern items lacking semantics
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/dyn_map.rs7
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs18
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs24
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/from_id.rs1
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/lib.rs39
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/semantics.rs1
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs3
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs14
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/defs.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/extern_block.rs19
10 files changed, 97 insertions, 31 deletions
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/dyn_map.rs b/src/tools/rust-analyzer/crates/hir-def/src/dyn_map.rs
index 0f73595347b..e9318d146dd 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/dyn_map.rs
+++ b/src/tools/rust-analyzer/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<K, V> = crate::dyn_map::Key<AstPtr<K>, V, AstPtrPolicy<K, V>>;
@@ -44,6 +44,7 @@ pub mod keys {
     pub const STATIC: Key<ast::Static, StaticId> = Key::new();
     pub const TYPE_ALIAS: Key<ast::TypeAlias, TypeAliasId> = Key::new();
     pub const IMPL: Key<ast::Impl, ImplId> = Key::new();
+    pub const EXTERN_BLOCK: Key<ast::ExternBlock, ExternBlockId> = Key::new();
     pub const TRAIT: Key<ast::Trait, TraitId> = Key::new();
     pub const TRAIT_ALIAS: Key<ast::TraitAlias, TraitAliasId> = Key::new();
     pub const STRUCT: Key<ast::Struct, StructId> = Key::new();
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs
index 65a39c56561..0ca1eb9bcfe 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs
+++ b/src/tools/rust-analyzer/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<ModuleDefId>,
 
     impls: Vec<ImplId>,
+    #[allow(clippy::box_collection)]
+    extern_blocks: Option<Box<Vec<ExternBlockId>>>,
     unnamed_consts: Vec<ConstId>,
     /// Traits imported via `use Trait as _;`.
     unnamed_trait_imports: FxHashMap<TraitId, Item<()>>,
@@ -319,6 +321,10 @@ impl ItemScope {
         self.extern_crate_decls.iter().copied()
     }
 
+    pub fn extern_blocks(&self) -> impl Iterator<Item = ExternBlockId> + '_ {
+        self.extern_blocks.iter().flat_map(|it| it.iter()).copied()
+    }
+
     pub fn use_decls(&self) -> impl ExactSizeIterator<Item = UseId> + '_ {
         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/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs
index 06276335b71..254c1379917 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs
+++ b/src/tools/rust-analyzer/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/src/tools/rust-analyzer/crates/hir/src/from_id.rs b/src/tools/rust-analyzer/crates/hir/src/from_id.rs
index 537401afdc3..72df07ef8c0 100644
--- a/src/tools/rust-analyzer/crates/hir/src/from_id.rs
+++ b/src/tools/rust-analyzer/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<AdtId> for Adt {
diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs
index 8b8203acb14..5923a1bc30e 100644
--- a/src/tools/rust-analyzer/crates/hir/src/lib.rs
+++ b/src/tools/rust-analyzer/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<ExternBlock> {
+        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<ExternBlock> {
+        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<EvaluatedConst, ConstEvalError> {
         db.const_eval(self.id.into(), Substitution::empty(Interner), None)
@@ -2929,6 +2943,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;
 
 impl StaticLifetime {
@@ -6177,9 +6202,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 }),
@@ -6191,7 +6222,7 @@ pub enum ItemContainer {
     Trait(Trait),
     Impl(Impl),
     Module(Module),
-    ExternBlock(),
+    ExternBlock(ExternBlock),
     Crate(CrateId),
 }
 
diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs
index 882a27182f0..c9145f7d212 100644
--- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs
+++ b/src/tools/rust-analyzer/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/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs b/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs
index d5dfb985718..d0fdf5cbdf7 100644
--- a/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs
+++ b/src/tools/rust-analyzer/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/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs b/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs
index 29d3736bae7..4481b8855fd 100644
--- a/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs
+++ b/src/tools/rust-analyzer/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<ExternCrateId> {
         self.to_def(src, keys::EXTERN_CRATE)
     }
+    pub(super) fn extern_block_to_def(
+        &mut self,
+        src: InFile<&ast::ExternBlock>,
+    ) -> Option<ExternBlockId> {
+        self.to_def(src, keys::EXTERN_BLOCK)
+    }
     #[allow(dead_code)]
     pub(super) fn use_to_def(&mut self, src: InFile<&ast::Use>) -> Option<UseId> {
         self.to_def(src, keys::USE)
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/defs.rs b/src/tools/rust-analyzer/crates/ide-db/src/defs.rs
index bad53608056..6f71c3d9bd7 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/defs.rs
+++ b/src/tools/rust-analyzer/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/src/tools/rust-analyzer/crates/ide/src/inlay_hints/extern_block.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/extern_block.rs
index 2bc91b68ed8..652dff0bc56 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/extern_block.rs
+++ b/src/tools/rust-analyzer/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<InlayHint>,
-    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<InlayHint>,
-    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<InlayHint>,
-    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(())
 }