Rollup merge of #118333 - eduardosm:print-missing-target-features, r=est31
Print list of missing target features when calling a function with target features outside an unsafe block Fixes https://github.com/rust-lang/rust/issues/108680 Supersedes https://github.com/rust-lang/rust/pull/109710. I used the same wording for the messages, but the implementation is different. r? `@est31`
This commit is contained in:
commit
911a5ee7ff
10 changed files with 375 additions and 124 deletions
|
@ -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,
|
||||||
|
|
|
@ -30,12 +30,32 @@ mir_build_borrow_of_moved_value = borrow of moved value
|
||||||
|
|
||||||
mir_build_call_to_fn_with_requires_unsafe =
|
mir_build_call_to_fn_with_requires_unsafe =
|
||||||
call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe block
|
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]`
|
.label = call to function with `#[target_feature]`
|
||||||
|
|
||||||
mir_build_call_to_fn_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
|
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
|
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]`
|
.label = call to function with `#[target_feature]`
|
||||||
|
|
||||||
mir_build_call_to_unsafe_fn_requires_unsafe =
|
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 =
|
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)
|
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]`
|
.label = call to function with `#[target_feature]`
|
||||||
|
|
||||||
mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe =
|
mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe =
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
|
use std::borrow::Cow;
|
||||||
|
|
||||||
use crate::build::ExprCategory;
|
use crate::build::ExprCategory;
|
||||||
use crate::errors::*;
|
use crate::errors::*;
|
||||||
use rustc_middle::thir::visit::{self, Visitor};
|
use rustc_middle::thir::visit::{self, Visitor};
|
||||||
|
|
||||||
|
use rustc_errors::DiagnosticArgValue;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_middle::mir::BorrowKind;
|
use rustc_middle::mir::BorrowKind;
|
||||||
use rustc_middle::thir::*;
|
use rustc_middle::thir::*;
|
||||||
|
@ -393,15 +396,29 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
|
||||||
// the call requires `unsafe`. Don't check this on wasm
|
// the call requires `unsafe`. Don't check this on wasm
|
||||||
// targets, though. For more information on wasm see the
|
// targets, though. For more information on wasm see the
|
||||||
// is_like_wasm check in hir_analysis/src/collect.rs
|
// 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
|
if !self.tcx.sess.target.options.is_like_wasm
|
||||||
&& !self
|
&& !callee_features
|
||||||
.tcx
|
|
||||||
.codegen_fn_attrs(func_did)
|
|
||||||
.target_features
|
|
||||||
.iter()
|
.iter()
|
||||||
.all(|feature| self.body_target_features.contains(feature))
|
.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 },
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -527,7 +544,7 @@ struct UnusedUnsafeWarning {
|
||||||
enclosing_unsafe: Option<UnusedUnsafeEnclosing>,
|
enclosing_unsafe: Option<UnusedUnsafeEnclosing>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq)]
|
#[derive(Clone, PartialEq)]
|
||||||
enum UnsafeOpKind {
|
enum UnsafeOpKind {
|
||||||
CallToUnsafeFunction(Option<DefId>),
|
CallToUnsafeFunction(Option<DefId>),
|
||||||
UseOfInlineAssembly,
|
UseOfInlineAssembly,
|
||||||
|
@ -538,7 +555,15 @@ enum UnsafeOpKind {
|
||||||
AccessToUnionField,
|
AccessToUnionField,
|
||||||
MutationOfLayoutConstrainedField,
|
MutationOfLayoutConstrainedField,
|
||||||
BorrowOfLayoutConstrainedField,
|
BorrowOfLayoutConstrainedField,
|
||||||
CallToFunctionWith(DefId),
|
CallToFunctionWith {
|
||||||
|
function: DefId,
|
||||||
|
/// 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>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
use UnsafeOpKind::*;
|
use UnsafeOpKind::*;
|
||||||
|
@ -659,13 +684,22 @@ impl UnsafeOpKind {
|
||||||
unsafe_not_inherited_note,
|
unsafe_not_inherited_note,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
CallToFunctionWith(did) => tcx.emit_spanned_lint(
|
CallToFunctionWith { function, missing, build_enabled } => tcx.emit_spanned_lint(
|
||||||
UNSAFE_OP_IN_UNSAFE_FN,
|
UNSAFE_OP_IN_UNSAFE_FN,
|
||||||
hir_id,
|
hir_id,
|
||||||
span,
|
span,
|
||||||
UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe {
|
UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe {
|
||||||
span,
|
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,
|
unsafe_not_inherited_note,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -822,18 +856,38 @@ impl UnsafeOpKind {
|
||||||
unsafe_not_inherited_note,
|
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 {
|
tcx.sess.emit_err(CallToFunctionWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
|
||||||
span,
|
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,
|
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 {
|
tcx.sess.emit_err(CallToFunctionWithRequiresUnsafe {
|
||||||
span,
|
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,
|
unsafe_not_inherited_note,
|
||||||
function: &tcx.def_path_str(*did),
|
function: &tcx.def_path_str(*function),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ use crate::{
|
||||||
fluent_generated as fluent,
|
fluent_generated as fluent,
|
||||||
thir::pattern::{deconstruct_pat::WitnessPat, MatchCheckCtxt},
|
thir::pattern::{deconstruct_pat::WitnessPat, MatchCheckCtxt},
|
||||||
};
|
};
|
||||||
|
use rustc_errors::DiagnosticArgValue;
|
||||||
use rustc_errors::{
|
use rustc_errors::{
|
||||||
error_code, AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
|
error_code, AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
|
||||||
Handler, IntoDiagnostic, MultiSpan, SubdiagnosticMessage,
|
Handler, IntoDiagnostic, MultiSpan, SubdiagnosticMessage,
|
||||||
|
@ -124,11 +125,17 @@ pub struct UnsafeOpInUnsafeFnBorrowOfLayoutConstrainedFieldRequiresUnsafe {
|
||||||
|
|
||||||
#[derive(LintDiagnostic)]
|
#[derive(LintDiagnostic)]
|
||||||
#[diag(mir_build_unsafe_op_in_unsafe_fn_call_to_fn_with_requires_unsafe)]
|
#[diag(mir_build_unsafe_op_in_unsafe_fn_call_to_fn_with_requires_unsafe)]
|
||||||
#[note]
|
#[help]
|
||||||
pub struct UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe<'a> {
|
pub struct UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe<'a> {
|
||||||
#[label]
|
#[label]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub function: &'a str,
|
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]
|
#[subdiagnostic]
|
||||||
pub unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>,
|
pub unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>,
|
||||||
}
|
}
|
||||||
|
@ -369,24 +376,36 @@ pub struct BorrowOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(mir_build_call_to_fn_with_requires_unsafe, code = "E0133")]
|
#[diag(mir_build_call_to_fn_with_requires_unsafe, code = "E0133")]
|
||||||
#[note]
|
#[help]
|
||||||
pub struct CallToFunctionWithRequiresUnsafe<'a> {
|
pub struct CallToFunctionWithRequiresUnsafe<'a> {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
#[label]
|
#[label]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub function: &'a str,
|
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]
|
#[subdiagnostic]
|
||||||
pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
|
pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(mir_build_call_to_fn_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")]
|
#[diag(mir_build_call_to_fn_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")]
|
||||||
#[note]
|
#[help]
|
||||||
pub struct CallToFunctionWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed<'a> {
|
pub struct CallToFunctionWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed<'a> {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
#[label]
|
#[label]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub function: &'a str,
|
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]
|
#[subdiagnostic]
|
||||||
pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
|
pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 => {
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,83 +1,115 @@
|
||||||
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: 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`.
|
For more information about this error, try `rustc --explain E0133`.
|
||||||
|
|
|
@ -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,21 @@ 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
|
||||||
|
|
||||||
|
#[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() {}
|
fn main() {}
|
||||||
|
|
|
@ -1,83 +1,115 @@
|
||||||
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]`
|
||||||
|
|
|
|
||||||
= 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
|
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]`
|
||||||
|
|
|
|
||||||
= 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
|
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]`
|
||||||
|
|
|
|
||||||
= 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
|
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]`
|
||||||
|
|
|
|
||||||
= 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
|
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]`
|
||||||
|
|
|
|
||||||
= 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
|
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]`
|
||||||
|
|
|
|
||||||
= 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
|
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]`
|
||||||
|
|
|
|
||||||
= 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
|
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]`
|
||||||
|
|
|
|
||||||
= 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
|
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]`
|
||||||
|
|
|
|
||||||
= 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
|
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
|
= 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 `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]`
|
||||||
|
|
|
||||||
|
= 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: 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`.
|
For more information about this error, try `rustc --explain E0133`.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue