Skip to content

Commit 3ea7daf

Browse files
committed
Add hir::HeaderSafety to make follow up commits simpler
1 parent 37e7459 commit 3ea7daf

File tree

23 files changed

+101
-39
lines changed

23 files changed

+101
-39
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
@@ -1338,8 +1338,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
13381338
} else {
13391339
hir::IsAsync::NotAsync
13401340
};
1341+
1342+
let safety = self.lower_safety(h.safety, default_safety);
1343+
let safety = safety.into();
1344+
13411345
hir::FnHeader {
1342-
safety: self.lower_safety(h.safety, default_safety),
1346+
safety,
13431347
asyncness,
13441348
constness: self.lower_constness(h.constness),
13451349
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
@@ -3720,9 +3720,20 @@ impl fmt::Display for Constness {
37203720
}
37213721
}
37223722

3723+
#[derive(Copy, Clone, Debug, HashStable_Generic, PartialEq, Eq)]
3724+
pub enum HeaderSafety {
3725+
Normal(Safety),
3726+
}
3727+
3728+
impl From<Safety> for HeaderSafety {
3729+
fn from(v: Safety) -> Self {
3730+
Self::Normal(v)
3731+
}
3732+
}
3733+
37233734
#[derive(Copy, Clone, Debug, HashStable_Generic)]
37243735
pub struct FnHeader {
3725-
pub safety: Safety,
3736+
pub safety: HeaderSafety,
37263737
pub constness: Constness,
37273738
pub asyncness: IsAsync,
37283739
pub abi: ExternAbi,
@@ -3738,7 +3749,17 @@ impl FnHeader {
37383749
}
37393750

37403751
pub fn is_unsafe(&self) -> bool {
3741-
self.safety.is_unsafe()
3752+
self.safety().is_unsafe()
3753+
}
3754+
3755+
pub fn is_safe(&self) -> bool {
3756+
self.safety().is_safe()
3757+
}
3758+
3759+
pub fn safety(&self) -> Safety {
3760+
match self.safety {
3761+
HeaderSafety::Normal(safety) => safety,
3762+
}
37423763
}
37433764
}
37443765

compiler/rustc_hir_analysis/src/collect.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1349,7 +1349,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFn
13491349
{
13501350
icx.lowerer().lower_fn_ty(
13511351
hir_id,
1352-
sig.header.safety,
1352+
sig.header.safety(),
13531353
sig.header.abi,
13541354
sig.decl,
13551355
Some(generics),
@@ -1364,13 +1364,18 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFn
13641364
kind: TraitItemKind::Fn(FnSig { header, decl, span: _ }, _),
13651365
generics,
13661366
..
1367-
}) => {
1368-
icx.lowerer().lower_fn_ty(hir_id, header.safety, header.abi, decl, Some(generics), None)
1369-
}
1367+
}) => icx.lowerer().lower_fn_ty(
1368+
hir_id,
1369+
header.safety(),
1370+
header.abi,
1371+
decl,
1372+
Some(generics),
1373+
None,
1374+
),
13701375

13711376
ForeignItem(&hir::ForeignItem { kind: ForeignItemKind::Fn(sig, _, _), .. }) => {
13721377
let abi = tcx.hir().get_foreign_abi(hir_id);
1373-
compute_sig_of_foreign_fn_decl(tcx, def_id, sig.decl, abi, sig.header.safety)
1378+
compute_sig_of_foreign_fn_decl(tcx, def_id, sig.decl, abi, sig.header.safety())
13741379
}
13751380

13761381
Ctor(data) | Variant(hir::Variant { data, .. }) if data.ctor().is_some() => {
@@ -1418,7 +1423,7 @@ fn lower_fn_sig_recovering_infer_ret_ty<'tcx>(
14181423

14191424
icx.lowerer().lower_fn_ty(
14201425
icx.tcx().local_def_id_to_hir_id(def_id),
1421-
sig.header.safety,
1426+
sig.header.safety(),
14221427
sig.header.abi,
14231428
sig.decl,
14241429
Some(generics),

compiler/rustc_hir_pretty/src/lib.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2385,7 +2385,7 @@ impl<'a> State<'a> {
23852385
self.print_fn(
23862386
decl,
23872387
hir::FnHeader {
2388-
safety,
2388+
safety: safety.into(),
23892389
abi,
23902390
constness: hir::Constness::NotConst,
23912391
asyncness: hir::IsAsync::NotAsync,
@@ -2401,12 +2401,16 @@ impl<'a> State<'a> {
24012401
fn print_fn_header_info(&mut self, header: hir::FnHeader) {
24022402
self.print_constness(header.constness);
24032403

2404+
let safety = match header.safety {
2405+
hir::HeaderSafety::Normal(safety) => safety,
2406+
};
2407+
24042408
match header.asyncness {
24052409
hir::IsAsync::NotAsync => {}
24062410
hir::IsAsync::Async(_) => self.word_nbsp("async"),
24072411
}
24082412

2409-
self.print_safety(header.safety);
2413+
self.print_safety(safety);
24102414

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

compiler/rustc_hir_typeck/src/coercion.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -923,10 +923,12 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
923923
return Err(TypeError::IntrinsicCast);
924924
}
925925

926-
// Safe `#[target_feature]` functions are not assignable to safe fn pointers (RFC 2396).
926+
// Safe `#[target_feature]` functions are not assignable to safe fn pointers (RFC 2396),
927+
// report a better error than a safety mismatch.
928+
// FIXME(target_feature): do this inside `coerce_from_safe_fn`
927929

928930
if b_hdr.safety.is_safe()
929-
&& !self.tcx.codegen_fn_attrs(def_id).target_features.is_empty()
931+
&& self.tcx.codegen_fn_attrs(def_id).safe_target_features
930932
{
931933
return Err(TypeError::TargetFeatureCast(def_id));
932934
}

compiler/rustc_hir_typeck/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ fn typeck_with_fallback<'tcx>(
151151

152152
if let Some(hir::FnSig { header, decl, .. }) = node.fn_sig() {
153153
let fn_sig = if decl.output.get_infer_ret_ty().is_some() {
154-
fcx.lowerer().lower_fn_ty(id, header.safety, header.abi, decl, None, None)
154+
fcx.lowerer().lower_fn_ty(id, header.safety(), header.abi, decl, None, None)
155155
} else {
156156
tcx.fn_sig(def_id).instantiate_identity()
157157
};

compiler/rustc_middle/src/middle/codegen_fn_attrs.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ pub struct CodegenFnAttrs {
2929
/// The `#[target_feature(enable = "...")]` attribute and the enabled
3030
/// features (only enabled features are supported right now).
3131
pub target_features: Vec<TargetFeature>,
32+
/// Whether the function was declared safe, but has target features
33+
pub safe_target_features: bool,
3234
/// The `#[linkage = "..."]` attribute on Rust-defined items and the value we found.
3335
pub linkage: Option<Linkage>,
3436
/// The `#[linkage = "..."]` attribute on foreign items and the value we found.
@@ -149,6 +151,7 @@ impl CodegenFnAttrs {
149151
link_name: None,
150152
link_ordinal: None,
151153
target_features: vec![],
154+
safe_target_features: false,
152155
linkage: None,
153156
import_linkage: None,
154157
link_section: None,

compiler/rustc_middle/src/ty/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ pub struct DelegationFnSig {
221221
pub param_count: usize,
222222
pub has_self: bool,
223223
pub c_variadic: bool,
224+
pub target_feature: bool,
224225
}
225226

226227
#[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)