diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index d4c54b67f24d5..e3c6577afcb70 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -676,6 +676,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ rustc_nounwind, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No, IMPL_DETAIL ), + rustc_attr!( + rustc_no_ubchecks, Normal, template!(Word), WarnFollowing, + EncodeCrossCrate::No, IMPL_DETAIL + ), rustc_attr!( rustc_reallocator, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No, IMPL_DETAIL diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs index 3ec553d0ba0c5..5ede3e7b1a64c 100644 --- a/compiler/rustc_mir_transform/src/instsimplify.rs +++ b/compiler/rustc_mir_transform/src/instsimplify.rs @@ -37,19 +37,27 @@ impl<'tcx> MirPass<'tcx> for InstSimplify { } fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + let def_id = body.source.def_id(); let ctx = InstSimplifyContext { tcx, local_decls: &body.local_decls, - param_env: tcx.param_env_reveal_all_normalized(body.source.def_id()), + param_env: tcx.param_env_reveal_all_normalized(def_id), }; let preserve_ub_checks = attr::contains_name(tcx.hir().krate_attrs(), sym::rustc_preserve_ub_checks); + let remove_ub_checks = tcx.has_attr(def_id, sym::rustc_no_ubchecks); for block in body.basic_blocks.as_mut() { for statement in block.statements.iter_mut() { match statement.kind { StatementKind::Assign(box (_place, ref mut rvalue)) => { - if !preserve_ub_checks { - ctx.simplify_ub_check(&statement.source_info, rvalue); + if remove_ub_checks { + ctx.simplify_ub_check(&statement.source_info, rvalue, false); + } else if !preserve_ub_checks { + ctx.simplify_ub_check( + &statement.source_info, + rvalue, + tcx.sess.ub_checks(), + ); } ctx.simplify_bool_cmp(&statement.source_info, rvalue); ctx.simplify_ref_deref(&statement.source_info, rvalue); @@ -199,9 +207,14 @@ impl<'tcx> InstSimplifyContext<'tcx, '_> { } } - fn simplify_ub_check(&self, source_info: &SourceInfo, rvalue: &mut Rvalue<'tcx>) { + fn simplify_ub_check( + &self, + source_info: &SourceInfo, + rvalue: &mut Rvalue<'tcx>, + ub_checks: bool, + ) { if let Rvalue::NullaryOp(NullOp::UbChecks, _) = *rvalue { - let const_ = Const::from_bool(self.tcx, self.tcx.sess.ub_checks()); + let const_ = Const::from_bool(self.tcx, ub_checks); let constant = ConstOperand { span: source_info.span, const_, user_ty: None }; *rvalue = Rvalue::Use(Operand::Constant(Box::new(constant))); } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index db09c948a8eae..2aea25123f42e 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1655,6 +1655,7 @@ symbols! { rustc_never_returns_null_ptr, rustc_never_type_options, rustc_no_mir_inline, + rustc_no_ubchecks, rustc_nonnull_optimization_guaranteed, rustc_nounwind, rustc_object_lifetime_default, diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index 7a9ca4011be84..bb3f6a00eb50f 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -859,6 +859,7 @@ pub fn take(dest: &mut T) -> T { #[must_use = "if you don't need the old value, you can just assign the new value directly"] #[rustc_const_unstable(feature = "const_replace", issue = "83164")] #[cfg_attr(not(test), rustc_diagnostic_item = "mem_replace")] +#[cfg_attr(not(bootstrap), rustc_no_ubchecks)] pub const fn replace(dest: &mut T, src: T) -> T { // It may be tempting to use `swap` to avoid `unsafe` here. Don't! // The compiler optimizes the implementation below to two `memcpy`s