diff options
| author | Caleb Zulawski <caleb.zulawski@gmail.com> | 2020-06-13 01:18:53 -0400 |
|---|---|---|
| committer | Caleb Zulawski <caleb.zulawski@gmail.com> | 2020-06-13 01:18:53 -0400 |
| commit | 144206e6d8c1ab4ffdbaf6d7b0f5a4201c0f2da4 (patch) | |
| tree | aefa08e9943299c9fb943dc558403eaffd1f99b3 | |
| parent | 1fb612bd15bb3ef098fd24c20d0727de573b4410 (diff) | |
| download | rust-144206e6d8c1ab4ffdbaf6d7b0f5a4201c0f2da4.tar.gz rust-144206e6d8c1ab4ffdbaf6d7b0f5a4201c0f2da4.zip | |
Don't implement Fn* traits for #[target_feature] functions
3 files changed, 78 insertions, 1 deletions
diff --git a/src/librustc_trait_selection/traits/select/candidate_assembly.rs b/src/librustc_trait_selection/traits/select/candidate_assembly.rs index 9045451056b..91c4d1d62aa 100644 --- a/src/librustc_trait_selection/traits/select/candidate_assembly.rs +++ b/src/librustc_trait_selection/traits/select/candidate_assembly.rs @@ -306,7 +306,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { candidates.ambiguous = true; // Could wind up being a fn() type. } // Provide an impl, but only for suitable `fn` pointers. - ty::FnDef(..) | ty::FnPtr(_) => { + ty::FnPtr(_) => { if let ty::FnSig { unsafety: hir::Unsafety::Normal, abi: Abi::Rust, @@ -317,6 +317,20 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { candidates.vec.push(FnPointerCandidate); } } + // Provide an impl for suitable functions, rejecting `#[target_feature]` functions (RFC 2396). + ty::FnDef(def_id, _) => { + if let ty::FnSig { + unsafety: hir::Unsafety::Normal, + abi: Abi::Rust, + c_variadic: false, + .. + } = self_ty.fn_sig(self.tcx()).skip_binder() + { + if self.tcx().codegen_fn_attrs(def_id).target_features.is_empty() { + candidates.vec.push(FnPointerCandidate); + } + } + } _ => {} } diff --git a/src/test/ui/rfcs/rfc-2396-target_feature-11/fn-traits.rs b/src/test/ui/rfcs/rfc-2396-target_feature-11/fn-traits.rs new file mode 100644 index 00000000000..58070b69bc1 --- /dev/null +++ b/src/test/ui/rfcs/rfc-2396-target_feature-11/fn-traits.rs @@ -0,0 +1,24 @@ +// only-x86_64 + +#![feature(target_feature_11)] + +#[target_feature(enable = "avx")] +fn foo() {} + +fn call(f: impl Fn()) { + f() +} + +fn call_mut(f: impl FnMut()) { + f() +} + +fn call_once(f: impl FnOnce()) { + f() +} + +fn main() { + call(foo); //~ ERROR expected a `std::ops::Fn<()>` closure, found `fn() {foo}` + call_mut(foo); //~ ERROR expected a `std::ops::FnMut<()>` closure, found `fn() {foo}` + call_once(foo); //~ ERROR expected a `std::ops::FnOnce<()>` closure, found `fn() {foo}` +} diff --git a/src/test/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr b/src/test/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr new file mode 100644 index 00000000000..6dcf31b4c74 --- /dev/null +++ b/src/test/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr @@ -0,0 +1,39 @@ +error[E0277]: expected a `std::ops::Fn<()>` closure, found `fn() {foo}` + --> $DIR/fn-traits.rs:21:10 + | +LL | fn call(f: impl Fn()) { + | ---- required by this bound in `call` +... +LL | call(foo); + | ^^^ expected an `Fn<()>` closure, found `fn() {foo}` + | + = help: the trait `std::ops::Fn<()>` is not implemented for `fn() {foo}` + = note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ } + +error[E0277]: expected a `std::ops::FnMut<()>` closure, found `fn() {foo}` + --> $DIR/fn-traits.rs:22:14 + | +LL | fn call_mut(f: impl FnMut()) { + | ------- required by this bound in `call_mut` +... +LL | call_mut(foo); + | ^^^ expected an `FnMut<()>` closure, found `fn() {foo}` + | + = help: the trait `std::ops::FnMut<()>` is not implemented for `fn() {foo}` + = note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ } + +error[E0277]: expected a `std::ops::FnOnce<()>` closure, found `fn() {foo}` + --> $DIR/fn-traits.rs:23:15 + | +LL | fn call_once(f: impl FnOnce()) { + | -------- required by this bound in `call_once` +... +LL | call_once(foo); + | ^^^ expected an `FnOnce<()>` closure, found `fn() {foo}` + | + = help: the trait `std::ops::FnOnce<()>` is not implemented for `fn() {foo}` + = note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ } + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. |
