Skip to content

Commit 144206e

Browse files
committed
Don't implement Fn* traits for #[target_feature] functions
1 parent 1fb612b commit 144206e

File tree

3 files changed

+78
-1
lines changed

3 files changed

+78
-1
lines changed

src/librustc_trait_selection/traits/select/candidate_assembly.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
306306
candidates.ambiguous = true; // Could wind up being a fn() type.
307307
}
308308
// Provide an impl, but only for suitable `fn` pointers.
309-
ty::FnDef(..) | ty::FnPtr(_) => {
309+
ty::FnPtr(_) => {
310310
if let ty::FnSig {
311311
unsafety: hir::Unsafety::Normal,
312312
abi: Abi::Rust,
@@ -317,6 +317,20 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
317317
candidates.vec.push(FnPointerCandidate);
318318
}
319319
}
320+
// Provide an impl for suitable functions, rejecting `#[target_feature]` functions (RFC 2396).
321+
ty::FnDef(def_id, _) => {
322+
if let ty::FnSig {
323+
unsafety: hir::Unsafety::Normal,
324+
abi: Abi::Rust,
325+
c_variadic: false,
326+
..
327+
} = self_ty.fn_sig(self.tcx()).skip_binder()
328+
{
329+
if self.tcx().codegen_fn_attrs(def_id).target_features.is_empty() {
330+
candidates.vec.push(FnPointerCandidate);
331+
}
332+
}
333+
}
320334
_ => {}
321335
}
322336

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// only-x86_64
2+
3+
#![feature(target_feature_11)]
4+
5+
#[target_feature(enable = "avx")]
6+
fn foo() {}
7+
8+
fn call(f: impl Fn()) {
9+
f()
10+
}
11+
12+
fn call_mut(f: impl FnMut()) {
13+
f()
14+
}
15+
16+
fn call_once(f: impl FnOnce()) {
17+
f()
18+
}
19+
20+
fn main() {
21+
call(foo); //~ ERROR expected a `std::ops::Fn<()>` closure, found `fn() {foo}`
22+
call_mut(foo); //~ ERROR expected a `std::ops::FnMut<()>` closure, found `fn() {foo}`
23+
call_once(foo); //~ ERROR expected a `std::ops::FnOnce<()>` closure, found `fn() {foo}`
24+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
error[E0277]: expected a `std::ops::Fn<()>` closure, found `fn() {foo}`
2+
--> $DIR/fn-traits.rs:21:10
3+
|
4+
LL | fn call(f: impl Fn()) {
5+
| ---- required by this bound in `call`
6+
...
7+
LL | call(foo);
8+
| ^^^ expected an `Fn<()>` closure, found `fn() {foo}`
9+
|
10+
= help: the trait `std::ops::Fn<()>` is not implemented for `fn() {foo}`
11+
= note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ }
12+
13+
error[E0277]: expected a `std::ops::FnMut<()>` closure, found `fn() {foo}`
14+
--> $DIR/fn-traits.rs:22:14
15+
|
16+
LL | fn call_mut(f: impl FnMut()) {
17+
| ------- required by this bound in `call_mut`
18+
...
19+
LL | call_mut(foo);
20+
| ^^^ expected an `FnMut<()>` closure, found `fn() {foo}`
21+
|
22+
= help: the trait `std::ops::FnMut<()>` is not implemented for `fn() {foo}`
23+
= note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ }
24+
25+
error[E0277]: expected a `std::ops::FnOnce<()>` closure, found `fn() {foo}`
26+
--> $DIR/fn-traits.rs:23:15
27+
|
28+
LL | fn call_once(f: impl FnOnce()) {
29+
| -------- required by this bound in `call_once`
30+
...
31+
LL | call_once(foo);
32+
| ^^^ expected an `FnOnce<()>` closure, found `fn() {foo}`
33+
|
34+
= help: the trait `std::ops::FnOnce<()>` is not implemented for `fn() {foo}`
35+
= note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ }
36+
37+
error: aborting due to 3 previous errors
38+
39+
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)