Auto merge of #129854 - Kobzol:revert-127537, r=lqd
Revert "Auto merge of #127537 - veluca93:struct_tf, r=BoxyUwU" This reverts https://github.com/rust-lang/rust/pull/127537 (commitacb4e8b625
), reversing changes made to100fde5246
. Opening to see if this can help resolve the recent perf. results [instability](https://rust-lang.zulipchat.com/#narrow/stream/247081-t-compiler.2Fperformance/topic/Weird.20perf.20results).
This commit is contained in:
commit
94885bc699
@ -1,6 +1,5 @@
|
|||||||
use rustc_ast::{ast, attr, MetaItemKind, NestedMetaItem};
|
use rustc_ast::{ast, attr, MetaItemKind, NestedMetaItem};
|
||||||
use rustc_attr::{list_contains_name, InlineAttr, InstructionSetAttr, OptimizeAttr};
|
use rustc_attr::{list_contains_name, InlineAttr, InstructionSetAttr, OptimizeAttr};
|
||||||
use rustc_data_structures::fx::FxHashSet;
|
|
||||||
use rustc_errors::codes::*;
|
use rustc_errors::codes::*;
|
||||||
use rustc_errors::{struct_span_code_err, DiagMessage, SubdiagMessage};
|
use rustc_errors::{struct_span_code_err, DiagMessage, SubdiagMessage};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
@ -9,7 +8,7 @@
|
|||||||
use rustc_hir::weak_lang_items::WEAK_LANG_ITEMS;
|
use rustc_hir::weak_lang_items::WEAK_LANG_ITEMS;
|
||||||
use rustc_hir::{lang_items, LangItem};
|
use rustc_hir::{lang_items, LangItem};
|
||||||
use rustc_middle::middle::codegen_fn_attrs::{
|
use rustc_middle::middle::codegen_fn_attrs::{
|
||||||
CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry, TargetFeature,
|
CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry,
|
||||||
};
|
};
|
||||||
use rustc_middle::mir::mono::Linkage;
|
use rustc_middle::mir::mono::Linkage;
|
||||||
use rustc_middle::query::Providers;
|
use rustc_middle::query::Providers;
|
||||||
@ -18,7 +17,6 @@
|
|||||||
use rustc_session::parse::feature_err;
|
use rustc_session::parse::feature_err;
|
||||||
use rustc_span::symbol::Ident;
|
use rustc_span::symbol::Ident;
|
||||||
use rustc_span::{sym, Span};
|
use rustc_span::{sym, Span};
|
||||||
use rustc_target::abi::VariantIdx;
|
|
||||||
use rustc_target::spec::{abi, SanitizerSet};
|
use rustc_target::spec::{abi, SanitizerSet};
|
||||||
|
|
||||||
use crate::errors;
|
use crate::errors;
|
||||||
@ -80,13 +78,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
|
|||||||
let mut link_ordinal_span = None;
|
let mut link_ordinal_span = None;
|
||||||
let mut no_sanitize_span = None;
|
let mut no_sanitize_span = None;
|
||||||
|
|
||||||
let fn_sig_outer = || {
|
|
||||||
use DefKind::*;
|
|
||||||
|
|
||||||
let def_kind = tcx.def_kind(did);
|
|
||||||
if let Fn | AssocFn | Variant | Ctor(..) = def_kind { Some(tcx.fn_sig(did)) } else { None }
|
|
||||||
};
|
|
||||||
|
|
||||||
for attr in attrs.iter() {
|
for attr in attrs.iter() {
|
||||||
// In some cases, attribute are only valid on functions, but it's the `check_attr`
|
// In some cases, attribute are only valid on functions, but it's the `check_attr`
|
||||||
// pass that check that they aren't used anywhere else, rather this module.
|
// pass that check that they aren't used anywhere else, rather this module.
|
||||||
@ -94,12 +85,16 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
|
|||||||
// functions (such as calling `fn_sig`, which ICEs if given a non-function). We also
|
// functions (such as calling `fn_sig`, which ICEs if given a non-function). We also
|
||||||
// report a delayed bug, just in case `check_attr` isn't doing its job.
|
// report a delayed bug, just in case `check_attr` isn't doing its job.
|
||||||
let fn_sig = || {
|
let fn_sig = || {
|
||||||
let sig = fn_sig_outer();
|
use DefKind::*;
|
||||||
if sig.is_none() {
|
|
||||||
|
let def_kind = tcx.def_kind(did);
|
||||||
|
if let Fn | AssocFn | Variant | Ctor(..) = def_kind {
|
||||||
|
Some(tcx.fn_sig(did))
|
||||||
|
} else {
|
||||||
tcx.dcx()
|
tcx.dcx()
|
||||||
.span_delayed_bug(attr.span, "this attribute can only be applied to functions");
|
.span_delayed_bug(attr.span, "this attribute can only be applied to functions");
|
||||||
|
None
|
||||||
}
|
}
|
||||||
sig
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let Some(Ident { name, .. }) = attr.ident() else {
|
let Some(Ident { name, .. }) = attr.ident() else {
|
||||||
@ -618,93 +613,7 @@ fn emit_error_with_label(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(sig) = fn_sig_outer() {
|
// If a function uses #[target_feature] it can't be inlined into general
|
||||||
// Collect target features from types reachable from arguments.
|
|
||||||
// We define a type as "reachable" if:
|
|
||||||
// - it is a function argument
|
|
||||||
// - it is a field of a reachable struct
|
|
||||||
// - there is a reachable reference to it
|
|
||||||
// FIXME(struct_target_features): we may want to cache the result of this computation.
|
|
||||||
let mut visited_types = FxHashSet::default();
|
|
||||||
let mut reachable_types: Vec<_> = sig.skip_binder().inputs().skip_binder().to_owned();
|
|
||||||
let mut additional_tf = vec![];
|
|
||||||
|
|
||||||
while let Some(ty) = reachable_types.pop() {
|
|
||||||
if visited_types.contains(&ty) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
visited_types.insert(ty);
|
|
||||||
match ty.kind() {
|
|
||||||
ty::Alias(..) => {
|
|
||||||
if let Ok(t) =
|
|
||||||
tcx.try_normalize_erasing_regions(tcx.param_env(did.to_def_id()), ty)
|
|
||||||
{
|
|
||||||
reachable_types.push(t)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ty::Ref(_, inner, _) => reachable_types.push(*inner),
|
|
||||||
ty::Tuple(tys) => reachable_types.extend(tys.iter()),
|
|
||||||
ty::Adt(adt_def, args) => {
|
|
||||||
additional_tf.extend_from_slice(tcx.struct_target_features(adt_def.did()));
|
|
||||||
// This only recurses into structs as i.e. an Option<TargetFeature> is an ADT
|
|
||||||
// that doesn't actually always contain a TargetFeature.
|
|
||||||
if adt_def.is_struct() {
|
|
||||||
reachable_types.extend(
|
|
||||||
adt_def
|
|
||||||
.variant(VariantIdx::from_usize(0))
|
|
||||||
.fields
|
|
||||||
.iter()
|
|
||||||
.map(|field| field.ty(tcx, args)),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ty::Bool
|
|
||||||
| ty::Char
|
|
||||||
| ty::Int(..)
|
|
||||||
| ty::Uint(..)
|
|
||||||
| ty::Float(..)
|
|
||||||
| ty::Foreign(..)
|
|
||||||
| ty::Str
|
|
||||||
| ty::Array(..)
|
|
||||||
| ty::Pat(..)
|
|
||||||
| ty::Slice(..)
|
|
||||||
| ty::RawPtr(..)
|
|
||||||
| ty::FnDef(..)
|
|
||||||
| ty::FnPtr(..)
|
|
||||||
| ty::Dynamic(..)
|
|
||||||
| ty::Closure(..)
|
|
||||||
| ty::CoroutineClosure(..)
|
|
||||||
| ty::Coroutine(..)
|
|
||||||
| ty::CoroutineWitness(..)
|
|
||||||
| ty::Never
|
|
||||||
| ty::Param(..)
|
|
||||||
| ty::Bound(..)
|
|
||||||
| ty::Placeholder(..)
|
|
||||||
| ty::Infer(..)
|
|
||||||
| ty::Error(..) => (),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME(struct_target_features): is this really necessary?
|
|
||||||
if !additional_tf.is_empty() && sig.skip_binder().abi() != abi::Abi::Rust {
|
|
||||||
tcx.dcx().span_err(
|
|
||||||
tcx.hir().span(tcx.local_def_id_to_hir_id(did)),
|
|
||||||
"cannot use a struct with target features in a function with non-Rust ABI",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if !additional_tf.is_empty() && codegen_fn_attrs.inline == InlineAttr::Always {
|
|
||||||
tcx.dcx().span_err(
|
|
||||||
tcx.hir().span(tcx.local_def_id_to_hir_id(did)),
|
|
||||||
"cannot use a struct with target features in a #[inline(always)] function",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
codegen_fn_attrs
|
|
||||||
.target_features
|
|
||||||
.extend(additional_tf.iter().map(|tf| TargetFeature { implied: true, ..*tf }));
|
|
||||||
}
|
|
||||||
|
|
||||||
// If a function uses non-default target_features it can't be inlined into general
|
|
||||||
// purpose functions as they wouldn't have the right target features
|
// purpose functions as they wouldn't have the right target features
|
||||||
// enabled. For that reason we also forbid #[inline(always)] as it can't be
|
// enabled. For that reason we also forbid #[inline(always)] as it can't be
|
||||||
// respected.
|
// respected.
|
||||||
@ -849,20 +758,6 @@ fn check_link_name_xor_ordinal(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn struct_target_features(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &[TargetFeature] {
|
|
||||||
let mut features = vec![];
|
|
||||||
let supported_features = tcx.supported_target_features(LOCAL_CRATE);
|
|
||||||
for attr in tcx.get_attrs(def_id, sym::target_feature) {
|
|
||||||
from_target_feature(tcx, attr, supported_features, &mut features);
|
|
||||||
}
|
|
||||||
tcx.arena.alloc_slice(&features)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn provide(providers: &mut Providers) {
|
pub fn provide(providers: &mut Providers) {
|
||||||
*providers = Providers {
|
*providers = Providers { codegen_fn_attrs, should_inherit_track_caller, ..*providers };
|
||||||
codegen_fn_attrs,
|
|
||||||
should_inherit_track_caller,
|
|
||||||
struct_target_features,
|
|
||||||
..*providers
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
@ -597,8 +597,6 @@ pub fn internal(&self, feature: Symbol) -> bool {
|
|||||||
(unstable, strict_provenance, "1.61.0", Some(95228)),
|
(unstable, strict_provenance, "1.61.0", Some(95228)),
|
||||||
/// Allows string patterns to dereference values to match them.
|
/// Allows string patterns to dereference values to match them.
|
||||||
(unstable, string_deref_patterns, "1.67.0", Some(87121)),
|
(unstable, string_deref_patterns, "1.67.0", Some(87121)),
|
||||||
/// Allows structs to carry target_feature information.
|
|
||||||
(incomplete, struct_target_features, "CURRENT_RUSTC_VERSION", Some(129107)),
|
|
||||||
/// Allows the use of `#[target_feature]` on safe functions.
|
/// Allows the use of `#[target_feature]` on safe functions.
|
||||||
(unstable, target_feature_11, "1.45.0", Some(69098)),
|
(unstable, target_feature_11, "1.45.0", Some(69098)),
|
||||||
/// Allows using `#[thread_local]` on `static` items.
|
/// Allows using `#[thread_local]` on `static` items.
|
||||||
|
@ -326,41 +326,6 @@ pub fn has_codegen_attrs(self) -> bool {
|
|||||||
| DefKind::ExternCrate => false,
|
| DefKind::ExternCrate => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether `query struct_target_features` should be used with this definition.
|
|
||||||
pub fn has_struct_target_features(self) -> bool {
|
|
||||||
match self {
|
|
||||||
DefKind::Struct | DefKind::Union | DefKind::Enum => true,
|
|
||||||
DefKind::Fn
|
|
||||||
| DefKind::AssocFn
|
|
||||||
| DefKind::Ctor(..)
|
|
||||||
| DefKind::Closure
|
|
||||||
| DefKind::Static { .. }
|
|
||||||
| DefKind::Mod
|
|
||||||
| DefKind::Variant
|
|
||||||
| DefKind::Trait
|
|
||||||
| DefKind::TyAlias
|
|
||||||
| DefKind::ForeignTy
|
|
||||||
| DefKind::TraitAlias
|
|
||||||
| DefKind::AssocTy
|
|
||||||
| DefKind::Const
|
|
||||||
| DefKind::AssocConst
|
|
||||||
| DefKind::Macro(..)
|
|
||||||
| DefKind::Use
|
|
||||||
| DefKind::ForeignMod
|
|
||||||
| DefKind::OpaqueTy
|
|
||||||
| DefKind::Impl { .. }
|
|
||||||
| DefKind::Field
|
|
||||||
| DefKind::TyParam
|
|
||||||
| DefKind::ConstParam
|
|
||||||
| DefKind::LifetimeParam
|
|
||||||
| DefKind::AnonConst
|
|
||||||
| DefKind::InlineConst
|
|
||||||
| DefKind::SyntheticCoroutineBody
|
|
||||||
| DefKind::GlobalAsm
|
|
||||||
| DefKind::ExternCrate => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The resolution of a path or export.
|
/// The resolution of a path or export.
|
||||||
|
@ -851,8 +851,6 @@ fn coerce_from_fn_item(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Safe `#[target_feature]` functions are not assignable to safe fn pointers (RFC 2396).
|
// Safe `#[target_feature]` functions are not assignable to safe fn pointers (RFC 2396).
|
||||||
// FIXME(struct_target_features): should this be true also for functions that inherit
|
|
||||||
// target features from structs?
|
|
||||||
|
|
||||||
if b_hdr.safety == hir::Safety::Safe
|
if b_hdr.safety == hir::Safety::Safe
|
||||||
&& !self.tcx.codegen_fn_attrs(def_id).target_features.is_empty()
|
&& !self.tcx.codegen_fn_attrs(def_id).target_features.is_empty()
|
||||||
|
@ -254,7 +254,6 @@ fn into_args(self) -> (DefId, SimplifiedType) {
|
|||||||
variances_of => { table }
|
variances_of => { table }
|
||||||
fn_sig => { table }
|
fn_sig => { table }
|
||||||
codegen_fn_attrs => { table }
|
codegen_fn_attrs => { table }
|
||||||
struct_target_features => { table }
|
|
||||||
impl_trait_header => { table }
|
impl_trait_header => { table }
|
||||||
const_param_default => { table }
|
const_param_default => { table }
|
||||||
object_lifetime_default => { table }
|
object_lifetime_default => { table }
|
||||||
|
@ -1392,9 +1392,6 @@ fn encode_def_ids(&mut self) {
|
|||||||
if def_kind.has_codegen_attrs() {
|
if def_kind.has_codegen_attrs() {
|
||||||
record!(self.tables.codegen_fn_attrs[def_id] <- self.tcx.codegen_fn_attrs(def_id));
|
record!(self.tables.codegen_fn_attrs[def_id] <- self.tcx.codegen_fn_attrs(def_id));
|
||||||
}
|
}
|
||||||
if def_kind.has_struct_target_features() {
|
|
||||||
record_array!(self.tables.struct_target_features[def_id] <- self.tcx.struct_target_features(def_id));
|
|
||||||
}
|
|
||||||
if should_encode_visibility(def_kind) {
|
if should_encode_visibility(def_kind) {
|
||||||
let vis =
|
let vis =
|
||||||
self.tcx.local_visibility(local_id).map_id(|def_id| def_id.local_def_index);
|
self.tcx.local_visibility(local_id).map_id(|def_id| def_id.local_def_index);
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
Decodable, Encodable, MetadataDecodable, MetadataEncodable, TyDecodable, TyEncodable,
|
Decodable, Encodable, MetadataDecodable, MetadataEncodable, TyDecodable, TyEncodable,
|
||||||
};
|
};
|
||||||
use rustc_middle::metadata::ModChild;
|
use rustc_middle::metadata::ModChild;
|
||||||
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrs, TargetFeature};
|
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
|
||||||
use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile;
|
use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile;
|
||||||
use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo};
|
use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo};
|
||||||
use rustc_middle::middle::lib_features::FeatureStability;
|
use rustc_middle::middle::lib_features::FeatureStability;
|
||||||
@ -427,7 +427,6 @@ fn encode(&self, buf: &mut FileEncoder) -> LazyTables {
|
|||||||
variances_of: Table<DefIndex, LazyArray<ty::Variance>>,
|
variances_of: Table<DefIndex, LazyArray<ty::Variance>>,
|
||||||
fn_sig: Table<DefIndex, LazyValue<ty::EarlyBinder<'static, ty::PolyFnSig<'static>>>>,
|
fn_sig: Table<DefIndex, LazyValue<ty::EarlyBinder<'static, ty::PolyFnSig<'static>>>>,
|
||||||
codegen_fn_attrs: Table<DefIndex, LazyValue<CodegenFnAttrs>>,
|
codegen_fn_attrs: Table<DefIndex, LazyValue<CodegenFnAttrs>>,
|
||||||
struct_target_features: Table<DefIndex, LazyArray<TargetFeature>>,
|
|
||||||
impl_trait_header: Table<DefIndex, LazyValue<ty::ImplTraitHeader<'static>>>,
|
impl_trait_header: Table<DefIndex, LazyValue<ty::ImplTraitHeader<'static>>>,
|
||||||
const_param_default: Table<DefIndex, LazyValue<ty::EarlyBinder<'static, rustc_middle::ty::Const<'static>>>>,
|
const_param_default: Table<DefIndex, LazyValue<ty::EarlyBinder<'static, rustc_middle::ty::Const<'static>>>>,
|
||||||
object_lifetime_default: Table<DefIndex, LazyValue<ObjectLifetimeDefault>>,
|
object_lifetime_default: Table<DefIndex, LazyValue<ObjectLifetimeDefault>>,
|
||||||
|
@ -26,8 +26,8 @@ pub struct CodegenFnAttrs {
|
|||||||
/// be set when `link_name` is set. This is for foreign items with the
|
/// be set when `link_name` is set. This is for foreign items with the
|
||||||
/// "raw-dylib" kind.
|
/// "raw-dylib" kind.
|
||||||
pub link_ordinal: Option<u16>,
|
pub link_ordinal: Option<u16>,
|
||||||
/// All the target features that are enabled for this function. Some features might be enabled
|
/// The `#[target_feature(enable = "...")]` attribute and the enabled
|
||||||
/// implicitly.
|
/// features (only enabled features are supported right now).
|
||||||
pub target_features: Vec<TargetFeature>,
|
pub target_features: Vec<TargetFeature>,
|
||||||
/// The `#[linkage = "..."]` attribute on Rust-defined items and the value we found.
|
/// The `#[linkage = "..."]` attribute on Rust-defined items and the value we found.
|
||||||
pub linkage: Option<Linkage>,
|
pub linkage: Option<Linkage>,
|
||||||
@ -55,8 +55,8 @@ pub struct CodegenFnAttrs {
|
|||||||
pub struct TargetFeature {
|
pub struct TargetFeature {
|
||||||
/// The name of the target feature (e.g. "avx")
|
/// The name of the target feature (e.g. "avx")
|
||||||
pub name: Symbol,
|
pub name: Symbol,
|
||||||
/// The feature is implied by another feature or by an argument, rather than explicitly
|
/// The feature is implied by another feature, rather than explicitly added by the
|
||||||
/// added by the `#[target_feature]` attribute
|
/// `#[target_feature]` attribute
|
||||||
pub implied: bool,
|
pub implied: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@
|
|||||||
use crate::infer::canonical::{self, Canonical};
|
use crate::infer::canonical::{self, Canonical};
|
||||||
use crate::lint::LintExpectation;
|
use crate::lint::LintExpectation;
|
||||||
use crate::metadata::ModChild;
|
use crate::metadata::ModChild;
|
||||||
use crate::middle::codegen_fn_attrs::{CodegenFnAttrs, TargetFeature};
|
use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
|
||||||
use crate::middle::debugger_visualizer::DebuggerVisualizerFile;
|
use crate::middle::debugger_visualizer::DebuggerVisualizerFile;
|
||||||
use crate::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo};
|
use crate::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo};
|
||||||
use crate::middle::lib_features::LibFeatures;
|
use crate::middle::lib_features::LibFeatures;
|
||||||
@ -1249,11 +1249,6 @@
|
|||||||
feedable
|
feedable
|
||||||
}
|
}
|
||||||
|
|
||||||
query struct_target_features(def_id: DefId) -> &'tcx [TargetFeature] {
|
|
||||||
separate_provide_extern
|
|
||||||
desc { |tcx| "computing target features for struct `{}`", tcx.def_path_str(def_id) }
|
|
||||||
}
|
|
||||||
|
|
||||||
query asm_target_features(def_id: DefId) -> &'tcx FxIndexSet<Symbol> {
|
query asm_target_features(def_id: DefId) -> &'tcx FxIndexSet<Symbol> {
|
||||||
desc { |tcx| "computing target features for inline asm of `{}`", tcx.def_path_str(def_id) }
|
desc { |tcx| "computing target features for inline asm of `{}`", tcx.def_path_str(def_id) }
|
||||||
}
|
}
|
||||||
|
@ -59,7 +59,6 @@ impl $crate::ty::ParameterizedOverTcx for $ty {
|
|||||||
std::string::String,
|
std::string::String,
|
||||||
crate::metadata::ModChild,
|
crate::metadata::ModChild,
|
||||||
crate::middle::codegen_fn_attrs::CodegenFnAttrs,
|
crate::middle::codegen_fn_attrs::CodegenFnAttrs,
|
||||||
crate::middle::codegen_fn_attrs::TargetFeature,
|
|
||||||
crate::middle::debugger_visualizer::DebuggerVisualizerFile,
|
crate::middle::debugger_visualizer::DebuggerVisualizerFile,
|
||||||
crate::middle::exported_symbols::SymbolExportInfo,
|
crate::middle::exported_symbols::SymbolExportInfo,
|
||||||
crate::middle::lib_features::FeatureStability,
|
crate::middle::lib_features::FeatureStability,
|
||||||
|
@ -125,17 +125,6 @@ mir_build_initializing_type_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed
|
|||||||
.note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior
|
.note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior
|
||||||
.label = initializing type with `rustc_layout_scalar_valid_range` attr
|
.label = initializing type with `rustc_layout_scalar_valid_range` attr
|
||||||
|
|
||||||
mir_build_initializing_type_with_target_feature_requires_unsafe =
|
|
||||||
initializing type with `target_feature` attr is unsafe and requires unsafe block
|
|
||||||
.note = this struct can only be constructed if the corresponding `target_feature`s are available
|
|
||||||
.label = initializing type with `target_feature` attr
|
|
||||||
|
|
||||||
mir_build_initializing_type_with_target_feature_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
|
|
||||||
initializing type with `target_feature` attr is unsafe and requires unsafe function or block
|
|
||||||
.note = this struct can only be constructed if the corresponding `target_feature`s are available
|
|
||||||
.label = initializing type with `target_feature` attr
|
|
||||||
|
|
||||||
|
|
||||||
mir_build_inline_assembly_requires_unsafe =
|
mir_build_inline_assembly_requires_unsafe =
|
||||||
use of inline assembly is unsafe and requires unsafe block
|
use of inline assembly is unsafe and requires unsafe block
|
||||||
.note = inline assembly is entirely unchecked and can cause undefined behavior
|
.note = inline assembly is entirely unchecked and can cause undefined behavior
|
||||||
@ -398,11 +387,6 @@ mir_build_unsafe_op_in_unsafe_fn_initializing_type_with_requires_unsafe =
|
|||||||
.note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior
|
.note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior
|
||||||
.label = initializing type with `rustc_layout_scalar_valid_range` attr
|
.label = initializing type with `rustc_layout_scalar_valid_range` attr
|
||||||
|
|
||||||
mir_build_unsafe_op_in_unsafe_fn_initializing_type_with_target_feature_requires_unsafe =
|
|
||||||
initializing type with `target_feature` attr is unsafe and requires unsafe block
|
|
||||||
.note = this struct can only be constructed if the corresponding `target_feature`s are available
|
|
||||||
.label = initializing type with `target_feature` attr
|
|
||||||
|
|
||||||
mir_build_unsafe_op_in_unsafe_fn_inline_assembly_requires_unsafe =
|
mir_build_unsafe_op_in_unsafe_fn_inline_assembly_requires_unsafe =
|
||||||
use of inline assembly is unsafe and requires unsafe block
|
use of inline assembly is unsafe and requires unsafe block
|
||||||
.note = inline assembly is entirely unchecked and can cause undefined behavior
|
.note = inline assembly is entirely unchecked and can cause undefined behavior
|
||||||
|
@ -461,18 +461,14 @@ fn visit_expr(&mut self, expr: &'a Expr<'tcx>) {
|
|||||||
};
|
};
|
||||||
self.requires_unsafe(expr.span, CallToUnsafeFunction(func_id));
|
self.requires_unsafe(expr.span, CallToUnsafeFunction(func_id));
|
||||||
} else if let &ty::FnDef(func_did, _) = self.thir[fun].ty.kind() {
|
} else if let &ty::FnDef(func_did, _) = self.thir[fun].ty.kind() {
|
||||||
// If the called function has explicit target features the calling function hasn't,
|
// If the called function has target features the calling function hasn't,
|
||||||
// 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
|
||||||
// Implicit target features are OK because they are either a consequence of some
|
|
||||||
// explicit target feature (which is checked to be present in the caller) or
|
|
||||||
// come from a witness argument.
|
|
||||||
let callee_features = &self.tcx.codegen_fn_attrs(func_did).target_features;
|
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
|
||||||
&& !callee_features.iter().all(|feature| {
|
&& !callee_features.iter().all(|feature| {
|
||||||
feature.implied
|
self.body_target_features.iter().any(|f| f.name == feature.name)
|
||||||
|| self.body_target_features.iter().any(|f| f.name == feature.name)
|
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
let missing: Vec<_> = callee_features
|
let missing: Vec<_> = callee_features
|
||||||
@ -546,16 +542,10 @@ fn visit_expr(&mut self, expr: &'a Expr<'tcx>) {
|
|||||||
user_ty: _,
|
user_ty: _,
|
||||||
fields: _,
|
fields: _,
|
||||||
base: _,
|
base: _,
|
||||||
}) => {
|
}) => match self.tcx.layout_scalar_valid_range(adt_def.did()) {
|
||||||
match self.tcx.layout_scalar_valid_range(adt_def.did()) {
|
(Bound::Unbounded, Bound::Unbounded) => {}
|
||||||
(Bound::Unbounded, Bound::Unbounded) => {}
|
_ => self.requires_unsafe(expr.span, InitializingTypeWith),
|
||||||
_ => self.requires_unsafe(expr.span, InitializingTypeWith),
|
},
|
||||||
}
|
|
||||||
if !self.tcx.struct_target_features(adt_def.did()).is_empty() {
|
|
||||||
self.requires_unsafe(expr.span, ConstructingTargetFeaturesType)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ExprKind::Closure(box ClosureExpr {
|
ExprKind::Closure(box ClosureExpr {
|
||||||
closure_id,
|
closure_id,
|
||||||
args: _,
|
args: _,
|
||||||
@ -657,7 +647,6 @@ enum UnsafeOpKind {
|
|||||||
CallToUnsafeFunction(Option<DefId>),
|
CallToUnsafeFunction(Option<DefId>),
|
||||||
UseOfInlineAssembly,
|
UseOfInlineAssembly,
|
||||||
InitializingTypeWith,
|
InitializingTypeWith,
|
||||||
ConstructingTargetFeaturesType,
|
|
||||||
UseOfMutableStatic,
|
UseOfMutableStatic,
|
||||||
UseOfExternStatic,
|
UseOfExternStatic,
|
||||||
DerefOfRawPointer,
|
DerefOfRawPointer,
|
||||||
@ -739,15 +728,6 @@ fn emit_unsafe_op_in_unsafe_fn_lint(
|
|||||||
unsafe_not_inherited_note,
|
unsafe_not_inherited_note,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
ConstructingTargetFeaturesType => tcx.emit_node_span_lint(
|
|
||||||
UNSAFE_OP_IN_UNSAFE_FN,
|
|
||||||
hir_id,
|
|
||||||
span,
|
|
||||||
UnsafeOpInUnsafeFnInitializingTypeWithTargetFeatureRequiresUnsafe {
|
|
||||||
span,
|
|
||||||
unsafe_not_inherited_note,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
UseOfMutableStatic => tcx.emit_node_span_lint(
|
UseOfMutableStatic => tcx.emit_node_span_lint(
|
||||||
UNSAFE_OP_IN_UNSAFE_FN,
|
UNSAFE_OP_IN_UNSAFE_FN,
|
||||||
hir_id,
|
hir_id,
|
||||||
@ -905,20 +885,6 @@ fn emit_requires_unsafe_err(
|
|||||||
unsafe_not_inherited_note,
|
unsafe_not_inherited_note,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
ConstructingTargetFeaturesType if unsafe_op_in_unsafe_fn_allowed => {
|
|
||||||
dcx.emit_err(
|
|
||||||
InitializingTypeWithTargetFeatureRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
|
|
||||||
span,
|
|
||||||
unsafe_not_inherited_note,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
ConstructingTargetFeaturesType => {
|
|
||||||
dcx.emit_err(InitializingTypeWithTargetFeatureRequiresUnsafe {
|
|
||||||
span,
|
|
||||||
unsafe_not_inherited_note,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
UseOfMutableStatic if unsafe_op_in_unsafe_fn_allowed => {
|
UseOfMutableStatic if unsafe_op_in_unsafe_fn_allowed => {
|
||||||
dcx.emit_err(UseOfMutableStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
|
dcx.emit_err(UseOfMutableStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
|
||||||
span,
|
span,
|
||||||
|
@ -86,16 +86,6 @@ pub(crate) struct UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe {
|
|||||||
pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>,
|
pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(LintDiagnostic)]
|
|
||||||
#[diag(mir_build_unsafe_op_in_unsafe_fn_initializing_type_with_target_feature_requires_unsafe, code = E0133)]
|
|
||||||
#[note]
|
|
||||||
pub(crate) struct UnsafeOpInUnsafeFnInitializingTypeWithTargetFeatureRequiresUnsafe {
|
|
||||||
#[label]
|
|
||||||
pub(crate) span: Span,
|
|
||||||
#[subdiagnostic]
|
|
||||||
pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(LintDiagnostic)]
|
#[derive(LintDiagnostic)]
|
||||||
#[diag(mir_build_unsafe_op_in_unsafe_fn_mutable_static_requires_unsafe, code = E0133)]
|
#[diag(mir_build_unsafe_op_in_unsafe_fn_mutable_static_requires_unsafe, code = E0133)]
|
||||||
#[note]
|
#[note]
|
||||||
@ -260,17 +250,6 @@ pub(crate) struct InitializingTypeWithRequiresUnsafe {
|
|||||||
pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
|
pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
|
||||||
#[diag(mir_build_initializing_type_with_target_feature_requires_unsafe, code = E0133)]
|
|
||||||
#[note]
|
|
||||||
pub(crate) struct InitializingTypeWithTargetFeatureRequiresUnsafe {
|
|
||||||
#[primary_span]
|
|
||||||
#[label]
|
|
||||||
pub(crate) span: Span,
|
|
||||||
#[subdiagnostic]
|
|
||||||
pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(
|
#[diag(
|
||||||
mir_build_initializing_type_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed,
|
mir_build_initializing_type_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed,
|
||||||
@ -285,20 +264,6 @@ pub(crate) struct InitializingTypeWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
|
|||||||
pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
|
pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
|
||||||
#[diag(
|
|
||||||
mir_build_initializing_type_with_target_feature_requires_unsafe_unsafe_op_in_unsafe_fn_allowed,
|
|
||||||
code = E0133
|
|
||||||
)]
|
|
||||||
#[note]
|
|
||||||
pub(crate) struct InitializingTypeWithTargetFeatureRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
|
|
||||||
#[primary_span]
|
|
||||||
#[label]
|
|
||||||
pub(crate) span: Span,
|
|
||||||
#[subdiagnostic]
|
|
||||||
pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(mir_build_mutable_static_requires_unsafe, code = E0133)]
|
#[diag(mir_build_mutable_static_requires_unsafe, code = E0133)]
|
||||||
#[note]
|
#[note]
|
||||||
|
@ -672,10 +672,6 @@ passes_should_be_applied_to_fn =
|
|||||||
*[false] not a function definition
|
*[false] not a function definition
|
||||||
}
|
}
|
||||||
|
|
||||||
passes_should_be_applied_to_fn_or_unit_struct =
|
|
||||||
attribute should be applied to a function definition or unit struct
|
|
||||||
.label = not a function definition or a unit struct
|
|
||||||
|
|
||||||
passes_should_be_applied_to_static =
|
passes_should_be_applied_to_static =
|
||||||
attribute should be applied to a static
|
attribute should be applied to a static
|
||||||
.label = not a static
|
.label = not a static
|
||||||
|
@ -747,35 +747,12 @@ fn check_target_feature(
|
|||||||
Target::Field | Target::Arm | Target::MacroDef => {
|
Target::Field | Target::Arm | Target::MacroDef => {
|
||||||
self.inline_attr_str_error_with_macro_def(hir_id, attr, "target_feature");
|
self.inline_attr_str_error_with_macro_def(hir_id, attr, "target_feature");
|
||||||
}
|
}
|
||||||
Target::Struct if self.tcx.features().struct_target_features => {
|
|
||||||
let ty = self.tcx.hir_node(hir_id).expect_item();
|
|
||||||
match ty.kind {
|
|
||||||
ItemKind::Struct(data, _) => {
|
|
||||||
if data.fields().len() != 0 {
|
|
||||||
self.dcx().emit_err(errors::AttrShouldBeAppliedToFnOrUnitStruct {
|
|
||||||
attr_span: attr.span,
|
|
||||||
defn_span: span,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
panic!("Target::Struct for a non-struct");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
_ => {
|
||||||
if self.tcx.features().struct_target_features {
|
self.dcx().emit_err(errors::AttrShouldBeAppliedToFn {
|
||||||
self.dcx().emit_err(errors::AttrShouldBeAppliedToFnOrUnitStruct {
|
attr_span: attr.span,
|
||||||
attr_span: attr.span,
|
defn_span: span,
|
||||||
defn_span: span,
|
on_crate: hir_id == CRATE_HIR_ID,
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
self.dcx().emit_err(errors::AttrShouldBeAppliedToFn {
|
|
||||||
attr_span: attr.span,
|
|
||||||
defn_span: span,
|
|
||||||
on_crate: hir_id == CRATE_HIR_ID,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -82,15 +82,6 @@ pub(crate) struct AttrShouldBeAppliedToFn {
|
|||||||
pub on_crate: bool,
|
pub on_crate: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
|
||||||
#[diag(passes_should_be_applied_to_fn_or_unit_struct)]
|
|
||||||
pub(crate) struct AttrShouldBeAppliedToFnOrUnitStruct {
|
|
||||||
#[primary_span]
|
|
||||||
pub attr_span: Span,
|
|
||||||
#[label]
|
|
||||||
pub defn_span: Span,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(passes_should_be_applied_to_fn, code = E0739)]
|
#[diag(passes_should_be_applied_to_fn, code = E0739)]
|
||||||
pub(crate) struct TrackedCallerWrongLocation {
|
pub(crate) struct TrackedCallerWrongLocation {
|
||||||
|
@ -1858,7 +1858,6 @@
|
|||||||
stringify,
|
stringify,
|
||||||
struct_field_attributes,
|
struct_field_attributes,
|
||||||
struct_inherit,
|
struct_inherit,
|
||||||
struct_target_features,
|
|
||||||
struct_variant,
|
struct_variant,
|
||||||
structural_match,
|
structural_match,
|
||||||
structural_peq,
|
structural_peq,
|
||||||
|
@ -439,8 +439,6 @@ pub fn report_selection_error(
|
|||||||
let is_target_feature_fn = if let ty::FnDef(def_id, _) =
|
let is_target_feature_fn = if let ty::FnDef(def_id, _) =
|
||||||
*leaf_trait_ref.skip_binder().self_ty().kind()
|
*leaf_trait_ref.skip_binder().self_ty().kind()
|
||||||
{
|
{
|
||||||
// FIXME(struct_target_features): should a function that inherits
|
|
||||||
// target_features through arguments implement Fn traits?
|
|
||||||
!self.tcx.codegen_fn_attrs(def_id).target_features.is_empty()
|
!self.tcx.codegen_fn_attrs(def_id).target_features.is_empty()
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
|
@ -546,8 +546,6 @@ fn assemble_fn_pointer_candidates(
|
|||||||
// Provide an impl for suitable functions, rejecting `#[target_feature]` functions (RFC 2396).
|
// Provide an impl for suitable functions, rejecting `#[target_feature]` functions (RFC 2396).
|
||||||
ty::FnDef(def_id, args) => {
|
ty::FnDef(def_id, args) => {
|
||||||
let tcx = self.tcx();
|
let tcx = self.tcx();
|
||||||
// FIXME(struct_target_features): should a function that inherits target_features
|
|
||||||
// through an argument implement Fn traits?
|
|
||||||
if tcx.fn_sig(def_id).skip_binder().is_fn_trait_compatible()
|
if tcx.fn_sig(def_id).skip_binder().is_fn_trait_compatible()
|
||||||
&& tcx.codegen_fn_attrs(def_id).target_features.is_empty()
|
&& tcx.codegen_fn_attrs(def_id).target_features.is_empty()
|
||||||
{
|
{
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
# `struct_target_features`
|
|
||||||
|
|
||||||
The tracking issue for this feature is: [#129107]
|
|
||||||
|
|
||||||
[#129107]: https://github.com/rust-lang/rust/issues/129107
|
|
||||||
|
|
||||||
------------------------
|
|
@ -1,37 +0,0 @@
|
|||||||
//@ compile-flags: -O
|
|
||||||
//@ assembly-output: emit-asm
|
|
||||||
//@ only-x86_64
|
|
||||||
|
|
||||||
#![crate_type = "lib"]
|
|
||||||
#![feature(struct_target_features)]
|
|
||||||
|
|
||||||
// Check that a struct_target_features type causes the compiler to effectively inline intrinsics.
|
|
||||||
|
|
||||||
use std::arch::x86_64::*;
|
|
||||||
|
|
||||||
#[target_feature(enable = "avx")]
|
|
||||||
struct Avx {}
|
|
||||||
|
|
||||||
#[target_feature(enable = "fma")]
|
|
||||||
struct Fma {}
|
|
||||||
|
|
||||||
pub fn add_simple(_: Avx, v: __m256) -> __m256 {
|
|
||||||
// CHECK-NOT: call
|
|
||||||
// CHECK: vaddps
|
|
||||||
unsafe { _mm256_add_ps(v, v) }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn add_complex_type(_: (&Avx, ()), v: __m256) -> __m256 {
|
|
||||||
// CHECK-NOT: call
|
|
||||||
// CHECK: vaddps
|
|
||||||
unsafe { _mm256_add_ps(v, v) }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn add_fma_combined(_: (&Avx, &Fma), v: __m256) -> (__m256, __m256) {
|
|
||||||
// CHECK-NOT: call
|
|
||||||
// CHECK-DAG: vaddps
|
|
||||||
let r1 = unsafe { _mm256_add_ps(v, v) };
|
|
||||||
// CHECK-DAG: vfmadd213ps
|
|
||||||
let r2 = unsafe { _mm256_fmadd_ps(v, v, v) };
|
|
||||||
(r1, r2)
|
|
||||||
}
|
|
@ -1,4 +0,0 @@
|
|||||||
#[target_feature(enable = "avx")] //~ ERROR attribute should be applied to a function definition
|
|
||||||
struct Avx {}
|
|
||||||
|
|
||||||
fn main() {}
|
|
@ -1,10 +0,0 @@
|
|||||||
error: attribute should be applied to a function definition
|
|
||||||
--> $DIR/feature-gate-struct-target-features.rs:1:1
|
|
||||||
|
|
|
||||||
LL | #[target_feature(enable = "avx")]
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
LL | struct Avx {}
|
|
||||||
| ------------- not a function definition
|
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
|
||||||
|
|
@ -1,98 +0,0 @@
|
|||||||
//@ only-x86_64
|
|
||||||
#![feature(struct_target_features)]
|
|
||||||
//~^ WARNING the feature `struct_target_features` is incomplete and may not be safe to use and/or cause compiler crashes
|
|
||||||
#![feature(target_feature_11)]
|
|
||||||
|
|
||||||
use std::arch::x86_64::*;
|
|
||||||
|
|
||||||
#[target_feature(enable = "avx")]
|
|
||||||
//~^ ERROR attribute should be applied to a function definition or unit struct
|
|
||||||
struct Invalid(u32);
|
|
||||||
|
|
||||||
#[target_feature(enable = "avx")]
|
|
||||||
struct Avx {}
|
|
||||||
|
|
||||||
#[target_feature(enable = "sse")]
|
|
||||||
struct Sse();
|
|
||||||
|
|
||||||
#[target_feature(enable = "avx")]
|
|
||||||
fn avx() {}
|
|
||||||
|
|
||||||
trait TFAssociatedType {
|
|
||||||
type Assoc;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TFAssociatedType for () {
|
|
||||||
type Assoc = Avx;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn avx_self(_: <() as TFAssociatedType>::Assoc) {
|
|
||||||
avx();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn avx_avx(_: Avx) {
|
|
||||||
avx();
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" fn bad_fun(_: Avx) {}
|
|
||||||
//~^ ERROR cannot use a struct with target features in a function with non-Rust ABI
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
//~^ ERROR cannot use `#[inline(always)]` with `#[target_feature]`
|
|
||||||
fn inline_fun(_: Avx) {}
|
|
||||||
//~^ ERROR cannot use a struct with target features in a #[inline(always)] function
|
|
||||||
|
|
||||||
trait Simd {
|
|
||||||
fn do_something(&self);
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Simd for Avx {
|
|
||||||
fn do_something(&self) {
|
|
||||||
unsafe {
|
|
||||||
println!("{:?}", _mm256_setzero_ps());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Simd for Sse {
|
|
||||||
fn do_something(&self) {
|
|
||||||
unsafe {
|
|
||||||
println!("{:?}", _mm_setzero_ps());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct WithAvx {
|
|
||||||
#[allow(dead_code)]
|
|
||||||
avx: Avx,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Simd for WithAvx {
|
|
||||||
fn do_something(&self) {
|
|
||||||
unsafe {
|
|
||||||
println!("{:?}", _mm256_setzero_ps());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(never)]
|
|
||||||
fn dosomething<S: Simd>(simd: &S) {
|
|
||||||
simd.do_something();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn avxfn(_: &Avx) {}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
Avx {};
|
|
||||||
//~^ ERROR initializing type with `target_feature` attr is unsafe and requires unsafe function or block [E0133]
|
|
||||||
|
|
||||||
if is_x86_feature_detected!("avx") {
|
|
||||||
let avx = unsafe { Avx {} };
|
|
||||||
avxfn(&avx);
|
|
||||||
dosomething(&avx);
|
|
||||||
dosomething(&WithAvx { avx });
|
|
||||||
}
|
|
||||||
if is_x86_feature_detected!("sse") {
|
|
||||||
dosomething(&unsafe { Sse {} })
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,47 +0,0 @@
|
|||||||
warning: the feature `struct_target_features` is incomplete and may not be safe to use and/or cause compiler crashes
|
|
||||||
--> $DIR/struct-target-features.rs:2:12
|
|
||||||
|
|
|
||||||
LL | #![feature(struct_target_features)]
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
= note: see issue #129107 <https://github.com/rust-lang/rust/issues/129107> for more information
|
|
||||||
= note: `#[warn(incomplete_features)]` on by default
|
|
||||||
|
|
||||||
error: attribute should be applied to a function definition or unit struct
|
|
||||||
--> $DIR/struct-target-features.rs:8:1
|
|
||||||
|
|
|
||||||
LL | #[target_feature(enable = "avx")]
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
LL |
|
|
||||||
LL | struct Invalid(u32);
|
|
||||||
| -------------------- not a function definition or a unit struct
|
|
||||||
|
|
||||||
error: cannot use a struct with target features in a function with non-Rust ABI
|
|
||||||
--> $DIR/struct-target-features.rs:37:1
|
|
||||||
|
|
|
||||||
LL | extern "C" fn bad_fun(_: Avx) {}
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
error: cannot use a struct with target features in a #[inline(always)] function
|
|
||||||
--> $DIR/struct-target-features.rs:42:1
|
|
||||||
|
|
|
||||||
LL | fn inline_fun(_: Avx) {}
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
error: cannot use `#[inline(always)]` with `#[target_feature]`
|
|
||||||
--> $DIR/struct-target-features.rs:40:1
|
|
||||||
|
|
|
||||||
LL | #[inline(always)]
|
|
||||||
| ^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
error[E0133]: initializing type with `target_feature` attr is unsafe and requires unsafe function or block
|
|
||||||
--> $DIR/struct-target-features.rs:86:5
|
|
||||||
|
|
|
||||||
LL | Avx {};
|
|
||||||
| ^^^^^^ initializing type with `target_feature` attr
|
|
||||||
|
|
|
||||||
= note: this struct can only be constructed if the corresponding `target_feature`s are available
|
|
||||||
|
|
||||||
error: aborting due to 5 previous errors; 1 warning emitted
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0133`.
|
|
Loading…
Reference in New Issue
Block a user