Print list of missing target features when calling a function with target features outside an unsafe block

This commit is contained in:
Eduardo Sánchez Muñoz 2023-11-26 19:55:01 +01:00
parent 274b5249eb
commit 51ba662d23
7 changed files with 191 additions and 95 deletions

View File

@ -27,7 +27,7 @@ pub enum UnsafetyViolationKind {
UnsafeFn, UnsafeFn,
} }
#[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)] #[derive(Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)]
pub enum UnsafetyViolationDetails { pub enum UnsafetyViolationDetails {
CallToUnsafeFunction, CallToUnsafeFunction,
UseOfInlineAssembly, UseOfInlineAssembly,
@ -39,10 +39,17 @@ pub enum UnsafetyViolationDetails {
AccessToUnionField, AccessToUnionField,
MutationOfLayoutConstrainedField, MutationOfLayoutConstrainedField,
BorrowOfLayoutConstrainedField, BorrowOfLayoutConstrainedField,
CallToFunctionWith, CallToFunctionWith {
/// Target features enabled in callee's `#[target_feature]` but missing in
/// caller's `#[target_feature]`.
missing: Vec<Symbol>,
/// Target features in `missing` that are enabled at compile time
/// (e.g., with `-C target-feature`).
build_enabled: Vec<Symbol>,
},
} }
#[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)] #[derive(Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)]
pub struct UnsafetyViolation { pub struct UnsafetyViolation {
pub source_info: SourceInfo, pub source_info: SourceInfo,
pub lint_root: hir::HirId, pub lint_root: hir::HirId,

View File

@ -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 .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_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 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 .note = packed structs are only aligned by one byte, and many modern architectures penalize unaligned field accesses

View File

@ -287,19 +287,20 @@ impl<'tcx> UnsafetyChecker<'_, 'tcx> {
.safety; .safety;
match safety { match safety {
// `unsafe` blocks are required in safe code // `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 { match violation.kind {
UnsafetyViolationKind::General => {} UnsafetyViolationKind::General => {}
UnsafetyViolationKind::UnsafeFn => { UnsafetyViolationKind::UnsafeFn => {
bug!("`UnsafetyViolationKind::UnsafeFn` in an `Safe` context") bug!("`UnsafetyViolationKind::UnsafeFn` in an `Safe` context")
} }
} }
if !self.violations.contains(&violation) { if !self.violations.contains(violation) {
self.violations.push(violation) self.violations.push(violation.clone())
} }
}), }),
// With the RFC 2585, no longer allow `unsafe` operations in `unsafe fn`s // 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; violation.kind = UnsafetyViolationKind::UnsafeFn;
if !self.violations.contains(&violation) { if !self.violations.contains(&violation) {
self.violations.push(violation) self.violations.push(violation)
@ -367,9 +368,22 @@ impl<'tcx> UnsafetyChecker<'_, 'tcx> {
// Is `callee_features` a subset of `calling_features`? // Is `callee_features` a subset of `calling_features`?
if !callee_features.iter().all(|feature| self_features.contains(feature)) { 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( self.require_unsafe(
UnsafetyViolationKind::General, 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 // Only suggest wrapping the entire function body in an unsafe block once
let mut suggest_unsafe_block = true; let mut suggest_unsafe_block = true;
for &UnsafetyViolation { source_info, lint_root, kind, details } in violations.iter() { for &UnsafetyViolation { source_info, lint_root, kind, ref details } in violations.iter() {
let details = errors::RequiresUnsafeDetail { violation: details, span: source_info.span }; let details =
errors::RequiresUnsafeDetail { violation: details.clone(), span: source_info.span };
match kind { match kind {
UnsafetyViolationKind::General => { UnsafetyViolationKind::General => {

View File

@ -1,6 +1,8 @@
use std::borrow::Cow;
use rustc_errors::{ use rustc_errors::{
Applicability, DecorateLint, DiagnosticBuilder, DiagnosticMessage, EmissionGuarantee, Handler, Applicability, DecorateLint, DiagnosticArgValue, DiagnosticBuilder, DiagnosticMessage,
IntoDiagnostic, EmissionGuarantee, Handler, IntoDiagnostic,
}; };
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
use rustc_middle::mir::{AssertKind, UnsafetyViolationDetails}; 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::def_id::DefId;
use rustc_span::Span; use rustc_span::Span;
use crate::fluent_generated as fluent;
#[derive(LintDiagnostic)] #[derive(LintDiagnostic)]
pub(crate) enum ConstMutate { pub(crate) enum ConstMutate {
#[diag(mir_transform_const_modify)] #[diag(mir_transform_const_modify)]
@ -61,72 +65,105 @@ pub(crate) struct RequiresUnsafe {
impl<'sess, G: EmissionGuarantee> IntoDiagnostic<'sess, G> for RequiresUnsafe { impl<'sess, G: EmissionGuarantee> IntoDiagnostic<'sess, G> for RequiresUnsafe {
#[track_caller] #[track_caller]
fn into_diagnostic(self, handler: &'sess Handler) -> DiagnosticBuilder<'sess, G> { fn into_diagnostic(self, handler: &'sess Handler) -> DiagnosticBuilder<'sess, G> {
let mut diag = let mut diag = handler.struct_diagnostic(fluent::mir_transform_requires_unsafe);
handler.struct_diagnostic(crate::fluent_generated::mir_transform_requires_unsafe);
diag.code(rustc_errors::DiagnosticId::Error("E0133".to_string())); diag.code(rustc_errors::DiagnosticId::Error("E0133".to_string()));
diag.set_span(self.span); diag.set_span(self.span);
diag.span_label(self.span, self.details.label()); 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()); let desc = handler.eagerly_translate_to_string(self.details.label(), [].into_iter());
diag.set_arg("details", desc); diag.set_arg("details", desc);
diag.set_arg("op_in_unsafe_fn_allowed", self.op_in_unsafe_fn_allowed); 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 { 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 diag
} }
} }
#[derive(Copy, Clone)] #[derive(Clone)]
pub(crate) struct RequiresUnsafeDetail { pub(crate) struct RequiresUnsafeDetail {
pub span: Span, pub span: Span,
pub violation: UnsafetyViolationDetails, pub violation: UnsafetyViolationDetails,
} }
impl RequiresUnsafeDetail { impl RequiresUnsafeDetail {
fn note(self) -> DiagnosticMessage { fn add_subdiagnostics<G: EmissionGuarantee>(&self, diag: &mut DiagnosticBuilder<'_, G>) {
use UnsafetyViolationDetails::*; use UnsafetyViolationDetails::*;
match self.violation { match self.violation {
CallToUnsafeFunction => crate::fluent_generated::mir_transform_call_to_unsafe_note, CallToUnsafeFunction => {
UseOfInlineAssembly => crate::fluent_generated::mir_transform_use_of_asm_note, diag.note(fluent::mir_transform_call_to_unsafe_note);
InitializingTypeWith => { }
crate::fluent_generated::mir_transform_initializing_valid_range_note UseOfInlineAssembly => {
diag.note(fluent::mir_transform_use_of_asm_note);
}
InitializingTypeWith => {
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 => { MutationOfLayoutConstrainedField => {
crate::fluent_generated::mir_transform_mutation_layout_constrained_note diag.note(fluent::mir_transform_mutation_layout_constrained_note);
} }
BorrowOfLayoutConstrainedField => { 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::*; use UnsafetyViolationDetails::*;
match self.violation { match self.violation {
CallToUnsafeFunction => crate::fluent_generated::mir_transform_call_to_unsafe_label, CallToUnsafeFunction => fluent::mir_transform_call_to_unsafe_label,
UseOfInlineAssembly => crate::fluent_generated::mir_transform_use_of_asm_label, UseOfInlineAssembly => fluent::mir_transform_use_of_asm_label,
InitializingTypeWith => { InitializingTypeWith => fluent::mir_transform_initializing_valid_range_label,
crate::fluent_generated::mir_transform_initializing_valid_range_label CastOfPointerToInt => fluent::mir_transform_const_ptr2int_label,
} UseOfMutableStatic => fluent::mir_transform_use_of_static_mut_label,
CastOfPointerToInt => crate::fluent_generated::mir_transform_const_ptr2int_label, UseOfExternStatic => fluent::mir_transform_use_of_extern_static_label,
UseOfMutableStatic => crate::fluent_generated::mir_transform_use_of_static_mut_label, DerefOfRawPointer => fluent::mir_transform_deref_ptr_label,
UseOfExternStatic => crate::fluent_generated::mir_transform_use_of_extern_static_label, AccessToUnionField => fluent::mir_transform_union_access_label,
DerefOfRawPointer => crate::fluent_generated::mir_transform_deref_ptr_label,
AccessToUnionField => crate::fluent_generated::mir_transform_union_access_label,
MutationOfLayoutConstrainedField => { MutationOfLayoutConstrainedField => {
crate::fluent_generated::mir_transform_mutation_layout_constrained_label fluent::mir_transform_mutation_layout_constrained_label
} }
BorrowOfLayoutConstrainedField => { 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()); let desc = handler.eagerly_translate_to_string(self.details.label(), [].into_iter());
diag.set_arg("details", desc); diag.set_arg("details", desc);
diag.span_label(self.details.span, self.details.label()); 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 { 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( diag.tool_only_multipart_suggestion(
crate::fluent_generated::mir_transform_suggestion, fluent::mir_transform_suggestion,
vec![(start, " unsafe {".into()), (end, "}".into())], vec![(start, " unsafe {".into()), (end, "}".into())],
Applicability::MaybeIncorrect, Applicability::MaybeIncorrect,
); );
@ -166,7 +203,7 @@ impl<'a> DecorateLint<'a, ()> for UnsafeOpInUnsafeFn {
} }
fn msg(&self) -> DiagnosticMessage { 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<P> {
fn msg(&self) -> DiagnosticMessage { fn msg(&self) -> DiagnosticMessage {
match self { match self {
AssertLint::ArithmeticOverflow(..) => { AssertLint::ArithmeticOverflow(..) => fluent::mir_transform_arithmetic_overflow,
crate::fluent_generated::mir_transform_arithmetic_overflow AssertLint::UnconditionalPanic(..) => fluent::mir_transform_operation_will_panic,
}
AssertLint::UnconditionalPanic(..) => {
crate::fluent_generated::mir_transform_operation_will_panic
}
} }
} }
} }
@ -255,11 +288,11 @@ impl<'a> DecorateLint<'a, ()> for MustNotSupend<'_, '_> {
self, self,
diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>, diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>,
) -> &'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 { if let Some(reason) = self.reason {
diag.subdiagnostic(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("pre", self.pre);
diag.set_arg("def_path", self.tcx.def_path_str(self.def_id)); diag.set_arg("def_path", self.tcx.def_path_str(self.def_id));
diag.set_arg("post", self.post); diag.set_arg("post", self.post);
@ -267,7 +300,7 @@ impl<'a> DecorateLint<'a, ()> for MustNotSupend<'_, '_> {
} }
fn msg(&self) -> rustc_errors::DiagnosticMessage { fn msg(&self) -> rustc_errors::DiagnosticMessage {
crate::fluent_generated::mir_transform_must_not_suspend fluent::mir_transform_must_not_suspend
} }
} }

View File

@ -1,83 +1,96 @@
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block 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(); LL | sse2();
| ^^^^^^ call to function with `#[target_feature]` | ^^^^^^ 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 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(); LL | avx_bmi2();
| ^^^^^^^^^^ call to function with `#[target_feature]` | ^^^^^^^^^^ 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 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(); LL | Quux.avx_bmi2();
| ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` | ^^^^^^^^^^^^^^^ 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 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(); LL | avx_bmi2();
| ^^^^^^^^^^ call to function with `#[target_feature]` | ^^^^^^^^^^ 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 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(); LL | Quux.avx_bmi2();
| ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` | ^^^^^^^^^^^^^^^ 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 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(); LL | sse2();
| ^^^^^^ call to function with `#[target_feature]` | ^^^^^^ 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 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(); LL | avx_bmi2();
| ^^^^^^^^^^ call to function with `#[target_feature]` | ^^^^^^^^^^ 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 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(); LL | Quux.avx_bmi2();
| ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` | ^^^^^^^^^^^^^^^ 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 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(); LL | sse2();
| ^^^^^^ call to function with `#[target_feature]` | ^^^^^^ 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 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(); LL | const _: () = sse2();
| ^^^^^^ call to function with `#[target_feature]` | ^^^^^^ 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`. For more information about this error, try `rustc --explain E0133`.

View File

@ -7,6 +7,11 @@
#[target_feature(enable = "sse2")] #[target_feature(enable = "sse2")]
const fn sse2() {} const fn sse2() {}
#[target_feature(enable = "sse2")]
#[target_feature(enable = "fxsr")]
const fn sse2_and_fxsr() {}
#[target_feature(enable = "avx")] #[target_feature(enable = "avx")]
#[target_feature(enable = "bmi2")] #[target_feature(enable = "bmi2")]
fn avx_bmi2() {} fn avx_bmi2() {}
@ -62,8 +67,12 @@ fn qux() {
//[thir]~^^ ERROR call to function `sse2` with `#[target_feature]` is unsafe //[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 //[mir]~^ ERROR call to function with `#[target_feature]` is unsafe
//[thir]~^^ ERROR call to function `sse2` 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() {} fn main() {}

View File

@ -1,5 +1,5 @@
error[E0133]: call to function `sse2` with `#[target_feature]` is unsafe and requires unsafe function or block 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(); LL | sse2();
| ^^^^^^ call to function with `#[target_feature]` | ^^^^^^ call to function with `#[target_feature]`
@ -7,7 +7,7 @@ LL | sse2();
= note: can only be called if the required target features are available = 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 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(); LL | avx_bmi2();
| ^^^^^^^^^^ call to function with `#[target_feature]` | ^^^^^^^^^^ 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 = 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 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(); LL | Quux.avx_bmi2();
| ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` | ^^^^^^^^^^^^^^^ 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 = 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 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(); LL | avx_bmi2();
| ^^^^^^^^^^ call to function with `#[target_feature]` | ^^^^^^^^^^ 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 = 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 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(); LL | Quux.avx_bmi2();
| ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` | ^^^^^^^^^^^^^^^ 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 = 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 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(); LL | sse2();
| ^^^^^^ call to function with `#[target_feature]` | ^^^^^^ call to function with `#[target_feature]`
@ -47,7 +47,7 @@ LL | sse2();
= note: can only be called if the required target features are available = 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 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(); LL | avx_bmi2();
| ^^^^^^^^^^ call to function with `#[target_feature]` | ^^^^^^^^^^ 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 = 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 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(); LL | Quux.avx_bmi2();
| ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` | ^^^^^^^^^^^^^^^ 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 = 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 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(); LL | sse2();
| ^^^^^^ call to function with `#[target_feature]` | ^^^^^^ call to function with `#[target_feature]`
@ -71,13 +71,21 @@ LL | sse2();
= note: can only be called if the required target features are available = 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 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(); LL | const _: () = sse2();
| ^^^^^^ call to function with `#[target_feature]` | ^^^^^^ call to function with `#[target_feature]`
| |
= note: can only be called if the required target features are available = 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`. For more information about this error, try `rustc --explain E0133`.