diff options
| author | Matthias Krüger <476013+matthiaskrgr@users.noreply.github.com> | 2025-03-13 17:44:07 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-03-13 17:44:07 +0100 |
| commit | 41d6e6e8daf428ee6773e93ac4ab8e3422e9a760 (patch) | |
| tree | 2eed196e6fbac7ab4050e3218319bef88a1b58df /compiler | |
| parent | b5955e74e80d074f71625cd3340a31c14f7765c8 (diff) | |
| parent | 63447f20954bdd0f15698b55a7eb7e68695b63ad (diff) | |
| download | rust-41d6e6e8daf428ee6773e93ac4ab8e3422e9a760.tar.gz rust-41d6e6e8daf428ee6773e93ac4ab8e3422e9a760.zip | |
Rollup merge of #138399 - Bryanskiy:delegation-extern-fn, r=petrochenkov
Delegation: allow foreign fns `reuse`
In example:
```rust
unsafe extern "C" {
fn foo();
}
reuse foo as bar;
```
Desugaring before:
```rust
fn bar() {
foo()
//~^ ERROR call to unsafe function `foo` is unsafe and requires unsafe function or block
}
```
after:
```rust
unsafe extern "C" fn bar() {
foo()
}
```
Fixes https://github.com/rust-lang/rust/issues/127412
r? `@petrochenkov`
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_ast_lowering/src/delegation.rs | 15 | ||||
| -rw-r--r-- | compiler/rustc_mir_build/src/check_unsafety.rs | 5 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/late.rs | 31 |
3 files changed, 38 insertions, 13 deletions
diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs index 946f2cafa15..efc1fa05c5f 100644 --- a/compiler/rustc_ast_lowering/src/delegation.rs +++ b/compiler/rustc_ast_lowering/src/delegation.rs @@ -190,14 +190,19 @@ impl<'hir> LoweringContext<'_, 'hir> { ) -> hir::FnSig<'hir> { let header = if let Some(local_sig_id) = sig_id.as_local() { match self.resolver.delegation_fn_sigs.get(&local_sig_id) { - Some(sig) => self.lower_fn_header( - sig.header, + Some(sig) => { + let parent = self.tcx.parent(sig_id); // HACK: we override the default safety instead of generating attributes from the ether. // We are not forwarding the attributes, as the delegation fn sigs are collected on the ast, // and here we need the hir attributes. - if sig.target_feature { hir::Safety::Unsafe } else { hir::Safety::Safe }, - &[], - ), + let default_safety = + if sig.target_feature || self.tcx.def_kind(parent) == DefKind::ForeignMod { + hir::Safety::Unsafe + } else { + hir::Safety::Safe + }; + self.lower_fn_header(sig.header, default_safety, &[]) + } None => self.generate_header_error(), } } else { diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index d78c874c766..7f2e7d5ca83 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -753,6 +753,11 @@ impl UnsafeOpKind { span: Span, suggest_unsafe_block: bool, ) { + if tcx.hir_opt_delegation_sig_id(hir_id.owner.def_id).is_some() { + // The body of the delegation item is synthesized, so it makes no sense + // to emit this lint. + return; + } let parent_id = tcx.hir_get_parent_item(hir_id); let parent_owner = tcx.hir_owner_node(parent_id); let should_suggest = parent_owner.fn_sig().is_some_and(|sig| { diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index d28988cd74f..f3f6c551580 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -5117,12 +5117,18 @@ struct ItemInfoCollector<'a, 'ra, 'tcx> { } impl ItemInfoCollector<'_, '_, '_> { - fn collect_fn_info(&mut self, sig: &FnSig, id: NodeId, attrs: &[Attribute]) { + fn collect_fn_info( + &mut self, + header: FnHeader, + decl: &FnDecl, + id: NodeId, + attrs: &[Attribute], + ) { let sig = DelegationFnSig { - header: sig.header, - param_count: sig.decl.inputs.len(), - has_self: sig.decl.has_self(), - c_variadic: sig.decl.c_variadic(), + header, + param_count: decl.inputs.len(), + has_self: decl.has_self(), + c_variadic: decl.c_variadic(), target_feature: attrs.iter().any(|attr| attr.has_name(sym::target_feature)), }; self.r.delegation_fn_sigs.insert(self.r.local_def_id(id), sig); @@ -5142,7 +5148,7 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> { | ItemKind::Trait(box Trait { generics, .. }) | ItemKind::TraitAlias(generics, _) => { if let ItemKind::Fn(box Fn { sig, .. }) = &item.kind { - self.collect_fn_info(sig, item.id, &item.attrs); + self.collect_fn_info(sig.header, &sig.decl, item.id, &item.attrs); } let def_id = self.r.local_def_id(item.id); @@ -5154,8 +5160,17 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> { self.r.item_generics_num_lifetimes.insert(def_id, count); } + ItemKind::ForeignMod(ForeignMod { extern_span, safety: _, abi, items }) => { + for foreign_item in items { + if let ForeignItemKind::Fn(box Fn { sig, .. }) = &foreign_item.kind { + let new_header = + FnHeader { ext: Extern::from_abi(*abi, *extern_span), ..sig.header }; + self.collect_fn_info(new_header, &sig.decl, foreign_item.id, &item.attrs); + } + } + } + ItemKind::Mod(..) - | ItemKind::ForeignMod(..) | ItemKind::Static(..) | ItemKind::Use(..) | ItemKind::ExternCrate(..) @@ -5175,7 +5190,7 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> { fn visit_assoc_item(&mut self, item: &'ast AssocItem, ctxt: AssocCtxt) { if let AssocItemKind::Fn(box Fn { sig, .. }) = &item.kind { - self.collect_fn_info(sig, item.id, &item.attrs); + self.collect_fn_info(sig.header, &sig.decl, item.id, &item.attrs); } visit::walk_assoc_item(self, item, ctxt); } |
