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

Lines changed: 2 additions & 2 deletions
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

Lines changed: 5 additions & 1 deletion
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

Lines changed: 23 additions & 2 deletions
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

Lines changed: 11 additions & 6 deletions
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

Lines changed: 6 additions & 2 deletions
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

Lines changed: 4 additions & 3 deletions
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 3 additions & 0 deletions
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

Lines changed: 1 addition & 0 deletions
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

Lines changed: 18 additions & 5 deletions
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();

0 commit comments

Comments
 (0)