From 3a64bef2ba54542d3440634602e088c2597d9ed2 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 13 Dec 2024 12:16:26 +0000 Subject: [PATCH 1/3] Also forbid target_feature annotated methods from being lang items --- compiler/rustc_passes/src/check_attr.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 074fe77324faf..a400fa6752a6e 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -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 => { From 8a4e5d7444c4d43097c2ca0d1b8e64be9dbeddfa Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 13 Dec 2024 12:19:46 +0000 Subject: [PATCH 2/3] Add some convenience helper methods on `hir::Safety` --- compiler/rustc_codegen_ssa/src/codegen_attrs.rs | 4 ++-- .../src/const_eval/fn_queries.rs | 5 ++--- compiler/rustc_hir/src/hir.rs | 15 ++++++++++++++- compiler/rustc_hir_analysis/src/check/check.rs | 4 ++-- compiler/rustc_hir_typeck/src/coercion.rs | 5 +++-- compiler/rustc_hir_typeck/src/fallback.rs | 6 +++--- compiler/rustc_middle/src/ty/context.rs | 6 +++--- compiler/rustc_middle/src/ty/mod.rs | 4 ++-- compiler/rustc_middle/src/ty/util.rs | 2 +- compiler/rustc_mir_build/src/check_unsafety.rs | 16 ++++++---------- compiler/rustc_symbol_mangling/src/v0.rs | 2 +- .../rustc_trait_selection/src/traits/misc.rs | 2 +- src/librustdoc/html/format.rs | 5 +---- src/librustdoc/html/render/print_item.rs | 6 ++---- src/librustdoc/json/conversions.rs | 8 ++++---- src/tools/clippy/clippy_lints/src/derive.rs | 4 ++-- .../clippy/clippy_lints/src/eta_reduction.rs | 2 +- .../src/functions/misnamed_getters.rs | 4 ++-- .../src/functions/not_unsafe_ptr_arg_deref.rs | 4 ++-- .../clippy_lints/src/inherent_to_string.rs | 4 ++-- .../src/multiple_unsafe_ops_per_block.rs | 6 +++--- .../clippy_lints/src/new_without_default.rs | 2 +- src/tools/clippy/clippy_lints/src/ptr.rs | 4 ++-- .../src/undocumented_unsafe_blocks.rs | 4 ++-- .../clippy/clippy_utils/src/check_proc_macro.rs | 2 +- src/tools/clippy/clippy_utils/src/ty.rs | 4 ++-- src/tools/clippy/clippy_utils/src/visitors.rs | 10 +++++----- 27 files changed, 72 insertions(+), 68 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 11744eabab0da..658a7f00b19df 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -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 diff --git a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs index beff0cd99fc47..3de4c21c356b4 100644 --- a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs @@ -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 ); diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 365e4cbb55676..b6cdf224fb26b 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -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() } } diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 022a6d457ec56..8ff94fa566d70 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -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)) diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index bf41dcbe4a365..7d7c9331edf00 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -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)); diff --git a/compiler/rustc_hir_typeck/src/fallback.rs b/compiler/rustc_hir_typeck/src/fallback.rs index ddd146fe785e3..64acff8c8bfe2 100644 --- a/compiler/rustc_hir_typeck/src/fallback.rs +++ b/compiler/rustc_hir_typeck/src/fallback.rs @@ -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), diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 2841470d24878..e382e63e2bdd2 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -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> 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 })) } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 70e0568b2025b..70d43abe8ed01 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -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()) } } diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index b9a45ea3c2c5a..270bb560c48d1 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -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 } diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index f37b3f977fa25..90be690e0345f 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -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(); diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 1a10ab8829cfb..2e1d85d15da3f 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -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 { diff --git a/compiler/rustc_trait_selection/src/traits/misc.rs b/compiler/rustc_trait_selection/src/traits/misc.rs index d216ae7291337..7a67b943e9494 100644 --- a/compiler/rustc_trait_selection/src/traits/misc.rs +++ b/compiler/rustc_trait_selection/src/traits/misc.rs @@ -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); } diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 0a563b1df2620..7d40f662ed09f 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -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() } } diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 4c8d704e65bc1..ced9ff2d68542 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -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() => { "" } @@ -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) diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index bb967b7f163ed..be39984c3da36 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -639,7 +639,7 @@ impl FromClean 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 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 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))) diff --git a/src/tools/clippy/clippy_lints/src/derive.rs b/src/tools/clippy/clippy_lints/src/derive.rs index 8125dab8adf6a..f65edd3625308 100644 --- a/src/tools/clippy/clippy_lints/src/derive.rs +++ b/src/tools/clippy/clippy_lints/src/derive.rs @@ -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 { diff --git a/src/tools/clippy/clippy_lints/src/eta_reduction.rs b/src/tools/clippy/clippy_lints/src/eta_reduction.rs index 8c22e43349f62..2cd48ef98e52a 100644 --- a/src/tools/clippy/clippy_lints/src/eta_reduction.rs +++ b/src/tools/clippy/clippy_lints/src/eta_reduction.rs @@ -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 diff --git a/src/tools/clippy/clippy_lints/src/functions/misnamed_getters.rs b/src/tools/clippy/clippy_lints/src/functions/misnamed_getters.rs index 2cbc4b072341c..017571c38db6e 100644 --- a/src/tools/clippy/clippy_lints/src/functions/misnamed_getters.rs +++ b/src/tools/clippy/clippy_lints/src/functions/misnamed_getters.rs @@ -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 diff --git a/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs b/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs index 4986a311eba84..3ded8dc301271 100644 --- a/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs +++ b/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs @@ -42,7 +42,7 @@ fn check_raw_ptr<'tcx>( body: &'tcx hir::Body<'tcx>, def_id: LocalDefId, ) { - if safety == hir::Safety::Safe && cx.effective_visibilities.is_exported(def_id) { + if safety.is_safe() && cx.effective_visibilities.is_exported(def_id) { let raw_ptrs = iter_input_pats(decl, body) .filter_map(|arg| raw_ptr_arg(cx, arg)) .collect::(); @@ -58,7 +58,7 @@ fn check_raw_ptr<'tcx>( }, hir::ExprKind::MethodCall(_, recv, args, _) => { let def_id = typeck.type_dependent_def_id(e.hir_id).unwrap(); - if cx.tcx.fn_sig(def_id).skip_binder().skip_binder().safety == hir::Safety::Unsafe { + if cx.tcx.fn_sig(def_id).skip_binder().skip_binder().safety.is_unsafe() { check_arg(cx, &raw_ptrs, recv); for arg in args { check_arg(cx, &raw_ptrs, arg); diff --git a/src/tools/clippy/clippy_lints/src/inherent_to_string.rs b/src/tools/clippy/clippy_lints/src/inherent_to_string.rs index ec6174bc0301a..e096dd2517593 100644 --- a/src/tools/clippy/clippy_lints/src/inherent_to_string.rs +++ b/src/tools/clippy/clippy_lints/src/inherent_to_string.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::ty::{implements_trait, is_type_lang_item}; use clippy_utils::{return_ty, trait_ref_of_method}; -use rustc_hir::{GenericParamKind, ImplItem, ImplItemKind, LangItem, Safety}; +use rustc_hir::{GenericParamKind, ImplItem, ImplItemKind, LangItem}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; use rustc_span::sym; @@ -95,7 +95,7 @@ impl<'tcx> LateLintPass<'tcx> for InherentToString { if let ImplItemKind::Fn(ref signature, _) = impl_item.kind // #11201 && let header = signature.header - && header.safety == Safety::Safe + && header.safety.is_safe() && header.abi == Abi::Rust && impl_item.ident.name == sym::to_string && let decl = signature.decl diff --git a/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs b/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs index 12bcc608174f2..79252bba74d72 100644 --- a/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs +++ b/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs @@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::visitors::{Descend, Visitable, for_each_expr}; use core::ops::ControlFlow::Continue; use hir::def::{DefKind, Res}; -use hir::{BlockCheckMode, ExprKind, QPath, Safety, UnOp}; +use hir::{BlockCheckMode, ExprKind, QPath, UnOp}; use rustc_ast::Mutability; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; @@ -133,7 +133,7 @@ fn collect_unsafe_exprs<'tcx>( ty::FnPtr(sig_tys, hdr) => sig_tys.with(hdr), _ => return Continue(Descend::Yes), }; - if sig.safety() == Safety::Unsafe { + if sig.safety().is_unsafe() { unsafe_ops.push(("unsafe function call occurs here", expr.span)); } }, @@ -144,7 +144,7 @@ fn collect_unsafe_exprs<'tcx>( .type_dependent_def_id(expr.hir_id) .map(|def_id| cx.tcx.fn_sig(def_id)) { - if sig.skip_binder().safety() == Safety::Unsafe { + if sig.skip_binder().safety().is_unsafe() { unsafe_ops.push(("unsafe method call occurs here", expr.span)); } } diff --git a/src/tools/clippy/clippy_lints/src/new_without_default.rs b/src/tools/clippy/clippy_lints/src/new_without_default.rs index b60fea3f03e0e..abdce69e76458 100644 --- a/src/tools/clippy/clippy_lints/src/new_without_default.rs +++ b/src/tools/clippy/clippy_lints/src/new_without_default.rs @@ -75,7 +75,7 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault { if let hir::ImplItemKind::Fn(ref sig, _) = impl_item.kind { let name = impl_item.ident.name; let id = impl_item.owner_id; - if sig.header.safety == hir::Safety::Unsafe { + if sig.header.safety.is_unsafe() { // can't be implemented for unsafe new return; } diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs index dec4c18a309ee..44a8789462b0f 100644 --- a/src/tools/clippy/clippy_lints/src/ptr.rs +++ b/src/tools/clippy/clippy_lints/src/ptr.rs @@ -8,7 +8,7 @@ use rustc_hir::hir_id::{HirId, HirIdMap}; use rustc_hir::intravisit::{Visitor, walk_expr}; use rustc_hir::{ self as hir, AnonConst, BinOpKind, BindingMode, Body, Expr, ExprKind, FnRetTy, FnSig, GenericArg, ImplItemKind, - ItemKind, Lifetime, Mutability, Node, Param, PatKind, QPath, Safety, TraitFn, TraitItem, TraitItemKind, TyKind, + ItemKind, Lifetime, Mutability, Node, Param, PatKind, QPath, TraitFn, TraitItem, TraitItemKind, TyKind, }; use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::traits::{Obligation, ObligationCause}; @@ -541,7 +541,7 @@ fn check_mut_from_ref<'tcx>(cx: &LateContext<'tcx>, sig: &FnSig<'_>, body: Optio .collect(); if let Some(args) = args && !args.is_empty() - && body.is_none_or(|body| sig.header.safety == Safety::Unsafe || contains_unsafe_block(cx, body.value)) + && body.is_none_or(|body| sig.header.safety.is_unsafe() || contains_unsafe_block(cx, body.value)) { span_lint_and_then( cx, diff --git a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs index b79e59f857bbf..45d730985bb1d 100644 --- a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs +++ b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs @@ -203,7 +203,7 @@ impl<'tcx> LateLintPass<'tcx> for UndocumentedUnsafeBlocks { let item_has_safety_comment = item_has_safety_comment(cx, item); match (&item.kind, item_has_safety_comment) { // lint unsafe impl without safety comment - (ItemKind::Impl(impl_), HasSafetyComment::No) if impl_.safety == hir::Safety::Unsafe => { + (ItemKind::Impl(impl_), HasSafetyComment::No) if impl_.safety.is_unsafe() => { if !is_lint_allowed(cx, UNDOCUMENTED_UNSAFE_BLOCKS, item.hir_id()) && !is_unsafe_from_proc_macro(cx, item.span) { @@ -227,7 +227,7 @@ impl<'tcx> LateLintPass<'tcx> for UndocumentedUnsafeBlocks { } }, // lint safe impl with unnecessary safety comment - (ItemKind::Impl(impl_), HasSafetyComment::Yes(pos)) if impl_.safety == hir::Safety::Safe => { + (ItemKind::Impl(impl_), HasSafetyComment::Yes(pos)) if impl_.safety.is_safe() => { if !is_lint_allowed(cx, UNNECESSARY_SAFETY_COMMENT, item.hir_id()) { let (span, help_span) = mk_spans(pos); diff --git a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs index 3269bf758ac0b..b71b53ea3bbfd 100644 --- a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs +++ b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs @@ -373,7 +373,7 @@ fn ty_search_pat(ty: &Ty<'_>) -> (Pat, Pat) { TyKind::Ptr(MutTy { ty, .. }) => (Pat::Str("*"), ty_search_pat(ty).1), TyKind::Ref(_, MutTy { ty, .. }) => (Pat::Str("&"), ty_search_pat(ty).1), TyKind::BareFn(bare_fn) => ( - if bare_fn.safety == Safety::Unsafe { + if bare_fn.safety.is_unsafe() { Pat::Str("unsafe") } else if bare_fn.abi != Abi::Rust { Pat::Str("extern") diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index 260d1b801e3d9..bc3c3ca5c2179 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -9,7 +9,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; use rustc_hir::def_id::DefId; -use rustc_hir::{Expr, FnDecl, LangItem, Safety, TyKind}; +use rustc_hir::{Expr, FnDecl, LangItem, TyKind}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::LateContext; use rustc_middle::mir::ConstValue; @@ -531,7 +531,7 @@ pub fn peel_mid_ty_refs_is_mutable(ty: Ty<'_>) -> (Ty<'_>, usize, Mutability) { /// Returns `true` if the given type is an `unsafe` function. pub fn type_is_unsafe_function<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { match ty.kind() { - ty::FnDef(..) | ty::FnPtr(..) => ty.fn_sig(cx.tcx).safety() == Safety::Unsafe, + ty::FnDef(..) | ty::FnPtr(..) => ty.fn_sig(cx.tcx).safety().is_unsafe(), _ => false, } } diff --git a/src/tools/clippy/clippy_utils/src/visitors.rs b/src/tools/clippy/clippy_utils/src/visitors.rs index 351e619d7b1e8..b3d998fbc5292 100644 --- a/src/tools/clippy/clippy_utils/src/visitors.rs +++ b/src/tools/clippy/clippy_utils/src/visitors.rs @@ -7,7 +7,7 @@ use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::intravisit::{self, Visitor, walk_block, walk_expr}; use rustc_hir::{ AnonConst, Arm, Block, BlockCheckMode, Body, BodyId, Expr, ExprKind, HirId, ItemId, ItemKind, LetExpr, Pat, QPath, - Safety, Stmt, UnOp, UnsafeSource, StructTailExpr, + Stmt, UnOp, UnsafeSource, StructTailExpr, }; use rustc_lint::LateContext; use rustc_middle::hir::nested_filter; @@ -426,15 +426,15 @@ pub fn is_expr_unsafe<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> bool { .cx .typeck_results() .type_dependent_def_id(e.hir_id) - .is_some_and(|id| self.cx.tcx.fn_sig(id).skip_binder().safety() == Safety::Unsafe) => + .is_some_and(|id| self.cx.tcx.fn_sig(id).skip_binder().safety().is_unsafe()) => { ControlFlow::Break(()) }, ExprKind::Call(func, _) => match *self.cx.typeck_results().expr_ty(func).peel_refs().kind() { - ty::FnDef(id, _) if self.cx.tcx.fn_sig(id).skip_binder().safety() == Safety::Unsafe => { + ty::FnDef(id, _) if self.cx.tcx.fn_sig(id).skip_binder().safety().is_unsafe() => { ControlFlow::Break(()) }, - ty::FnPtr(_, hdr) if hdr.safety == Safety::Unsafe => ControlFlow::Break(()), + ty::FnPtr(_, hdr) if hdr.safety.is_unsafe() => ControlFlow::Break(()), _ => walk_expr(self, e), }, ExprKind::Path(ref p) @@ -458,7 +458,7 @@ pub fn is_expr_unsafe<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> bool { } fn visit_nested_item(&mut self, id: ItemId) -> Self::Result { if let ItemKind::Impl(i) = &self.cx.tcx.hir().item(id).kind - && i.safety == Safety::Unsafe + && i.safety.is_unsafe() { ControlFlow::Break(()) } else { From 69bacc5a5d65981e733371817e4211dcab2445fb Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 13 Dec 2024 12:19:46 +0000 Subject: [PATCH 3/3] Treat safe target_feature functions as unsafe by default --- compiler/rustc_ast_lowering/src/delegation.rs | 10 +++++- compiler/rustc_ast_lowering/src/item.rs | 36 ++++++++++++++----- .../rustc_codegen_gcc/src/intrinsic/mod.rs | 6 ++-- compiler/rustc_codegen_llvm/src/intrinsic.rs | 6 ++-- .../rustc_codegen_ssa/src/codegen_attrs.rs | 6 ++-- compiler/rustc_hir/src/hir.rs | 16 ++++++--- .../rustc_hir_analysis/src/check/intrinsic.rs | 6 ++-- .../src/coherence/unsafety.rs | 12 +++---- compiler/rustc_hir_analysis/src/collect.rs | 2 +- compiler/rustc_hir_pretty/src/lib.rs | 4 +-- compiler/rustc_hir_typeck/src/coercion.rs | 11 ++++-- compiler/rustc_metadata/src/rmeta/table.rs | 15 +++++--- compiler/rustc_middle/src/ty/context.rs | 10 ++++-- compiler/rustc_middle/src/ty/mod.rs | 1 + .../rustc_mir_build/src/check_unsafety.rs | 10 ++++-- compiler/rustc_resolve/src/def_collector.rs | 4 ++- compiler/rustc_resolve/src/late.rs | 7 ++-- .../rustc_smir/src/rustc_internal/internal.rs | 2 +- .../rustc_smir/src/rustc_smir/convert/mod.rs | 2 +- .../traits/on_unimplemented.rs | 2 +- src/librustdoc/html/render/print_item.rs | 2 +- .../clippy_utils/src/check_proc_macro.rs | 4 +-- .../fn-exception-target-features.stderr | 5 +-- .../rfc-2396-target_feature-11/fn-ptr.stderr | 8 ++--- .../rfc-2396-target_feature-11/fn-traits.rs | 6 ++-- .../fn-traits.stderr | 27 +++++++------- .../safe-calls.stderr | 12 +++++++ .../rfc-2396-target_feature-11/trait-impl.rs | 1 + .../trait-impl.stderr | 19 ++++++++-- tests/ui/target-feature/invalid-attribute.rs | 4 +++ .../target-feature/invalid-attribute.stderr | 24 ++++++++++--- 31 files changed, 195 insertions(+), 85 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs index 70c94f4019ae2..7a5a10b7ae09d 100644 --- a/compiler/rustc_ast_lowering/src/delegation.rs +++ b/compiler/rustc_ast_lowering/src/delegation.rs @@ -189,7 +189,15 @@ impl<'hir> LoweringContext<'_, 'hir> { ) -> hir::FnSig<'hir> { let header = if let Some(local_sig_id) = sig_id.as_local() { match self.resolver.delegation_fn_sigs.get(&local_sig_id) { - Some(sig) => self.lower_fn_header(sig.header, hir::Safety::Safe), + Some(sig) => self.lower_fn_header( + sig.header, + if sig.target_feature && !matches!(sig.header.safety, Safety::Unsafe(_)) { + hir::Safety::Unsafe { target_feature: true } + } else { + hir::Safety::Safe + }, + &[], + ), None => self.generate_header_error(), } } else { diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 7d6c41992eb09..31678d041a3bb 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -231,7 +231,7 @@ impl<'hir> LoweringContext<'_, 'hir> { }); let sig = hir::FnSig { decl, - header: this.lower_fn_header(*header, hir::Safety::Safe), + header: this.lower_fn_header(*header, hir::Safety::Safe, attrs), span: this.lower_span(*fn_sig_span), }; hir::ItemKind::Fn(sig, generics, body_id) @@ -609,7 +609,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_foreign_item(&mut self, i: &ForeignItem) -> &'hir hir::ForeignItem<'hir> { let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id); let owner_id = hir_id.expect_owner(); - self.lower_attrs(hir_id, &i.attrs); + let attrs = self.lower_attrs(hir_id, &i.attrs); let item = hir::ForeignItem { owner_id, ident: self.lower_ident(i.ident), @@ -633,7 +633,11 @@ impl<'hir> LoweringContext<'_, 'hir> { }); // Unmarked safety in unsafe block defaults to unsafe. - let header = self.lower_fn_header(sig.header, hir::Safety::Unsafe); + let header = self.lower_fn_header( + sig.header, + hir::Safety::Unsafe { target_feature: false }, + attrs, + ); hir::ForeignItemKind::Fn( hir::FnSig { header, decl, span: self.lower_span(sig.span) }, @@ -644,7 +648,8 @@ impl<'hir> LoweringContext<'_, 'hir> { ForeignItemKind::Static(box StaticItem { ty, mutability, expr: _, safety }) => { let ty = self .lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::StaticTy)); - let safety = self.lower_safety(*safety, hir::Safety::Unsafe); + let safety = + self.lower_safety(*safety, hir::Safety::Unsafe { target_feature: false }); hir::ForeignItemKind::Static(ty, *mutability, safety) } @@ -748,7 +753,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> { let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id); - self.lower_attrs(hir_id, &i.attrs); + let attrs = self.lower_attrs(hir_id, &i.attrs); let trait_item_def_id = hir_id.expect_owner(); let (generics, kind, has_default) = match &i.kind { @@ -775,6 +780,7 @@ impl<'hir> LoweringContext<'_, 'hir> { i.id, FnDeclKind::Trait, sig.header.coroutine_kind, + attrs, ); (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)), false) } @@ -793,6 +799,7 @@ impl<'hir> LoweringContext<'_, 'hir> { i.id, FnDeclKind::Trait, sig.header.coroutine_kind, + attrs, ); (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)), true) } @@ -878,7 +885,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let has_value = true; let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value); let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id); - self.lower_attrs(hir_id, &i.attrs); + let attrs = self.lower_attrs(hir_id, &i.attrs); let (generics, kind) = match &i.kind { AssocItemKind::Const(box ConstItem { generics, ty, expr, .. }) => self.lower_generics( @@ -908,6 +915,7 @@ impl<'hir> LoweringContext<'_, 'hir> { i.id, if self.is_in_trait_impl { FnDeclKind::Impl } else { FnDeclKind::Inherent }, sig.header.coroutine_kind, + attrs, ); (generics, hir::ImplItemKind::Fn(sig, body_id)) @@ -1322,8 +1330,9 @@ impl<'hir> LoweringContext<'_, 'hir> { id: NodeId, kind: FnDeclKind, coroutine_kind: Option, + attrs: &[Attribute], ) -> (&'hir hir::Generics<'hir>, hir::FnSig<'hir>) { - let header = self.lower_fn_header(sig.header, hir::Safety::Safe); + let header = self.lower_fn_header(sig.header, hir::Safety::Safe, attrs); let itctx = ImplTraitContext::Universal; let (generics, decl) = self.lower_generics(generics, id, itctx, |this| { this.lower_fn_decl(&sig.decl, id, sig.span, kind, coroutine_kind) @@ -1335,12 +1344,23 @@ impl<'hir> LoweringContext<'_, 'hir> { &mut self, h: FnHeader, default_safety: hir::Safety, + attrs: &[Attribute], ) -> hir::FnHeader { let asyncness = if let Some(CoroutineKind::Async { span, .. }) = h.coroutine_kind { hir::IsAsync::Async(span) } else { hir::IsAsync::NotAsync }; + + let default_safety = if attrs.iter().any(|attr| attr.has_name(sym::target_feature)) + && !matches!(h.safety, Safety::Unsafe(_)) + && default_safety.is_safe() + { + hir::Safety::Unsafe { target_feature: true } + } else { + default_safety + }; + hir::FnHeader { safety: self.lower_safety(h.safety, default_safety), asyncness, @@ -1394,7 +1414,7 @@ impl<'hir> LoweringContext<'_, 'hir> { pub(super) fn lower_safety(&mut self, s: Safety, default: hir::Safety) -> hir::Safety { match s { - Safety::Unsafe(_) => hir::Safety::Unsafe, + Safety::Unsafe(_) => hir::Safety::Unsafe { target_feature: false }, Safety::Default => default, Safety::Safe(_) => hir::Safety::Safe, } diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs index 69326f409bb3e..c97f78c5eadcb 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs @@ -1222,7 +1222,7 @@ fn get_rust_try_fn<'a, 'gcc, 'tcx>( iter::once(i8p), tcx.types.unit, false, - rustc_hir::Safety::Unsafe, + rustc_hir::Safety::Unsafe { target_feature: false }, Abi::Rust, )), ); @@ -1233,7 +1233,7 @@ fn get_rust_try_fn<'a, 'gcc, 'tcx>( [i8p, i8p].iter().cloned(), tcx.types.unit, false, - rustc_hir::Safety::Unsafe, + rustc_hir::Safety::Unsafe { target_feature: false }, Abi::Rust, )), ); @@ -1242,7 +1242,7 @@ fn get_rust_try_fn<'a, 'gcc, 'tcx>( [try_fn_ty, i8p, catch_fn_ty], tcx.types.i32, false, - rustc_hir::Safety::Unsafe, + rustc_hir::Safety::Unsafe { target_feature: false }, Abi::Rust, )); let rust_try = gen_fn(cx, "__rust_try", rust_fn_sig, codegen); diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index c38c5d4c6442c..2cae57ec74d05 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -1091,7 +1091,7 @@ fn get_rust_try_fn<'ll, 'tcx>( [i8p], tcx.types.unit, false, - hir::Safety::Unsafe, + hir::Safety::Unsafe { target_feature: false }, ExternAbi::Rust, )), ); @@ -1102,7 +1102,7 @@ fn get_rust_try_fn<'ll, 'tcx>( [i8p, i8p], tcx.types.unit, false, - hir::Safety::Unsafe, + hir::Safety::Unsafe { target_feature: false }, ExternAbi::Rust, )), ); @@ -1111,7 +1111,7 @@ fn get_rust_try_fn<'ll, 'tcx>( [try_fn_ty, i8p, catch_fn_ty], tcx.types.i32, false, - hir::Safety::Unsafe, + hir::Safety::Unsafe { target_feature: false }, ExternAbi::Rust, )); let rust_try = gen_fn(cx, "__rust_try", rust_fn_sig, codegen); diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 658a7f00b19df..e4638d22f6ca3 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -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::{HirId, LangItem, lang_items}; +use rustc_hir::{self as hir, HirId, LangItem, lang_items}; use rustc_middle::middle::codegen_fn_attrs::{ CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry, }; @@ -251,7 +251,9 @@ 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().is_safe() + && matches!(fn_sig.skip_binder().safety(), hir::Safety::Unsafe { + target_feature: true + }) { if tcx.sess.target.is_like_wasm || tcx.sess.opts.actually_rustdoc { // The `#[target_feature]` attribute is allowed on diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index b6cdf224fb26b..3a390ffefe221 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -3390,14 +3390,21 @@ impl<'hir> Item<'hir> { #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] #[derive(Encodable, Decodable, HashStable_Generic)] pub enum Safety { - Unsafe, + Unsafe { + /// Whether this is a safe target_feature function. + /// We treat those as unsafe almost everywhere, but in unsafeck, + /// which allows calling them from other target_feature functions + /// without an `unsafe` block. + target_feature: bool, + }, Safe, } impl Safety { pub fn prefix_str(self) -> &'static str { match self { - Self::Unsafe => "unsafe ", + Self::Unsafe { target_feature: false } => "unsafe ", + Self::Unsafe { target_feature: true } => "#[target_feature] ", Self::Safe => "", } } @@ -3410,7 +3417,7 @@ impl Safety { #[inline] pub fn is_safe(self) -> bool { match self { - Self::Unsafe => false, + Self::Unsafe { .. } => false, Self::Safe => true, } } @@ -3419,7 +3426,8 @@ impl Safety { impl fmt::Display for Safety { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str(match *self { - Self::Unsafe => "unsafe", + Self::Unsafe { target_feature: false } => "unsafe", + Self::Unsafe { target_feature: true } => "#[target_feature] safe", Self::Safe => "safe", }) } diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 2e6b511412bb1..190d1096857b0 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -76,7 +76,7 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) - tcx.fn_sig(intrinsic_id).skip_binder().safety() } else { // Old-style intrinsics are never safe - Safety::Unsafe + Safety::Unsafe { target_feature: false } }; let is_in_list = match tcx.item_name(intrinsic_id.into()) { // When adding a new intrinsic to this list, @@ -137,7 +137,7 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) - | sym::fdiv_algebraic | sym::frem_algebraic | sym::const_eval_select => hir::Safety::Safe, - _ => hir::Safety::Unsafe, + _ => hir::Safety::Unsafe { target_feature: false }, }; if has_safe_attr != is_in_list { @@ -216,7 +216,7 @@ pub fn check_intrinsic_type( return; } }; - (n_tps, 0, 0, inputs, output, hir::Safety::Unsafe) + (n_tps, 0, 0, inputs, output, hir::Safety::Unsafe { target_feature: false }) } else { let safety = intrinsic_operation_unsafety(tcx, intrinsic_id); let (n_tps, n_cts, inputs, output) = match intrinsic_name { diff --git a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs index 86839e4033034..99f0d709103ab 100644 --- a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs +++ b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs @@ -24,7 +24,7 @@ pub(super) fn check_item( let trait_def_safety = if is_copy { // If `Self` has unsafe fields, `Copy` is unsafe to implement. if trait_header.trait_ref.skip_binder().self_ty().has_unsafe_fields() { - rustc_hir::Safety::Unsafe + rustc_hir::Safety::Unsafe { target_feature: false } } else { rustc_hir::Safety::Safe } @@ -33,7 +33,7 @@ pub(super) fn check_item( }; match (trait_def_safety, unsafe_attr, trait_header.safety, trait_header.polarity) { - (Safety::Safe, None, Safety::Unsafe, Positive | Reservation) => { + (Safety::Safe, None, Safety::Unsafe { .. }, Positive | Reservation) => { let span = tcx.def_span(def_id); return Err(struct_span_code_err!( tcx.dcx(), @@ -51,7 +51,7 @@ pub(super) fn check_item( .emit()); } - (Safety::Unsafe, _, Safety::Safe, Positive | Reservation) => { + (Safety::Unsafe { .. }, _, Safety::Safe, Positive | Reservation) => { let span = tcx.def_span(def_id); return Err(struct_span_code_err!( tcx.dcx(), @@ -109,14 +109,14 @@ pub(super) fn check_item( .emit()); } - (_, _, Safety::Unsafe, Negative) => { + (_, _, Safety::Unsafe { .. }, Negative) => { // Reported in AST validation assert!(tcx.dcx().has_errors().is_some(), "unsafe negative impl"); Ok(()) } (_, _, Safety::Safe, Negative) - | (Safety::Unsafe, _, Safety::Unsafe, Positive | Reservation) - | (Safety::Safe, Some(_), Safety::Unsafe, Positive | Reservation) + | (Safety::Unsafe { .. }, _, Safety::Unsafe { .. }, Positive | Reservation) + | (Safety::Safe, Some(_), Safety::Unsafe { .. }, Positive | Reservation) | (Safety::Safe, None, Safety::Safe, _) => Ok(()), } } diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 96d2714252af9..752a7f48b1b29 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1371,7 +1371,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFn // constructors for structs with `layout_scalar_valid_range` are unsafe to call let safety = match tcx.layout_scalar_valid_range(adt_def_id) { (Bound::Unbounded, Bound::Unbounded) => hir::Safety::Safe, - _ => hir::Safety::Unsafe, + _ => hir::Safety::Unsafe { target_feature: false }, }; ty::Binder::dummy(tcx.mk_fn_sig(inputs, ty, false, safety, ExternAbi::Rust)) } diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index a74e36c45c6ef..b91a4fbdd5368 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -2293,8 +2293,8 @@ impl<'a> State<'a> { fn print_safety(&mut self, s: hir::Safety) { match s { - hir::Safety::Safe => {} - hir::Safety::Unsafe => self.word_nbsp("unsafe"), + hir::Safety::Unsafe { target_feature: true } | hir::Safety::Safe => {} + hir::Safety::Unsafe { target_feature: false } => self.word_nbsp("unsafe"), } } diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 7d7c9331edf00..dffad13f8ba22 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -863,7 +863,10 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { let outer_universe = self.infcx.universe(); let result = if let ty::FnPtr(_, hdr_b) = b.kind() - && fn_ty_a.safety().is_safe() + && matches!( + fn_ty_a.safety(), + hir::Safety::Safe | hir::Safety::Unsafe { target_feature: true } + ) && hdr_b.safety.is_unsafe() { let unsafe_a = self.tcx.safe_to_unsafe_fn_ty(fn_ty_a); @@ -924,10 +927,12 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { return Err(TypeError::IntrinsicCast); } - // Safe `#[target_feature]` functions are not assignable to safe fn pointers (RFC 2396). + // Safe `#[target_feature]` functions are not assignable to safe fn pointers (RFC 2396), + // report a better error than a safety mismatch. + // FIXME(target_feature): do this inside `coerce_from_safe_fn` if b_hdr.safety.is_safe() - && !self.tcx.codegen_fn_attrs(def_id).target_features.is_empty() + && matches!(a_sig.safety(), hir::Safety::Unsafe { target_feature: true }) { return Err(TypeError::TargetFeatureCast(def_id)); } diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs index 28f406fbc9629..b01ecb8681d79 100644 --- a/compiler/rustc_metadata/src/rmeta/table.rs +++ b/compiler/rustc_metadata/src/rmeta/table.rs @@ -155,13 +155,17 @@ fixed_size_enum! { ( Impl { of_trait: false } ) ( Impl { of_trait: true } ) ( Closure ) - ( Static { safety: hir::Safety::Unsafe, mutability: ast::Mutability::Not, nested: false } ) + ( Static { safety: hir::Safety::Unsafe { target_feature: true }, mutability: ast::Mutability::Not, nested: false } ) + ( Static { safety: hir::Safety::Unsafe { target_feature: false }, mutability: ast::Mutability::Not, nested: false } ) ( Static { safety: hir::Safety::Safe, mutability: ast::Mutability::Not, nested: false } ) - ( Static { safety: hir::Safety::Unsafe, mutability: ast::Mutability::Mut, nested: false } ) + ( Static { safety: hir::Safety::Unsafe{ target_feature: true }, mutability: ast::Mutability::Mut, nested: false } ) + ( Static { safety: hir::Safety::Unsafe{ target_feature: false }, mutability: ast::Mutability::Mut, nested: false } ) ( Static { safety: hir::Safety::Safe, mutability: ast::Mutability::Mut, nested: false } ) - ( Static { safety: hir::Safety::Unsafe, mutability: ast::Mutability::Not, nested: true } ) + ( Static { safety: hir::Safety::Unsafe{ target_feature: true }, mutability: ast::Mutability::Not, nested: true } ) + ( Static { safety: hir::Safety::Unsafe{ target_feature: false }, mutability: ast::Mutability::Not, nested: true } ) ( Static { safety: hir::Safety::Safe, mutability: ast::Mutability::Not, nested: true } ) - ( Static { safety: hir::Safety::Unsafe, mutability: ast::Mutability::Mut, nested: true } ) + ( Static { safety: hir::Safety::Unsafe{ target_feature: true }, mutability: ast::Mutability::Mut, nested: true } ) + ( Static { safety: hir::Safety::Unsafe{ target_feature: false }, mutability: ast::Mutability::Mut, nested: true } ) ( Static { safety: hir::Safety::Safe, mutability: ast::Mutability::Mut, nested: true } ) ( Ctor(CtorOf::Struct, CtorKind::Fn) ) ( Ctor(CtorOf::Struct, CtorKind::Const) ) @@ -199,7 +203,8 @@ fixed_size_enum! { fixed_size_enum! { hir::Safety { - ( Unsafe ) + ( Unsafe { target_feature: false } ) + ( Unsafe { target_feature: true } ) ( Safe ) } } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index e382e63e2bdd2..42aaa923022b3 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -2521,8 +2521,14 @@ 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!(sig.safety().is_safe()); - Ty::new_fn_ptr(self, sig.map_bound(|sig| ty::FnSig { safety: hir::Safety::Unsafe, ..sig })) + matches!(sig.safety(), hir::Safety::Safe | hir::Safety::Unsafe { target_feature: true }); + Ty::new_fn_ptr( + self, + sig.map_bound(|sig| ty::FnSig { + safety: hir::Safety::Unsafe { target_feature: false }, + ..sig + }), + ) } /// Given the def_id of a Trait `trait_def_id` and the name of an associated item `assoc_name` diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 70d43abe8ed01..675a5de482573 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -221,6 +221,7 @@ pub struct DelegationFnSig { pub param_count: usize, pub has_self: bool, pub c_variadic: bool, + pub target_feature: bool, } #[derive(Clone, Copy, Debug)] diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 90be690e0345f..d7f53999a88fd 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -479,7 +479,9 @@ 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().is_unsafe() { + if matches!(self.thir[fun].ty.fn_sig(self.tcx).safety(), hir::Safety::Unsafe { + target_feature: false + }) { let func_id = if let ty::FnDef(func_id, _) = self.thir[fun].ty.kind() { Some(*func_id) } else { @@ -1112,7 +1114,11 @@ 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.is_unsafe() { SafetyContext::UnsafeFn } else { SafetyContext::Safe } + if matches!(fn_sig.header.safety, hir::Safety::Unsafe { target_feature: false }) { + SafetyContext::UnsafeFn + } else { + SafetyContext::Safe + } }); let body_target_features = &tcx.body_codegen_attrs(def.to_def_id()).target_features; let mut warnings = Vec::new(); diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index 6649284258121..8be10d3de142a 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -226,7 +226,9 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { let def_kind = match fi.kind { ForeignItemKind::Static(box StaticItem { ty: _, mutability, expr: _, safety }) => { let safety = match safety { - ast::Safety::Unsafe(_) | ast::Safety::Default => hir::Safety::Unsafe, + ast::Safety::Unsafe(_) | ast::Safety::Default => { + hir::Safety::Unsafe { target_feature: false } + } ast::Safety::Safe(_) => hir::Safety::Safe, }; diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 789d74876f722..9687408ca4da9 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -4959,12 +4959,13 @@ struct ItemInfoCollector<'a, 'ra, 'tcx> { } impl ItemInfoCollector<'_, '_, '_> { - fn collect_fn_info(&mut self, sig: &FnSig, id: NodeId) { + fn collect_fn_info(&mut self, sig: &FnSig, id: NodeId, attrs: &[Attribute]) { let sig = DelegationFnSig { header: sig.header, param_count: sig.decl.inputs.len(), has_self: sig.decl.has_self(), c_variadic: sig.decl.c_variadic(), + target_feature: attrs.iter().any(|attr| attr.has_name(sym::target_feature)), }; self.r.delegation_fn_sigs.insert(self.r.local_def_id(id), sig); } @@ -4983,7 +4984,7 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> { | ItemKind::Trait(box Trait { ref generics, .. }) | ItemKind::TraitAlias(ref generics, _) => { if let ItemKind::Fn(box Fn { ref sig, .. }) = &item.kind { - self.collect_fn_info(sig, item.id); + self.collect_fn_info(sig, item.id, &item.attrs); } let def_id = self.r.local_def_id(item.id); @@ -5016,7 +5017,7 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> { fn visit_assoc_item(&mut self, item: &'ast AssocItem, ctxt: AssocCtxt) { if let AssocItemKind::Fn(box Fn { ref sig, .. }) = &item.kind { - self.collect_fn_info(sig, item.id); + self.collect_fn_info(sig, item.id, &item.attrs); } visit::walk_assoc_item(self, item, ctxt); } diff --git a/compiler/rustc_smir/src/rustc_internal/internal.rs b/compiler/rustc_smir/src/rustc_internal/internal.rs index dec2a77619bad..ebd52026d37f8 100644 --- a/compiler/rustc_smir/src/rustc_internal/internal.rs +++ b/compiler/rustc_smir/src/rustc_internal/internal.rs @@ -489,7 +489,7 @@ impl RustcInternal for Safety { fn internal<'tcx>(&self, _tables: &mut Tables<'_>, _tcx: TyCtxt<'tcx>) -> Self::T<'tcx> { match self { - Safety::Unsafe => rustc_hir::Safety::Unsafe, + Safety::Unsafe => rustc_hir::Safety::Unsafe { target_feature: false }, Safety::Safe => rustc_hir::Safety::Safe, } } diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mod.rs b/compiler/rustc_smir/src/rustc_smir/convert/mod.rs index 4f8da08eff916..5d03468207dda 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/mod.rs @@ -15,7 +15,7 @@ impl<'tcx> Stable<'tcx> for rustc_hir::Safety { type T = stable_mir::mir::Safety; fn stable(&self, _: &mut Tables<'_>) -> Self::T { match self { - rustc_hir::Safety::Unsafe => stable_mir::mir::Safety::Unsafe, + rustc_hir::Safety::Unsafe { .. } => stable_mir::mir::Safety::Unsafe, rustc_hir::Safety::Safe => stable_mir::mir::Safety::Safe, } } diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs index f10314c1c9e07..f9a165928858b 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs @@ -207,7 +207,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { let fn_sig = self_ty.fn_sig(self.tcx); let shortname = match fn_sig.safety() { hir::Safety::Safe => "fn", - hir::Safety::Unsafe => "unsafe fn", + hir::Safety::Unsafe { .. } => "unsafe fn", }; flags.push((sym::_Self, Some(shortname.to_owned()))); } diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index ced9ff2d68542..56dd4400e0d76 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -473,7 +473,7 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl { "" } - clean::ForeignStaticItem(_, hir::Safety::Unsafe) => { + clean::ForeignStaticItem(_, hir::Safety::Unsafe { .. }) => { "" } _ => "", diff --git a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs index b71b53ea3bbfd..748bf135a2ab5 100644 --- a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs +++ b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs @@ -252,9 +252,9 @@ fn item_search_pat(item: &Item<'_>) -> (Pat, Pat) { ItemKind::Struct(VariantData::Struct { .. }, _) => (Pat::Str("struct"), Pat::Str("}")), ItemKind::Struct(..) => (Pat::Str("struct"), Pat::Str(";")), ItemKind::Union(..) => (Pat::Str("union"), Pat::Str("}")), - ItemKind::Trait(_, Safety::Unsafe, ..) + ItemKind::Trait(_, Safety::Unsafe{..}, ..) | ItemKind::Impl(Impl { - safety: Safety::Unsafe, .. + safety: Safety::Unsafe{..}, .. }) => (Pat::Str("unsafe"), Pat::Str("}")), ItemKind::Trait(IsAuto::Yes, ..) => (Pat::Str("auto"), Pat::Str("}")), ItemKind::Trait(..) => (Pat::Str("trait"), Pat::Str("}")), diff --git a/tests/ui/async-await/async-closures/fn-exception-target-features.stderr b/tests/ui/async-await/async-closures/fn-exception-target-features.stderr index db5895108bb0e..67baaf4fd367c 100644 --- a/tests/ui/async-await/async-closures/fn-exception-target-features.stderr +++ b/tests/ui/async-await/async-closures/fn-exception-target-features.stderr @@ -1,11 +1,12 @@ -error[E0277]: the trait bound `fn() -> Pin + 'static)>> {target_feature}: AsyncFn()` is not satisfied +error[E0277]: the trait bound `#[target_feature] fn() -> Pin + 'static)>> {target_feature}: AsyncFn()` is not satisfied --> $DIR/fn-exception-target-features.rs:16:10 | LL | test(target_feature); - | ---- ^^^^^^^^^^^^^^ the trait `AsyncFn()` is not implemented for fn item `fn() -> Pin + 'static)>> {target_feature}` + | ---- ^^^^^^^^^^^^^^ unsatisfied trait bound | | | required by a bound introduced by this call | + = help: the trait `AsyncFn()` is not implemented for fn item `#[target_feature] fn() -> Pin + 'static)>> {target_feature}` note: required by a bound in `test` --> $DIR/fn-exception-target-features.rs:13:17 | diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.stderr index cc941be5479e3..c56eb92768230 100644 --- a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.stderr +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.stderr @@ -10,13 +10,9 @@ LL | let foo: fn() = foo; | expected due to this | = note: expected fn pointer `fn()` - found fn item `fn() {foo}` - = note: fn items are distinct from fn pointers + found fn item `#[target_feature] fn() {foo}` = note: functions with `#[target_feature]` can only be coerced to `unsafe` function pointers -help: consider casting to a fn pointer - | -LL | let foo: fn() = foo as fn(); - | ~~~~~~~~~~~ + = note: unsafe functions cannot be coerced into safe function pointers error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.rs b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.rs index 3c370a1b8f321..3ad4cd1a4c7c5 100644 --- a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.rs +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.rs @@ -21,9 +21,9 @@ fn call_once(f: impl FnOnce()) { } fn main() { - call(foo); //~ ERROR expected a `Fn()` closure, found `fn() {foo}` - call_mut(foo); //~ ERROR expected a `FnMut()` closure, found `fn() {foo}` - call_once(foo); //~ ERROR expected a `FnOnce()` closure, found `fn() {foo}` + call(foo); //~ ERROR expected a `Fn()` closure, found `#[target_feature] fn() {foo}` + call_mut(foo); //~ ERROR expected a `FnMut()` closure, found `#[target_feature] fn() {foo}` + call_once(foo); //~ ERROR expected a `FnOnce()` closure, found `#[target_feature] fn() {foo}` call(foo_unsafe); //~^ ERROR expected a `Fn()` closure, found `unsafe fn() {foo_unsafe}` diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr index 4c07f4d6b990d..654304f86be91 100644 --- a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr @@ -1,13 +1,14 @@ -error[E0277]: expected a `Fn()` closure, found `fn() {foo}` +error[E0277]: expected a `Fn()` closure, found `#[target_feature] fn() {foo}` --> $DIR/fn-traits.rs:24:10 | LL | call(foo); - | ---- ^^^ expected an `Fn()` closure, found `fn() {foo}` + | ---- ^^^ call the function in a closure: `|| unsafe { /* code */ }` | | | required by a bound introduced by this call | - = help: the trait `Fn()` is not implemented for fn item `fn() {foo}` - = note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ }` + = help: the trait `Fn()` is not implemented for fn item `#[target_feature] fn() {foo}` + = note: unsafe function cannot be called generically without an unsafe block + = note: wrap the `#[target_feature] fn() {foo}` in a closure with no arguments: `|| { /* code */ }` = note: `#[target_feature]` functions do not implement the `Fn` traits note: required by a bound in `call` --> $DIR/fn-traits.rs:11:17 @@ -15,16 +16,17 @@ note: required by a bound in `call` LL | fn call(f: impl Fn()) { | ^^^^ required by this bound in `call` -error[E0277]: expected a `FnMut()` closure, found `fn() {foo}` +error[E0277]: expected a `FnMut()` closure, found `#[target_feature] fn() {foo}` --> $DIR/fn-traits.rs:25:14 | LL | call_mut(foo); - | -------- ^^^ expected an `FnMut()` closure, found `fn() {foo}` + | -------- ^^^ call the function in a closure: `|| unsafe { /* code */ }` | | | required by a bound introduced by this call | - = help: the trait `FnMut()` is not implemented for fn item `fn() {foo}` - = note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ }` + = help: the trait `FnMut()` is not implemented for fn item `#[target_feature] fn() {foo}` + = note: unsafe function cannot be called generically without an unsafe block + = note: wrap the `#[target_feature] fn() {foo}` in a closure with no arguments: `|| { /* code */ }` = note: `#[target_feature]` functions do not implement the `Fn` traits note: required by a bound in `call_mut` --> $DIR/fn-traits.rs:15:25 @@ -32,16 +34,17 @@ note: required by a bound in `call_mut` LL | fn call_mut(mut f: impl FnMut()) { | ^^^^^^^ required by this bound in `call_mut` -error[E0277]: expected a `FnOnce()` closure, found `fn() {foo}` +error[E0277]: expected a `FnOnce()` closure, found `#[target_feature] fn() {foo}` --> $DIR/fn-traits.rs:26:15 | LL | call_once(foo); - | --------- ^^^ expected an `FnOnce()` closure, found `fn() {foo}` + | --------- ^^^ call the function in a closure: `|| unsafe { /* code */ }` | | | required by a bound introduced by this call | - = help: the trait `FnOnce()` is not implemented for fn item `fn() {foo}` - = note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ }` + = help: the trait `FnOnce()` is not implemented for fn item `#[target_feature] fn() {foo}` + = note: unsafe function cannot be called generically without an unsafe block + = note: wrap the `#[target_feature] fn() {foo}` in a closure with no arguments: `|| { /* code */ }` = note: `#[target_feature]` functions do not implement the `Fn` traits note: required by a bound in `call_once` --> $DIR/fn-traits.rs:19:22 diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.stderr index 1ddf05b40a606..4cfbdcdbef5b1 100644 --- a/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.stderr +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.stderr @@ -26,6 +26,9 @@ LL | Quux.avx_bmi2(); error[E0133]: call to function `avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block --> $DIR/safe-calls.rs:38:5 | +LL | fn bar() { + | -------- items do not inherit unsafety from separate enclosing items +LL | sse2(); LL | avx_bmi2(); | ^^^^^^^^^^ call to function with `#[target_feature]` | @@ -34,6 +37,9 @@ LL | avx_bmi2(); error[E0133]: call to function `Quux::avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block --> $DIR/safe-calls.rs:40:5 | +LL | fn bar() { + | -------- items do not inherit unsafety from separate enclosing items +... LL | Quux.avx_bmi2(); | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` | @@ -42,6 +48,9 @@ LL | Quux.avx_bmi2(); error[E0133]: call to function `avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block --> $DIR/safe-calls.rs:47:5 | +LL | fn baz() { + | -------- items do not inherit unsafety from separate enclosing items +LL | sse2(); LL | avx_bmi2(); | ^^^^^^^^^^ call to function with `#[target_feature]` | @@ -50,6 +59,9 @@ LL | avx_bmi2(); error[E0133]: call to function `Quux::avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block --> $DIR/safe-calls.rs:49:5 | +LL | fn baz() { + | -------- items do not inherit unsafety from separate enclosing items +... LL | Quux.avx_bmi2(); | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` | diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/trait-impl.rs b/tests/ui/rfcs/rfc-2396-target_feature-11/trait-impl.rs index df575b0f6b636..a2ac6ff45fccf 100644 --- a/tests/ui/rfcs/rfc-2396-target_feature-11/trait-impl.rs +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/trait-impl.rs @@ -13,6 +13,7 @@ impl Foo for Bar { #[target_feature(enable = "sse2")] //~^ ERROR cannot be applied to safe trait method fn foo(&self) {} + //~^ ERROR method `foo` has an incompatible type for trait #[target_feature(enable = "sse2")] unsafe fn unsf_foo(&self) {} diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/trait-impl.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/trait-impl.stderr index 00efbb52f159b..de9c1e6bf9624 100644 --- a/tests/ui/rfcs/rfc-2396-target_feature-11/trait-impl.stderr +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/trait-impl.stderr @@ -1,3 +1,17 @@ +error[E0053]: method `foo` has an incompatible type for trait + --> $DIR/trait-impl.rs:15:5 + | +LL | fn foo(&self) {} + | ^^^^^^^^^^^^^ expected safe fn, found #[target_feature] safe fn + | +note: type in trait + --> $DIR/trait-impl.rs:6:5 + | +LL | fn foo(&self); + | ^^^^^^^^^^^^^^ + = note: expected signature `fn(&Bar)` + found signature `#[target_feature] fn(&Bar)` + error: `#[target_feature(..)]` cannot be applied to safe trait method --> $DIR/trait-impl.rs:13:5 | @@ -8,7 +22,7 @@ LL | fn foo(&self) {} | ------------- not an `unsafe` function error: `#[target_feature(..)]` cannot be applied to safe trait method - --> $DIR/trait-impl.rs:22:5 + --> $DIR/trait-impl.rs:23:5 | LL | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot be applied to safe trait method @@ -16,5 +30,6 @@ LL | LL | fn foo(&self) {} | ------------- not an `unsafe` function -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors +For more information about this error, try `rustc --explain E0053`. diff --git a/tests/ui/target-feature/invalid-attribute.rs b/tests/ui/target-feature/invalid-attribute.rs index 2f951c4a00a9e..07bfba7c19c0c 100644 --- a/tests/ui/target-feature/invalid-attribute.rs +++ b/tests/ui/target-feature/invalid-attribute.rs @@ -97,6 +97,7 @@ impl Foo {} trait Quux { fn foo(); //~ NOTE `foo` from trait + //~^ NOTE: type in trait } impl Quux for Foo { @@ -106,6 +107,9 @@ impl Quux for Foo { //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date fn foo() {} //~^ NOTE not an `unsafe` function + //~| ERROR: incompatible type for trait + //~| NOTE: expected safe fn, found #[target_feature] safe fn + //~| NOTE: expected signature `fn()` } fn main() { diff --git a/tests/ui/target-feature/invalid-attribute.stderr b/tests/ui/target-feature/invalid-attribute.stderr index bf48911edec5f..b9a07c5063709 100644 --- a/tests/ui/target-feature/invalid-attribute.stderr +++ b/tests/ui/target-feature/invalid-attribute.stderr @@ -126,7 +126,7 @@ LL | impl Foo {} | ----------- not a function definition error: attribute should be applied to a function definition - --> $DIR/invalid-attribute.rs:112:5 + --> $DIR/invalid-attribute.rs:116:5 | LL | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -138,7 +138,7 @@ LL | | } | |_____- not a function definition error: attribute should be applied to a function definition - --> $DIR/invalid-attribute.rs:120:5 + --> $DIR/invalid-attribute.rs:124:5 | LL | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -192,8 +192,22 @@ LL | impl Quux for u8 {} LL | fn foo(); | --------- `foo` from trait +error[E0053]: method `foo` has an incompatible type for trait + --> $DIR/invalid-attribute.rs:108:5 + | +LL | fn foo() {} + | ^^^^^^^^ expected safe fn, found #[target_feature] safe fn + | +note: type in trait + --> $DIR/invalid-attribute.rs:99:5 + | +LL | fn foo(); + | ^^^^^^^^^ + = note: expected signature `fn()` + found signature `#[target_feature] fn()` + error[E0658]: `#[target_feature(..)]` can only be applied to `unsafe` functions - --> $DIR/invalid-attribute.rs:103:5 + --> $DIR/invalid-attribute.rs:104:5 | LL | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -205,7 +219,7 @@ LL | fn foo() {} = help: add `#![feature(target_feature_11)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 23 previous errors +error: aborting due to 24 previous errors -Some errors have detailed explanations: E0046, E0658. +Some errors have detailed explanations: E0046, E0053, E0658. For more information about an error, try `rustc --explain E0046`.