Treat safe target_feature functions as unsafe by default
This commit is contained in:
parent
a907c56a77
commit
56178ddc90
20 changed files with 159 additions and 56 deletions
|
@ -188,7 +188,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
) -> hir::FnSig<'hir> {
|
||||
let header = if let Some(local_sig_id) = sig_id.as_local() {
|
||||
match self.resolver.delegation_fn_sigs.get(&local_sig_id) {
|
||||
Some(sig) => self.lower_fn_header(sig.header, hir::Safety::Safe),
|
||||
Some(sig) => self.lower_fn_header(
|
||||
sig.header,
|
||||
// HACK: we override the default safety instead of generating attributes from the ether.
|
||||
// We are not forwarding the attributes, as the delegation fn sigs are collected on the ast,
|
||||
// and here we need the hir attributes.
|
||||
if sig.target_feature { hir::Safety::Unsafe } else { hir::Safety::Safe },
|
||||
&[],
|
||||
),
|
||||
None => self.generate_header_error(),
|
||||
}
|
||||
} else {
|
||||
|
@ -198,7 +205,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
Asyncness::No => hir::IsAsync::NotAsync,
|
||||
};
|
||||
hir::FnHeader {
|
||||
safety: sig.safety.into(),
|
||||
safety: if self.tcx.codegen_fn_attrs(sig_id).safe_target_features {
|
||||
hir::HeaderSafety::SafeTargetFeatures
|
||||
} else {
|
||||
hir::HeaderSafety::Normal(sig.safety)
|
||||
},
|
||||
constness: self.tcx.constness(sig_id),
|
||||
asyncness,
|
||||
abi: sig.abi,
|
||||
|
|
|
@ -231,7 +231,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
});
|
||||
let sig = hir::FnSig {
|
||||
decl,
|
||||
header: this.lower_fn_header(*header, hir::Safety::Safe),
|
||||
header: this.lower_fn_header(*header, hir::Safety::Safe, attrs),
|
||||
span: this.lower_span(*fn_sig_span),
|
||||
};
|
||||
hir::ItemKind::Fn { sig, generics, body: body_id, has_body: body.is_some() }
|
||||
|
@ -610,7 +610,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
fn lower_foreign_item(&mut self, i: &ForeignItem) -> &'hir hir::ForeignItem<'hir> {
|
||||
let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id);
|
||||
let owner_id = hir_id.expect_owner();
|
||||
self.lower_attrs(hir_id, &i.attrs);
|
||||
let attrs = self.lower_attrs(hir_id, &i.attrs);
|
||||
let item = hir::ForeignItem {
|
||||
owner_id,
|
||||
ident: self.lower_ident(i.ident),
|
||||
|
@ -634,7 +634,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
});
|
||||
|
||||
// Unmarked safety in unsafe block defaults to unsafe.
|
||||
let header = self.lower_fn_header(sig.header, hir::Safety::Unsafe);
|
||||
let header = self.lower_fn_header(sig.header, hir::Safety::Unsafe, attrs);
|
||||
|
||||
hir::ForeignItemKind::Fn(
|
||||
hir::FnSig { header, decl, span: self.lower_span(sig.span) },
|
||||
|
@ -776,6 +776,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
i.id,
|
||||
FnDeclKind::Trait,
|
||||
sig.header.coroutine_kind,
|
||||
attrs,
|
||||
);
|
||||
(generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)), false)
|
||||
}
|
||||
|
@ -795,6 +796,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
i.id,
|
||||
FnDeclKind::Trait,
|
||||
sig.header.coroutine_kind,
|
||||
attrs,
|
||||
);
|
||||
(generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)), true)
|
||||
}
|
||||
|
@ -911,6 +913,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
i.id,
|
||||
if self.is_in_trait_impl { FnDeclKind::Impl } else { FnDeclKind::Inherent },
|
||||
sig.header.coroutine_kind,
|
||||
attrs,
|
||||
);
|
||||
|
||||
(generics, hir::ImplItemKind::Fn(sig, body_id))
|
||||
|
@ -1339,8 +1342,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
id: NodeId,
|
||||
kind: FnDeclKind,
|
||||
coroutine_kind: Option<CoroutineKind>,
|
||||
attrs: &[hir::Attribute],
|
||||
) -> (&'hir hir::Generics<'hir>, hir::FnSig<'hir>) {
|
||||
let header = self.lower_fn_header(sig.header, hir::Safety::Safe);
|
||||
let header = self.lower_fn_header(sig.header, hir::Safety::Safe, attrs);
|
||||
let itctx = ImplTraitContext::Universal;
|
||||
let (generics, decl) = self.lower_generics(generics, id, itctx, |this| {
|
||||
this.lower_fn_decl(&sig.decl, id, sig.span, kind, coroutine_kind)
|
||||
|
@ -1352,6 +1356,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
&mut self,
|
||||
h: FnHeader,
|
||||
default_safety: hir::Safety,
|
||||
attrs: &[hir::Attribute],
|
||||
) -> hir::FnHeader {
|
||||
let asyncness = if let Some(CoroutineKind::Async { span, .. }) = h.coroutine_kind {
|
||||
hir::IsAsync::Async(span)
|
||||
|
@ -1360,7 +1365,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
};
|
||||
|
||||
let safety = self.lower_safety(h.safety, default_safety);
|
||||
let safety = safety.into();
|
||||
|
||||
// Treat safe `#[target_feature]` functions as unsafe, but also remember that we did so.
|
||||
let safety = if attrs.iter().any(|attr| attr.has_name(sym::target_feature))
|
||||
&& safety.is_safe()
|
||||
&& !self.tcx.sess.target.is_like_wasm
|
||||
{
|
||||
hir::HeaderSafety::SafeTargetFeatures
|
||||
} else {
|
||||
safety.into()
|
||||
};
|
||||
|
||||
hir::FnHeader {
|
||||
safety,
|
||||
|
|
|
@ -250,10 +250,14 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
|
|||
}
|
||||
}
|
||||
sym::target_feature => {
|
||||
if !tcx.is_closure_like(did.to_def_id())
|
||||
&& let Some(fn_sig) = fn_sig()
|
||||
&& fn_sig.skip_binder().safety().is_safe()
|
||||
{
|
||||
let Some(sig) = tcx.hir_node_by_def_id(did).fn_sig() else {
|
||||
tcx.dcx().span_delayed_bug(attr.span, "target_feature applied to non-fn");
|
||||
continue;
|
||||
};
|
||||
let safe_target_features =
|
||||
matches!(sig.header.safety, hir::HeaderSafety::SafeTargetFeatures);
|
||||
codegen_fn_attrs.safe_target_features = safe_target_features;
|
||||
if safe_target_features {
|
||||
if tcx.sess.target.is_like_wasm || tcx.sess.opts.actually_rustdoc {
|
||||
// The `#[target_feature]` attribute is allowed on
|
||||
// WebAssembly targets on all functions, including safe
|
||||
|
|
|
@ -3762,8 +3762,18 @@ impl fmt::Display for Constness {
|
|||
}
|
||||
}
|
||||
|
||||
/// The actualy safety specified in syntax. We may treat
|
||||
/// its safety different within the type system to create a
|
||||
/// "sound by default" system that needs checking this enum
|
||||
/// explicitly to allow unsafe operations.
|
||||
#[derive(Copy, Clone, Debug, HashStable_Generic, PartialEq, Eq)]
|
||||
pub enum HeaderSafety {
|
||||
/// A safe function annotated with `#[target_features]`.
|
||||
/// The type system treats this function as an unsafe function,
|
||||
/// but safety checking will check this enum to treat it as safe
|
||||
/// and allowing calling other safe target feature functions with
|
||||
/// the same features without requiring an additional unsafe block.
|
||||
SafeTargetFeatures,
|
||||
Normal(Safety),
|
||||
}
|
||||
|
||||
|
@ -3800,6 +3810,7 @@ impl FnHeader {
|
|||
|
||||
pub fn safety(&self) -> Safety {
|
||||
match self.safety {
|
||||
HeaderSafety::SafeTargetFeatures => Safety::Unsafe,
|
||||
HeaderSafety::Normal(safety) => safety,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2424,6 +2424,10 @@ impl<'a> State<'a> {
|
|||
self.print_constness(header.constness);
|
||||
|
||||
let safety = match header.safety {
|
||||
hir::HeaderSafety::SafeTargetFeatures => {
|
||||
self.word_nbsp("#[target_feature]");
|
||||
hir::Safety::Safe
|
||||
}
|
||||
hir::HeaderSafety::Normal(safety) => safety,
|
||||
};
|
||||
|
||||
|
|
|
@ -932,9 +932,15 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
|||
return Err(TypeError::ForceInlineCast);
|
||||
}
|
||||
|
||||
// Safe `#[target_feature]` functions are not assignable to safe fn pointers (RFC 2396),
|
||||
// report a better error than a safety mismatch.
|
||||
// FIXME(target_feature): do this inside `coerce_from_safe_fn`.
|
||||
let fn_attrs = self.tcx.codegen_fn_attrs(def_id);
|
||||
if matches!(fn_attrs.inline, InlineAttr::Force { .. }) {
|
||||
return Err(TypeError::ForceInlineCast);
|
||||
}
|
||||
|
||||
// FIXME(target_feature): Safe `#[target_feature]` functions could be cast to safe fn pointers (RFC 2396),
|
||||
// as you can already write that "cast" in user code by wrapping a target_feature fn call in a closure,
|
||||
// which is safe. This is sound because you already need to be executing code that is satisfying the target
|
||||
// feature constraints..
|
||||
if b_hdr.safety.is_safe()
|
||||
&& self.tcx.codegen_fn_attrs(def_id).safe_target_features
|
||||
{
|
||||
|
|
|
@ -1120,6 +1120,10 @@ pub(crate) fn check_unsafety(tcx: TyCtxt<'_>, def: LocalDefId) {
|
|||
let hir_id = tcx.local_def_id_to_hir_id(def);
|
||||
let safety_context = tcx.hir().fn_sig_by_hir_id(hir_id).map_or(SafetyContext::Safe, |fn_sig| {
|
||||
match fn_sig.header.safety {
|
||||
// We typeck the body as safe, but otherwise treat it as unsafe everywhere else.
|
||||
// Call sites to other SafeTargetFeatures functions are checked explicitly and don't need
|
||||
// to care about safety of the body.
|
||||
hir::HeaderSafety::SafeTargetFeatures => SafetyContext::Safe,
|
||||
hir::HeaderSafety::Normal(safety) => match safety {
|
||||
hir::Safety::Unsafe => SafetyContext::UnsafeFn,
|
||||
hir::Safety::Safe => SafetyContext::Safe,
|
||||
|
|
|
@ -668,14 +668,25 @@ impl Item {
|
|||
ty::Asyncness::Yes => hir::IsAsync::Async(DUMMY_SP),
|
||||
ty::Asyncness::No => hir::IsAsync::NotAsync,
|
||||
};
|
||||
hir::FnHeader { safety: sig.safety().into(), abi: sig.abi(), constness, asyncness }
|
||||
hir::FnHeader {
|
||||
safety: if tcx.codegen_fn_attrs(def_id).safe_target_features {
|
||||
hir::HeaderSafety::SafeTargetFeatures
|
||||
} else {
|
||||
sig.safety().into()
|
||||
},
|
||||
abi: sig.abi(),
|
||||
constness,
|
||||
asyncness,
|
||||
}
|
||||
}
|
||||
let header = match self.kind {
|
||||
ItemKind::ForeignFunctionItem(_, safety) => {
|
||||
let def_id = self.def_id().unwrap();
|
||||
let abi = tcx.fn_sig(def_id).skip_binder().abi();
|
||||
hir::FnHeader {
|
||||
safety: if abi == ExternAbi::RustIntrinsic {
|
||||
safety: if tcx.codegen_fn_attrs(def_id).safe_target_features {
|
||||
hir::HeaderSafety::SafeTargetFeatures
|
||||
} else if abi == ExternAbi::RustIntrinsic {
|
||||
intrinsic_operation_unsafety(tcx, def_id.expect_local()).into()
|
||||
} else {
|
||||
safety.into()
|
||||
|
|
|
@ -1640,6 +1640,7 @@ impl PrintWithSpace for hir::Safety {
|
|||
impl PrintWithSpace for hir::HeaderSafety {
|
||||
fn print_with_space(&self) -> &str {
|
||||
match self {
|
||||
hir::HeaderSafety::SafeTargetFeatures => "",
|
||||
hir::HeaderSafety::Normal(safety) => safety.print_with_space(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
error[E0277]: the trait bound `fn() -> Pin<Box<(dyn Future<Output = ()> + 'static)>> {target_feature}: AsyncFn()` is not satisfied
|
||||
error[E0277]: the trait bound `unsafe fn() -> Pin<Box<(dyn Future<Output = ()> + 'static)>> {target_feature}: AsyncFn()` is not satisfied
|
||||
--> $DIR/fn-exception-target-features.rs:16:10
|
||||
|
|
||||
LL | test(target_feature);
|
||||
| ---- ^^^^^^^^^^^^^^ the trait `AsyncFn()` is not implemented for fn item `fn() -> Pin<Box<(dyn Future<Output = ()> + 'static)>> {target_feature}`
|
||||
| ---- ^^^^^^^^^^^^^^ the trait `AsyncFn()` is not implemented for fn item `unsafe fn() -> Pin<Box<(dyn Future<Output = ()> + 'static)>> {target_feature}`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
|
|
|
@ -3,8 +3,6 @@ fn main() {
|
|||
.map(
|
||||
#[target_feature(enable = "")]
|
||||
//~^ ERROR: attribute should be applied to a function
|
||||
//~| ERROR: feature named `` is not valid
|
||||
//~| NOTE: `` is not valid for this target
|
||||
#[track_caller]
|
||||
//~^ ERROR: `#[track_caller]` on closures is currently unstable
|
||||
//~| NOTE: see issue #87417
|
||||
|
|
|
@ -7,14 +7,8 @@ LL | #[target_feature(enable = "")]
|
|||
LL | |_| (),
|
||||
| ------ not a function definition
|
||||
|
||||
error: the feature named `` is not valid for this target
|
||||
--> $DIR/issue-68060.rs:4:30
|
||||
|
|
||||
LL | #[target_feature(enable = "")]
|
||||
| ^^^^^^^^^^^ `` is not valid for this target
|
||||
|
||||
error[E0658]: `#[track_caller]` on closures is currently unstable
|
||||
--> $DIR/issue-68060.rs:8:13
|
||||
--> $DIR/issue-68060.rs:6:13
|
||||
|
|
||||
LL | #[track_caller]
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
@ -23,6 +17,6 @@ LL | #[track_caller]
|
|||
= help: add `#![feature(closure_track_caller)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
|
|
|
@ -10,13 +10,9 @@ LL | let foo: fn() = foo;
|
|||
| expected due to this
|
||||
|
|
||||
= note: expected fn pointer `fn()`
|
||||
found fn item `fn() {foo}`
|
||||
= note: fn items are distinct from fn pointers
|
||||
found fn item `unsafe fn() {foo}`
|
||||
= note: functions with `#[target_feature]` can only be coerced to `unsafe` function pointers
|
||||
help: consider casting to a fn pointer
|
||||
|
|
||||
LL | let foo: fn() = foo as fn();
|
||||
| ~~~~~~~~~~~
|
||||
= note: unsafe functions cannot be coerced into safe function pointers
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
|
@ -21,9 +21,9 @@ fn call_once(f: impl FnOnce()) {
|
|||
}
|
||||
|
||||
fn main() {
|
||||
call(foo); //~ ERROR expected a `Fn()` closure, found `fn() {foo}`
|
||||
call_mut(foo); //~ ERROR expected a `FnMut()` closure, found `fn() {foo}`
|
||||
call_once(foo); //~ ERROR expected a `FnOnce()` closure, found `fn() {foo}`
|
||||
call(foo); //~ ERROR expected a `Fn()` closure, found `unsafe fn() {foo}`
|
||||
call_mut(foo); //~ ERROR expected a `FnMut()` closure, found `unsafe fn() {foo}`
|
||||
call_once(foo); //~ ERROR expected a `FnOnce()` closure, found `unsafe fn() {foo}`
|
||||
|
||||
call(foo_unsafe);
|
||||
//~^ ERROR expected a `Fn()` closure, found `unsafe fn() {foo_unsafe}`
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
error[E0277]: expected a `Fn()` closure, found `fn() {foo}`
|
||||
error[E0277]: expected a `Fn()` closure, found `unsafe fn() {foo}`
|
||||
--> $DIR/fn-traits.rs:24:10
|
||||
|
|
||||
LL | call(foo);
|
||||
| ---- ^^^ expected an `Fn()` closure, found `fn() {foo}`
|
||||
| ---- ^^^ call the function in a closure: `|| unsafe { /* code */ }`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= help: the trait `Fn()` is not implemented for fn item `fn() {foo}`
|
||||
= note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ }`
|
||||
= help: the trait `Fn()` is not implemented for fn item `unsafe fn() {foo}`
|
||||
= note: unsafe function cannot be called generically without an unsafe block
|
||||
= note: wrap the `unsafe fn() {foo}` in a closure with no arguments: `|| { /* code */ }`
|
||||
= note: `#[target_feature]` functions do not implement the `Fn` traits
|
||||
note: required by a bound in `call`
|
||||
--> $DIR/fn-traits.rs:11:17
|
||||
|
@ -15,16 +16,17 @@ note: required by a bound in `call`
|
|||
LL | fn call(f: impl Fn()) {
|
||||
| ^^^^ required by this bound in `call`
|
||||
|
||||
error[E0277]: expected a `FnMut()` closure, found `fn() {foo}`
|
||||
error[E0277]: expected a `FnMut()` closure, found `unsafe fn() {foo}`
|
||||
--> $DIR/fn-traits.rs:25:14
|
||||
|
|
||||
LL | call_mut(foo);
|
||||
| -------- ^^^ expected an `FnMut()` closure, found `fn() {foo}`
|
||||
| -------- ^^^ call the function in a closure: `|| unsafe { /* code */ }`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= help: the trait `FnMut()` is not implemented for fn item `fn() {foo}`
|
||||
= note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ }`
|
||||
= help: the trait `FnMut()` is not implemented for fn item `unsafe fn() {foo}`
|
||||
= note: unsafe function cannot be called generically without an unsafe block
|
||||
= note: wrap the `unsafe fn() {foo}` in a closure with no arguments: `|| { /* code */ }`
|
||||
= note: `#[target_feature]` functions do not implement the `Fn` traits
|
||||
note: required by a bound in `call_mut`
|
||||
--> $DIR/fn-traits.rs:15:25
|
||||
|
@ -32,16 +34,17 @@ note: required by a bound in `call_mut`
|
|||
LL | fn call_mut(mut f: impl FnMut()) {
|
||||
| ^^^^^^^ required by this bound in `call_mut`
|
||||
|
||||
error[E0277]: expected a `FnOnce()` closure, found `fn() {foo}`
|
||||
error[E0277]: expected a `FnOnce()` closure, found `unsafe fn() {foo}`
|
||||
--> $DIR/fn-traits.rs:26:15
|
||||
|
|
||||
LL | call_once(foo);
|
||||
| --------- ^^^ expected an `FnOnce()` closure, found `fn() {foo}`
|
||||
| --------- ^^^ call the function in a closure: `|| unsafe { /* code */ }`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= help: the trait `FnOnce()` is not implemented for fn item `fn() {foo}`
|
||||
= note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ }`
|
||||
= help: the trait `FnOnce()` is not implemented for fn item `unsafe fn() {foo}`
|
||||
= note: unsafe function cannot be called generically without an unsafe block
|
||||
= note: wrap the `unsafe fn() {foo}` in a closure with no arguments: `|| { /* code */ }`
|
||||
= note: `#[target_feature]` functions do not implement the `Fn` traits
|
||||
note: required by a bound in `call_once`
|
||||
--> $DIR/fn-traits.rs:19:22
|
||||
|
|
|
@ -26,6 +26,9 @@ LL | Quux.avx_bmi2();
|
|||
error[E0133]: call to function `avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block
|
||||
--> $DIR/safe-calls.rs:38:5
|
||||
|
|
||||
LL | fn bar() {
|
||||
| -------- items do not inherit unsafety from separate enclosing items
|
||||
LL | sse2();
|
||||
LL | avx_bmi2();
|
||||
| ^^^^^^^^^^ call to function with `#[target_feature]`
|
||||
|
|
||||
|
@ -34,6 +37,9 @@ LL | avx_bmi2();
|
|||
error[E0133]: call to function `Quux::avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block
|
||||
--> $DIR/safe-calls.rs:40:5
|
||||
|
|
||||
LL | fn bar() {
|
||||
| -------- items do not inherit unsafety from separate enclosing items
|
||||
...
|
||||
LL | Quux.avx_bmi2();
|
||||
| ^^^^^^^^^^^^^^^ call to function with `#[target_feature]`
|
||||
|
|
||||
|
@ -42,6 +48,9 @@ LL | Quux.avx_bmi2();
|
|||
error[E0133]: call to function `avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block
|
||||
--> $DIR/safe-calls.rs:47:5
|
||||
|
|
||||
LL | fn baz() {
|
||||
| -------- items do not inherit unsafety from separate enclosing items
|
||||
LL | sse2();
|
||||
LL | avx_bmi2();
|
||||
| ^^^^^^^^^^ call to function with `#[target_feature]`
|
||||
|
|
||||
|
@ -50,6 +59,9 @@ LL | avx_bmi2();
|
|||
error[E0133]: call to function `Quux::avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block
|
||||
--> $DIR/safe-calls.rs:49:5
|
||||
|
|
||||
LL | fn baz() {
|
||||
| -------- items do not inherit unsafety from separate enclosing items
|
||||
...
|
||||
LL | Quux.avx_bmi2();
|
||||
| ^^^^^^^^^^^^^^^ call to function with `#[target_feature]`
|
||||
|
|
||||
|
|
|
@ -13,6 +13,7 @@ impl Foo for Bar {
|
|||
#[target_feature(enable = "sse2")]
|
||||
//~^ ERROR cannot be applied to safe trait method
|
||||
fn foo(&self) {}
|
||||
//~^ ERROR method `foo` has an incompatible type for trait
|
||||
|
||||
#[target_feature(enable = "sse2")]
|
||||
unsafe fn unsf_foo(&self) {}
|
||||
|
|
|
@ -1,3 +1,17 @@
|
|||
error[E0053]: method `foo` has an incompatible type for trait
|
||||
--> $DIR/trait-impl.rs:15:5
|
||||
|
|
||||
LL | fn foo(&self) {}
|
||||
| ^^^^^^^^^^^^^ expected safe fn, found unsafe fn
|
||||
|
|
||||
note: type in trait
|
||||
--> $DIR/trait-impl.rs:6:5
|
||||
|
|
||||
LL | fn foo(&self);
|
||||
| ^^^^^^^^^^^^^^
|
||||
= note: expected signature `fn(&Bar)`
|
||||
found signature `unsafe fn(&Bar)`
|
||||
|
||||
error: `#[target_feature(..)]` cannot be applied to safe trait method
|
||||
--> $DIR/trait-impl.rs:13:5
|
||||
|
|
||||
|
@ -8,7 +22,7 @@ LL | fn foo(&self) {}
|
|||
| ------------- not an `unsafe` function
|
||||
|
||||
error: `#[target_feature(..)]` cannot be applied to safe trait method
|
||||
--> $DIR/trait-impl.rs:22:5
|
||||
--> $DIR/trait-impl.rs:23:5
|
||||
|
|
||||
LL | #[target_feature(enable = "sse2")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot be applied to safe trait method
|
||||
|
@ -16,5 +30,6 @@ LL |
|
|||
LL | fn foo(&self) {}
|
||||
| ------------- not an `unsafe` function
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0053`.
|
||||
|
|
|
@ -97,6 +97,7 @@ impl Foo {}
|
|||
|
||||
trait Quux {
|
||||
fn foo(); //~ NOTE `foo` from trait
|
||||
//~^ NOTE: type in trait
|
||||
}
|
||||
|
||||
impl Quux for Foo {
|
||||
|
@ -106,6 +107,9 @@ impl Quux for Foo {
|
|||
//~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
fn foo() {}
|
||||
//~^ NOTE not an `unsafe` function
|
||||
//~| ERROR: incompatible type for trait
|
||||
//~| NOTE: expected safe fn, found unsafe fn
|
||||
//~| NOTE: expected signature `fn()`
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
|
|
@ -126,7 +126,7 @@ LL | impl Foo {}
|
|||
| ----------- not a function definition
|
||||
|
||||
error: attribute should be applied to a function definition
|
||||
--> $DIR/invalid-attribute.rs:112:5
|
||||
--> $DIR/invalid-attribute.rs:116:5
|
||||
|
|
||||
LL | #[target_feature(enable = "sse2")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -138,7 +138,7 @@ LL | | }
|
|||
| |_____- not a function definition
|
||||
|
||||
error: attribute should be applied to a function definition
|
||||
--> $DIR/invalid-attribute.rs:120:5
|
||||
--> $DIR/invalid-attribute.rs:124:5
|
||||
|
|
||||
LL | #[target_feature(enable = "sse2")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -192,8 +192,22 @@ LL | impl Quux for u8 {}
|
|||
LL | fn foo();
|
||||
| --------- `foo` from trait
|
||||
|
||||
error[E0053]: method `foo` has an incompatible type for trait
|
||||
--> $DIR/invalid-attribute.rs:108:5
|
||||
|
|
||||
LL | fn foo() {}
|
||||
| ^^^^^^^^ expected safe fn, found unsafe fn
|
||||
|
|
||||
note: type in trait
|
||||
--> $DIR/invalid-attribute.rs:99:5
|
||||
|
|
||||
LL | fn foo();
|
||||
| ^^^^^^^^^
|
||||
= note: expected signature `fn()`
|
||||
found signature `unsafe fn()`
|
||||
|
||||
error[E0658]: `#[target_feature(..)]` can only be applied to `unsafe` functions
|
||||
--> $DIR/invalid-attribute.rs:103:5
|
||||
--> $DIR/invalid-attribute.rs:104:5
|
||||
|
|
||||
LL | #[target_feature(enable = "sse2")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -205,7 +219,7 @@ LL | fn foo() {}
|
|||
= help: add `#![feature(target_feature_11)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error: aborting due to 23 previous errors
|
||||
error: aborting due to 24 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0046, E0658.
|
||||
Some errors have detailed explanations: E0046, E0053, E0658.
|
||||
For more information about an error, try `rustc --explain E0046`.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue