Skip to content

Commit

Permalink
Add new fn safety enum for functions
Browse files Browse the repository at this point in the history
  • Loading branch information
spastorino committed Apr 27, 2024
1 parent aed2187 commit 0a2dee6
Show file tree
Hide file tree
Showing 62 changed files with 297 additions and 204 deletions.
19 changes: 13 additions & 6 deletions compiler/rustc_ast/src/ast.rs
Expand Up @@ -2099,7 +2099,7 @@ impl Ty {

#[derive(Clone, Encodable, Decodable, Debug)]
pub struct BareFnTy {
pub unsafety: Unsafe,
pub safety: FnSafety,
pub ext: Extern,
pub generic_params: ThinVec<GenericParam>,
pub decl: P<FnDecl>,
Expand Down Expand Up @@ -2485,6 +2485,13 @@ pub enum Unsafe {
No,
}

#[derive(Copy, Clone, PartialEq, Eq, Hash, Encodable, Decodable, Debug)]
#[derive(HashStable_Generic)]
pub enum FnSafety {
Unsafe(Span),
Default,
}

/// Describes what kind of coroutine markers, if any, a function has.
///
/// Coroutine markers are things that cause the function to generate a coroutine, such as `async`,
Expand Down Expand Up @@ -3001,8 +3008,8 @@ impl Extern {
/// included in this struct (e.g., `async unsafe fn` or `const extern "C" fn`).
#[derive(Clone, Copy, Encodable, Decodable, Debug)]
pub struct FnHeader {
/// The `unsafe` keyword, if any
pub unsafety: Unsafe,
/// The safety keyword, if any
pub safety: FnSafety,
/// Whether this is `async`, `gen`, or nothing.
pub coroutine_kind: Option<CoroutineKind>,
/// The `const` keyword, if any
Expand All @@ -3014,8 +3021,8 @@ pub struct FnHeader {
impl FnHeader {
/// Does this function header have any qualifiers or is it empty?
pub fn has_qualifiers(&self) -> bool {
let Self { unsafety, coroutine_kind, constness, ext } = self;
matches!(unsafety, Unsafe::Yes(_))
let Self { safety, coroutine_kind, constness, ext } = self;
matches!(safety, FnSafety::Unsafe(_))
|| coroutine_kind.is_some()
|| matches!(constness, Const::Yes(_))
|| !matches!(ext, Extern::None)
Expand All @@ -3025,7 +3032,7 @@ impl FnHeader {
impl Default for FnHeader {
fn default() -> FnHeader {
FnHeader {
unsafety: Unsafe::No,
safety: FnSafety::Default,
coroutine_kind: None,
constness: Const::No,
ext: Extern::None,
Expand Down
15 changes: 11 additions & 4 deletions compiler/rustc_ast/src/mut_visit.rs
Expand Up @@ -499,8 +499,8 @@ pub fn noop_visit_ty<T: MutVisitor>(ty: &mut P<Ty>, vis: &mut T) {
vis.visit_mt(mt);
}
TyKind::BareFn(bft) => {
let BareFnTy { unsafety, ext: _, generic_params, decl, decl_span } = bft.deref_mut();
visit_unsafety(unsafety, vis);
let BareFnTy { safety, ext: _, generic_params, decl, decl_span } = bft.deref_mut();
visit_fn_safety(safety, vis);
generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param));
vis.visit_fn_decl(decl);
vis.visit_span(decl_span);
Expand Down Expand Up @@ -864,6 +864,13 @@ fn visit_unsafety<T: MutVisitor>(unsafety: &mut Unsafe, vis: &mut T) {
}
}

fn visit_fn_safety<T: MutVisitor>(safety: &mut FnSafety, vis: &mut T) {
match safety {
FnSafety::Unsafe(span) => vis.visit_span(span),
FnSafety::Default => {}
}
}

// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
fn visit_polarity<T: MutVisitor>(polarity: &mut ImplPolarity, vis: &mut T) {
match polarity {
Expand Down Expand Up @@ -1226,10 +1233,10 @@ fn visit_const_item<T: MutVisitor>(
}

fn noop_visit_fn_header<T: MutVisitor>(header: &mut FnHeader, vis: &mut T) {
let FnHeader { unsafety, coroutine_kind, constness, ext: _ } = header;
let FnHeader { safety, coroutine_kind, constness, ext: _ } = header;
visit_constness(constness, vis);
coroutine_kind.as_mut().map(|coroutine_kind| vis.visit_coroutine_kind(coroutine_kind));
visit_unsafety(unsafety, vis);
visit_fn_safety(safety, vis);
}

pub fn noop_visit_crate<T: MutVisitor>(krate: &mut Crate, vis: &mut T) {
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_ast_lowering/src/delegation.rs
Expand Up @@ -188,7 +188,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
Asyncness::No => hir::IsAsync::NotAsync,
};
hir::FnHeader {
unsafety: sig.unsafety,
safety: sig.safety,
constness: self.tcx.constness(sig_id),
asyncness,
abi: sig.abi,
Expand Down Expand Up @@ -341,7 +341,7 @@ impl<'hir> LoweringContext<'_, 'hir> {

fn generate_header_error(&self) -> hir::FnHeader {
hir::FnHeader {
unsafety: hir::Unsafety::Normal,
safety: hir::FnSafety::Default,
constness: hir::Constness::NotConst,
asyncness: hir::IsAsync::NotAsync,
abi: abi::Abi::Rust,
Expand Down
9 changes: 8 additions & 1 deletion compiler/rustc_ast_lowering/src/item.rs
Expand Up @@ -1351,7 +1351,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
hir::IsAsync::NotAsync
};
hir::FnHeader {
unsafety: self.lower_unsafety(h.unsafety),
safety: self.lower_fn_safety(h.safety),
asyncness: asyncness,
constness: self.lower_constness(h.constness),
abi: self.lower_extern(h.ext),
Expand Down Expand Up @@ -1408,6 +1408,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
}

pub(super) fn lower_fn_safety(&mut self, u: FnSafety) -> hir::FnSafety {
match u {
FnSafety::Unsafe(_) => hir::FnSafety::Unsafe,
FnSafety::Default => hir::FnSafety::Default,
}
}

/// Return the pair of the lowered `generics` as `hir::Generics` and the evaluation of `f` with
/// the carried impl trait definitions and bounds.
#[instrument(level = "debug", skip(self, f))]
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_ast_lowering/src/lib.rs
Expand Up @@ -1324,7 +1324,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let generic_params = self.lower_lifetime_binder(t.id, &f.generic_params);
hir::TyKind::BareFn(self.arena.alloc(hir::BareFnTy {
generic_params,
unsafety: self.lower_unsafety(f.unsafety),
safety: self.lower_fn_safety(f.safety),
abi: self.lower_extern(f.ext),
decl: self.lower_fn_decl(&f.decl, t.id, t.span, FnDeclKind::Pointer, None),
param_names: self.lower_fn_params_to_names(&f.decl),
Expand Down
10 changes: 5 additions & 5 deletions compiler/rustc_ast_passes/src/ast_validation.rs
Expand Up @@ -521,17 +521,17 @@ impl<'a> AstValidator<'a> {
fn check_foreign_fn_headerless(
&self,
// Deconstruct to ensure exhaustiveness
FnHeader { unsafety, coroutine_kind, constness, ext }: FnHeader,
FnHeader { safety, coroutine_kind, constness, ext }: FnHeader,
) {
let report_err = |span| {
self.dcx().emit_err(errors::FnQualifierInExtern {
span: span,
block: self.current_extern_span(),
});
};
match unsafety {
Unsafe::Yes(span) => report_err(span),
Unsafe::No => (),
match safety {
FnSafety::Unsafe(span) => report_err(span),
FnSafety::Default => (),
}
match coroutine_kind {
Some(knd) => report_err(knd.span()),
Expand Down Expand Up @@ -592,7 +592,7 @@ impl<'a> AstValidator<'a> {
(Some(FnCtxt::Free), Some(header)) => match header.ext {
Extern::Explicit(StrLit { symbol_unescaped: sym::C, .. }, _)
| Extern::Implicit(_)
if matches!(header.unsafety, Unsafe::Yes(_)) =>
if matches!(header.safety, FnSafety::Unsafe(_)) =>
{
return;
}
Expand Down
15 changes: 11 additions & 4 deletions compiler/rustc_ast_pretty/src/pprust/state.rs
Expand Up @@ -1138,7 +1138,7 @@ impl<'a> State<'a> {
self.pclose();
}
ast::TyKind::BareFn(f) => {
self.print_ty_fn(f.ext, f.unsafety, &f.decl, None, &f.generic_params);
self.print_ty_fn(f.ext, f.safety, &f.decl, None, &f.generic_params);
}
ast::TyKind::Path(None, path) => {
self.print_path(path, false, 0);
Expand Down Expand Up @@ -1892,7 +1892,7 @@ impl<'a> State<'a> {
fn print_ty_fn(
&mut self,
ext: ast::Extern,
unsafety: ast::Unsafe,
safety: ast::FnSafety,
decl: &ast::FnDecl,
name: Option<Ident>,
generic_params: &[ast::GenericParam],
Expand All @@ -1908,15 +1908,15 @@ impl<'a> State<'a> {
},
span: DUMMY_SP,
};
let header = ast::FnHeader { unsafety, ext, ..ast::FnHeader::default() };
let header = ast::FnHeader { safety, ext, ..ast::FnHeader::default() };
self.print_fn(decl, header, name, &generics);
self.end();
}

fn print_fn_header_info(&mut self, header: ast::FnHeader) {
self.print_constness(header.constness);
header.coroutine_kind.map(|coroutine_kind| self.print_coroutine_kind(coroutine_kind));
self.print_unsafety(header.unsafety);
self.print_fn_safety(header.safety);

match header.ext {
ast::Extern::None => {}
Expand All @@ -1940,6 +1940,13 @@ impl<'a> State<'a> {
}
}

fn print_fn_safety(&mut self, s: ast::FnSafety) {
match s {
ast::FnSafety::Default => {}
ast::FnSafety::Unsafe(_) => self.word_nbsp("unsafe"),
}
}

fn print_constness(&mut self, s: ast::Const) {
match s {
ast::Const::No => {}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_borrowck/src/diagnostics/region_errors.rs
Expand Up @@ -1097,7 +1097,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
liberated_sig.inputs().iter().copied(),
peeled_ty,
liberated_sig.c_variadic,
hir::Unsafety::Normal,
hir::FnSafety::Default,
rustc_target::spec::abi::Abi::Rust,
)),
);
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_borrowck/src/type_check/input_output.rs
Expand Up @@ -101,7 +101,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
user_provided_sig.inputs().iter().copied(),
output_ty,
user_provided_sig.c_variadic,
user_provided_sig.unsafety,
user_provided_sig.safety,
user_provided_sig.abi,
);
}
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_borrowck/src/type_check/mod.rs
Expand Up @@ -2063,13 +2063,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
}
}

CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(unsafety)) => {
CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(safety)) => {
let sig = match op.ty(body, tcx).kind() {
ty::Closure(_, args) => args.as_closure().sig(),
_ => bug!(),
};
let ty_fn_ptr_from =
Ty::new_fn_ptr(tcx, tcx.signature_unclosure(sig, *unsafety));
Ty::new_fn_ptr(tcx, tcx.signature_unclosure(sig, *safety));

if let Err(terr) = self.eq_types(
*ty,
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_builtin_macros/src/alloc_error_handler.rs
Expand Up @@ -3,7 +3,7 @@ use crate::util::check_builtin_macro_attribute;

use rustc_ast::ptr::P;
use rustc_ast::{self as ast, FnHeader, FnSig, Generics, StmtKind};
use rustc_ast::{Fn, ItemKind, Stmt, TyKind, Unsafe};
use rustc_ast::{Fn, FnSafety, ItemKind, Stmt, TyKind};
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::Span;
Expand Down Expand Up @@ -78,7 +78,7 @@ fn generate_handler(cx: &ExtCtxt<'_>, handler: Ident, span: Span, sig_span: Span
let never = ast::FnRetTy::Ty(cx.ty(span, TyKind::Never));
let params = thin_vec![cx.param(span, size, ty_usize.clone()), cx.param(span, align, ty_usize)];
let decl = cx.fn_decl(params, never);
let header = FnHeader { unsafety: Unsafe::Yes(span), ..FnHeader::default() };
let header = FnHeader { safety: FnSafety::Unsafe(span), ..FnHeader::default() };
let sig = FnSig { decl, header, span: span };

let body = Some(cx.block_expr(call));
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_builtin_macros/src/global_allocator.rs
Expand Up @@ -6,7 +6,7 @@ use rustc_ast::expand::allocator::{
};
use rustc_ast::ptr::P;
use rustc_ast::{self as ast, AttrVec, Expr, FnHeader, FnSig, Generics, Param, StmtKind};
use rustc_ast::{Fn, ItemKind, Mutability, Stmt, Ty, TyKind, Unsafe};
use rustc_ast::{Fn, FnSafety, ItemKind, Mutability, Stmt, Ty, TyKind};
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::Span;
Expand Down Expand Up @@ -73,7 +73,7 @@ impl AllocFnFactory<'_, '_> {
let result = self.call_allocator(method.name, args);
let output_ty = self.ret_ty(&method.output);
let decl = self.cx.fn_decl(abi_args, ast::FnRetTy::Ty(output_ty));
let header = FnHeader { unsafety: Unsafe::Yes(self.span), ..FnHeader::default() };
let header = FnHeader { safety: FnSafety::Unsafe(self.span), ..FnHeader::default() };
let sig = FnSig { decl, header, span: self.span };
let body = Some(self.cx.block_expr(result));
let kind = ItemKind::Fn(Box::new(Fn {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_builtin_macros/src/test.rs
Expand Up @@ -548,7 +548,7 @@ fn check_test_signature(
let has_should_panic_attr = attr::contains_name(&i.attrs, sym::should_panic);
let dcx = cx.dcx();

if let ast::Unsafe::Yes(span) = f.sig.header.unsafety {
if let ast::FnSafety::Unsafe(span) = f.sig.header.safety {
return Err(dcx.emit_err(errors::TestBadFn { span: i.span, cause: span, kind: "unsafe" }));
}

Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_codegen_llvm/src/intrinsic.rs
Expand Up @@ -986,7 +986,7 @@ fn get_rust_try_fn<'ll, 'tcx>(
[i8p],
Ty::new_unit(tcx),
false,
hir::Unsafety::Unsafe,
hir::FnSafety::Unsafe,
Abi::Rust,
)),
);
Expand All @@ -997,7 +997,7 @@ fn get_rust_try_fn<'ll, 'tcx>(
[i8p, i8p],
Ty::new_unit(tcx),
false,
hir::Unsafety::Unsafe,
hir::FnSafety::Unsafe,
Abi::Rust,
)),
);
Expand All @@ -1006,7 +1006,7 @@ fn get_rust_try_fn<'ll, 'tcx>(
[try_fn_ty, i8p, catch_fn_ty],
tcx.types.i32,
false,
hir::Unsafety::Unsafe,
hir::FnSafety::Unsafe,
Abi::Rust,
));
let rust_try = gen_fn(cx, "__rust_try", rust_fn_sig, codegen);
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_ssa/src/codegen_attrs.rs
Expand Up @@ -276,7 +276,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
sym::target_feature => {
if !tcx.is_closure_like(did.to_def_id())
&& let Some(fn_sig) = fn_sig()
&& fn_sig.skip_binder().unsafety() == hir::Unsafety::Normal
&& fn_sig.skip_binder().safety() == hir::FnSafety::Default
{
if tcx.sess.target.is_like_wasm || tcx.sess.opts.actually_rustdoc {
// The `#[target_feature]` attribute is allowed on
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
Expand Up @@ -364,7 +364,7 @@ fn push_debuginfo_type_name<'tcx>(
}
output.push_str(" (*)(");
} else {
output.push_str(sig.unsafety.prefix_str());
output.push_str(sig.safety.prefix_str());

if sig.abi != rustc_target::spec::abi::Abi::Rust {
output.push_str("extern \"");
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_const_eval/src/const_eval/fn_queries.rs
Expand Up @@ -81,8 +81,8 @@ fn is_promotable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
if cfg!(debug_assertions) && stab.promotable {
let sig = tcx.fn_sig(def_id);
assert_eq!(
sig.skip_binder().unsafety(),
hir::Unsafety::Normal,
sig.skip_binder().safety(),
hir::FnSafety::Default,
"don't mark const unsafe fns as promotable",
// https://github.com/rust-lang/rust/pull/53851#issuecomment-418760682
);
Expand Down

0 comments on commit 0a2dee6

Please sign in to comment.