Skip to content

Add some convenience helper methods on hir::Safety #134285

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Dec 15, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions compiler/rustc_codegen_ssa/src/codegen_attrs.rs
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@ use rustc_errors::{DiagMessage, SubdiagMessage, struct_span_code_err};
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId};
use rustc_hir::weak_lang_items::WEAK_LANG_ITEMS;
use rustc_hir::{self as hir, HirId, LangItem, lang_items};
use rustc_hir::{HirId, LangItem, lang_items};
use rustc_middle::middle::codegen_fn_attrs::{
CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry,
};
@@ -251,7 +251,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().safety() == hir::Safety::Safe
&& fn_sig.skip_binder().safety().is_safe()
{
if tcx.sess.target.is_like_wasm || tcx.sess.opts.actually_rustdoc {
// The `#[target_feature]` attribute is allowed on
5 changes: 2 additions & 3 deletions compiler/rustc_const_eval/src/const_eval/fn_queries.rs
Original file line number Diff line number Diff line change
@@ -53,9 +53,8 @@ fn is_promotable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
Some(stab) => {
if cfg!(debug_assertions) && stab.promotable {
let sig = tcx.fn_sig(def_id);
assert_eq!(
sig.skip_binder().safety(),
hir::Safety::Safe,
assert!(
sig.skip_binder().safety().is_safe(),
"don't mark const unsafe fns as promotable",
// https://github.com/rust-lang/rust/pull/53851#issuecomment-418760682
);
15 changes: 14 additions & 1 deletion compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
@@ -3401,6 +3401,19 @@ impl Safety {
Self::Safe => "",
}
}

#[inline]
pub fn is_unsafe(self) -> bool {
!self.is_safe()
}

#[inline]
pub fn is_safe(self) -> bool {
match self {
Self::Unsafe => false,
Self::Safe => true,
}
}
}

impl fmt::Display for Safety {
@@ -3445,7 +3458,7 @@ impl FnHeader {
}

pub fn is_unsafe(&self) -> bool {
matches!(&self.safety, Safety::Unsafe)
self.safety.is_unsafe()
}
}

4 changes: 2 additions & 2 deletions compiler/rustc_hir_analysis/src/check/check.rs
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@ use rustc_data_structures::unord::{UnordMap, UnordSet};
use rustc_errors::MultiSpan;
use rustc_errors::codes::*;
use rustc_hir::def::{CtorKind, DefKind};
use rustc_hir::{Node, Safety, intravisit};
use rustc_hir::{Node, intravisit};
use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt};
use rustc_infer::traits::{Obligation, ObligationCauseCode};
use rustc_lint_defs::builtin::{
@@ -161,7 +161,7 @@ fn check_unsafe_fields(tcx: TyCtxt<'_>, item_def_id: LocalDefId) {
};
let typing_env = ty::TypingEnv::non_body_analysis(tcx, item_def_id);
for field in def.all_fields() {
if field.safety != Safety::Unsafe {
if !field.safety.is_unsafe() {
continue;
}
let Ok(field_ty) = tcx.try_normalize_erasing_regions(typing_env, field.ty(tcx, args))
5 changes: 3 additions & 2 deletions compiler/rustc_hir_typeck/src/coercion.rs
Original file line number Diff line number Diff line change
@@ -863,7 +863,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
let outer_universe = self.infcx.universe();

let result = if let ty::FnPtr(_, hdr_b) = b.kind()
&& let (hir::Safety::Safe, hir::Safety::Unsafe) = (fn_ty_a.safety(), hdr_b.safety)
&& fn_ty_a.safety().is_safe()
&& hdr_b.safety.is_unsafe()
{
let unsafe_a = self.tcx.safe_to_unsafe_fn_ty(fn_ty_a);
self.unify_and(unsafe_a, b, to_unsafe)
@@ -925,7 +926,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {

// Safe `#[target_feature]` functions are not assignable to safe fn pointers (RFC 2396).

if b_hdr.safety == hir::Safety::Safe
if b_hdr.safety.is_safe()
&& !self.tcx.codegen_fn_attrs(def_id).target_features.is_empty()
{
return Err(TypeError::TargetFeatureCast(def_id));
6 changes: 3 additions & 3 deletions compiler/rustc_hir_typeck/src/fallback.rs
Original file line number Diff line number Diff line change
@@ -765,7 +765,7 @@ fn compute_unsafe_infer_vars<'a, 'tcx>(
if let Some(def_id) = typeck_results.type_dependent_def_id(ex.hir_id)
&& let method_ty = self.fcx.tcx.type_of(def_id).instantiate_identity()
&& let sig = method_ty.fn_sig(self.fcx.tcx)
&& let hir::Safety::Unsafe = sig.safety()
&& sig.safety().is_unsafe()
{
let mut collector = InferVarCollector {
value: (ex.hir_id, ex.span, UnsafeUseReason::Method),
@@ -785,7 +785,7 @@ fn compute_unsafe_infer_vars<'a, 'tcx>(

if func_ty.is_fn()
&& let sig = func_ty.fn_sig(self.fcx.tcx)
&& let hir::Safety::Unsafe = sig.safety()
&& sig.safety().is_unsafe()
{
let mut collector = InferVarCollector {
value: (ex.hir_id, ex.span, UnsafeUseReason::Call),
@@ -816,7 +816,7 @@ fn compute_unsafe_infer_vars<'a, 'tcx>(
// `is_fn` excludes closures, but those can't be unsafe.
if ty.is_fn()
&& let sig = ty.fn_sig(self.fcx.tcx)
&& let hir::Safety::Unsafe = sig.safety()
&& sig.safety().is_unsafe()
{
let mut collector = InferVarCollector {
value: (ex.hir_id, ex.span, UnsafeUseReason::Path),
6 changes: 3 additions & 3 deletions compiler/rustc_middle/src/ty/context.rs
Original file line number Diff line number Diff line change
@@ -586,7 +586,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
}

fn trait_is_unsafe(self, trait_def_id: Self::DefId) -> bool {
self.trait_def(trait_def_id).safety == hir::Safety::Unsafe
self.trait_def(trait_def_id).safety.is_unsafe()
}

fn is_impl_trait_in_trait(self, def_id: DefId) -> bool {
@@ -722,7 +722,7 @@ impl<'tcx> rustc_type_ir::inherent::Safety<TyCtxt<'tcx>> for hir::Safety {
}

fn is_safe(self) -> bool {
matches!(self, hir::Safety::Safe)
self.is_safe()
}

fn prefix_str(self) -> &'static str {
@@ -2521,7 +2521,7 @@ impl<'tcx> TyCtxt<'tcx> {
/// that is, a `fn` type that is equivalent in every way for being
/// unsafe.
pub fn safe_to_unsafe_fn_ty(self, sig: PolyFnSig<'tcx>) -> Ty<'tcx> {
assert_eq!(sig.safety(), hir::Safety::Safe);
assert!(sig.safety().is_safe());
Ty::new_fn_ptr(self, sig.map_bound(|sig| ty::FnSig { safety: hir::Safety::Unsafe, ..sig }))
}

4 changes: 2 additions & 2 deletions compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
@@ -33,9 +33,9 @@ use rustc_data_structures::intern::Interned;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::steal::Steal;
use rustc_errors::{Diag, ErrorGuaranteed, StashKey};
use rustc_hir::LangItem;
use rustc_hir::def::{CtorKind, CtorOf, DefKind, DocLinkResMap, LifetimeRes, Res};
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap};
use rustc_hir::{LangItem, Safety};
use rustc_index::IndexVec;
use rustc_macros::{
Decodable, Encodable, HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable,
@@ -1279,7 +1279,7 @@ impl VariantDef {

/// Returns whether this variant has unsafe fields.
pub fn has_unsafe_fields(&self) -> bool {
self.fields.iter().any(|x| x.safety == Safety::Unsafe)
self.fields.iter().any(|x| x.safety.is_unsafe())
}
}

2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/ty/util.rs
Original file line number Diff line number Diff line change
@@ -1291,7 +1291,7 @@ impl<'tcx> Ty<'tcx> {
/// Checks whether this type is an ADT that has unsafe fields.
pub fn has_unsafe_fields(self) -> bool {
if let ty::Adt(adt_def, ..) = self.kind() {
adt_def.all_fields().any(|x| x.safety == hir::Safety::Unsafe)
adt_def.all_fields().any(|x| x.safety.is_unsafe())
} else {
false
}
16 changes: 6 additions & 10 deletions compiler/rustc_mir_build/src/check_unsafety.rs
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@ use std::ops::Bound;

use rustc_errors::DiagArgValue;
use rustc_hir::def::DefKind;
use rustc_hir::{self as hir, BindingMode, ByRef, HirId, Mutability, Safety};
use rustc_hir::{self as hir, BindingMode, ByRef, HirId, Mutability};
use rustc_middle::middle::codegen_fn_attrs::TargetFeature;
use rustc_middle::mir::BorrowKind;
use rustc_middle::span_bug;
@@ -342,7 +342,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
PatKind::Leaf { subpatterns, .. } => {
if let ty::Adt(adt_def, ..) = pat.ty.kind() {
for pat in subpatterns {
if adt_def.non_enum_variant().fields[pat.field].safety == Safety::Unsafe {
if adt_def.non_enum_variant().fields[pat.field].safety.is_unsafe() {
self.requires_unsafe(pat.pattern.span, UseOfUnsafeField);
}
}
@@ -367,7 +367,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
PatKind::Variant { adt_def, args: _, variant_index, subpatterns } => {
for pat in subpatterns {
let field = &pat.field;
if adt_def.variant(*variant_index).fields[*field].safety == Safety::Unsafe {
if adt_def.variant(*variant_index).fields[*field].safety.is_unsafe() {
self.requires_unsafe(pat.pattern.span, UseOfUnsafeField);
}
}
@@ -479,7 +479,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
return; // don't visit the whole expression
}
ExprKind::Call { fun, ty: _, args: _, from_hir_call: _, fn_span: _ } => {
if self.thir[fun].ty.fn_sig(self.tcx).safety() == hir::Safety::Unsafe {
if self.thir[fun].ty.fn_sig(self.tcx).safety().is_unsafe() {
let func_id = if let ty::FnDef(func_id, _) = self.thir[fun].ty.kind() {
Some(*func_id)
} else {
@@ -623,7 +623,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
ExprKind::Field { lhs, variant_index, name } => {
let lhs = &self.thir[lhs];
if let ty::Adt(adt_def, _) = lhs.ty.kind() {
if adt_def.variant(variant_index).fields[name].safety == Safety::Unsafe {
if adt_def.variant(variant_index).fields[name].safety.is_unsafe() {
self.requires_unsafe(expr.span, UseOfUnsafeField);
} else if adt_def.is_union() {
if let Some(assigned_ty) = self.assignment_info {
@@ -1112,11 +1112,7 @@ pub(crate) fn check_unsafety(tcx: TyCtxt<'_>, def: LocalDefId) {

let hir_id = tcx.local_def_id_to_hir_id(def);
let safety_context = tcx.hir().fn_sig_by_hir_id(hir_id).map_or(SafetyContext::Safe, |fn_sig| {
if fn_sig.header.safety == hir::Safety::Unsafe {
SafetyContext::UnsafeFn
} else {
SafetyContext::Safe
}
if fn_sig.header.safety.is_unsafe() { SafetyContext::UnsafeFn } else { SafetyContext::Safe }
});
let body_target_features = &tcx.body_codegen_attrs(def.to_def_id()).target_features;
let mut warnings = Vec::new();
4 changes: 2 additions & 2 deletions compiler/rustc_passes/src/check_attr.rs
Original file line number Diff line number Diff line change
@@ -715,7 +715,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
attrs: &[Attribute],
) {
match target {
Target::Fn => {
Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent)
| Target::Fn => {
// `#[target_feature]` is not allowed in lang items.
if let Some((lang_item, _)) = hir::lang_items::extract(attrs)
// Calling functions with `#[target_feature]` is
@@ -732,7 +733,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
});
}
}
Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => {}
// FIXME: #[target_feature] was previously erroneously allowed on statements and some
// crates used this, so only emit a warning.
Target::Statement => {
2 changes: 1 addition & 1 deletion compiler/rustc_symbol_mangling/src/v0.rs
Original file line number Diff line number Diff line change
@@ -439,7 +439,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
let sig = sig_tys.with(hdr);
self.push("F");
self.in_binder(&sig, |cx, sig| {
if sig.safety == hir::Safety::Unsafe {
if sig.safety.is_unsafe() {
cx.push("U");
}
match sig.abi {
2 changes: 1 addition & 1 deletion compiler/rustc_trait_selection/src/traits/misc.rs
Original file line number Diff line number Diff line change
@@ -84,7 +84,7 @@ pub fn type_allowed_to_implement_copy<'tcx>(
return Err(CopyImplementationError::HasDestructor);
}

if impl_safety == hir::Safety::Safe && self_type.has_unsafe_fields() {
if impl_safety.is_safe() && self_type.has_unsafe_fields() {
return Err(CopyImplementationError::HasUnsafeFields);
}

5 changes: 1 addition & 4 deletions src/librustdoc/html/format.rs
Original file line number Diff line number Diff line change
@@ -1626,10 +1626,7 @@ pub(crate) trait PrintWithSpace {

impl PrintWithSpace for hir::Safety {
fn print_with_space(&self) -> &str {
match self {
hir::Safety::Unsafe => "unsafe ",
hir::Safety::Safe => "",
}
self.prefix_str()
}
}

6 changes: 2 additions & 4 deletions src/librustdoc/html/render/print_item.rs
Original file line number Diff line number Diff line change
@@ -469,7 +469,7 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl

let unsafety_flag = match myitem.kind {
clean::FunctionItem(_) | clean::ForeignFunctionItem(..)
if myitem.fn_header(tcx).unwrap().safety == hir::Safety::Unsafe =>
if myitem.fn_header(tcx).unwrap().safety.is_unsafe() =>
{
"<sup title=\"unsafe function\">⚠</sup>"
}
@@ -1926,9 +1926,7 @@ fn item_static(
buffer,
"{vis}{safe}static {mutability}{name}: {typ}",
vis = visibility_print_with_space(it, cx),
safe = safety
.map(|safe| if safe == hir::Safety::Unsafe { "unsafe " } else { "" })
.unwrap_or(""),
safe = safety.map(|safe| safe.prefix_str()).unwrap_or(""),
mutability = s.mutability.print_with_space(),
name = it.name.unwrap(),
typ = s.type_.print(cx)
8 changes: 4 additions & 4 deletions src/librustdoc/json/conversions.rs
Original file line number Diff line number Diff line change
@@ -639,7 +639,7 @@ impl FromClean<clean::BareFunctionDecl> for FunctionPointer {
let clean::BareFunctionDecl { safety, generic_params, decl, abi } = bare_decl;
FunctionPointer {
header: FunctionHeader {
is_unsafe: matches!(safety, rustc_hir::Safety::Unsafe),
is_unsafe: safety.is_unsafe(),
is_const: false,
is_async: false,
abi: convert_abi(abi),
@@ -669,7 +669,7 @@ impl FromClean<clean::Trait> for Trait {
fn from_clean(trait_: clean::Trait, renderer: &JsonRenderer<'_>) -> Self {
let tcx = renderer.tcx;
let is_auto = trait_.is_auto(tcx);
let is_unsafe = trait_.safety(tcx) == rustc_hir::Safety::Unsafe;
let is_unsafe = trait_.safety(tcx).is_unsafe();
let is_dyn_compatible = trait_.is_dyn_compatible(tcx);
let clean::Trait { items, generics, bounds, .. } = trait_;
Trait {
@@ -711,7 +711,7 @@ impl FromClean<clean::Impl> for Impl {
ty::ImplPolarity::Negative => true,
};
Impl {
is_unsafe: safety == rustc_hir::Safety::Unsafe,
is_unsafe: safety.is_unsafe(),
generics: generics.into_json(renderer),
provided_trait_methods: provided_trait_methods
.into_iter()
@@ -840,7 +840,7 @@ fn convert_static(
Static {
type_: (*stat.type_).into_json(renderer),
is_mutable: stat.mutability == ast::Mutability::Mut,
is_unsafe: safety == rustc_hir::Safety::Unsafe,
is_unsafe: safety.is_unsafe(),
expr: stat
.expr
.map(|e| rendered_const(tcx, tcx.hir().body(e), tcx.hir().body_owner_def_id(e)))
4 changes: 2 additions & 2 deletions src/tools/clippy/clippy_lints/src/derive.rs
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@ use rustc_errors::Applicability;
use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::{FnKind, Visitor, walk_expr, walk_fn, walk_item};
use rustc_hir::{
self as hir, BlockCheckMode, BodyId, Expr, ExprKind, FnDecl, Impl, Item, ItemKind, Safety, UnsafeSource,
self as hir, BlockCheckMode, BodyId, Expr, ExprKind, FnDecl, Impl, Item, ItemKind, UnsafeSource,
};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::hir::nested_filter;
@@ -421,7 +421,7 @@ impl<'tcx> Visitor<'tcx> for UnsafeVisitor<'_, 'tcx> {
id: LocalDefId,
) -> Self::Result {
if let Some(header) = kind.header()
&& header.safety == Safety::Unsafe
&& header.safety.is_unsafe()
{
ControlFlow::Break(())
} else {
2 changes: 1 addition & 1 deletion src/tools/clippy/clippy_lints/src/eta_reduction.rs
Original file line number Diff line number Diff line change
@@ -281,7 +281,7 @@ fn check_inputs(
}

fn check_sig<'tcx>(closure_sig: FnSig<'tcx>, call_sig: FnSig<'tcx>) -> bool {
call_sig.safety == Safety::Safe && !has_late_bound_to_non_late_bound_regions(closure_sig, call_sig)
call_sig.safety.is_safe() && !has_late_bound_to_non_late_bound_regions(closure_sig, call_sig)
}

/// This walks through both signatures and checks for any time a late-bound region is expected by an
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::snippet;
use rustc_errors::Applicability;
use rustc_hir::intravisit::FnKind;
use rustc_hir::{Body, ExprKind, FnDecl, ImplicitSelfKind, Safety};
use rustc_hir::{Body, ExprKind, FnDecl, ImplicitSelfKind};
use rustc_lint::LateContext;
use rustc_middle::ty;
use rustc_span::Span;
@@ -34,7 +34,7 @@ pub fn check_fn(cx: &LateContext<'_>, kind: FnKind<'_>, decl: &FnDecl<'_>, body:
ImplicitSelfKind::None => return,
};

let name = if sig.header.safety == Safety::Unsafe {
let name = if sig.header.safety.is_unsafe() {
name.strip_suffix("_unchecked").unwrap_or(name)
} else {
name
Loading