From 51ba662d23f1814bf5c5fc9bff7c86e9659fe5a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20S=C3=A1nchez=20Mu=C3=B1oz?= Date: Sun, 26 Nov 2023 19:55:01 +0100 Subject: [PATCH 1/2] Print list of missing target features when calling a function with target features outside an unsafe block --- compiler/rustc_middle/src/mir/query.rs | 13 +- compiler/rustc_mir_transform/messages.ftl | 13 +- .../rustc_mir_transform/src/check_unsafety.rs | 29 +++- compiler/rustc_mir_transform/src/errors.rs | 125 +++++++++++------- .../safe-calls.mir.stderr | 59 +++++---- .../rfc-2396-target_feature-11/safe-calls.rs | 11 +- .../safe-calls.thir.stderr | 34 +++-- 7 files changed, 190 insertions(+), 94 deletions(-) diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index ab8fef5129b5d..98642adc19090 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -27,7 +27,7 @@ pub enum UnsafetyViolationKind { UnsafeFn, } -#[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)] +#[derive(Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)] pub enum UnsafetyViolationDetails { CallToUnsafeFunction, UseOfInlineAssembly, @@ -39,10 +39,17 @@ pub enum UnsafetyViolationDetails { AccessToUnionField, MutationOfLayoutConstrainedField, BorrowOfLayoutConstrainedField, - CallToFunctionWith, + CallToFunctionWith { + /// Target features enabled in callee's `#[target_feature]` but missing in + /// caller's `#[target_feature]`. + missing: Vec, + /// Target features in `missing` that are enabled at compile time + /// (e.g., with `-C target-feature`). + build_enabled: Vec, + }, } -#[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)] +#[derive(Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)] pub struct UnsafetyViolation { pub source_info: SourceInfo, pub lint_root: hir::HirId, diff --git a/compiler/rustc_mir_transform/messages.ftl b/compiler/rustc_mir_transform/messages.ftl index 5a99afc45b020..b8dbdf18db3ea 100644 --- a/compiler/rustc_mir_transform/messages.ftl +++ b/compiler/rustc_mir_transform/messages.ftl @@ -42,8 +42,19 @@ mir_transform_requires_unsafe = {$details} is unsafe and requires unsafe {$op_in } .not_inherited = items do not inherit unsafety from separate enclosing items +mir_transform_target_feature_call_help = in order for the call to be safe, the context requires the following additional target {$missing_target_features_count -> + [1] feature + *[count] features + }: {$missing_target_features} + mir_transform_target_feature_call_label = call to function with `#[target_feature]` -mir_transform_target_feature_call_note = can only be called if the required target features are available +mir_transform_target_feature_call_note = the {$build_target_features} target {$build_target_features_count -> + [1] feature + *[count] features + } being enabled in the build configuration does not remove the requirement to list {$build_target_features_count -> + [1] it + *[count] them + } in `#[target_feature]` mir_transform_unaligned_packed_ref = reference to packed field is unaligned .note = packed structs are only aligned by one byte, and many modern architectures penalize unaligned field accesses diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs index cfcd5acb9e953..b3bf9f8da25da 100644 --- a/compiler/rustc_mir_transform/src/check_unsafety.rs +++ b/compiler/rustc_mir_transform/src/check_unsafety.rs @@ -287,19 +287,20 @@ impl<'tcx> UnsafetyChecker<'_, 'tcx> { .safety; match safety { // `unsafe` blocks are required in safe code - Safety::Safe => violations.into_iter().for_each(|&violation| { + Safety::Safe => violations.into_iter().for_each(|violation| { match violation.kind { UnsafetyViolationKind::General => {} UnsafetyViolationKind::UnsafeFn => { bug!("`UnsafetyViolationKind::UnsafeFn` in an `Safe` context") } } - if !self.violations.contains(&violation) { - self.violations.push(violation) + if !self.violations.contains(violation) { + self.violations.push(violation.clone()) } }), // With the RFC 2585, no longer allow `unsafe` operations in `unsafe fn`s - Safety::FnUnsafe => violations.into_iter().for_each(|&(mut violation)| { + Safety::FnUnsafe => violations.into_iter().for_each(|violation| { + let mut violation = violation.clone(); violation.kind = UnsafetyViolationKind::UnsafeFn; if !self.violations.contains(&violation) { self.violations.push(violation) @@ -367,9 +368,22 @@ impl<'tcx> UnsafetyChecker<'_, 'tcx> { // Is `callee_features` a subset of `calling_features`? if !callee_features.iter().all(|feature| self_features.contains(feature)) { + let missing: Vec<_> = callee_features + .iter() + .copied() + .filter(|feature| !self_features.contains(feature)) + .collect(); + let build_enabled = self + .tcx + .sess + .target_features + .iter() + .copied() + .filter(|feature| missing.contains(feature)) + .collect(); self.require_unsafe( UnsafetyViolationKind::General, - UnsafetyViolationDetails::CallToFunctionWith, + UnsafetyViolationDetails::CallToFunctionWith { missing, build_enabled }, ) } } @@ -528,8 +542,9 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: LocalDefId) { // Only suggest wrapping the entire function body in an unsafe block once let mut suggest_unsafe_block = true; - for &UnsafetyViolation { source_info, lint_root, kind, details } in violations.iter() { - let details = errors::RequiresUnsafeDetail { violation: details, span: source_info.span }; + for &UnsafetyViolation { source_info, lint_root, kind, ref details } in violations.iter() { + let details = + errors::RequiresUnsafeDetail { violation: details.clone(), span: source_info.span }; match kind { UnsafetyViolationKind::General => { diff --git a/compiler/rustc_mir_transform/src/errors.rs b/compiler/rustc_mir_transform/src/errors.rs index 5879a803946d6..3a5270f105ae4 100644 --- a/compiler/rustc_mir_transform/src/errors.rs +++ b/compiler/rustc_mir_transform/src/errors.rs @@ -1,6 +1,8 @@ +use std::borrow::Cow; + use rustc_errors::{ - Applicability, DecorateLint, DiagnosticBuilder, DiagnosticMessage, EmissionGuarantee, Handler, - IntoDiagnostic, + Applicability, DecorateLint, DiagnosticArgValue, DiagnosticBuilder, DiagnosticMessage, + EmissionGuarantee, Handler, IntoDiagnostic, }; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_middle::mir::{AssertKind, UnsafetyViolationDetails}; @@ -9,6 +11,8 @@ use rustc_session::lint::{self, Lint}; use rustc_span::def_id::DefId; use rustc_span::Span; +use crate::fluent_generated as fluent; + #[derive(LintDiagnostic)] pub(crate) enum ConstMutate { #[diag(mir_transform_const_modify)] @@ -61,72 +65,105 @@ pub(crate) struct RequiresUnsafe { impl<'sess, G: EmissionGuarantee> IntoDiagnostic<'sess, G> for RequiresUnsafe { #[track_caller] fn into_diagnostic(self, handler: &'sess Handler) -> DiagnosticBuilder<'sess, G> { - let mut diag = - handler.struct_diagnostic(crate::fluent_generated::mir_transform_requires_unsafe); + let mut diag = handler.struct_diagnostic(fluent::mir_transform_requires_unsafe); diag.code(rustc_errors::DiagnosticId::Error("E0133".to_string())); diag.set_span(self.span); diag.span_label(self.span, self.details.label()); - diag.note(self.details.note()); let desc = handler.eagerly_translate_to_string(self.details.label(), [].into_iter()); diag.set_arg("details", desc); diag.set_arg("op_in_unsafe_fn_allowed", self.op_in_unsafe_fn_allowed); + self.details.add_subdiagnostics(&mut diag); if let Some(sp) = self.enclosing { - diag.span_label(sp, crate::fluent_generated::mir_transform_not_inherited); + diag.span_label(sp, fluent::mir_transform_not_inherited); } diag } } -#[derive(Copy, Clone)] +#[derive(Clone)] pub(crate) struct RequiresUnsafeDetail { pub span: Span, pub violation: UnsafetyViolationDetails, } impl RequiresUnsafeDetail { - fn note(self) -> DiagnosticMessage { + fn add_subdiagnostics(&self, diag: &mut DiagnosticBuilder<'_, G>) { use UnsafetyViolationDetails::*; match self.violation { - CallToUnsafeFunction => crate::fluent_generated::mir_transform_call_to_unsafe_note, - UseOfInlineAssembly => crate::fluent_generated::mir_transform_use_of_asm_note, + CallToUnsafeFunction => { + diag.note(fluent::mir_transform_call_to_unsafe_note); + } + UseOfInlineAssembly => { + diag.note(fluent::mir_transform_use_of_asm_note); + } InitializingTypeWith => { - crate::fluent_generated::mir_transform_initializing_valid_range_note + diag.note(fluent::mir_transform_initializing_valid_range_note); + } + CastOfPointerToInt => { + diag.note(fluent::mir_transform_const_ptr2int_note); + } + UseOfMutableStatic => { + diag.note(fluent::mir_transform_use_of_static_mut_note); + } + UseOfExternStatic => { + diag.note(fluent::mir_transform_use_of_extern_static_note); + } + DerefOfRawPointer => { + diag.note(fluent::mir_transform_deref_ptr_note); + } + AccessToUnionField => { + diag.note(fluent::mir_transform_union_access_note); } - CastOfPointerToInt => crate::fluent_generated::mir_transform_const_ptr2int_note, - UseOfMutableStatic => crate::fluent_generated::mir_transform_use_of_static_mut_note, - UseOfExternStatic => crate::fluent_generated::mir_transform_use_of_extern_static_note, - DerefOfRawPointer => crate::fluent_generated::mir_transform_deref_ptr_note, - AccessToUnionField => crate::fluent_generated::mir_transform_union_access_note, MutationOfLayoutConstrainedField => { - crate::fluent_generated::mir_transform_mutation_layout_constrained_note + diag.note(fluent::mir_transform_mutation_layout_constrained_note); } BorrowOfLayoutConstrainedField => { - crate::fluent_generated::mir_transform_mutation_layout_constrained_borrow_note + diag.note(fluent::mir_transform_mutation_layout_constrained_borrow_note); + } + CallToFunctionWith { ref missing, ref build_enabled } => { + diag.help(fluent::mir_transform_target_feature_call_help); + diag.set_arg( + "missing_target_features", + DiagnosticArgValue::StrListSepByAnd( + missing.iter().map(|feature| Cow::from(feature.as_str())).collect(), + ), + ); + diag.set_arg("missing_target_features_count", missing.len()); + if !build_enabled.is_empty() { + diag.note(fluent::mir_transform_target_feature_call_note); + diag.set_arg( + "build_target_features", + DiagnosticArgValue::StrListSepByAnd( + build_enabled + .iter() + .map(|feature| Cow::from(feature.as_str())) + .collect(), + ), + ); + diag.set_arg("build_target_features_count", build_enabled.len()); + } } - CallToFunctionWith => crate::fluent_generated::mir_transform_target_feature_call_note, } } - fn label(self) -> DiagnosticMessage { + fn label(&self) -> DiagnosticMessage { use UnsafetyViolationDetails::*; match self.violation { - CallToUnsafeFunction => crate::fluent_generated::mir_transform_call_to_unsafe_label, - UseOfInlineAssembly => crate::fluent_generated::mir_transform_use_of_asm_label, - InitializingTypeWith => { - crate::fluent_generated::mir_transform_initializing_valid_range_label - } - CastOfPointerToInt => crate::fluent_generated::mir_transform_const_ptr2int_label, - UseOfMutableStatic => crate::fluent_generated::mir_transform_use_of_static_mut_label, - UseOfExternStatic => crate::fluent_generated::mir_transform_use_of_extern_static_label, - DerefOfRawPointer => crate::fluent_generated::mir_transform_deref_ptr_label, - AccessToUnionField => crate::fluent_generated::mir_transform_union_access_label, + CallToUnsafeFunction => fluent::mir_transform_call_to_unsafe_label, + UseOfInlineAssembly => fluent::mir_transform_use_of_asm_label, + InitializingTypeWith => fluent::mir_transform_initializing_valid_range_label, + CastOfPointerToInt => fluent::mir_transform_const_ptr2int_label, + UseOfMutableStatic => fluent::mir_transform_use_of_static_mut_label, + UseOfExternStatic => fluent::mir_transform_use_of_extern_static_label, + DerefOfRawPointer => fluent::mir_transform_deref_ptr_label, + AccessToUnionField => fluent::mir_transform_union_access_label, MutationOfLayoutConstrainedField => { - crate::fluent_generated::mir_transform_mutation_layout_constrained_label + fluent::mir_transform_mutation_layout_constrained_label } BorrowOfLayoutConstrainedField => { - crate::fluent_generated::mir_transform_mutation_layout_constrained_borrow_label + fluent::mir_transform_mutation_layout_constrained_borrow_label } - CallToFunctionWith => crate::fluent_generated::mir_transform_target_feature_call_label, + CallToFunctionWith { .. } => fluent::mir_transform_target_feature_call_label, } } } @@ -151,12 +188,12 @@ impl<'a> DecorateLint<'a, ()> for UnsafeOpInUnsafeFn { let desc = handler.eagerly_translate_to_string(self.details.label(), [].into_iter()); diag.set_arg("details", desc); diag.span_label(self.details.span, self.details.label()); - diag.note(self.details.note()); + self.details.add_subdiagnostics(diag); if let Some((start, end, fn_sig)) = self.suggest_unsafe_block { - diag.span_note(fn_sig, crate::fluent_generated::mir_transform_note); + diag.span_note(fn_sig, fluent::mir_transform_note); diag.tool_only_multipart_suggestion( - crate::fluent_generated::mir_transform_suggestion, + fluent::mir_transform_suggestion, vec![(start, " unsafe {".into()), (end, "}".into())], Applicability::MaybeIncorrect, ); @@ -166,7 +203,7 @@ impl<'a> DecorateLint<'a, ()> for UnsafeOpInUnsafeFn { } fn msg(&self) -> DiagnosticMessage { - crate::fluent_generated::mir_transform_unsafe_op_in_unsafe_fn + fluent::mir_transform_unsafe_op_in_unsafe_fn } } @@ -193,12 +230,8 @@ impl<'a, P: std::fmt::Debug> DecorateLint<'a, ()> for AssertLint

{ fn msg(&self) -> DiagnosticMessage { match self { - AssertLint::ArithmeticOverflow(..) => { - crate::fluent_generated::mir_transform_arithmetic_overflow - } - AssertLint::UnconditionalPanic(..) => { - crate::fluent_generated::mir_transform_operation_will_panic - } + AssertLint::ArithmeticOverflow(..) => fluent::mir_transform_arithmetic_overflow, + AssertLint::UnconditionalPanic(..) => fluent::mir_transform_operation_will_panic, } } } @@ -255,11 +288,11 @@ impl<'a> DecorateLint<'a, ()> for MustNotSupend<'_, '_> { self, diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>, ) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> { - diag.span_label(self.yield_sp, crate::fluent_generated::_subdiag::label); + diag.span_label(self.yield_sp, fluent::_subdiag::label); if let Some(reason) = self.reason { diag.subdiagnostic(reason); } - diag.span_help(self.src_sp, crate::fluent_generated::_subdiag::help); + diag.span_help(self.src_sp, fluent::_subdiag::help); diag.set_arg("pre", self.pre); diag.set_arg("def_path", self.tcx.def_path_str(self.def_id)); diag.set_arg("post", self.post); @@ -267,7 +300,7 @@ impl<'a> DecorateLint<'a, ()> for MustNotSupend<'_, '_> { } fn msg(&self) -> rustc_errors::DiagnosticMessage { - crate::fluent_generated::mir_transform_must_not_suspend + fluent::mir_transform_must_not_suspend } } diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.mir.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.mir.stderr index 0ef7b8b09f11f..c925034b253f4 100644 --- a/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.mir.stderr +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.mir.stderr @@ -1,83 +1,96 @@ error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:23:5 + --> $DIR/safe-calls.rs:28:5 | LL | sse2(); | ^^^^^^ call to function with `#[target_feature]` | - = note: can only be called if the required target features are available + = help: in order for the call to be safe, the context requires the following additional target feature: sse2 + = note: the sse2 target feature being enabled in the build configuration does not remove the requirement to list it in `#[target_feature]` error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:26:5 + --> $DIR/safe-calls.rs:31:5 | LL | avx_bmi2(); | ^^^^^^^^^^ call to function with `#[target_feature]` | - = note: can only be called if the required target features are available + = help: in order for the call to be safe, the context requires the following additional target features: avx and bmi2 error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:29:5 + --> $DIR/safe-calls.rs:34:5 | LL | Quux.avx_bmi2(); | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` | - = note: can only be called if the required target features are available + = help: in order for the call to be safe, the context requires the following additional target features: avx and bmi2 error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:36:5 + --> $DIR/safe-calls.rs:41:5 | LL | avx_bmi2(); | ^^^^^^^^^^ call to function with `#[target_feature]` | - = note: can only be called if the required target features are available + = help: in order for the call to be safe, the context requires the following additional target features: avx and bmi2 error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:39:5 + --> $DIR/safe-calls.rs:44:5 | LL | Quux.avx_bmi2(); | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` | - = note: can only be called if the required target features are available + = help: in order for the call to be safe, the context requires the following additional target features: avx and bmi2 error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:46:5 + --> $DIR/safe-calls.rs:51:5 | LL | sse2(); | ^^^^^^ call to function with `#[target_feature]` | - = note: can only be called if the required target features are available + = help: in order for the call to be safe, the context requires the following additional target feature: sse2 + = note: the sse2 target feature being enabled in the build configuration does not remove the requirement to list it in `#[target_feature]` error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:49:5 + --> $DIR/safe-calls.rs:54:5 | LL | avx_bmi2(); | ^^^^^^^^^^ call to function with `#[target_feature]` | - = note: can only be called if the required target features are available + = help: in order for the call to be safe, the context requires the following additional target feature: bmi2 error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:52:5 + --> $DIR/safe-calls.rs:57:5 | LL | Quux.avx_bmi2(); | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` | - = note: can only be called if the required target features are available + = help: in order for the call to be safe, the context requires the following additional target feature: bmi2 error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:60:5 + --> $DIR/safe-calls.rs:65:5 | LL | sse2(); | ^^^^^^ call to function with `#[target_feature]` | - = note: can only be called if the required target features are available + = help: in order for the call to be safe, the context requires the following additional target feature: sse2 + = note: the sse2 target feature being enabled in the build configuration does not remove the requirement to list it in `#[target_feature]` error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:65:18 + --> $DIR/safe-calls.rs:70:15 | -LL | const name: () = sse2(); - | ^^^^^^ call to function with `#[target_feature]` +LL | const _: () = sse2(); + | ^^^^^^ call to function with `#[target_feature]` | - = note: can only be called if the required target features are available + = help: in order for the call to be safe, the context requires the following additional target feature: sse2 + = note: the sse2 target feature being enabled in the build configuration does not remove the requirement to list it in `#[target_feature]` -error: aborting due to 10 previous errors +error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block + --> $DIR/safe-calls.rs:74:15 + | +LL | const _: () = sse2_and_fxsr(); + | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` + | + = help: in order for the call to be safe, the context requires the following additional target features: sse2 and fxsr + = note: the fxsr and sse2 target features being enabled in the build configuration does not remove the requirement to list them in `#[target_feature]` + +error: aborting due to 11 previous errors For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.rs b/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.rs index cebc6f9478404..db9cf97282a3f 100644 --- a/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.rs +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.rs @@ -7,6 +7,11 @@ #[target_feature(enable = "sse2")] const fn sse2() {} +#[target_feature(enable = "sse2")] +#[target_feature(enable = "fxsr")] +const fn sse2_and_fxsr() {} + + #[target_feature(enable = "avx")] #[target_feature(enable = "bmi2")] fn avx_bmi2() {} @@ -62,8 +67,12 @@ fn qux() { //[thir]~^^ ERROR call to function `sse2` with `#[target_feature]` is unsafe } -const name: () = sse2(); +const _: () = sse2(); //[mir]~^ ERROR call to function with `#[target_feature]` is unsafe //[thir]~^^ ERROR call to function `sse2` with `#[target_feature]` is unsafe +const _: () = sse2_and_fxsr(); +//[mir]~^ ERROR call to function with `#[target_feature]` is unsafe +//[thir]~^^ ERROR call to function `sse2_and_fxsr` with `#[target_feature]` is unsafe + fn main() {} diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.thir.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.thir.stderr index c75ac6e8b9ae0..28a7adb012bdd 100644 --- a/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.thir.stderr +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.thir.stderr @@ -1,5 +1,5 @@ error[E0133]: call to function `sse2` with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:23:5 + --> $DIR/safe-calls.rs:28:5 | LL | sse2(); | ^^^^^^ call to function with `#[target_feature]` @@ -7,7 +7,7 @@ LL | sse2(); = note: can only be called if the required target features are available error[E0133]: call to function `avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:26:5 + --> $DIR/safe-calls.rs:31:5 | LL | avx_bmi2(); | ^^^^^^^^^^ call to function with `#[target_feature]` @@ -15,7 +15,7 @@ LL | avx_bmi2(); = note: can only be called if the required target features are available error[E0133]: call to function `Quux::avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:29:5 + --> $DIR/safe-calls.rs:34:5 | LL | Quux.avx_bmi2(); | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` @@ -23,7 +23,7 @@ LL | Quux.avx_bmi2(); = note: can only be called if the required target features are available error[E0133]: call to function `avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:36:5 + --> $DIR/safe-calls.rs:41:5 | LL | avx_bmi2(); | ^^^^^^^^^^ call to function with `#[target_feature]` @@ -31,7 +31,7 @@ LL | avx_bmi2(); = note: can only be called if the required target features are available error[E0133]: call to function `Quux::avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:39:5 + --> $DIR/safe-calls.rs:44:5 | LL | Quux.avx_bmi2(); | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` @@ -39,7 +39,7 @@ LL | Quux.avx_bmi2(); = note: can only be called if the required target features are available error[E0133]: call to function `sse2` with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:46:5 + --> $DIR/safe-calls.rs:51:5 | LL | sse2(); | ^^^^^^ call to function with `#[target_feature]` @@ -47,7 +47,7 @@ LL | sse2(); = note: can only be called if the required target features are available error[E0133]: call to function `avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:49:5 + --> $DIR/safe-calls.rs:54:5 | LL | avx_bmi2(); | ^^^^^^^^^^ call to function with `#[target_feature]` @@ -55,7 +55,7 @@ LL | avx_bmi2(); = note: can only be called if the required target features are available error[E0133]: call to function `Quux::avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:52:5 + --> $DIR/safe-calls.rs:57:5 | LL | Quux.avx_bmi2(); | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` @@ -63,7 +63,7 @@ LL | Quux.avx_bmi2(); = note: can only be called if the required target features are available error[E0133]: call to function `sse2` with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:60:5 + --> $DIR/safe-calls.rs:65:5 | LL | sse2(); | ^^^^^^ call to function with `#[target_feature]` @@ -71,13 +71,21 @@ LL | sse2(); = note: can only be called if the required target features are available error[E0133]: call to function `sse2` with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:65:18 + --> $DIR/safe-calls.rs:70:15 | -LL | const name: () = sse2(); - | ^^^^^^ call to function with `#[target_feature]` +LL | const _: () = sse2(); + | ^^^^^^ call to function with `#[target_feature]` | = note: can only be called if the required target features are available -error: aborting due to 10 previous errors +error[E0133]: call to function `sse2_and_fxsr` with `#[target_feature]` is unsafe and requires unsafe function or block + --> $DIR/safe-calls.rs:74:15 + | +LL | const _: () = sse2_and_fxsr(); + | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` + | + = note: can only be called if the required target features are available + +error: aborting due to 11 previous errors For more information about this error, try `rustc --explain E0133`. From 6b066a9305f03425c6627c16419d0d7197a4c526 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20S=C3=A1nchez=20Mu=C3=B1oz?= Date: Tue, 28 Nov 2023 20:37:02 +0100 Subject: [PATCH 2/2] thir-unsafeck: print list of missing target features when calling a function with target features outside an unsafe block --- compiler/rustc_mir_build/messages.ftl | 36 ++++++++- .../rustc_mir_build/src/check_unsafety.rs | 80 ++++++++++++++++--- compiler/rustc_mir_build/src/errors.rs | 25 +++++- .../safe-calls.mir.stderr | 21 ++++- .../rfc-2396-target_feature-11/safe-calls.rs | 9 +++ .../safe-calls.thir.stderr | 48 ++++++++--- 6 files changed, 187 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl index 7dd0e7d4b928b..c8d6c2114e9eb 100644 --- a/compiler/rustc_mir_build/messages.ftl +++ b/compiler/rustc_mir_build/messages.ftl @@ -30,12 +30,32 @@ mir_build_borrow_of_moved_value = borrow of moved value mir_build_call_to_fn_with_requires_unsafe = call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe block - .note = can only be called if the required target features are available + .help = in order for the call to be safe, the context requires the following additional target {$missing_target_features_count -> + [1] feature + *[count] features + }: {$missing_target_features} + .note = the {$build_target_features} target {$build_target_features_count -> + [1] feature + *[count] features + } being enabled in the build configuration does not remove the requirement to list {$build_target_features_count -> + [1] it + *[count] them + } in `#[target_feature]` .label = call to function with `#[target_feature]` mir_build_call_to_fn_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe function or block - .note = can only be called if the required target features are available + .help = in order for the call to be safe, the context requires the following additional target {$missing_target_features_count -> + [1] feature + *[count] features + }: {$missing_target_features} + .note = the {$build_target_features} target {$build_target_features_count -> + [1] feature + *[count] features + } being enabled in the build configuration does not remove the requirement to list {$build_target_features_count -> + [1] it + *[count] them + } in `#[target_feature]` .label = call to function with `#[target_feature]` mir_build_call_to_unsafe_fn_requires_unsafe = @@ -330,7 +350,17 @@ mir_build_unsafe_op_in_unsafe_fn_borrow_of_layout_constrained_field_requires_uns mir_build_unsafe_op_in_unsafe_fn_call_to_fn_with_requires_unsafe = call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe block (error E0133) - .note = can only be called if the required target features are available + .help = in order for the call to be safe, the context requires the following additional target {$missing_target_features_count -> + [1] feature + *[count] features + }: {$missing_target_features} + .note = the {$build_target_features} target {$build_target_features_count -> + [1] feature + *[count] features + } being enabled in the build configuration does not remove the requirement to list {$build_target_features_count -> + [1] it + *[count] them + } in `#[target_feature]` .label = call to function with `#[target_feature]` mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe = diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index db0efd1d12eff..2186fdf8dc28d 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -1,7 +1,10 @@ +use std::borrow::Cow; + use crate::build::ExprCategory; use crate::errors::*; use rustc_middle::thir::visit::{self, Visitor}; +use rustc_errors::DiagnosticArgValue; use rustc_hir as hir; use rustc_middle::mir::BorrowKind; use rustc_middle::thir::*; @@ -392,15 +395,29 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { // the call requires `unsafe`. Don't check this on wasm // targets, though. For more information on wasm see the // is_like_wasm check in hir_analysis/src/collect.rs + let callee_features = &self.tcx.codegen_fn_attrs(func_did).target_features; if !self.tcx.sess.target.options.is_like_wasm - && !self - .tcx - .codegen_fn_attrs(func_did) - .target_features + && !callee_features .iter() .all(|feature| self.body_target_features.contains(feature)) { - self.requires_unsafe(expr.span, CallToFunctionWith(func_did)); + let missing: Vec<_> = callee_features + .iter() + .copied() + .filter(|feature| !self.body_target_features.contains(feature)) + .collect(); + let build_enabled = self + .tcx + .sess + .target_features + .iter() + .copied() + .filter(|feature| missing.contains(feature)) + .collect(); + self.requires_unsafe( + expr.span, + CallToFunctionWith { function: func_did, missing, build_enabled }, + ); } } } @@ -526,7 +543,7 @@ struct UnusedUnsafeWarning { enclosing_unsafe: Option, } -#[derive(Clone, Copy, PartialEq)] +#[derive(Clone, PartialEq)] enum UnsafeOpKind { CallToUnsafeFunction(Option), UseOfInlineAssembly, @@ -537,7 +554,15 @@ enum UnsafeOpKind { AccessToUnionField, MutationOfLayoutConstrainedField, BorrowOfLayoutConstrainedField, - CallToFunctionWith(DefId), + CallToFunctionWith { + function: DefId, + /// Target features enabled in callee's `#[target_feature]` but missing in + /// caller's `#[target_feature]`. + missing: Vec, + /// Target features in `missing` that are enabled at compile time + /// (e.g., with `-C target-feature`). + build_enabled: Vec, + }, } use UnsafeOpKind::*; @@ -658,13 +683,22 @@ impl UnsafeOpKind { unsafe_not_inherited_note, }, ), - CallToFunctionWith(did) => tcx.emit_spanned_lint( + CallToFunctionWith { function, missing, build_enabled } => tcx.emit_spanned_lint( UNSAFE_OP_IN_UNSAFE_FN, hir_id, span, UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe { span, - function: &with_no_trimmed_paths!(tcx.def_path_str(*did)), + function: &with_no_trimmed_paths!(tcx.def_path_str(*function)), + missing_target_features: DiagnosticArgValue::StrListSepByAnd( + missing.iter().map(|feature| Cow::from(feature.as_str())).collect(), + ), + missing_target_features_count: missing.len(), + note: if build_enabled.is_empty() { None } else { Some(()) }, + build_target_features: DiagnosticArgValue::StrListSepByAnd( + build_enabled.iter().map(|feature| Cow::from(feature.as_str())).collect(), + ), + build_target_features_count: build_enabled.len(), unsafe_not_inherited_note, }, ), @@ -821,18 +855,38 @@ impl UnsafeOpKind { unsafe_not_inherited_note, }); } - CallToFunctionWith(did) if unsafe_op_in_unsafe_fn_allowed => { + CallToFunctionWith { function, missing, build_enabled } + if unsafe_op_in_unsafe_fn_allowed => + { tcx.sess.emit_err(CallToFunctionWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span, + missing_target_features: DiagnosticArgValue::StrListSepByAnd( + missing.iter().map(|feature| Cow::from(feature.as_str())).collect(), + ), + missing_target_features_count: missing.len(), + note: if build_enabled.is_empty() { None } else { Some(()) }, + build_target_features: DiagnosticArgValue::StrListSepByAnd( + build_enabled.iter().map(|feature| Cow::from(feature.as_str())).collect(), + ), + build_target_features_count: build_enabled.len(), unsafe_not_inherited_note, - function: &tcx.def_path_str(*did), + function: &tcx.def_path_str(*function), }); } - CallToFunctionWith(did) => { + CallToFunctionWith { function, missing, build_enabled } => { tcx.sess.emit_err(CallToFunctionWithRequiresUnsafe { span, + missing_target_features: DiagnosticArgValue::StrListSepByAnd( + missing.iter().map(|feature| Cow::from(feature.as_str())).collect(), + ), + missing_target_features_count: missing.len(), + note: if build_enabled.is_empty() { None } else { Some(()) }, + build_target_features: DiagnosticArgValue::StrListSepByAnd( + build_enabled.iter().map(|feature| Cow::from(feature.as_str())).collect(), + ), + build_target_features_count: build_enabled.len(), unsafe_not_inherited_note, - function: &tcx.def_path_str(*did), + function: &tcx.def_path_str(*function), }); } } diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 418f9bb9de94d..8d2a559e73ce4 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -2,6 +2,7 @@ use crate::{ fluent_generated as fluent, thir::pattern::{deconstruct_pat::WitnessPat, MatchCheckCtxt}, }; +use rustc_errors::DiagnosticArgValue; use rustc_errors::{ error_code, AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, Handler, IntoDiagnostic, MultiSpan, SubdiagnosticMessage, @@ -124,11 +125,17 @@ pub struct UnsafeOpInUnsafeFnBorrowOfLayoutConstrainedFieldRequiresUnsafe { #[derive(LintDiagnostic)] #[diag(mir_build_unsafe_op_in_unsafe_fn_call_to_fn_with_requires_unsafe)] -#[note] +#[help] pub struct UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe<'a> { #[label] pub span: Span, pub function: &'a str, + pub missing_target_features: DiagnosticArgValue<'a>, + pub missing_target_features_count: usize, + #[note] + pub note: Option<()>, + pub build_target_features: DiagnosticArgValue<'a>, + pub build_target_features_count: usize, #[subdiagnostic] pub unsafe_not_inherited_note: Option, } @@ -369,24 +376,36 @@ pub struct BorrowOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed #[derive(Diagnostic)] #[diag(mir_build_call_to_fn_with_requires_unsafe, code = "E0133")] -#[note] +#[help] pub struct CallToFunctionWithRequiresUnsafe<'a> { #[primary_span] #[label] pub span: Span, pub function: &'a str, + pub missing_target_features: DiagnosticArgValue<'a>, + pub missing_target_features_count: usize, + #[note] + pub note: Option<()>, + pub build_target_features: DiagnosticArgValue<'a>, + pub build_target_features_count: usize, #[subdiagnostic] pub unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] #[diag(mir_build_call_to_fn_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")] -#[note] +#[help] pub struct CallToFunctionWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed<'a> { #[primary_span] #[label] pub span: Span, pub function: &'a str, + pub missing_target_features: DiagnosticArgValue<'a>, + pub missing_target_features_count: usize, + #[note] + pub note: Option<()>, + pub build_target_features: DiagnosticArgValue<'a>, + pub build_target_features_count: usize, #[subdiagnostic] pub unsafe_not_inherited_note: Option, } diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.mir.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.mir.stderr index c925034b253f4..cabc475fa61cf 100644 --- a/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.mir.stderr +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.mir.stderr @@ -91,6 +91,25 @@ LL | const _: () = sse2_and_fxsr(); = help: in order for the call to be safe, the context requires the following additional target features: sse2 and fxsr = note: the fxsr and sse2 target features being enabled in the build configuration does not remove the requirement to list them in `#[target_feature]` -error: aborting due to 11 previous errors +error: call to function with `#[target_feature]` is unsafe and requires unsafe block (error E0133) + --> $DIR/safe-calls.rs:82:5 + | +LL | sse2(); + | ^^^^^^ call to function with `#[target_feature]` + | + = help: in order for the call to be safe, the context requires the following additional target feature: sse2 + = note: the sse2 target feature being enabled in the build configuration does not remove the requirement to list it in `#[target_feature]` +note: an unsafe function restricts its caller, but its body is safe by default + --> $DIR/safe-calls.rs:81:1 + | +LL | unsafe fn needs_unsafe_block() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: the lint level is defined here + --> $DIR/safe-calls.rs:78:8 + | +LL | #[deny(unsafe_op_in_unsafe_fn)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 12 previous errors For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.rs b/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.rs index db9cf97282a3f..f17dab269bc4b 100644 --- a/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.rs +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.rs @@ -75,4 +75,13 @@ const _: () = sse2_and_fxsr(); //[mir]~^ ERROR call to function with `#[target_feature]` is unsafe //[thir]~^^ ERROR call to function `sse2_and_fxsr` with `#[target_feature]` is unsafe +#[deny(unsafe_op_in_unsafe_fn)] +#[target_feature(enable = "avx")] +#[target_feature(enable = "bmi2")] +unsafe fn needs_unsafe_block() { + sse2(); + //[mir]~^ ERROR call to function with `#[target_feature]` is unsafe + //[thir]~^^ ERROR call to function `sse2` with `#[target_feature]` is unsafe +} + fn main() {} diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.thir.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.thir.stderr index 28a7adb012bdd..13b58fde862d5 100644 --- a/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.thir.stderr +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.thir.stderr @@ -4,7 +4,8 @@ error[E0133]: call to function `sse2` with `#[target_feature]` is unsafe and req LL | sse2(); | ^^^^^^ call to function with `#[target_feature]` | - = note: can only be called if the required target features are available + = help: in order for the call to be safe, the context requires the following additional target feature: sse2 + = note: the sse2 target feature being enabled in the build configuration does not remove the requirement to list it in `#[target_feature]` error[E0133]: call to function `avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block --> $DIR/safe-calls.rs:31:5 @@ -12,7 +13,7 @@ error[E0133]: call to function `avx_bmi2` with `#[target_feature]` is unsafe and LL | avx_bmi2(); | ^^^^^^^^^^ call to function with `#[target_feature]` | - = note: can only be called if the required target features are available + = help: in order for the call to be safe, the context requires the following additional target features: avx and bmi2 error[E0133]: call to function `Quux::avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block --> $DIR/safe-calls.rs:34:5 @@ -20,7 +21,7 @@ error[E0133]: call to function `Quux::avx_bmi2` with `#[target_feature]` is unsa LL | Quux.avx_bmi2(); | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` | - = note: can only be called if the required target features are available + = help: in order for the call to be safe, the context requires the following additional target features: avx and bmi2 error[E0133]: call to function `avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block --> $DIR/safe-calls.rs:41:5 @@ -28,7 +29,7 @@ error[E0133]: call to function `avx_bmi2` with `#[target_feature]` is unsafe and LL | avx_bmi2(); | ^^^^^^^^^^ call to function with `#[target_feature]` | - = note: can only be called if the required target features are available + = help: in order for the call to be safe, the context requires the following additional target features: avx and bmi2 error[E0133]: call to function `Quux::avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block --> $DIR/safe-calls.rs:44:5 @@ -36,7 +37,7 @@ error[E0133]: call to function `Quux::avx_bmi2` with `#[target_feature]` is unsa LL | Quux.avx_bmi2(); | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` | - = note: can only be called if the required target features are available + = help: in order for the call to be safe, the context requires the following additional target features: avx and bmi2 error[E0133]: call to function `sse2` with `#[target_feature]` is unsafe and requires unsafe function or block --> $DIR/safe-calls.rs:51:5 @@ -44,7 +45,8 @@ error[E0133]: call to function `sse2` with `#[target_feature]` is unsafe and req LL | sse2(); | ^^^^^^ call to function with `#[target_feature]` | - = note: can only be called if the required target features are available + = help: in order for the call to be safe, the context requires the following additional target feature: sse2 + = note: the sse2 target feature being enabled in the build configuration does not remove the requirement to list it in `#[target_feature]` error[E0133]: call to function `avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block --> $DIR/safe-calls.rs:54:5 @@ -52,7 +54,7 @@ error[E0133]: call to function `avx_bmi2` with `#[target_feature]` is unsafe and LL | avx_bmi2(); | ^^^^^^^^^^ call to function with `#[target_feature]` | - = note: can only be called if the required target features are available + = help: in order for the call to be safe, the context requires the following additional target feature: bmi2 error[E0133]: call to function `Quux::avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block --> $DIR/safe-calls.rs:57:5 @@ -60,7 +62,7 @@ error[E0133]: call to function `Quux::avx_bmi2` with `#[target_feature]` is unsa LL | Quux.avx_bmi2(); | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` | - = note: can only be called if the required target features are available + = help: in order for the call to be safe, the context requires the following additional target feature: bmi2 error[E0133]: call to function `sse2` with `#[target_feature]` is unsafe and requires unsafe function or block --> $DIR/safe-calls.rs:65:5 @@ -68,7 +70,8 @@ error[E0133]: call to function `sse2` with `#[target_feature]` is unsafe and req LL | sse2(); | ^^^^^^ call to function with `#[target_feature]` | - = note: can only be called if the required target features are available + = help: in order for the call to be safe, the context requires the following additional target feature: sse2 + = note: the sse2 target feature being enabled in the build configuration does not remove the requirement to list it in `#[target_feature]` error[E0133]: call to function `sse2` with `#[target_feature]` is unsafe and requires unsafe function or block --> $DIR/safe-calls.rs:70:15 @@ -76,7 +79,8 @@ error[E0133]: call to function `sse2` with `#[target_feature]` is unsafe and req LL | const _: () = sse2(); | ^^^^^^ call to function with `#[target_feature]` | - = note: can only be called if the required target features are available + = help: in order for the call to be safe, the context requires the following additional target feature: sse2 + = note: the sse2 target feature being enabled in the build configuration does not remove the requirement to list it in `#[target_feature]` error[E0133]: call to function `sse2_and_fxsr` with `#[target_feature]` is unsafe and requires unsafe function or block --> $DIR/safe-calls.rs:74:15 @@ -84,8 +88,28 @@ error[E0133]: call to function `sse2_and_fxsr` with `#[target_feature]` is unsaf LL | const _: () = sse2_and_fxsr(); | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` | - = note: can only be called if the required target features are available + = help: in order for the call to be safe, the context requires the following additional target features: sse2 and fxsr + = note: the fxsr and sse2 target features being enabled in the build configuration does not remove the requirement to list them in `#[target_feature]` -error: aborting due to 11 previous errors +error: call to function `sse2` with `#[target_feature]` is unsafe and requires unsafe block (error E0133) + --> $DIR/safe-calls.rs:82:5 + | +LL | sse2(); + | ^^^^^^ call to function with `#[target_feature]` + | + = help: in order for the call to be safe, the context requires the following additional target feature: sse2 + = note: the sse2 target feature being enabled in the build configuration does not remove the requirement to list it in `#[target_feature]` +note: an unsafe function restricts its caller, but its body is safe by default + --> $DIR/safe-calls.rs:81:1 + | +LL | unsafe fn needs_unsafe_block() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: the lint level is defined here + --> $DIR/safe-calls.rs:78:8 + | +LL | #[deny(unsafe_op_in_unsafe_fn)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 12 previous errors For more information about this error, try `rustc --explain E0133`.