Skip to content

Commit a907c56

Browse files
committed
Add hir::HeaderSafety to make follow up commits simpler
1 parent e491cae commit a907c56

File tree

23 files changed

+101
-40
lines changed

23 files changed

+101
-40
lines changed

compiler/rustc_ast_lowering/src/delegation.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
198198
Asyncness::No => hir::IsAsync::NotAsync,
199199
};
200200
hir::FnHeader {
201-
safety: sig.safety,
201+
safety: sig.safety.into(),
202202
constness: self.tcx.constness(sig_id),
203203
asyncness,
204204
abi: sig.abi,
@@ -384,7 +384,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
384384

385385
fn generate_header_error(&self) -> hir::FnHeader {
386386
hir::FnHeader {
387-
safety: hir::Safety::Safe,
387+
safety: hir::Safety::Safe.into(),
388388
constness: hir::Constness::NotConst,
389389
asyncness: hir::IsAsync::NotAsync,
390390
abi: abi::Abi::Rust,

compiler/rustc_ast_lowering/src/item.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -1358,8 +1358,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
13581358
} else {
13591359
hir::IsAsync::NotAsync
13601360
};
1361+
1362+
let safety = self.lower_safety(h.safety, default_safety);
1363+
let safety = safety.into();
1364+
13611365
hir::FnHeader {
1362-
safety: self.lower_safety(h.safety, default_safety),
1366+
safety,
13631367
asyncness,
13641368
constness: self.lower_constness(h.constness),
13651369
abi: self.lower_extern(h.ext),

compiler/rustc_hir/src/hir.rs

+23-2
Original file line numberDiff line numberDiff line change
@@ -3762,9 +3762,20 @@ impl fmt::Display for Constness {
37623762
}
37633763
}
37643764

3765+
#[derive(Copy, Clone, Debug, HashStable_Generic, PartialEq, Eq)]
3766+
pub enum HeaderSafety {
3767+
Normal(Safety),
3768+
}
3769+
3770+
impl From<Safety> for HeaderSafety {
3771+
fn from(v: Safety) -> Self {
3772+
Self::Normal(v)
3773+
}
3774+
}
3775+
37653776
#[derive(Copy, Clone, Debug, HashStable_Generic)]
37663777
pub struct FnHeader {
3767-
pub safety: Safety,
3778+
pub safety: HeaderSafety,
37683779
pub constness: Constness,
37693780
pub asyncness: IsAsync,
37703781
pub abi: ExternAbi,
@@ -3780,7 +3791,17 @@ impl FnHeader {
37803791
}
37813792

37823793
pub fn is_unsafe(&self) -> bool {
3783-
self.safety.is_unsafe()
3794+
self.safety().is_unsafe()
3795+
}
3796+
3797+
pub fn is_safe(&self) -> bool {
3798+
self.safety().is_safe()
3799+
}
3800+
3801+
pub fn safety(&self) -> Safety {
3802+
match self.safety {
3803+
HeaderSafety::Normal(safety) => safety,
3804+
}
37843805
}
37853806
}
37863807

compiler/rustc_hir_analysis/src/collect.rs

+11-6
Original file line numberDiff line numberDiff line change
@@ -1336,7 +1336,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFn
13361336
{
13371337
icx.lowerer().lower_fn_ty(
13381338
hir_id,
1339-
sig.header.safety,
1339+
sig.header.safety(),
13401340
sig.header.abi,
13411341
sig.decl,
13421342
Some(generics),
@@ -1351,13 +1351,18 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFn
13511351
kind: TraitItemKind::Fn(FnSig { header, decl, span: _ }, _),
13521352
generics,
13531353
..
1354-
}) => {
1355-
icx.lowerer().lower_fn_ty(hir_id, header.safety, header.abi, decl, Some(generics), None)
1356-
}
1354+
}) => icx.lowerer().lower_fn_ty(
1355+
hir_id,
1356+
header.safety(),
1357+
header.abi,
1358+
decl,
1359+
Some(generics),
1360+
None,
1361+
),
13571362

13581363
ForeignItem(&hir::ForeignItem { kind: ForeignItemKind::Fn(sig, _, _), .. }) => {
13591364
let abi = tcx.hir().get_foreign_abi(hir_id);
1360-
compute_sig_of_foreign_fn_decl(tcx, def_id, sig.decl, abi, sig.header.safety)
1365+
compute_sig_of_foreign_fn_decl(tcx, def_id, sig.decl, abi, sig.header.safety())
13611366
}
13621367

13631368
Ctor(data) | Variant(hir::Variant { data, .. }) if data.ctor().is_some() => {
@@ -1405,7 +1410,7 @@ fn lower_fn_sig_recovering_infer_ret_ty<'tcx>(
14051410

14061411
icx.lowerer().lower_fn_ty(
14071412
icx.tcx().local_def_id_to_hir_id(def_id),
1408-
sig.header.safety,
1413+
sig.header.safety(),
14091414
sig.header.abi,
14101415
sig.decl,
14111416
Some(generics),

compiler/rustc_hir_pretty/src/lib.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -2407,7 +2407,7 @@ impl<'a> State<'a> {
24072407
self.print_fn(
24082408
decl,
24092409
hir::FnHeader {
2410-
safety,
2410+
safety: safety.into(),
24112411
abi,
24122412
constness: hir::Constness::NotConst,
24132413
asyncness: hir::IsAsync::NotAsync,
@@ -2423,12 +2423,16 @@ impl<'a> State<'a> {
24232423
fn print_fn_header_info(&mut self, header: hir::FnHeader) {
24242424
self.print_constness(header.constness);
24252425

2426+
let safety = match header.safety {
2427+
hir::HeaderSafety::Normal(safety) => safety,
2428+
};
2429+
24262430
match header.asyncness {
24272431
hir::IsAsync::NotAsync => {}
24282432
hir::IsAsync::Async(_) => self.word_nbsp("async"),
24292433
}
24302434

2431-
self.print_safety(header.safety);
2435+
self.print_safety(safety);
24322436

24332437
if header.abi != ExternAbi::Rust {
24342438
self.word_nbsp("extern");

compiler/rustc_hir_typeck/src/coercion.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -932,10 +932,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
932932
return Err(TypeError::ForceInlineCast);
933933
}
934934

935-
// Safe `#[target_feature]` functions are not assignable to safe fn pointers
936-
// (RFC 2396).
935+
// Safe `#[target_feature]` functions are not assignable to safe fn pointers (RFC 2396),
936+
// report a better error than a safety mismatch.
937+
// FIXME(target_feature): do this inside `coerce_from_safe_fn`.
937938
if b_hdr.safety.is_safe()
938-
&& !self.tcx.codegen_fn_attrs(def_id).target_features.is_empty()
939+
&& self.tcx.codegen_fn_attrs(def_id).safe_target_features
939940
{
940941
return Err(TypeError::TargetFeatureCast(def_id));
941942
}

compiler/rustc_hir_typeck/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ fn typeck_with_fallback<'tcx>(
139139
// type that has an infer in it, lower the type directly so that it'll
140140
// be correctly filled with infer. We'll use this inference to provide
141141
// a suggestion later on.
142-
fcx.lowerer().lower_fn_ty(id, header.safety, header.abi, decl, None, None)
142+
fcx.lowerer().lower_fn_ty(id, header.safety(), header.abi, decl, None, None)
143143
} else {
144144
tcx.fn_sig(def_id).instantiate_identity()
145145
};

compiler/rustc_middle/src/middle/codegen_fn_attrs.rs

+3
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ pub struct CodegenFnAttrs {
3030
/// features (only enabled features are supported right now).
3131
/// Implied target features have already been applied.
3232
pub target_features: Vec<TargetFeature>,
33+
/// Whether the function was declared safe, but has target features
34+
pub safe_target_features: bool,
3335
/// The `#[linkage = "..."]` attribute on Rust-defined items and the value we found.
3436
pub linkage: Option<Linkage>,
3537
/// The `#[linkage = "..."]` attribute on foreign items and the value we found.
@@ -150,6 +152,7 @@ impl CodegenFnAttrs {
150152
link_name: None,
151153
link_ordinal: None,
152154
target_features: vec![],
155+
safe_target_features: false,
153156
linkage: None,
154157
import_linkage: None,
155158
link_section: None,

compiler/rustc_middle/src/ty/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ pub struct DelegationFnSig {
222222
pub param_count: usize,
223223
pub has_self: bool,
224224
pub c_variadic: bool,
225+
pub target_feature: bool,
225226
}
226227

227228
#[derive(Clone, Copy, Debug)]

compiler/rustc_mir_build/src/check_unsafety.rs

+18-5
Original file line numberDiff line numberDiff line change
@@ -478,19 +478,27 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
478478
return; // don't visit the whole expression
479479
}
480480
ExprKind::Call { fun, ty: _, args: _, from_hir_call: _, fn_span: _ } => {
481-
if self.thir[fun].ty.fn_sig(self.tcx).safety().is_unsafe() {
482-
let func_id = if let ty::FnDef(func_id, _) = self.thir[fun].ty.kind() {
481+
let fn_ty = self.thir[fun].ty;
482+
let sig = fn_ty.fn_sig(self.tcx);
483+
let (callee_features, safe_target_features): (&[_], _) = match fn_ty.kind() {
484+
ty::FnDef(func_id, ..) => {
485+
let cg_attrs = self.tcx.codegen_fn_attrs(func_id);
486+
(&cg_attrs.target_features, cg_attrs.safe_target_features)
487+
}
488+
_ => (&[], false),
489+
};
490+
if sig.safety().is_unsafe() && !safe_target_features {
491+
let func_id = if let ty::FnDef(func_id, _) = fn_ty.kind() {
483492
Some(*func_id)
484493
} else {
485494
None
486495
};
487496
self.requires_unsafe(expr.span, CallToUnsafeFunction(func_id));
488-
} else if let &ty::FnDef(func_did, _) = self.thir[fun].ty.kind() {
497+
} else if let &ty::FnDef(func_did, _) = fn_ty.kind() {
489498
// If the called function has target features the calling function hasn't,
490499
// the call requires `unsafe`. Don't check this on wasm
491500
// targets, though. For more information on wasm see the
492501
// is_like_wasm check in hir_analysis/src/collect.rs
493-
let callee_features = &self.tcx.codegen_fn_attrs(func_did).target_features;
494502
if !self.tcx.sess.target.options.is_like_wasm
495503
&& !callee_features.iter().all(|feature| {
496504
self.body_target_features.iter().any(|f| f.name == feature.name)
@@ -1111,7 +1119,12 @@ pub(crate) fn check_unsafety(tcx: TyCtxt<'_>, def: LocalDefId) {
11111119

11121120
let hir_id = tcx.local_def_id_to_hir_id(def);
11131121
let safety_context = tcx.hir().fn_sig_by_hir_id(hir_id).map_or(SafetyContext::Safe, |fn_sig| {
1114-
if fn_sig.header.safety.is_unsafe() { SafetyContext::UnsafeFn } else { SafetyContext::Safe }
1122+
match fn_sig.header.safety {
1123+
hir::HeaderSafety::Normal(safety) => match safety {
1124+
hir::Safety::Unsafe => SafetyContext::UnsafeFn,
1125+
hir::Safety::Safe => SafetyContext::Safe,
1126+
},
1127+
}
11151128
});
11161129
let body_target_features = &tcx.body_codegen_attrs(def.to_def_id()).target_features;
11171130
let mut warnings = Vec::new();

compiler/rustc_resolve/src/late.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -5019,12 +5019,13 @@ struct ItemInfoCollector<'a, 'ra, 'tcx> {
50195019
}
50205020

50215021
impl ItemInfoCollector<'_, '_, '_> {
5022-
fn collect_fn_info(&mut self, sig: &FnSig, id: NodeId) {
5022+
fn collect_fn_info(&mut self, sig: &FnSig, id: NodeId, attrs: &[Attribute]) {
50235023
let sig = DelegationFnSig {
50245024
header: sig.header,
50255025
param_count: sig.decl.inputs.len(),
50265026
has_self: sig.decl.has_self(),
50275027
c_variadic: sig.decl.c_variadic(),
5028+
target_feature: attrs.iter().any(|attr| attr.has_name(sym::target_feature)),
50285029
};
50295030
self.r.delegation_fn_sigs.insert(self.r.local_def_id(id), sig);
50305031
}
@@ -5043,7 +5044,7 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> {
50435044
| ItemKind::Trait(box Trait { ref generics, .. })
50445045
| ItemKind::TraitAlias(ref generics, _) => {
50455046
if let ItemKind::Fn(box Fn { ref sig, .. }) = &item.kind {
5046-
self.collect_fn_info(sig, item.id);
5047+
self.collect_fn_info(sig, item.id, &item.attrs);
50475048
}
50485049

50495050
let def_id = self.r.local_def_id(item.id);
@@ -5076,7 +5077,7 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> {
50765077

50775078
fn visit_assoc_item(&mut self, item: &'ast AssocItem, ctxt: AssocCtxt) {
50785079
if let AssocItemKind::Fn(box Fn { ref sig, .. }) = &item.kind {
5079-
self.collect_fn_info(sig, item.id);
5080+
self.collect_fn_info(sig, item.id, &item.attrs);
50805081
}
50815082
visit::walk_assoc_item(self, item, ctxt);
50825083
}

src/librustdoc/clean/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -3094,7 +3094,7 @@ fn clean_maybe_renamed_foreign_item<'tcx>(
30943094
let kind = match item.kind {
30953095
hir::ForeignItemKind::Fn(sig, names, generics) => ForeignFunctionItem(
30963096
clean_function(cx, &sig, generics, FunctionArgs::Names(names)),
3097-
sig.header.safety,
3097+
sig.header.safety(),
30983098
),
30993099
hir::ForeignItemKind::Static(ty, mutability, safety) => ForeignStaticItem(
31003100
Static { type_: Box::new(clean_ty(ty, cx)), mutability, expr: None },

src/librustdoc/clean/types.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -668,17 +668,17 @@ impl Item {
668668
ty::Asyncness::Yes => hir::IsAsync::Async(DUMMY_SP),
669669
ty::Asyncness::No => hir::IsAsync::NotAsync,
670670
};
671-
hir::FnHeader { safety: sig.safety(), abi: sig.abi(), constness, asyncness }
671+
hir::FnHeader { safety: sig.safety().into(), abi: sig.abi(), constness, asyncness }
672672
}
673673
let header = match self.kind {
674674
ItemKind::ForeignFunctionItem(_, safety) => {
675675
let def_id = self.def_id().unwrap();
676676
let abi = tcx.fn_sig(def_id).skip_binder().abi();
677677
hir::FnHeader {
678678
safety: if abi == ExternAbi::RustIntrinsic {
679-
intrinsic_operation_unsafety(tcx, def_id.expect_local())
679+
intrinsic_operation_unsafety(tcx, def_id.expect_local()).into()
680680
} else {
681-
safety
681+
safety.into()
682682
},
683683
abi,
684684
constness: if tcx.is_const_fn(def_id) {

src/librustdoc/html/format.rs

+8
Original file line numberDiff line numberDiff line change
@@ -1637,6 +1637,14 @@ impl PrintWithSpace for hir::Safety {
16371637
}
16381638
}
16391639

1640+
impl PrintWithSpace for hir::HeaderSafety {
1641+
fn print_with_space(&self) -> &str {
1642+
match self {
1643+
hir::HeaderSafety::Normal(safety) => safety.print_with_space(),
1644+
}
1645+
}
1646+
}
1647+
16401648
impl PrintWithSpace for hir::IsAsync {
16411649
fn print_with_space(&self) -> &str {
16421650
match self {

src/librustdoc/html/render/print_item.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -469,7 +469,7 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl
469469

470470
let unsafety_flag = match myitem.kind {
471471
clean::FunctionItem(_) | clean::ForeignFunctionItem(..)
472-
if myitem.fn_header(tcx).unwrap().safety.is_unsafe() =>
472+
if myitem.fn_header(tcx).unwrap().is_unsafe() =>
473473
{
474474
"<sup title=\"unsafe function\">⚠</sup>"
475475
}

src/tools/clippy/clippy_lints/src/derive.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -419,7 +419,7 @@ impl<'tcx> Visitor<'tcx> for UnsafeVisitor<'_, 'tcx> {
419419
id: LocalDefId,
420420
) -> Self::Result {
421421
if let Some(header) = kind.header()
422-
&& header.safety.is_unsafe()
422+
&& header.is_unsafe()
423423
{
424424
ControlFlow::Break(())
425425
} else {

src/tools/clippy/clippy_lints/src/doc/missing_headers.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ pub fn check(
3232
}
3333

3434
let span = cx.tcx.def_span(owner_id);
35-
match (headers.safety, sig.header.safety) {
35+
match (headers.safety, sig.header.safety()) {
3636
(false, Safety::Unsafe) => span_lint(
3737
cx,
3838
MISSING_SAFETY_DOC,

src/tools/clippy/clippy_lints/src/functions/misnamed_getters.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ pub fn check_fn(cx: &LateContext<'_>, kind: FnKind<'_>, decl: &FnDecl<'_>, body:
3434
ImplicitSelfKind::None => return,
3535
};
3636

37-
let name = if sig.header.safety.is_unsafe() {
37+
let name = if sig.header.is_unsafe() {
3838
name.strip_suffix("_unchecked").unwrap_or(name)
3939
} else {
4040
name

src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ pub(super) fn check_fn<'tcx>(
2020
def_id: LocalDefId,
2121
) {
2222
let safety = match kind {
23-
intravisit::FnKind::ItemFn(_, _, hir::FnHeader { safety, .. }) => safety,
24-
intravisit::FnKind::Method(_, sig) => sig.header.safety,
23+
intravisit::FnKind::ItemFn(_, _, header) => header.safety(),
24+
intravisit::FnKind::Method(_, sig) => sig.header.safety(),
2525
intravisit::FnKind::Closure => return,
2626
};
2727

@@ -31,7 +31,7 @@ pub(super) fn check_fn<'tcx>(
3131
pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'_>) {
3232
if let hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(eid)) = item.kind {
3333
let body = cx.tcx.hir().body(eid);
34-
check_raw_ptr(cx, sig.header.safety, sig.decl, body, item.owner_id.def_id);
34+
check_raw_ptr(cx, sig.header.safety(), sig.decl, body, item.owner_id.def_id);
3535
}
3636
}
3737

src/tools/clippy/clippy_lints/src/inherent_to_string.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ impl<'tcx> LateLintPass<'tcx> for InherentToString {
9595
if let ImplItemKind::Fn(ref signature, _) = impl_item.kind
9696
// #11201
9797
&& let header = signature.header
98-
&& header.safety.is_safe()
98+
&& header.is_safe()
9999
&& header.abi == Abi::Rust
100100
&& impl_item.ident.name == sym::to_string
101101
&& let decl = signature.decl

src/tools/clippy/clippy_lints/src/methods/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -5309,7 +5309,7 @@ fn lint_binary_expr_with_method_call(cx: &LateContext<'_>, info: &mut BinaryExpr
53095309
}
53105310

53115311
const FN_HEADER: hir::FnHeader = hir::FnHeader {
5312-
safety: hir::Safety::Safe,
5312+
safety: hir::HeaderSafety::Normal(hir::Safety::Safe),
53135313
constness: hir::Constness::NotConst,
53145314
asyncness: hir::IsAsync::NotAsync,
53155315
abi: rustc_target::spec::abi::Abi::Rust,

src/tools/clippy/clippy_lints/src/new_without_default.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault {
7575
if let hir::ImplItemKind::Fn(ref sig, _) = impl_item.kind {
7676
let name = impl_item.ident.name;
7777
let id = impl_item.owner_id;
78-
if sig.header.safety.is_unsafe() {
78+
if sig.header.is_unsafe() {
7979
// can't be implemented for unsafe new
8080
return;
8181
}

0 commit comments

Comments
 (0)