about summary refs log tree commit diff
diff options
context:
space:
mode:
authorCaleb Zulawski <caleb.zulawski@gmail.com>2020-06-13 01:18:53 -0400
committerCaleb Zulawski <caleb.zulawski@gmail.com>2020-06-13 01:18:53 -0400
commit144206e6d8c1ab4ffdbaf6d7b0f5a4201c0f2da4 (patch)
treeaefa08e9943299c9fb943dc558403eaffd1f99b3
parent1fb612bd15bb3ef098fd24c20d0727de573b4410 (diff)
downloadrust-144206e6d8c1ab4ffdbaf6d7b0f5a4201c0f2da4.tar.gz
rust-144206e6d8c1ab4ffdbaf6d7b0f5a4201c0f2da4.zip
Don't implement Fn* traits for #[target_feature] functions
-rw-r--r--src/librustc_trait_selection/traits/select/candidate_assembly.rs16
-rw-r--r--src/test/ui/rfcs/rfc-2396-target_feature-11/fn-traits.rs24
-rw-r--r--src/test/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr39
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`.