From 2474f0ed88bc1a06e02230619b18e7bc8bb673fc Mon Sep 17 00:00:00 2001 From: LeSeulArtichaut Date: Fri, 1 May 2020 14:17:02 +0200 Subject: [PATCH 1/4] Allow `#[target_feature]` on safe functions --- src/librustc_feature/active.rs | 3 ++ src/librustc_span/symbol.rs | 1 + src/librustc_typeck/collect.rs | 51 ++++++++++++++++++++++++++++------ 3 files changed, 47 insertions(+), 8 deletions(-) diff --git a/src/librustc_feature/active.rs b/src/librustc_feature/active.rs index 7b3c599e8c7ca..cec9e0ce3af71 100644 --- a/src/librustc_feature/active.rs +++ b/src/librustc_feature/active.rs @@ -559,6 +559,9 @@ declare_features! ( /// Allow negative trait implementations. (active, negative_impls, "1.44.0", Some(68318), None), + /// Allows the use of `#[target_feature]` on safe functions. + (active, target_feature_11, "1.45.0", Some(69098), None), + // ------------------------------------------------------------------------- // feature-group-end: actual feature gates // ------------------------------------------------------------------------- diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs index 1575e6fd53332..74d73404acd8e 100644 --- a/src/librustc_span/symbol.rs +++ b/src/librustc_span/symbol.rs @@ -722,6 +722,7 @@ symbols! { suggestion, sync_trait, target_feature, + target_feature_11, target_has_atomic, target_has_atomic_load_store, target_thread_local, diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 9f70a0fbc2462..eba8f0085375a 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -29,7 +29,7 @@ use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE}; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::weak_lang_items; -use rustc_hir::{GenericParamKind, Node, Unsafety}; +use rustc_hir::{GenericParamKind, Node}; use rustc_middle::hir::map::blocks::FnLikeNode; use rustc_middle::hir::map::Map; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; @@ -2413,13 +2413,12 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { codegen_fn_attrs.export_name = Some(s); } } else if attr.check_name(sym::target_feature) { - if tcx.is_closure(id) || tcx.fn_sig(id).unsafety() == Unsafety::Normal { - let msg = "`#[target_feature(..)]` can only be applied to `unsafe` functions"; - tcx.sess - .struct_span_err(attr.span, msg) - .span_label(attr.span, "can only be applied to `unsafe` functions") - .span_label(tcx.def_span(id), "not an `unsafe` function") - .emit(); + if !tcx.features().target_feature_11 { + check_target_feature_safe_fn(tcx, id, attr.span); + } else if let Some(local_id) = id.as_local() { + if tcx.fn_sig(id).unsafety() == hir::Unsafety::Normal { + check_target_feature_trait_unsafe(tcx, local_id, attr.span); + } } from_target_feature(tcx, id, attr, &whitelist, &mut codegen_fn_attrs.target_features); } else if attr.check_name(sym::linkage) { @@ -2666,3 +2665,39 @@ fn check_link_name_xor_ordinal( tcx.sess.err(msg); } } + +/// Checks the function annotated with `#[target_feature]` is unsafe, +/// reporting an error if it isn't. +fn check_target_feature_safe_fn(tcx: TyCtxt<'_>, id: DefId, attr_span: Span) { + if tcx.is_closure(id) || tcx.fn_sig(id).unsafety() == hir::Unsafety::Normal { + let mut err = feature_err( + &tcx.sess.parse_sess, + sym::target_feature_11, + attr_span, + "`#[target_feature(..)]` can only be applied to `unsafe` functions", + ); + err.span_label(tcx.def_span(id), "not an `unsafe` function"); + err.emit(); + } +} + +/// Checks the function annotated with `#[target_feature]` is not a safe +/// trait method implementation, reporting an error if it is. +fn check_target_feature_trait_unsafe(tcx: TyCtxt<'_>, id: LocalDefId, attr_span: Span) { + let hir_id = tcx.hir().as_local_hir_id(id); + let node = tcx.hir().get(hir_id); + if let Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }) = node { + let parent_id = tcx.hir().get_parent_item(hir_id); + let parent_item = tcx.hir().expect_item(parent_id); + if let hir::ItemKind::Impl { of_trait: Some(_), .. } = parent_item.kind { + tcx.sess + .struct_span_err( + attr_span, + "`#[target_feature(..)]` cannot be applied to safe trait method", + ) + .span_label(attr_span, "cannot be applied to safe trait method") + .span_label(tcx.def_span(id), "not an `unsafe` function") + .emit(); + } + } +} From f2c6cbd98fa8be80951385f789f49d560916c726 Mon Sep 17 00:00:00 2001 From: LeSeulArtichaut Date: Fri, 1 May 2020 15:16:17 +0200 Subject: [PATCH 2/4] Prevent calls to functions with `#[target_feature]` in safe contexts --- src/librustc_mir/transform/check_unsafety.rs | 26 +++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index 1c1560cbf9de7..a015dc603520b 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -19,6 +19,7 @@ use crate::util; pub struct UnsafetyChecker<'a, 'tcx> { body: &'a Body<'tcx>, + body_did: LocalDefId, const_context: bool, min_const_fn: bool, violations: Vec, @@ -35,6 +36,7 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { const_context: bool, min_const_fn: bool, body: &'a Body<'tcx>, + body_did: LocalDefId, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, ) -> Self { @@ -44,6 +46,7 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { } Self { body, + body_did, const_context, min_const_fn, violations: vec![], @@ -87,6 +90,10 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { UnsafetyViolationKind::GeneralAndConstFn, ) } + + if let ty::FnDef(func_id, _) = func_ty.kind { + self.check_target_features(func_id); + } } } self.super_terminator(terminator, location); @@ -436,6 +443,22 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { } } } + + /// Checks whether calling `func_did` needs an `unsafe` context or not, i.e. whether + /// the called function has target features the calling function hasn't. + fn check_target_features(&mut self, func_did: DefId) { + let callee_features = &self.tcx.codegen_fn_attrs(func_did).target_features; + let self_features = &self.tcx.codegen_fn_attrs(self.body_did).target_features; + + // Is `callee_features` a subset of `calling_features`? + if !callee_features.iter().all(|feature| self_features.contains(feature)) { + self.require_unsafe( + "call to function with `#[target_feature]`", + "can only be called if the required target features are available", + UnsafetyViolationKind::GeneralAndConstFn, + ) + } + } } pub(crate) fn provide(providers: &mut Providers<'_>) { @@ -502,7 +525,8 @@ fn unsafety_check_result(tcx: TyCtxt<'_>, def_id: LocalDefId) -> UnsafetyCheckRe } hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) => (true, false), }; - let mut checker = UnsafetyChecker::new(const_context, min_const_fn, body, tcx, param_env); + let mut checker = + UnsafetyChecker::new(const_context, min_const_fn, body, def_id, tcx, param_env); checker.visit_body(&body); check_unused_unsafe(tcx, def_id, &checker.used_unsafe, &mut checker.inherited_blocks); From f9b9ba51d3a5d3e5ae3db4a351c2be47e36ef366 Mon Sep 17 00:00:00 2001 From: LeSeulArtichaut Date: Fri, 1 May 2020 15:17:20 +0200 Subject: [PATCH 3/4] Prevent functions with `#[target_feature]` to be coerced to safe function pointers --- src/librustc_middle/ty/error.rs | 23 +++++++++++++++++++++- src/librustc_middle/ty/structural_impls.rs | 1 + src/librustc_typeck/check/coercion.rs | 12 ++++++++++- 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/librustc_middle/ty/error.rs b/src/librustc_middle/ty/error.rs index d0bc0d5fabfae..78a94b62d4722 100644 --- a/src/librustc_middle/ty/error.rs +++ b/src/librustc_middle/ty/error.rs @@ -3,11 +3,13 @@ use rustc_ast::ast; use rustc_errors::{pluralize, Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::def_id::DefId; +use rustc_span::symbol::sym; use rustc_span::Span; use rustc_target::spec::abi; use std::borrow::Cow; use std::fmt; +use std::ops::Deref; #[derive(Clone, Copy, Debug, PartialEq, Eq, TypeFoldable)] pub struct ExpectedFound { @@ -58,6 +60,8 @@ pub enum TypeError<'tcx> { ConstMismatch(ExpectedFound<&'tcx ty::Const<'tcx>>), IntrinsicCast, + /// Safe `#[target_feature]` functions are not assignable to safe function pointers. + TargetFeatureCast(DefId), } pub enum UnconstrainedNumeric { @@ -183,6 +187,10 @@ impl<'tcx> fmt::Display for TypeError<'tcx> { write!(f, "expected `{}`, found `{}`", values.expected, values.found) } IntrinsicCast => write!(f, "cannot coerce intrinsics to function pointers"), + TargetFeatureCast(_) => write!( + f, + "cannot coerce functions with `#[target_feature]` to safe function pointers" + ), ObjectUnsafeCoercion(_) => write!(f, "coercion to object-unsafe trait object"), } } @@ -193,7 +201,8 @@ impl<'tcx> TypeError<'tcx> { use self::TypeError::*; match self { CyclicTy(_) | UnsafetyMismatch(_) | Mismatch | AbiMismatch(_) | FixedArraySize(_) - | Sorts(_) | IntMismatch(_) | FloatMismatch(_) | VariadicMismatch(_) => false, + | Sorts(_) | IntMismatch(_) | FloatMismatch(_) | VariadicMismatch(_) + | TargetFeatureCast(_) => false, Mutability | TupleSize(_) @@ -489,6 +498,18 @@ impl Trait for X { ); } } + TargetFeatureCast(def_id) => { + let attrs = self.get_attrs(*def_id); + let target_spans = attrs + .deref() + .iter() + .filter(|attr| attr.has_name(sym::target_feature)) + .map(|attr| attr.span); + db.note( + "functions with `#[target_feature]` can only be coerced to `unsafe` function pointers" + ); + db.span_labels(target_spans, "`#[target_feature]` added here"); + } _ => {} } } diff --git a/src/librustc_middle/ty/structural_impls.rs b/src/librustc_middle/ty/structural_impls.rs index 1c0ffe12314b3..c8406a024ecff 100644 --- a/src/librustc_middle/ty/structural_impls.rs +++ b/src/librustc_middle/ty/structural_impls.rs @@ -645,6 +645,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::error::TypeError<'a> { ExistentialMismatch(ref x) => return tcx.lift(x).map(ExistentialMismatch), ConstMismatch(ref x) => return tcx.lift(x).map(ConstMismatch), IntrinsicCast => IntrinsicCast, + TargetFeatureCast(ref x) => TargetFeatureCast(*x), ObjectUnsafeCoercion(ref x) => return tcx.lift(x).map(ObjectUnsafeCoercion), }) } diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index 5d1a1a164855d..9a3bb7ee88a0f 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -688,12 +688,22 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { debug!("coerce_from_fn_item(a={:?}, b={:?})", a, b); match b.kind { - ty::FnPtr(_) => { + ty::FnPtr(b_sig) => { let a_sig = a.fn_sig(self.tcx); // Intrinsics are not coercible to function pointers if a_sig.abi() == Abi::RustIntrinsic || a_sig.abi() == Abi::PlatformIntrinsic { return Err(TypeError::IntrinsicCast); } + + // Safe `#[target_feature]` functions are not assignable to safe fn pointers (RFC 2396). + if let ty::FnDef(def_id, _) = a.kind { + if b_sig.unsafety() == hir::Unsafety::Normal + && !self.tcx.codegen_fn_attrs(def_id).target_features.is_empty() + { + return Err(TypeError::TargetFeatureCast(def_id)); + } + } + let InferOk { value: a_sig, mut obligations } = self.normalize_associated_types_in_as_infer_ok(self.cause.span, &a_sig); From 8d9f73a6902064e1a5508af98d77aed2ae055944 Mon Sep 17 00:00:00 2001 From: LeSeulArtichaut Date: Fri, 1 May 2020 15:32:28 +0200 Subject: [PATCH 4/4] Add new tests and bless old tests --- src/test/ui/macros/issue-68060.stderr | 10 ++- .../rfc-2396-target_feature-11/check-pass.rs | 50 +++++++++++ .../feature-gate-target_feature_11.rs | 6 ++ .../feature-gate-target_feature_11.stderr | 14 ++++ .../rfcs/rfc-2396-target_feature-11/fn-ptr.rs | 10 +++ .../rfc-2396-target_feature-11/fn-ptr.stderr | 18 ++++ .../rfc-2396-target_feature-11/safe-calls.rs | 47 +++++++++++ .../safe-calls.stderr | 83 +++++++++++++++++++ .../rfc-2396-target_feature-11/trait-impl.rs | 21 +++++ .../trait-impl.stderr | 11 +++ .../ui/target-feature/invalid-attribute.rs | 6 +- .../target-feature/invalid-attribute.stderr | 22 +++-- 12 files changed, 286 insertions(+), 12 deletions(-) create mode 100644 src/test/ui/rfcs/rfc-2396-target_feature-11/check-pass.rs create mode 100644 src/test/ui/rfcs/rfc-2396-target_feature-11/feature-gate-target_feature_11.rs create mode 100644 src/test/ui/rfcs/rfc-2396-target_feature-11/feature-gate-target_feature_11.stderr create mode 100644 src/test/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.rs create mode 100644 src/test/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.stderr create mode 100644 src/test/ui/rfcs/rfc-2396-target_feature-11/safe-calls.rs create mode 100644 src/test/ui/rfcs/rfc-2396-target_feature-11/safe-calls.stderr create mode 100644 src/test/ui/rfcs/rfc-2396-target_feature-11/trait-impl.rs create mode 100644 src/test/ui/rfcs/rfc-2396-target_feature-11/trait-impl.stderr diff --git a/src/test/ui/macros/issue-68060.stderr b/src/test/ui/macros/issue-68060.stderr index 3ea49e614e633..22187c4a4098a 100644 --- a/src/test/ui/macros/issue-68060.stderr +++ b/src/test/ui/macros/issue-68060.stderr @@ -1,11 +1,14 @@ -error: `#[target_feature(..)]` can only be applied to `unsafe` functions +error[E0658]: `#[target_feature(..)]` can only be applied to `unsafe` functions --> $DIR/issue-68060.rs:6:13 | LL | #[target_feature(enable = "")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can only be applied to `unsafe` functions + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | |_| (), | ------ not an `unsafe` function + | + = note: see issue #69098 for more information + = help: add `#![feature(target_feature_11)]` to the crate attributes to enable error: the feature named `` is not valid for this target --> $DIR/issue-68060.rs:6:30 @@ -21,4 +24,5 @@ LL | #[track_caller] error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0737`. +Some errors have detailed explanations: E0658, E0737. +For more information about an error, try `rustc --explain E0658`. diff --git a/src/test/ui/rfcs/rfc-2396-target_feature-11/check-pass.rs b/src/test/ui/rfcs/rfc-2396-target_feature-11/check-pass.rs new file mode 100644 index 0000000000000..58a2c271ecfbc --- /dev/null +++ b/src/test/ui/rfcs/rfc-2396-target_feature-11/check-pass.rs @@ -0,0 +1,50 @@ +// Tests the new rules added by RFC 2396, including: +// - applying `#[target_feature]` to safe functions is allowed +// - calling functions with `#[target_feature]` is allowed in +// functions which have (at least) the same features +// - calling functions with `#[target_feature]` is allowed in +// unsafe contexts +// - functions with `#[target_feature]` can coerce to unsafe fn pointers + +// check-pass +// only-x86_64 + +#![feature(target_feature_11)] + +#[target_feature(enable = "sse2")] +const fn sse2() {} + +#[cfg(target_feature = "sse2")] +const SSE2_ONLY: () = unsafe { + sse2(); +}; + +#[target_feature(enable = "sse2")] +fn also_sse2() { + sse2(); +} + +#[target_feature(enable = "sse2")] +#[target_feature(enable = "avx")] +fn sse2_and_avx() { + sse2(); +} + +struct Foo; + +impl Foo { + #[target_feature(enable = "sse2")] + fn sse2(&self) { + sse2(); + } +} + +fn main() { + if cfg!(target_feature = "sse2") { + unsafe { + sse2(); + Foo.sse2(); + } + } + let sse2_ptr: unsafe fn() = sse2; +} diff --git a/src/test/ui/rfcs/rfc-2396-target_feature-11/feature-gate-target_feature_11.rs b/src/test/ui/rfcs/rfc-2396-target_feature-11/feature-gate-target_feature_11.rs new file mode 100644 index 0000000000000..975d7a1f694c6 --- /dev/null +++ b/src/test/ui/rfcs/rfc-2396-target_feature-11/feature-gate-target_feature_11.rs @@ -0,0 +1,6 @@ +// only-x86_64 + +#[target_feature(enable = "sse2")] //~ ERROR can only be applied to `unsafe` functions +fn foo() {} + +fn main() {} diff --git a/src/test/ui/rfcs/rfc-2396-target_feature-11/feature-gate-target_feature_11.stderr b/src/test/ui/rfcs/rfc-2396-target_feature-11/feature-gate-target_feature_11.stderr new file mode 100644 index 0000000000000..413890f436d0f --- /dev/null +++ b/src/test/ui/rfcs/rfc-2396-target_feature-11/feature-gate-target_feature_11.stderr @@ -0,0 +1,14 @@ +error[E0658]: `#[target_feature(..)]` can only be applied to `unsafe` functions + --> $DIR/feature-gate-target_feature_11.rs:3:1 + | +LL | #[target_feature(enable = "sse2")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn foo() {} + | ----------- not an `unsafe` function + | + = note: see issue #69098 for more information + = help: add `#![feature(target_feature_11)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.rs b/src/test/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.rs new file mode 100644 index 0000000000000..3ecea5c531390 --- /dev/null +++ b/src/test/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.rs @@ -0,0 +1,10 @@ +// only-x86_64 + +#![feature(target_feature_11)] + +#[target_feature(enable = "sse2")] +fn foo() {} + +fn main() { + let foo: fn() = foo; //~ ERROR mismatched types +} diff --git a/src/test/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.stderr b/src/test/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.stderr new file mode 100644 index 0000000000000..06cfdde3fb974 --- /dev/null +++ b/src/test/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.stderr @@ -0,0 +1,18 @@ +error[E0308]: mismatched types + --> $DIR/fn-ptr.rs:9:21 + | +LL | #[target_feature(enable = "sse2")] + | ---------------------------------- `#[target_feature]` added here +... +LL | let foo: fn() = foo; + | ---- ^^^ cannot coerce functions with `#[target_feature]` to safe function pointers + | | + | expected due to this + | + = note: expected fn pointer `fn()` + found fn item `fn() {foo}` + = note: functions with `#[target_feature]` can only be coerced to `unsafe` function pointers + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/rfcs/rfc-2396-target_feature-11/safe-calls.rs b/src/test/ui/rfcs/rfc-2396-target_feature-11/safe-calls.rs new file mode 100644 index 0000000000000..8da3affc4477b --- /dev/null +++ b/src/test/ui/rfcs/rfc-2396-target_feature-11/safe-calls.rs @@ -0,0 +1,47 @@ +// only-x86_64 + +#![feature(target_feature_11)] + +#[target_feature(enable = "sse2")] +const fn sse2() {} + +#[target_feature(enable = "avx")] +#[target_feature(enable = "bmi2")] +fn avx_bmi2() {} + +struct Quux; + +impl Quux { + #[target_feature(enable = "avx")] + #[target_feature(enable = "bmi2")] + fn avx_bmi2(&self) {} +} + +fn foo() { + sse2(); //~ ERROR call to function with `#[target_feature]` is unsafe + avx_bmi2(); //~ ERROR call to function with `#[target_feature]` is unsafe + Quux.avx_bmi2(); //~ ERROR call to function with `#[target_feature]` is unsafe +} + +#[target_feature(enable = "sse2")] +fn bar() { + avx_bmi2(); //~ ERROR call to function with `#[target_feature]` is unsafe + Quux.avx_bmi2(); //~ ERROR call to function with `#[target_feature]` is unsafe +} + +#[target_feature(enable = "avx")] +fn baz() { + sse2(); //~ ERROR call to function with `#[target_feature]` is unsafe + avx_bmi2(); //~ ERROR call to function with `#[target_feature]` is unsafe + Quux.avx_bmi2(); //~ ERROR call to function with `#[target_feature]` is unsafe +} + +#[target_feature(enable = "avx")] +#[target_feature(enable = "bmi2")] +fn qux() { + sse2(); //~ ERROR call to function with `#[target_feature]` is unsafe +} + +const name: () = sse2(); //~ ERROR call to function with `#[target_feature]` is unsafe + +fn main() {} diff --git a/src/test/ui/rfcs/rfc-2396-target_feature-11/safe-calls.stderr b/src/test/ui/rfcs/rfc-2396-target_feature-11/safe-calls.stderr new file mode 100644 index 0000000000000..b9f748640b558 --- /dev/null +++ b/src/test/ui/rfcs/rfc-2396-target_feature-11/safe-calls.stderr @@ -0,0 +1,83 @@ +error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block + --> $DIR/safe-calls.rs:21:5 + | +LL | sse2(); + | ^^^^^^ call to function with `#[target_feature]` + | + = note: can only be called if the required target features are available + +error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block + --> $DIR/safe-calls.rs:22:5 + | +LL | avx_bmi2(); + | ^^^^^^^^^^ call to function with `#[target_feature]` + | + = note: can only be called if the required target features are available + +error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block + --> $DIR/safe-calls.rs:23:5 + | +LL | Quux.avx_bmi2(); + | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` + | + = note: can only be called if the required target features are available + +error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block + --> $DIR/safe-calls.rs:28:5 + | +LL | avx_bmi2(); + | ^^^^^^^^^^ call to function with `#[target_feature]` + | + = note: can only be called if the required target features are available + +error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block + --> $DIR/safe-calls.rs:29:5 + | +LL | Quux.avx_bmi2(); + | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` + | + = note: can only be called if the required target features are available + +error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block + --> $DIR/safe-calls.rs:34:5 + | +LL | sse2(); + | ^^^^^^ call to function with `#[target_feature]` + | + = note: can only be called if the required target features are available + +error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block + --> $DIR/safe-calls.rs:35:5 + | +LL | avx_bmi2(); + | ^^^^^^^^^^ call to function with `#[target_feature]` + | + = note: can only be called if the required target features are available + +error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block + --> $DIR/safe-calls.rs:36:5 + | +LL | Quux.avx_bmi2(); + | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` + | + = note: can only be called if the required target features are available + +error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block + --> $DIR/safe-calls.rs:42:5 + | +LL | sse2(); + | ^^^^^^ call to function with `#[target_feature]` + | + = note: can only be called if the required target features are available + +error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block + --> $DIR/safe-calls.rs:45:18 + | +LL | const name: () = sse2(); + | ^^^^^^ call to function with `#[target_feature]` + | + = note: can only be called if the required target features are available + +error: aborting due to 10 previous errors + +For more information about this error, try `rustc --explain E0133`. diff --git a/src/test/ui/rfcs/rfc-2396-target_feature-11/trait-impl.rs b/src/test/ui/rfcs/rfc-2396-target_feature-11/trait-impl.rs new file mode 100644 index 0000000000000..7314fa8cced2a --- /dev/null +++ b/src/test/ui/rfcs/rfc-2396-target_feature-11/trait-impl.rs @@ -0,0 +1,21 @@ +// only-x86_64 + +#![feature(target_feature_11)] + +trait Foo { + fn foo(&self); + unsafe fn unsf_foo(&self); +} + +struct Bar; + +impl Foo for Bar { + #[target_feature(enable = "sse2")] + //~^ ERROR cannot be applied to safe trait method + fn foo(&self) {} + + #[target_feature(enable = "sse2")] + unsafe fn unsf_foo(&self) {} +} + +fn main() {} diff --git a/src/test/ui/rfcs/rfc-2396-target_feature-11/trait-impl.stderr b/src/test/ui/rfcs/rfc-2396-target_feature-11/trait-impl.stderr new file mode 100644 index 0000000000000..3c56e0fc5c6e3 --- /dev/null +++ b/src/test/ui/rfcs/rfc-2396-target_feature-11/trait-impl.stderr @@ -0,0 +1,11 @@ +error: `#[target_feature(..)]` cannot be applied to safe trait method + --> $DIR/trait-impl.rs:13:5 + | +LL | #[target_feature(enable = "sse2")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot be applied to safe trait method +LL | +LL | fn foo(&self) {} + | ---------------- not an `unsafe` function + +error: aborting due to previous error + diff --git a/src/test/ui/target-feature/invalid-attribute.rs b/src/test/ui/target-feature/invalid-attribute.rs index 19c8c3dd4886b..63b1951a71631 100644 --- a/src/test/ui/target-feature/invalid-attribute.rs +++ b/src/test/ui/target-feature/invalid-attribute.rs @@ -26,7 +26,7 @@ unsafe fn foo() {} #[target_feature(enable = "sse2")] //~^ ERROR `#[target_feature(..)]` can only be applied to `unsafe` functions -//~| NOTE can only be applied to `unsafe` functions +//~| NOTE see issue #69098 fn bar() {} //~^ NOTE not an `unsafe` function @@ -72,7 +72,7 @@ trait Quux { impl Quux for Foo { #[target_feature(enable = "sse2")] //~^ ERROR `#[target_feature(..)]` can only be applied to `unsafe` functions - //~| NOTE can only be applied to `unsafe` functions + //~| NOTE see issue #69098 fn foo() {} //~^ NOTE not an `unsafe` function } @@ -84,7 +84,7 @@ fn main() { } #[target_feature(enable = "sse2")] //~^ ERROR `#[target_feature(..)]` can only be applied to `unsafe` functions - //~| NOTE can only be applied to `unsafe` functions + //~| NOTE see issue #69098 || {}; //~^ NOTE not an `unsafe` function } diff --git a/src/test/ui/target-feature/invalid-attribute.stderr b/src/test/ui/target-feature/invalid-attribute.stderr index 76273d66ac2cf..21d6aa218ec79 100644 --- a/src/test/ui/target-feature/invalid-attribute.stderr +++ b/src/test/ui/target-feature/invalid-attribute.stderr @@ -22,14 +22,17 @@ error: malformed `target_feature` attribute input LL | #[target_feature(disable = "baz")] | ^^^^^^^^^^^^^^^ help: must be of the form: `enable = ".."` -error: `#[target_feature(..)]` can only be applied to `unsafe` functions +error[E0658]: `#[target_feature(..)]` can only be applied to `unsafe` functions --> $DIR/invalid-attribute.rs:27:1 | LL | #[target_feature(enable = "sse2")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can only be applied to `unsafe` functions + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | fn bar() {} | ----------- not an `unsafe` function + | + = note: see issue #69098 for more information + = help: add `#![feature(target_feature_11)]` to the crate attributes to enable error: attribute should be applied to a function --> $DIR/invalid-attribute.rs:33:1 @@ -91,23 +94,30 @@ error: cannot use `#[inline(always)]` with `#[target_feature]` LL | #[inline(always)] | ^^^^^^^^^^^^^^^^^ -error: `#[target_feature(..)]` can only be applied to `unsafe` functions +error[E0658]: `#[target_feature(..)]` can only be applied to `unsafe` functions --> $DIR/invalid-attribute.rs:85:5 | LL | #[target_feature(enable = "sse2")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can only be applied to `unsafe` functions + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | || {}; | ----- not an `unsafe` function + | + = note: see issue #69098 for more information + = help: add `#![feature(target_feature_11)]` to the crate attributes to enable -error: `#[target_feature(..)]` can only be applied to `unsafe` functions +error[E0658]: `#[target_feature(..)]` can only be applied to `unsafe` functions --> $DIR/invalid-attribute.rs:73:5 | LL | #[target_feature(enable = "sse2")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can only be applied to `unsafe` functions + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | fn foo() {} | ----------- not an `unsafe` function + | + = note: see issue #69098 for more information + = help: add `#![feature(target_feature_11)]` to the crate attributes to enable error: aborting due to 14 previous errors +For more information about this error, try `rustc --explain E0658`.