about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.rs59
-rw-r--r--tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.stderr78
2 files changed, 137 insertions, 0 deletions
diff --git a/tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.rs b/tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.rs
new file mode 100644
index 00000000000..6380449124f
--- /dev/null
+++ b/tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.rs
@@ -0,0 +1,59 @@
+// ICE argument to function with "rust-call" ABI is not a tuple
+// issue: rust-lang/rust#81974
+
+#![feature(unboxed_closures)]
+#![feature(fn_traits)]
+
+use std::collections::HashMap;
+use std::hash::Hash;
+
+struct CachedFun<A, B> {
+    cache: HashMap<A, B>,
+    fun: fn(&mut CachedFun<A, B>, A) -> B,
+}
+
+impl<A: Eq + Hash, B> CachedFun<A, B> {
+    fn new(fun: fn(&mut Self, A) -> B) -> Self {
+        CachedFun {
+            cache: HashMap::new(),
+            fun,
+        }
+    }
+}
+
+impl<A, B> FnOnce<A> for CachedFun<A, B>
+//~^ ERROR type parameter to bare `FnOnce` trait must be a tuple
+where
+    A: Eq + Hash + Clone,
+    B: Clone,
+{
+    type Output = B;
+    extern "rust-call" fn call_once(mut self, a: A) -> Self::Output {
+    //~^ ERROR functions with the "rust-call" ABI must take a single non-self tuple argument
+        self.call_mut(a)
+        //~^ ERROR `A` is not a tuple
+    }
+}
+
+impl<A, B> FnMut<A> for CachedFun<A, B>
+//~^ ERROR type parameter to bare `FnMut` trait must be a tuple
+where
+    A: Eq + Hash + Clone,
+    B: Clone,
+{
+    extern "rust-call" fn call_mut(&mut self, a: A) -> Self::Output {
+    //~^ ERROR functions with the "rust-call" ABI must take a single non-self tuple argument
+        self.cache.get(&a).map(|a| a.clone()).unwrap_or_else(|| {
+            let b = (self.fun)(self, a.clone());
+            self.cache.insert(a, b.clone());
+            b
+        })
+    }
+}
+
+fn main() -> () {
+    let pesce = |y: &mut CachedFun<i32, i32>, x| x + 1;
+    let cachedcoso = CachedFun::new(pesce);
+    cachedcoso.call_once(1);
+    //~^ ERROR `i32` is not a tuple
+}
diff --git a/tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.stderr b/tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.stderr
new file mode 100644
index 00000000000..cceaddf7803
--- /dev/null
+++ b/tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.stderr
@@ -0,0 +1,78 @@
+error[E0059]: type parameter to bare `FnOnce` trait must be a tuple
+  --> $DIR/rust-call-abi-not-a-tuple-ice-81974.rs:24:12
+   |
+LL | impl<A, B> FnOnce<A> for CachedFun<A, B>
+   |            ^^^^^^^^^ the trait `Tuple` is not implemented for `A`
+   |
+note: required by a bound in `FnOnce`
+  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
+help: consider further restricting this bound
+   |
+LL |     A: Eq + Hash + Clone + std::marker::Tuple,
+   |                          ++++++++++++++++++++
+
+error[E0059]: type parameter to bare `FnMut` trait must be a tuple
+  --> $DIR/rust-call-abi-not-a-tuple-ice-81974.rs:38:12
+   |
+LL | impl<A, B> FnMut<A> for CachedFun<A, B>
+   |            ^^^^^^^^ the trait `Tuple` is not implemented for `A`
+   |
+note: required by a bound in `FnMut`
+  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
+help: consider further restricting this bound
+   |
+LL |     A: Eq + Hash + Clone + std::marker::Tuple,
+   |                          ++++++++++++++++++++
+
+error[E0277]: functions with the "rust-call" ABI must take a single non-self tuple argument
+  --> $DIR/rust-call-abi-not-a-tuple-ice-81974.rs:31:5
+   |
+LL |     extern "rust-call" fn call_once(mut self, a: A) -> Self::Output {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Tuple` is not implemented for `A`
+   |
+help: consider further restricting this bound
+   |
+LL |     A: Eq + Hash + Clone + std::marker::Tuple,
+   |                          ++++++++++++++++++++
+
+error[E0277]: functions with the "rust-call" ABI must take a single non-self tuple argument
+  --> $DIR/rust-call-abi-not-a-tuple-ice-81974.rs:44:5
+   |
+LL |     extern "rust-call" fn call_mut(&mut self, a: A) -> Self::Output {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Tuple` is not implemented for `A`
+   |
+help: consider further restricting this bound
+   |
+LL |     A: Eq + Hash + Clone + std::marker::Tuple,
+   |                          ++++++++++++++++++++
+
+error[E0277]: `A` is not a tuple
+  --> $DIR/rust-call-abi-not-a-tuple-ice-81974.rs:33:23
+   |
+LL |         self.call_mut(a)
+   |              -------- ^ the trait `Tuple` is not implemented for `A`
+   |              |
+   |              required by a bound introduced by this call
+   |
+note: required by a bound in `call_mut`
+  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
+help: consider further restricting this bound
+   |
+LL |     A: Eq + Hash + Clone + std::marker::Tuple,
+   |                          ++++++++++++++++++++
+
+error[E0277]: `i32` is not a tuple
+  --> $DIR/rust-call-abi-not-a-tuple-ice-81974.rs:57:26
+   |
+LL |     cachedcoso.call_once(1);
+   |                --------- ^ the trait `Tuple` is not implemented for `i32`
+   |                |
+   |                required by a bound introduced by this call
+   |
+note: required by a bound in `call_once`
+  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
+
+error: aborting due to 6 previous errors
+
+Some errors have detailed explanations: E0059, E0277.
+For more information about an error, try `rustc --explain E0059`.