Merge "Update crossbeam-channel to 0.5.2" am: d10935e3d5 am: fb9f546a46 am: c8f69fabe5 am: 134994aa01

Original change: https://android-review.googlesource.com/c/platform/external/rust/crates/crossbeam-channel/+/2005034

Change-Id: Iabbe9906d14ddbe8cb3a86ead047d320da8d6cca
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index 28a14f3..f15a046 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,5 +1,6 @@
 {
   "git": {
-    "sha1": "b13fdeef2ab90bac1482d38959beadbc6b0a08ed"
-  }
-}
+    "sha1": "f9cec068fa94bced547a66289cd288dca58c2e83"
+  },
+  "path_in_vcs": "crossbeam-channel"
+}
\ No newline at end of file
diff --git a/Android.bp b/Android.bp
index b040e15..a5821d8 100644
--- a/Android.bp
+++ b/Android.bp
@@ -47,7 +47,7 @@
     host_supported: true,
     crate_name: "crossbeam_channel",
     cargo_env_compat: true,
-    cargo_pkg_version: "0.5.1",
+    cargo_pkg_version: "0.5.2",
     srcs: ["src/lib.rs"],
     edition: "2018",
     features: [
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 98fd9f6..6bfd923 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+# Version 0.5.2
+
+- Fix stacked borrows violations. (#763, #764)
+
 # Version 0.5.1
 
 - Fix memory leak in unbounded channel. (#669)
diff --git a/Cargo.lock b/Cargo.lock
index 1ae0d57..feb6e75 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3,12 +3,6 @@
 version = 3
 
 [[package]]
-name = "autocfg"
-version = "1.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
-
-[[package]]
 name = "cfg-if"
 version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -16,7 +10,7 @@
 
 [[package]]
 name = "crossbeam-channel"
-version = "0.5.1"
+version = "0.5.2"
 dependencies = [
  "cfg-if",
  "crossbeam-utils",
@@ -27,20 +21,19 @@
 
 [[package]]
 name = "crossbeam-utils"
-version = "0.8.3"
+version = "0.8.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e7e9d99fa91428effe99c5c6d4634cdeba32b8cf784fc428a2a687f61a952c49"
+checksum = "cfcae03edb34f947e64acdb1c33ec169824e20657e9ecb61cef6c8c74dcb8120"
 dependencies = [
- "autocfg",
  "cfg-if",
  "lazy_static",
 ]
 
 [[package]]
 name = "getrandom"
-version = "0.2.2"
+version = "0.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8"
+checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
 dependencies = [
  "cfg-if",
  "libc",
@@ -49,9 +42,9 @@
 
 [[package]]
 name = "hermit-abi"
-version = "0.1.18"
+version = "0.1.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c"
+checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
 dependencies = [
  "libc",
 ]
@@ -64,15 +57,15 @@
 
 [[package]]
 name = "libc"
-version = "0.2.93"
+version = "0.2.112"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9385f66bf6105b241aa65a61cb923ef20efc665cb9f9bb50ac2f0c4b7f378d41"
+checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125"
 
 [[package]]
 name = "num_cpus"
-version = "1.13.0"
+version = "1.13.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
+checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
 dependencies = [
  "hermit-abi",
  "libc",
@@ -80,15 +73,15 @@
 
 [[package]]
 name = "ppv-lite86"
-version = "0.2.10"
+version = "0.2.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
+checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
 
 [[package]]
 name = "rand"
-version = "0.8.3"
+version = "0.8.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e"
+checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8"
 dependencies = [
  "libc",
  "rand_chacha",
@@ -98,9 +91,9 @@
 
 [[package]]
 name = "rand_chacha"
-version = "0.3.0"
+version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d"
+checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
 dependencies = [
  "ppv-lite86",
  "rand_core",
@@ -108,27 +101,27 @@
 
 [[package]]
 name = "rand_core"
-version = "0.6.2"
+version = "0.6.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7"
+checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
 dependencies = [
  "getrandom",
 ]
 
 [[package]]
 name = "rand_hc"
-version = "0.3.0"
+version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73"
+checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7"
 dependencies = [
  "rand_core",
 ]
 
 [[package]]
 name = "signal-hook"
-version = "0.3.8"
+version = "0.3.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ef33d6d0cd06e0840fba9985aab098c147e67e05cee14d412d3345ed14ff30ac"
+checksum = "647c97df271007dcea485bb74ffdb57f2e683f1306c854f468a0c244badabf2d"
 dependencies = [
  "libc",
  "signal-hook-registry",
@@ -136,9 +129,9 @@
 
 [[package]]
 name = "signal-hook-registry"
-version = "1.3.0"
+version = "1.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "16f1d0fef1604ba8f7a073c7e701f213e056707210e9020af4528e0101ce11a6"
+checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0"
 dependencies = [
  "libc",
 ]
diff --git a/Cargo.toml b/Cargo.toml
index abcc485..87a889f 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -3,21 +3,19 @@
 # When uploading crates to the registry Cargo will automatically
 # "normalize" Cargo.toml files for maximal compatibility
 # with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies
+# to registry (e.g., crates.io) dependencies.
 #
-# If you believe there's an error in this file please file an
-# issue against the rust-lang/cargo repository. If you're
-# editing this file be aware that the upstream Cargo.toml
-# will likely look very different (and much more reasonable)
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
 
 [package]
 edition = "2018"
+rust-version = "1.36"
 name = "crossbeam-channel"
-version = "0.5.1"
-authors = ["The Crossbeam Project Developers"]
+version = "0.5.2"
 description = "Multi-producer multi-consumer channels for message passing"
 homepage = "https://github.com/crossbeam-rs/crossbeam/tree/master/crossbeam-channel"
-documentation = "https://docs.rs/crossbeam-channel"
 keywords = ["channel", "mpmc", "select", "golang", "message"]
 categories = ["algorithms", "concurrency", "data-structures"]
 license = "MIT OR Apache-2.0"
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index 0e048a2..640a808 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -4,13 +4,12 @@
 # - Update CHANGELOG.md
 # - Update README.md
 # - Create "crossbeam-channel-X.Y.Z" git tag
-version = "0.5.1"
-authors = ["The Crossbeam Project Developers"]
+version = "0.5.2"
 edition = "2018"
+rust-version = "1.36"
 license = "MIT OR Apache-2.0"
 repository = "https://github.com/crossbeam-rs/crossbeam"
 homepage = "https://github.com/crossbeam-rs/crossbeam/tree/master/crossbeam-channel"
-documentation = "https://docs.rs/crossbeam-channel"
 description = "Multi-producer multi-consumer channels for message passing"
 keywords = ["channel", "mpmc", "select", "golang", "message"]
 categories = ["algorithms", "concurrency", "data-structures"]
@@ -20,6 +19,8 @@
 
 # Enable to use APIs that require `std`.
 # This is enabled by default.
+#
+# NOTE: Disabling `std` feature is not supported yet.
 std = ["crossbeam-utils/std"]
 
 [dependencies]
diff --git a/METADATA b/METADATA
index c1dad0e..6cbb05f 100644
--- a/METADATA
+++ b/METADATA
@@ -7,13 +7,13 @@
   }
   url {
     type: ARCHIVE
-    value: "https://static.crates.io/crates/crossbeam-channel/crossbeam-channel-0.5.1.crate"
+    value: "https://static.crates.io/crates/crossbeam-channel/crossbeam-channel-0.5.2.crate"
   }
-  version: "0.5.1"
+  version: "0.5.2"
   license_type: NOTICE
   last_upgrade_date {
-    year: 2021
-    month: 5
-    day: 19
+    year: 2022
+    month: 3
+    day: 1
   }
 }
diff --git a/benches/crossbeam.rs b/benches/crossbeam.rs
index 9870c98..1c05222 100644
--- a/benches/crossbeam.rs
+++ b/benches/crossbeam.rs
@@ -13,7 +13,7 @@
 
     #[bench]
     fn create(b: &mut Bencher) {
-        b.iter(|| unbounded::<i32>());
+        b.iter(unbounded::<i32>);
     }
 
     #[bench]
diff --git a/examples/fibonacci.rs b/examples/fibonacci.rs
index cf22b7a..e6f5e89 100644
--- a/examples/fibonacci.rs
+++ b/examples/fibonacci.rs
@@ -10,7 +10,7 @@
     while sender.send(x).is_ok() {
         let tmp = x;
         x = y;
-        y = tmp + y;
+        y += tmp;
     }
 }
 
diff --git a/examples/stopwatch.rs b/examples/stopwatch.rs
index 98895c5..3a7578e 100644
--- a/examples/stopwatch.rs
+++ b/examples/stopwatch.rs
@@ -33,11 +33,7 @@
 
     // Prints the elapsed time.
     fn show(dur: Duration) {
-        println!(
-            "Elapsed: {}.{:03} sec",
-            dur.as_secs(),
-            dur.subsec_nanos() / 1_000_000
-        );
+        println!("Elapsed: {}.{:03} sec", dur.as_secs(), dur.subsec_millis());
     }
 
     let start = Instant::now();
diff --git a/src/context.rs b/src/context.rs
index e2e8480..7467b80 100644
--- a/src/context.rs
+++ b/src/context.rs
@@ -1,7 +1,8 @@
 //! Thread-local context used in select.
 
 use std::cell::Cell;
-use std::sync::atomic::{AtomicUsize, Ordering};
+use std::ptr;
+use std::sync::atomic::{AtomicPtr, AtomicUsize, Ordering};
 use std::sync::Arc;
 use std::thread::{self, Thread, ThreadId};
 use std::time::Instant;
@@ -11,6 +12,7 @@
 use crate::select::Selected;
 
 /// Thread-local context used in select.
+// This is a private API that is used by the select macro.
 #[derive(Debug, Clone)]
 pub struct Context {
     inner: Arc<Inner>,
@@ -23,7 +25,7 @@
     select: AtomicUsize,
 
     /// A slot into which another thread may store a pointer to its `Packet`.
-    packet: AtomicUsize,
+    packet: AtomicPtr<()>,
 
     /// Thread handle.
     thread: Thread,
@@ -45,7 +47,7 @@
         }
 
         let mut f = Some(f);
-        let mut f = move |cx: &Context| -> R {
+        let mut f = |cx: &Context| -> R {
             let f = f.take().unwrap();
             f(cx)
         };
@@ -69,7 +71,7 @@
         Context {
             inner: Arc::new(Inner {
                 select: AtomicUsize::new(Selected::Waiting.into()),
-                packet: AtomicUsize::new(0),
+                packet: AtomicPtr::new(ptr::null_mut()),
                 thread: thread::current(),
                 thread_id: thread::current().id(),
             }),
@@ -82,7 +84,7 @@
         self.inner
             .select
             .store(Selected::Waiting.into(), Ordering::Release);
-        self.inner.packet.store(0, Ordering::Release);
+        self.inner.packet.store(ptr::null_mut(), Ordering::Release);
     }
 
     /// Attempts to select an operation.
@@ -112,19 +114,19 @@
     ///
     /// This method must be called after `try_select` succeeds and there is a packet to provide.
     #[inline]
-    pub fn store_packet(&self, packet: usize) {
-        if packet != 0 {
+    pub fn store_packet(&self, packet: *mut ()) {
+        if !packet.is_null() {
             self.inner.packet.store(packet, Ordering::Release);
         }
     }
 
     /// Waits until a packet is provided and returns it.
     #[inline]
-    pub fn wait_packet(&self) -> usize {
+    pub fn wait_packet(&self) -> *mut () {
         let backoff = Backoff::new();
         loop {
             let packet = self.inner.packet.load(Ordering::Acquire);
-            if packet != 0 {
+            if !packet.is_null() {
                 return packet;
             }
             backoff.snooze();
diff --git a/src/flavors/array.rs b/src/flavors/array.rs
index c49eef1..871768c 100644
--- a/src/flavors/array.rs
+++ b/src/flavors/array.rs
@@ -10,7 +10,7 @@
 
 use std::cell::UnsafeCell;
 use std::marker::PhantomData;
-use std::mem::{self, MaybeUninit};
+use std::mem::MaybeUninit;
 use std::ptr;
 use std::sync::atomic::{self, AtomicUsize, Ordering};
 use std::time::Instant;
@@ -110,7 +110,7 @@
         // Allocate a buffer of `cap` slots initialized
         // with stamps.
         let buffer = {
-            let mut boxed: Box<[Slot<T>]> = (0..cap)
+            let boxed: Box<[Slot<T>]> = (0..cap)
                 .map(|i| {
                     // Set the stamp to `{ lap: 0, mark: 0, index: i }`.
                     Slot {
@@ -119,9 +119,7 @@
                     }
                 })
                 .collect();
-            let ptr = boxed.as_mut_ptr();
-            mem::forget(boxed);
-            ptr
+            Box::into_raw(boxed) as *mut Slot<T>
         };
 
         Channel {
diff --git a/src/flavors/zero.rs b/src/flavors/zero.rs
index 9790b77..4afbd8f 100644
--- a/src/flavors/zero.rs
+++ b/src/flavors/zero.rs
@@ -6,6 +6,7 @@
 use std::marker::PhantomData;
 use std::sync::atomic::{AtomicBool, Ordering};
 use std::time::Instant;
+use std::{fmt, ptr};
 
 use crossbeam_utils::Backoff;
 
@@ -16,7 +17,19 @@
 use crate::waker::Waker;
 
 /// A pointer to a packet.
-pub(crate) type ZeroToken = usize;
+pub struct ZeroToken(*mut ());
+
+impl Default for ZeroToken {
+    fn default() -> Self {
+        Self(ptr::null_mut())
+    }
+}
+
+impl fmt::Debug for ZeroToken {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::Debug::fmt(&(self.0 as usize), f)
+    }
+}
 
 /// A slot for passing one message from a sender to a receiver.
 struct Packet<T> {
@@ -117,10 +130,10 @@
 
         // If there's a waiting receiver, pair up with it.
         if let Some(operation) = inner.receivers.try_select() {
-            token.zero = operation.packet;
+            token.zero.0 = operation.packet;
             true
         } else if inner.is_disconnected {
-            token.zero = 0;
+            token.zero.0 = ptr::null_mut();
             true
         } else {
             false
@@ -130,11 +143,11 @@
     /// Writes a message into the packet.
     pub(crate) unsafe fn write(&self, token: &mut Token, msg: T) -> Result<(), T> {
         // If there is no packet, the channel is disconnected.
-        if token.zero == 0 {
+        if token.zero.0.is_null() {
             return Err(msg);
         }
 
-        let packet = &*(token.zero as *const Packet<T>);
+        let packet = &*(token.zero.0 as *const Packet<T>);
         packet.msg.get().write(Some(msg));
         packet.ready.store(true, Ordering::Release);
         Ok(())
@@ -146,10 +159,10 @@
 
         // If there's a waiting sender, pair up with it.
         if let Some(operation) = inner.senders.try_select() {
-            token.zero = operation.packet;
+            token.zero.0 = operation.packet;
             true
         } else if inner.is_disconnected {
-            token.zero = 0;
+            token.zero.0 = ptr::null_mut();
             true
         } else {
             false
@@ -159,11 +172,11 @@
     /// Reads a message from the packet.
     pub(crate) unsafe fn read(&self, token: &mut Token) -> Result<T, ()> {
         // If there is no packet, the channel is disconnected.
-        if token.zero == 0 {
+        if token.zero.0.is_null() {
             return Err(());
         }
 
-        let packet = &*(token.zero as *const Packet<T>);
+        let packet = &*(token.zero.0 as *const Packet<T>);
 
         if packet.on_stack {
             // The message has been in the packet from the beginning, so there is no need to wait
@@ -177,7 +190,7 @@
             // heap-allocated packet.
             packet.wait_ready();
             let msg = packet.msg.get().replace(None).unwrap();
-            drop(Box::from_raw(packet as *const Packet<T> as *mut Packet<T>));
+            drop(Box::from_raw(token.zero.0 as *mut Packet<T>));
             Ok(msg)
         }
     }
@@ -189,7 +202,7 @@
 
         // If there's a waiting receiver, pair up with it.
         if let Some(operation) = inner.receivers.try_select() {
-            token.zero = operation.packet;
+            token.zero.0 = operation.packet;
             drop(inner);
             unsafe {
                 self.write(token, msg).ok().unwrap();
@@ -213,7 +226,7 @@
 
         // If there's a waiting receiver, pair up with it.
         if let Some(operation) = inner.receivers.try_select() {
-            token.zero = operation.packet;
+            token.zero.0 = operation.packet;
             drop(inner);
             unsafe {
                 self.write(token, msg).ok().unwrap();
@@ -228,10 +241,10 @@
         Context::with(|cx| {
             // Prepare for blocking until a receiver wakes us up.
             let oper = Operation::hook(token);
-            let packet = Packet::<T>::message_on_stack(msg);
+            let mut packet = Packet::<T>::message_on_stack(msg);
             inner
                 .senders
-                .register_with_packet(oper, &packet as *const Packet<T> as usize, cx);
+                .register_with_packet(oper, &mut packet as *mut Packet<T> as *mut (), cx);
             inner.receivers.notify();
             drop(inner);
 
@@ -266,7 +279,7 @@
 
         // If there's a waiting sender, pair up with it.
         if let Some(operation) = inner.senders.try_select() {
-            token.zero = operation.packet;
+            token.zero.0 = operation.packet;
             drop(inner);
             unsafe { self.read(token).map_err(|_| TryRecvError::Disconnected) }
         } else if inner.is_disconnected {
@@ -283,7 +296,7 @@
 
         // If there's a waiting sender, pair up with it.
         if let Some(operation) = inner.senders.try_select() {
-            token.zero = operation.packet;
+            token.zero.0 = operation.packet;
             drop(inner);
             unsafe {
                 return self.read(token).map_err(|_| RecvTimeoutError::Disconnected);
@@ -297,10 +310,12 @@
         Context::with(|cx| {
             // Prepare for blocking until a sender wakes us up.
             let oper = Operation::hook(token);
-            let packet = Packet::<T>::empty_on_stack();
-            inner
-                .receivers
-                .register_with_packet(oper, &packet as *const Packet<T> as usize, cx);
+            let mut packet = Packet::<T>::empty_on_stack();
+            inner.receivers.register_with_packet(
+                oper,
+                &mut packet as *mut Packet<T> as *mut (),
+                cx,
+            );
             inner.senders.notify();
             drop(inner);
 
@@ -385,7 +400,7 @@
         let mut inner = self.0.inner.lock();
         inner
             .receivers
-            .register_with_packet(oper, packet as usize, cx);
+            .register_with_packet(oper, packet as *mut (), cx);
         inner.senders.notify();
         inner.senders.can_select() || inner.is_disconnected
     }
@@ -399,7 +414,7 @@
     }
 
     fn accept(&self, token: &mut Token, cx: &Context) -> bool {
-        token.zero = cx.wait_packet();
+        token.zero.0 = cx.wait_packet();
         true
     }
 
@@ -435,7 +450,7 @@
         let mut inner = self.0.inner.lock();
         inner
             .senders
-            .register_with_packet(oper, packet as usize, cx);
+            .register_with_packet(oper, packet as *mut (), cx);
         inner.receivers.notify();
         inner.receivers.can_select() || inner.is_disconnected
     }
@@ -449,7 +464,7 @@
     }
 
     fn accept(&self, token: &mut Token, cx: &Context) -> bool {
-        token.zero = cx.wait_packet();
+        token.zero.0 = cx.wait_packet();
         true
     }
 
diff --git a/src/select.rs b/src/select.rs
index 5259328..6103ef4 100644
--- a/src/select.rs
+++ b/src/select.rs
@@ -19,6 +19,7 @@
 /// `read` or `write`.
 ///
 /// Each field contains data associated with a specific channel flavor.
+// This is a private API that is used by the select macro.
 #[derive(Debug, Default)]
 pub struct Token {
     pub at: flavors::at::AtToken,
@@ -93,6 +94,7 @@
 ///
 /// This is a handle that assists select in executing an operation, registration, deciding on the
 /// appropriate deadline for blocking, etc.
+// This is a private API (exposed inside crossbeam_channel::internal module) that is used by the select macro.
 pub trait SelectHandle {
     /// Attempts to select an operation and returns `true` on success.
     fn try_select(&self, token: &mut Token) -> bool;
@@ -442,6 +444,7 @@
 }
 
 /// Attempts to select one of the operations without blocking.
+// This is a private API (exposed inside crossbeam_channel::internal module) that is used by the select macro.
 #[inline]
 pub fn try_select<'a>(
     handles: &mut [(&'a dyn SelectHandle, usize, *const u8)],
@@ -458,6 +461,7 @@
 }
 
 /// Blocks until one of the operations becomes ready and selects it.
+// This is a private API (exposed inside crossbeam_channel::internal module) that is used by the select macro.
 #[inline]
 pub fn select<'a>(
     handles: &mut [(&'a dyn SelectHandle, usize, *const u8)],
@@ -476,6 +480,7 @@
 }
 
 /// Blocks for a limited time until one of the operations becomes ready and selects it.
+// This is a private API (exposed inside crossbeam_channel::internal module) that is used by the select macro.
 #[inline]
 pub fn select_timeout<'a>(
     handles: &mut [(&'a dyn SelectHandle, usize, *const u8)],
diff --git a/src/waker.rs b/src/waker.rs
index 62defa2..dec73a9 100644
--- a/src/waker.rs
+++ b/src/waker.rs
@@ -1,5 +1,6 @@
 //! Waking mechanism for threads blocked on channel operations.
 
+use std::ptr;
 use std::sync::atomic::{AtomicBool, Ordering};
 use std::thread::{self, ThreadId};
 
@@ -13,7 +14,7 @@
     pub(crate) oper: Operation,
 
     /// Optional packet.
-    pub(crate) packet: usize,
+    pub(crate) packet: *mut (),
 
     /// Context associated with the thread owning this operation.
     pub(crate) cx: Context,
@@ -44,12 +45,12 @@
     /// Registers a select operation.
     #[inline]
     pub(crate) fn register(&mut self, oper: Operation, cx: &Context) {
-        self.register_with_packet(oper, 0, cx);
+        self.register_with_packet(oper, ptr::null_mut(), cx);
     }
 
     /// Registers a select operation and a packet.
     #[inline]
-    pub(crate) fn register_with_packet(&mut self, oper: Operation, packet: usize, cx: &Context) {
+    pub(crate) fn register_with_packet(&mut self, oper: Operation, packet: *mut (), cx: &Context) {
         self.selectors.push(Entry {
             oper,
             packet,
@@ -76,34 +77,26 @@
     /// Attempts to find another thread's entry, select the operation, and wake it up.
     #[inline]
     pub(crate) fn try_select(&mut self) -> Option<Entry> {
-        let mut entry = None;
-
-        if !self.selectors.is_empty() {
-            let thread_id = current_thread_id();
-
-            for i in 0..self.selectors.len() {
+        self.selectors
+            .iter()
+            .position(|selector| {
                 // Does the entry belong to a different thread?
-                if self.selectors[i].cx.thread_id() != thread_id {
-                    // Try selecting this operation.
-                    let sel = Selected::Operation(self.selectors[i].oper);
-                    let res = self.selectors[i].cx.try_select(sel);
-
-                    if res.is_ok() {
+                selector.cx.thread_id() != current_thread_id()
+                    && selector // Try selecting this operation.
+                        .cx
+                        .try_select(Selected::Operation(selector.oper))
+                        .is_ok()
+                    && {
                         // Provide the packet.
-                        self.selectors[i].cx.store_packet(self.selectors[i].packet);
+                        selector.cx.store_packet(selector.packet);
                         // Wake the thread up.
-                        self.selectors[i].cx.unpark();
-
-                        // Remove the entry from the queue to keep it clean and improve
-                        // performance.
-                        entry = Some(self.selectors.remove(i));
-                        break;
+                        selector.cx.unpark();
+                        true
                     }
-                }
-            }
-        }
-
-        entry
+            })
+            // Remove the entry from the queue to keep it clean and improve
+            // performance.
+            .map(|pos| self.selectors.remove(pos))
     }
 
     /// Returns `true` if there is an entry which can be selected by the current thread.
@@ -125,7 +118,7 @@
     pub(crate) fn watch(&mut self, oper: Operation, cx: &Context) {
         self.observers.push(Entry {
             oper,
-            packet: 0,
+            packet: ptr::null_mut(),
             cx: cx.clone(),
         });
     }
@@ -269,7 +262,7 @@
 impl Drop for SyncWaker {
     #[inline]
     fn drop(&mut self) {
-        debug_assert_eq!(self.is_empty.load(Ordering::SeqCst), true);
+        debug_assert!(self.is_empty.load(Ordering::SeqCst));
     }
 }
 
diff --git a/tests/after.rs b/tests/after.rs
index 20670dc..678a8c6 100644
--- a/tests/after.rs
+++ b/tests/after.rs
@@ -1,5 +1,7 @@
 //! Tests for the after channel flavor.
 
+#![cfg(not(miri))] // TODO: many assertions failed due to Miri is slow
+
 use std::sync::atomic::AtomicUsize;
 use std::sync::atomic::Ordering;
 use std::thread;
@@ -56,20 +58,20 @@
     let r = after(ms(50));
 
     assert_eq!(r.len(), 0);
-    assert_eq!(r.is_empty(), true);
-    assert_eq!(r.is_full(), false);
+    assert!(r.is_empty());
+    assert!(!r.is_full());
 
     thread::sleep(ms(100));
 
     assert_eq!(r.len(), 1);
-    assert_eq!(r.is_empty(), false);
-    assert_eq!(r.is_full(), true);
+    assert!(!r.is_empty());
+    assert!(r.is_full());
 
     r.try_recv().unwrap();
 
     assert_eq!(r.len(), 0);
-    assert_eq!(r.is_empty(), true);
-    assert_eq!(r.is_full(), false);
+    assert!(r.is_empty());
+    assert!(!r.is_full());
 }
 
 #[test]
@@ -211,7 +213,7 @@
                             break;
                         }
                         i => {
-                            oper.recv(&v[i]).unwrap();
+                            oper.recv(v[i]).unwrap();
                             hits.fetch_add(1, Ordering::SeqCst);
                         }
                     }
diff --git a/tests/array.rs b/tests/array.rs
index 15c30a5..bb2cebe 100644
--- a/tests/array.rs
+++ b/tests/array.rs
@@ -1,5 +1,7 @@
 //! Tests for the array channel flavor.
 
+#![cfg(not(miri))] // TODO: many assertions failed due to Miri is slow
+
 use std::any::Any;
 use std::sync::atomic::AtomicUsize;
 use std::sync::atomic::Ordering;
@@ -43,38 +45,38 @@
     let (s, r) = bounded(2);
 
     assert_eq!(s.len(), 0);
-    assert_eq!(s.is_empty(), true);
-    assert_eq!(s.is_full(), false);
+    assert!(s.is_empty());
+    assert!(!s.is_full());
     assert_eq!(r.len(), 0);
-    assert_eq!(r.is_empty(), true);
-    assert_eq!(r.is_full(), false);
+    assert!(r.is_empty());
+    assert!(!r.is_full());
 
     s.send(()).unwrap();
 
     assert_eq!(s.len(), 1);
-    assert_eq!(s.is_empty(), false);
-    assert_eq!(s.is_full(), false);
+    assert!(!s.is_empty());
+    assert!(!s.is_full());
     assert_eq!(r.len(), 1);
-    assert_eq!(r.is_empty(), false);
-    assert_eq!(r.is_full(), false);
+    assert!(!r.is_empty());
+    assert!(!r.is_full());
 
     s.send(()).unwrap();
 
     assert_eq!(s.len(), 2);
-    assert_eq!(s.is_empty(), false);
-    assert_eq!(s.is_full(), true);
+    assert!(!s.is_empty());
+    assert!(s.is_full());
     assert_eq!(r.len(), 2);
-    assert_eq!(r.is_empty(), false);
-    assert_eq!(r.is_full(), true);
+    assert!(!r.is_empty());
+    assert!(r.is_full());
 
     r.recv().unwrap();
 
     assert_eq!(s.len(), 1);
-    assert_eq!(s.is_empty(), false);
-    assert_eq!(s.is_full(), false);
+    assert!(!s.is_empty());
+    assert!(!s.is_full());
     assert_eq!(r.len(), 1);
-    assert_eq!(r.is_empty(), false);
-    assert_eq!(r.is_full(), false);
+    assert!(!r.is_empty());
+    assert!(!r.is_full());
 }
 
 #[test]
diff --git a/tests/golang.rs b/tests/golang.rs
index cd70013..05d67f6 100644
--- a/tests/golang.rs
+++ b/tests/golang.rs
@@ -9,6 +9,8 @@
 //!   - https://golang.org/LICENSE
 //!   - https://golang.org/PATENTS
 
+#![allow(clippy::mutex_atomic, clippy::redundant_clone)]
+
 use std::alloc::{GlobalAlloc, Layout, System};
 use std::any::Any;
 use std::cell::Cell;
@@ -176,7 +178,7 @@
         if !ret.is_null() {
             ALLOCATED.fetch_add(layout.size(), SeqCst);
         }
-        return ret;
+        ret
     }
 
     unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
@@ -232,6 +234,9 @@
 mod doubleselect {
     use super::*;
 
+    #[cfg(miri)]
+    const ITERATIONS: i32 = 100;
+    #[cfg(not(miri))]
     const ITERATIONS: i32 = 10_000;
 
     fn sender(n: i32, c1: Chan<i32>, c2: Chan<i32>, c3: Chan<i32>, c4: Chan<i32>) {
@@ -691,6 +696,11 @@
 mod select2 {
     use super::*;
 
+    #[cfg(miri)]
+    const N: i32 = 1000;
+    #[cfg(not(miri))]
+    const N: i32 = 100000;
+
     #[test]
     fn main() {
         fn sender(c: &Chan<i32>, n: i32) {
@@ -702,9 +712,7 @@
         fn receiver(c: &Chan<i32>, dummy: &Chan<i32>, n: i32) {
             for _ in 0..n {
                 select! {
-                    recv(c.rx()) -> _ => {
-                        ()
-                    }
+                    recv(c.rx()) -> _ => {}
                     recv(dummy.rx()) -> _ => {
                         panic!("dummy");
                     }
@@ -717,15 +725,18 @@
 
         ALLOCATED.store(0, SeqCst);
 
-        go!(c, sender(&c, 100000));
-        receiver(&c, &dummy, 100000);
+        go!(c, sender(&c, N));
+        receiver(&c, &dummy, N);
 
         let alloc = ALLOCATED.load(SeqCst);
 
-        go!(c, sender(&c, 100000));
-        receiver(&c, &dummy, 100000);
+        go!(c, sender(&c, N));
+        receiver(&c, &dummy, N);
 
-        assert!(!(ALLOCATED.load(SeqCst) > alloc && (ALLOCATED.load(SeqCst) - alloc) > 110000))
+        assert!(
+            !(ALLOCATED.load(SeqCst) > alloc
+                && (ALLOCATED.load(SeqCst) - alloc) > (N as usize + 10000))
+        )
     }
 }
 
@@ -913,6 +924,9 @@
 
     #[test]
     fn test_chan() {
+        #[cfg(miri)]
+        const N: i32 = 20;
+        #[cfg(not(miri))]
         const N: i32 = 200;
 
         for cap in 0..N {
@@ -1052,6 +1066,9 @@
 
     #[test]
     fn test_nonblock_recv_race() {
+        #[cfg(miri)]
+        const N: usize = 100;
+        #[cfg(not(miri))]
         const N: usize = 1000;
 
         for _ in 0..N {
@@ -1073,6 +1090,9 @@
 
     #[test]
     fn test_nonblock_select_race() {
+        #[cfg(miri)]
+        const N: usize = 100;
+        #[cfg(not(miri))]
         const N: usize = 1000;
 
         let done = make::<bool>(1);
@@ -1106,6 +1126,9 @@
 
     #[test]
     fn test_nonblock_select_race2() {
+        #[cfg(miri)]
+        const N: usize = 100;
+        #[cfg(not(miri))]
         const N: usize = 1000;
 
         let done = make::<bool>(1);
@@ -1142,6 +1165,11 @@
         // Ensure that send/recv on the same chan in select
         // does not crash nor deadlock.
 
+        #[cfg(miri)]
+        const N: usize = 100;
+        #[cfg(not(miri))]
+        const N: usize = 1000;
+
         for &cap in &[0, 10] {
             let wg = WaitGroup::new();
             wg.add(2);
@@ -1151,7 +1179,7 @@
                 let p = p;
                 go!(wg, p, c, {
                     defer! { wg.done() }
-                    for i in 0..1000 {
+                    for i in 0..N {
                         if p == 0 || i % 2 == 0 {
                             select! {
                                 send(c.tx(), p) -> _ => {}
@@ -1180,6 +1208,11 @@
 
     #[test]
     fn test_select_stress() {
+        #[cfg(miri)]
+        const N: usize = 100;
+        #[cfg(not(miri))]
+        const N: usize = 10000;
+
         let c = vec![
             make::<i32>(0),
             make::<i32>(0),
@@ -1187,8 +1220,6 @@
             make::<i32>(3),
         ];
 
-        const N: usize = 10000;
-
         // There are 4 goroutines that send N values on each of the chans,
         // + 4 goroutines that receive N values on each of the chans,
         // + 1 goroutine that sends N values on each of the chans in a single select,
@@ -1286,6 +1317,9 @@
 
     #[test]
     fn test_select_fairness() {
+        #[cfg(miri)]
+        const TRIALS: usize = 100;
+        #[cfg(not(miri))]
         const TRIALS: usize = 10000;
 
         let c1 = make::<u8>(TRIALS + 1);
@@ -1369,6 +1403,9 @@
 
     #[test]
     fn test_pseudo_random_send() {
+        #[cfg(miri)]
+        const N: usize = 20;
+        #[cfg(not(miri))]
         const N: usize = 100;
 
         for cap in 0..N {
@@ -1412,6 +1449,9 @@
     #[test]
     fn test_multi_consumer() {
         const NWORK: usize = 23;
+        #[cfg(miri)]
+        const NITER: usize = 100;
+        #[cfg(not(miri))]
         const NITER: usize = 271828;
 
         let pn = [2, 3, 7, 11, 13, 17, 19, 23, 27, 31];
@@ -1510,6 +1550,9 @@
     use super::*;
 
     // sent messages
+    #[cfg(miri)]
+    const N: usize = 100;
+    #[cfg(not(miri))]
     const N: usize = 1000;
     // receiving "goroutines"
     const M: usize = 10;
diff --git a/tests/iter.rs b/tests/iter.rs
index 38bcac2..463f3b0 100644
--- a/tests/iter.rs
+++ b/tests/iter.rs
@@ -93,7 +93,7 @@
 
     assert_eq!(iter.next().unwrap(), 1);
     assert_eq!(iter.next().unwrap(), 2);
-    assert_eq!(iter.next().is_none(), true);
+    assert!(iter.next().is_none());
 }
 
 #[test]
@@ -106,5 +106,5 @@
     let mut iter = (&r).into_iter();
     assert_eq!(iter.next().unwrap(), 1);
     assert_eq!(iter.next().unwrap(), 2);
-    assert_eq!(iter.next().is_none(), true);
+    assert!(iter.next().is_none());
 }
diff --git a/tests/list.rs b/tests/list.rs
index f166a19..619e1fc 100644
--- a/tests/list.rs
+++ b/tests/list.rs
@@ -41,29 +41,29 @@
     let (s, r) = unbounded();
 
     assert_eq!(s.len(), 0);
-    assert_eq!(s.is_empty(), true);
-    assert_eq!(s.is_full(), false);
+    assert!(s.is_empty());
+    assert!(!s.is_full());
     assert_eq!(r.len(), 0);
-    assert_eq!(r.is_empty(), true);
-    assert_eq!(r.is_full(), false);
+    assert!(r.is_empty());
+    assert!(!r.is_full());
 
     s.send(()).unwrap();
 
     assert_eq!(s.len(), 1);
-    assert_eq!(s.is_empty(), false);
-    assert_eq!(s.is_full(), false);
+    assert!(!s.is_empty());
+    assert!(!s.is_full());
     assert_eq!(r.len(), 1);
-    assert_eq!(r.is_empty(), false);
-    assert_eq!(r.is_full(), false);
+    assert!(!r.is_empty());
+    assert!(!r.is_full());
 
     r.recv().unwrap();
 
     assert_eq!(s.len(), 0);
-    assert_eq!(s.is_empty(), true);
-    assert_eq!(s.is_full(), false);
+    assert!(s.is_empty());
+    assert!(!s.is_full());
     assert_eq!(r.len(), 0);
-    assert_eq!(r.is_empty(), true);
-    assert_eq!(r.is_full(), false);
+    assert!(r.is_empty());
+    assert!(!r.is_full());
 }
 
 #[test]
@@ -239,6 +239,9 @@
 
 #[test]
 fn spsc() {
+    #[cfg(miri)]
+    const COUNT: usize = 100;
+    #[cfg(not(miri))]
     const COUNT: usize = 100_000;
 
     let (s, r) = unbounded();
@@ -261,6 +264,9 @@
 
 #[test]
 fn mpmc() {
+    #[cfg(miri)]
+    const COUNT: usize = 100;
+    #[cfg(not(miri))]
     const COUNT: usize = 25_000;
     const THREADS: usize = 4;
 
@@ -295,6 +301,9 @@
 
 #[test]
 fn stress_oneshot() {
+    #[cfg(miri)]
+    const COUNT: usize = 100;
+    #[cfg(not(miri))]
     const COUNT: usize = 10_000;
 
     for _ in 0..COUNT {
@@ -310,6 +319,9 @@
 
 #[test]
 fn stress_iter() {
+    #[cfg(miri)]
+    const COUNT: usize = 100;
+    #[cfg(not(miri))]
     const COUNT: usize = 100_000;
 
     let (request_s, request_r) = unbounded();
@@ -371,8 +383,11 @@
     .unwrap();
 }
 
+#[cfg_attr(miri, ignore)] // Miri is too slow
 #[test]
 fn drops() {
+    const RUNS: usize = 100;
+
     static DROPS: AtomicUsize = AtomicUsize::new(0);
 
     #[derive(Debug, PartialEq)]
@@ -386,7 +401,7 @@
 
     let mut rng = thread_rng();
 
-    for _ in 0..100 {
+    for _ in 0..RUNS {
         let steps = rng.gen_range(0..10_000);
         let additional = rng.gen_range(0..1000);
 
@@ -421,6 +436,9 @@
 
 #[test]
 fn linearizable() {
+    #[cfg(miri)]
+    const COUNT: usize = 100;
+    #[cfg(not(miri))]
     const COUNT: usize = 25_000;
     const THREADS: usize = 4;
 
@@ -441,6 +459,9 @@
 
 #[test]
 fn fairness() {
+    #[cfg(miri)]
+    const COUNT: usize = 100;
+    #[cfg(not(miri))]
     const COUNT: usize = 10_000;
 
     let (s1, r1) = unbounded::<()>();
@@ -463,6 +484,9 @@
 
 #[test]
 fn fairness_duplicates() {
+    #[cfg(miri)]
+    const COUNT: usize = 100;
+    #[cfg(not(miri))]
     const COUNT: usize = 10_000;
 
     let (s, r) = unbounded();
@@ -496,6 +520,9 @@
 
 #[test]
 fn channel_through_channel() {
+    #[cfg(miri)]
+    const COUNT: usize = 100;
+    #[cfg(not(miri))]
     const COUNT: usize = 1000;
 
     type T = Box<dyn Any + Send>;
diff --git a/tests/mpsc.rs b/tests/mpsc.rs
index 2a0786a..4d6e179 100644
--- a/tests/mpsc.rs
+++ b/tests/mpsc.rs
@@ -20,6 +20,12 @@
 //!   - https://github.com/rust-lang/rust/blob/master/COPYRIGHT
 //!   - https://www.rust-lang.org/en-US/legal.html
 
+#![allow(
+    clippy::drop_copy,
+    clippy::match_single_binding,
+    clippy::redundant_clone
+)]
+
 use std::sync::mpsc::{RecvError, RecvTimeoutError, TryRecvError};
 use std::sync::mpsc::{SendError, TrySendError};
 use std::thread::JoinHandle;
@@ -176,7 +182,7 @@
     ) => ({
         cc::crossbeam_channel_internal! {
             $(
-                recv(($rx).inner) -> res => {
+                $meth(($rx).inner) -> res => {
                     let $name = res.map_err(|_| ::std::sync::mpsc::RecvError);
                     $code
                 }
@@ -314,13 +320,18 @@
 
     #[test]
     fn stress() {
+        #[cfg(miri)]
+        const COUNT: usize = 500;
+        #[cfg(not(miri))]
+        const COUNT: usize = 10000;
+
         let (tx, rx) = channel::<i32>();
         let t = thread::spawn(move || {
-            for _ in 0..10000 {
+            for _ in 0..COUNT {
                 tx.send(1).unwrap();
             }
         });
-        for _ in 0..10000 {
+        for _ in 0..COUNT {
             assert_eq!(rx.recv().unwrap(), 1);
         }
         t.join().ok().unwrap();
@@ -328,6 +339,9 @@
 
     #[test]
     fn stress_shared() {
+        #[cfg(miri)]
+        const AMT: u32 = 500;
+        #[cfg(not(miri))]
         const AMT: u32 = 10000;
         const NTHREADS: u32 = 8;
         let (tx, rx) = channel::<i32>();
@@ -336,10 +350,7 @@
             for _ in 0..AMT * NTHREADS {
                 assert_eq!(rx.recv().unwrap(), 1);
             }
-            match rx.try_recv() {
-                Ok(..) => panic!(),
-                _ => {}
-            }
+            assert!(rx.try_recv().is_err());
         });
 
         let mut ts = Vec::with_capacity(NTHREADS as usize);
@@ -735,12 +746,17 @@
 
     #[test]
     fn recv_a_lot() {
+        #[cfg(miri)]
+        const N: usize = 100;
+        #[cfg(not(miri))]
+        const N: usize = 10000;
+
         // Regression test that we don't run out of stack in scheduler context
         let (tx, rx) = channel();
-        for _ in 0..10000 {
+        for _ in 0..N {
             tx.send(()).unwrap();
         }
-        for _ in 0..10000 {
+        for _ in 0..N {
             rx.recv().unwrap();
         }
     }
@@ -880,7 +896,7 @@
         };
         assert_eq!(iter.next().unwrap(), 1);
         assert_eq!(iter.next().unwrap(), 2);
-        assert_eq!(iter.next().is_none(), true);
+        assert!(iter.next().is_none());
     }
 
     #[test]
@@ -892,7 +908,7 @@
         let mut iter = (&rx).into_iter();
         assert_eq!(iter.next().unwrap(), 1);
         assert_eq!(iter.next().unwrap(), 2);
-        assert_eq!(iter.next().is_none(), true);
+        assert!(iter.next().is_none());
     }
 
     #[test]
@@ -1079,13 +1095,18 @@
 
     #[test]
     fn stress() {
+        #[cfg(miri)]
+        const N: usize = 100;
+        #[cfg(not(miri))]
+        const N: usize = 10000;
+
         let (tx, rx) = sync_channel::<i32>(0);
         let t = thread::spawn(move || {
-            for _ in 0..10000 {
+            for _ in 0..N {
                 tx.send(1).unwrap();
             }
         });
-        for _ in 0..10000 {
+        for _ in 0..N {
             assert_eq!(rx.recv().unwrap(), 1);
         }
         t.join().unwrap();
@@ -1093,10 +1114,15 @@
 
     #[test]
     fn stress_recv_timeout_two_threads() {
+        #[cfg(miri)]
+        const N: usize = 100;
+        #[cfg(not(miri))]
+        const N: usize = 10000;
+
         let (tx, rx) = sync_channel::<i32>(0);
 
         let t = thread::spawn(move || {
-            for _ in 0..10000 {
+            for _ in 0..N {
                 tx.send(1).unwrap();
             }
         });
@@ -1113,12 +1139,15 @@
             }
         }
 
-        assert_eq!(recv_count, 10000);
+        assert_eq!(recv_count, N);
         t.join().unwrap();
     }
 
     #[test]
     fn stress_recv_timeout_shared() {
+        #[cfg(miri)]
+        const AMT: u32 = 100;
+        #[cfg(not(miri))]
         const AMT: u32 = 1000;
         const NTHREADS: u32 = 8;
         let (tx, rx) = sync_channel::<i32>(0);
@@ -1165,6 +1194,9 @@
 
     #[test]
     fn stress_shared() {
+        #[cfg(miri)]
+        const AMT: u32 = 100;
+        #[cfg(not(miri))]
         const AMT: u32 = 1000;
         const NTHREADS: u32 = 8;
         let (tx, rx) = sync_channel::<i32>(0);
@@ -1174,10 +1206,7 @@
             for _ in 0..AMT * NTHREADS {
                 assert_eq!(rx.recv().unwrap(), 1);
             }
-            match rx.try_recv() {
-                Ok(..) => panic!(),
-                _ => {}
-            }
+            assert!(rx.try_recv().is_err());
             dtx.send(()).unwrap();
         });
 
@@ -1449,12 +1478,17 @@
 
     #[test]
     fn recv_a_lot() {
+        #[cfg(miri)]
+        const N: usize = 100;
+        #[cfg(not(miri))]
+        const N: usize = 10000;
+
         // Regression test that we don't run out of stack in scheduler context
-        let (tx, rx) = sync_channel(10000);
-        for _ in 0..10000 {
+        let (tx, rx) = sync_channel(N);
+        for _ in 0..N {
             tx.send(()).unwrap();
         }
-        for _ in 0..10000 {
+        for _ in 0..N {
             rx.recv().unwrap();
         }
     }
@@ -1792,7 +1826,11 @@
 
     #[test]
     fn stress() {
+        #[cfg(miri)]
+        const AMT: i32 = 100;
+        #[cfg(not(miri))]
         const AMT: i32 = 10000;
+
         let (tx1, rx1) = channel::<i32>();
         let (tx2, rx2) = channel::<i32>();
         let (tx3, rx3) = channel::<()>();
diff --git a/tests/never.rs b/tests/never.rs
index 31cebf6..f275126 100644
--- a/tests/never.rs
+++ b/tests/never.rs
@@ -65,8 +65,8 @@
 fn len_empty_full() {
     let r = never::<i32>();
     assert_eq!(r.len(), 0);
-    assert_eq!(r.is_empty(), true);
-    assert_eq!(r.is_full(), true);
+    assert!(r.is_empty());
+    assert!(r.is_full());
 }
 
 #[test]
diff --git a/tests/ready.rs b/tests/ready.rs
index 6779694..d8dd6ce 100644
--- a/tests/ready.rs
+++ b/tests/ready.rs
@@ -1,5 +1,7 @@
 //! Tests for channel readiness using the `Select` struct.
 
+#![allow(clippy::drop_copy)]
+
 use std::any::Any;
 use std::cell::Cell;
 use std::thread;
@@ -490,6 +492,9 @@
 
 #[test]
 fn stress_recv() {
+    #[cfg(miri)]
+    const COUNT: usize = 100;
+    #[cfg(not(miri))]
     const COUNT: usize = 10_000;
 
     let (s1, r1) = unbounded();
@@ -527,6 +532,9 @@
 
 #[test]
 fn stress_send() {
+    #[cfg(miri)]
+    const COUNT: usize = 100;
+    #[cfg(not(miri))]
     const COUNT: usize = 10_000;
 
     let (s1, r1) = bounded(0);
@@ -561,6 +569,9 @@
 
 #[test]
 fn stress_mixed() {
+    #[cfg(miri)]
+    const COUNT: usize = 100;
+    #[cfg(not(miri))]
     const COUNT: usize = 10_000;
 
     let (s1, r1) = bounded(0);
@@ -666,6 +677,9 @@
 
 #[test]
 fn channel_through_channel() {
+    #[cfg(miri)]
+    const COUNT: usize = 100;
+    #[cfg(not(miri))]
     const COUNT: usize = 1000;
 
     type T = Box<dyn Any + Send>;
@@ -722,6 +736,9 @@
 
 #[test]
 fn fairness1() {
+    #[cfg(miri)]
+    const COUNT: usize = 100;
+    #[cfg(not(miri))]
     const COUNT: usize = 10_000;
 
     let (s1, r1) = bounded::<()>(COUNT);
@@ -767,6 +784,9 @@
 
 #[test]
 fn fairness2() {
+    #[cfg(miri)]
+    const COUNT: usize = 100;
+    #[cfg(not(miri))]
     const COUNT: usize = 100_000;
 
     let (s1, r1) = unbounded::<()>();
diff --git a/tests/select.rs b/tests/select.rs
index fcc291e..f24aed8 100644
--- a/tests/select.rs
+++ b/tests/select.rs
@@ -1,5 +1,7 @@
 //! Tests for channel selection using the `Select` struct.
 
+#![allow(clippy::drop_copy)]
+
 use std::any::Any;
 use std::cell::Cell;
 use std::thread;
@@ -406,6 +408,7 @@
     .unwrap();
 }
 
+#[cfg_attr(miri, ignore)] // Miri is too slow
 #[test]
 fn loop_try() {
     const RUNS: usize = 20;
@@ -690,6 +693,9 @@
 
 #[test]
 fn stress_recv() {
+    #[cfg(miri)]
+    const COUNT: usize = 100;
+    #[cfg(not(miri))]
     const COUNT: usize = 10_000;
 
     let (s1, r1) = unbounded();
@@ -728,6 +734,9 @@
 
 #[test]
 fn stress_send() {
+    #[cfg(miri)]
+    const COUNT: usize = 100;
+    #[cfg(not(miri))]
     const COUNT: usize = 10_000;
 
     let (s1, r1) = bounded(0);
@@ -763,6 +772,9 @@
 
 #[test]
 fn stress_mixed() {
+    #[cfg(miri)]
+    const COUNT: usize = 100;
+    #[cfg(not(miri))]
     const COUNT: usize = 10_000;
 
     let (s1, r1) = bounded(0);
@@ -895,12 +907,12 @@
         for i in 0..THREADS {
             scope.spawn(move |_| {
                 let mut sel = Select::new();
-                let oper1 = sel.recv(&r);
-                let oper2 = sel.send(&s);
+                let oper1 = sel.recv(r);
+                let oper2 = sel.send(s);
                 let oper = sel.select();
                 match oper.index() {
-                    ix if ix == oper1 => assert_ne!(oper.recv(&r), Ok(i)),
-                    ix if ix == oper2 => assert!(oper.send(&s, i).is_ok()),
+                    ix if ix == oper1 => assert_ne!(oper.recv(r), Ok(i)),
+                    ix if ix == oper2 => assert!(oper.send(s, i).is_ok()),
                     _ => unreachable!(),
                 }
             });
@@ -921,12 +933,12 @@
         for i in 0..THREADS {
             scope.spawn(move |_| {
                 let mut sel = Select::new();
-                let oper1 = sel.recv(&r);
-                let oper2 = sel.send(&s);
+                let oper1 = sel.recv(r);
+                let oper2 = sel.send(s);
                 let oper = sel.select();
                 match oper.index() {
-                    ix if ix == oper1 => assert_ne!(oper.recv(&r), Ok(i)),
-                    ix if ix == oper2 => assert!(oper.send(&s, i).is_ok()),
+                    ix if ix == oper1 => assert_ne!(oper.recv(r), Ok(i)),
+                    ix if ix == oper2 => assert!(oper.send(s, i).is_ok()),
                     _ => unreachable!(),
                 }
             });
@@ -940,6 +952,9 @@
 
 #[test]
 fn channel_through_channel() {
+    #[cfg(miri)]
+    const COUNT: usize = 100;
+    #[cfg(not(miri))]
     const COUNT: usize = 1000;
 
     type T = Box<dyn Any + Send>;
@@ -998,6 +1013,9 @@
 
 #[test]
 fn linearizable_try() {
+    #[cfg(miri)]
+    const COUNT: usize = 100;
+    #[cfg(not(miri))]
     const COUNT: usize = 100_000;
 
     for step in 0..2 {
@@ -1050,6 +1068,9 @@
 
 #[test]
 fn linearizable_timeout() {
+    #[cfg(miri)]
+    const COUNT: usize = 100;
+    #[cfg(not(miri))]
     const COUNT: usize = 100_000;
 
     for step in 0..2 {
@@ -1102,6 +1123,9 @@
 
 #[test]
 fn fairness1() {
+    #[cfg(miri)]
+    const COUNT: usize = 100;
+    #[cfg(not(miri))]
     const COUNT: usize = 10_000;
 
     let (s1, r1) = bounded::<()>(COUNT);
@@ -1148,6 +1172,9 @@
 
 #[test]
 fn fairness2() {
+    #[cfg(miri)]
+    const COUNT: usize = 100;
+    #[cfg(not(miri))]
     const COUNT: usize = 10_000;
 
     let (s1, r1) = unbounded::<()>();
@@ -1212,8 +1239,8 @@
     let (s, r) = &bounded::<usize>(0);
 
     let mut sel = Select::new();
-    let oper1 = sel.recv(&r);
-    let oper2 = sel.send(&s);
+    let oper1 = sel.recv(r);
+    let oper2 = sel.send(s);
     let sel = &sel;
 
     scope(|scope| {
@@ -1222,8 +1249,8 @@
                 let mut sel = sel.clone();
                 let oper = sel.select();
                 match oper.index() {
-                    ix if ix == oper1 => assert_ne!(oper.recv(&r), Ok(i)),
-                    ix if ix == oper2 => assert!(oper.send(&s, i).is_ok()),
+                    ix if ix == oper1 => assert_ne!(oper.recv(r), Ok(i)),
+                    ix if ix == oper2 => assert!(oper.send(s, i).is_ok()),
                     _ => unreachable!(),
                 }
             });
@@ -1241,8 +1268,8 @@
     let (s, r) = &bounded::<usize>(0);
 
     let mut sel = Select::new();
-    let oper1 = sel.recv(&r);
-    let oper2 = sel.send(&s);
+    let oper1 = sel.recv(r);
+    let oper2 = sel.send(s);
 
     scope(|scope| {
         for i in 0..THREADS {
@@ -1250,8 +1277,8 @@
             scope.spawn(move |_| {
                 let oper = sel.select();
                 match oper.index() {
-                    ix if ix == oper1 => assert_ne!(oper.recv(&r), Ok(i)),
-                    ix if ix == oper2 => assert!(oper.send(&s, i).is_ok()),
+                    ix if ix == oper1 => assert_ne!(oper.recv(r), Ok(i)),
+                    ix if ix == oper2 => assert!(oper.send(s, i).is_ok()),
                     _ => unreachable!(),
                 }
             });
@@ -1264,6 +1291,9 @@
 
 #[test]
 fn reuse() {
+    #[cfg(miri)]
+    const COUNT: usize = 100;
+    #[cfg(not(miri))]
     const COUNT: usize = 10_000;
 
     let (s1, r1) = bounded(0);
diff --git a/tests/select_macro.rs b/tests/select_macro.rs
index c05f7a0..0b9a21a 100644
--- a/tests/select_macro.rs
+++ b/tests/select_macro.rs
@@ -1,6 +1,7 @@
 //! Tests for the `select!` macro.
 
 #![forbid(unsafe_code)] // select! is safe.
+#![allow(clippy::drop_copy, clippy::match_single_binding)]
 
 use std::any::Any;
 use std::cell::Cell;
@@ -283,6 +284,7 @@
     .unwrap();
 }
 
+#[cfg_attr(miri, ignore)] // Miri is too slow
 #[test]
 fn loop_try() {
     const RUNS: usize = 20;
@@ -485,6 +487,9 @@
 
 #[test]
 fn stress_recv() {
+    #[cfg(miri)]
+    const COUNT: usize = 100;
+    #[cfg(not(miri))]
     const COUNT: usize = 10_000;
 
     let (s1, r1) = unbounded();
@@ -518,6 +523,9 @@
 
 #[test]
 fn stress_send() {
+    #[cfg(miri)]
+    const COUNT: usize = 100;
+    #[cfg(not(miri))]
     const COUNT: usize = 10_000;
 
     let (s1, r1) = bounded(0);
@@ -548,6 +556,9 @@
 
 #[test]
 fn stress_mixed() {
+    #[cfg(miri)]
+    const COUNT: usize = 100;
+    #[cfg(not(miri))]
     const COUNT: usize = 10_000;
 
     let (s1, r1) = bounded(0);
@@ -681,6 +692,9 @@
 
 #[test]
 fn channel_through_channel() {
+    #[cfg(miri)]
+    const COUNT: usize = 100;
+    #[cfg(not(miri))]
     const COUNT: usize = 1000;
 
     type T = Box<dyn Any + Send>;
@@ -726,6 +740,9 @@
 
 #[test]
 fn linearizable_default() {
+    #[cfg(miri)]
+    const COUNT: usize = 100;
+    #[cfg(not(miri))]
     const COUNT: usize = 100_000;
 
     for step in 0..2 {
@@ -770,6 +787,9 @@
 
 #[test]
 fn linearizable_timeout() {
+    #[cfg(miri)]
+    const COUNT: usize = 100;
+    #[cfg(not(miri))]
     const COUNT: usize = 100_000;
 
     for step in 0..2 {
@@ -814,6 +834,9 @@
 
 #[test]
 fn fairness1() {
+    #[cfg(miri)]
+    const COUNT: usize = 100;
+    #[cfg(not(miri))]
     const COUNT: usize = 10_000;
 
     let (s1, r1) = bounded::<()>(COUNT);
@@ -838,6 +861,9 @@
 
 #[test]
 fn fairness2() {
+    #[cfg(miri)]
+    const COUNT: usize = 100;
+    #[cfg(not(miri))]
     const COUNT: usize = 10_000;
 
     let (s1, r1) = unbounded::<()>();
@@ -875,6 +901,9 @@
 
 #[test]
 fn fairness_recv() {
+    #[cfg(miri)]
+    const COUNT: usize = 100;
+    #[cfg(not(miri))]
     const COUNT: usize = 10_000;
 
     let (s1, r1) = bounded::<()>(COUNT);
@@ -897,6 +926,9 @@
 
 #[test]
 fn fairness_send() {
+    #[cfg(miri)]
+    const COUNT: usize = 100;
+    #[cfg(not(miri))]
     const COUNT: usize = 10_000;
 
     let (s1, _r1) = bounded::<()>(COUNT);
@@ -912,6 +944,7 @@
     assert!(hits.iter().all(|x| *x >= COUNT / 4));
 }
 
+#[allow(clippy::or_fun_call)] // This is intentional.
 #[test]
 fn references() {
     let (s, r) = unbounded::<i32>();
@@ -958,6 +991,7 @@
     drop(s);
 }
 
+#[allow(clippy::redundant_closure_call)] // This is intentional.
 #[test]
 fn move_handles() {
     let (s, r) = unbounded::<i32>();
diff --git a/tests/thread_locals.rs b/tests/thread_locals.rs
index 9e27146..effb6a1 100644
--- a/tests/thread_locals.rs
+++ b/tests/thread_locals.rs
@@ -1,5 +1,7 @@
 //! Tests that make sure accessing thread-locals while exiting the thread doesn't cause panics.
 
+#![cfg(not(miri))] // error: abnormal termination: the evaluated program aborted execution
+
 use std::thread;
 use std::time::Duration;
 
diff --git a/tests/tick.rs b/tests/tick.rs
index 1273f64..23bbb1f 100644
--- a/tests/tick.rs
+++ b/tests/tick.rs
@@ -1,5 +1,7 @@
 //! Tests for the tick channel flavor.
 
+#![cfg(not(miri))] // TODO: many assertions failed due to Miri is slow
+
 use std::sync::atomic::AtomicUsize;
 use std::sync::atomic::Ordering;
 use std::thread;
@@ -78,20 +80,20 @@
     let r = tick(ms(50));
 
     assert_eq!(r.len(), 0);
-    assert_eq!(r.is_empty(), true);
-    assert_eq!(r.is_full(), false);
+    assert!(r.is_empty());
+    assert!(!r.is_full());
 
     thread::sleep(ms(100));
 
     assert_eq!(r.len(), 1);
-    assert_eq!(r.is_empty(), false);
-    assert_eq!(r.is_full(), true);
+    assert!(!r.is_empty());
+    assert!(r.is_full());
 
     r.try_recv().unwrap();
 
     assert_eq!(r.len(), 0);
-    assert_eq!(r.is_empty(), true);
-    assert_eq!(r.is_full(), false);
+    assert!(r.is_empty());
+    assert!(!r.is_full());
 }
 
 #[test]
diff --git a/tests/zero.rs b/tests/zero.rs
index 1dd39e1..ba41b1a 100644
--- a/tests/zero.rs
+++ b/tests/zero.rs
@@ -35,11 +35,11 @@
     let (s, r) = bounded(0);
 
     assert_eq!(s.len(), 0);
-    assert_eq!(s.is_empty(), true);
-    assert_eq!(s.is_full(), true);
+    assert!(s.is_empty());
+    assert!(s.is_full());
     assert_eq!(r.len(), 0);
-    assert_eq!(r.is_empty(), true);
-    assert_eq!(r.is_full(), true);
+    assert!(r.is_empty());
+    assert!(r.is_full());
 
     scope(|scope| {
         scope.spawn(|_| s.send(0).unwrap());
@@ -48,11 +48,11 @@
     .unwrap();
 
     assert_eq!(s.len(), 0);
-    assert_eq!(s.is_empty(), true);
-    assert_eq!(s.is_full(), true);
+    assert!(s.is_empty());
+    assert!(s.is_full());
     assert_eq!(r.len(), 0);
-    assert_eq!(r.is_empty(), true);
-    assert_eq!(r.is_full(), true);
+    assert!(r.is_empty());
+    assert!(r.is_full());
 }
 
 #[test]
@@ -187,6 +187,9 @@
 
 #[test]
 fn len() {
+    #[cfg(miri)]
+    const COUNT: usize = 100;
+    #[cfg(not(miri))]
     const COUNT: usize = 25_000;
 
     let (s, r) = bounded(0);
@@ -249,6 +252,9 @@
 
 #[test]
 fn spsc() {
+    #[cfg(miri)]
+    const COUNT: usize = 100;
+    #[cfg(not(miri))]
     const COUNT: usize = 100_000;
 
     let (s, r) = bounded(0);
@@ -271,6 +277,9 @@
 
 #[test]
 fn mpmc() {
+    #[cfg(miri)]
+    const COUNT: usize = 100;
+    #[cfg(not(miri))]
     const COUNT: usize = 25_000;
     const THREADS: usize = 4;
 
@@ -303,6 +312,9 @@
 
 #[test]
 fn stress_oneshot() {
+    #[cfg(miri)]
+    const COUNT: usize = 100;
+    #[cfg(not(miri))]
     const COUNT: usize = 10_000;
 
     for _ in 0..COUNT {
@@ -316,6 +328,7 @@
     }
 }
 
+#[cfg_attr(miri, ignore)] // Miri is too slow
 #[test]
 fn stress_iter() {
     const COUNT: usize = 1000;
@@ -383,8 +396,11 @@
     .unwrap();
 }
 
+#[cfg_attr(miri, ignore)] // Miri is too slow
 #[test]
 fn drops() {
+    const RUNS: usize = 100;
+
     static DROPS: AtomicUsize = AtomicUsize::new(0);
 
     #[derive(Debug, PartialEq)]
@@ -398,7 +414,7 @@
 
     let mut rng = thread_rng();
 
-    for _ in 0..100 {
+    for _ in 0..RUNS {
         let steps = rng.gen_range(0..3_000);
 
         DROPS.store(0, Ordering::SeqCst);
@@ -428,6 +444,9 @@
 
 #[test]
 fn fairness() {
+    #[cfg(miri)]
+    const COUNT: usize = 100;
+    #[cfg(not(miri))]
     const COUNT: usize = 10_000;
 
     let (s1, r1) = bounded::<()>(0);
@@ -459,6 +478,9 @@
 
 #[test]
 fn fairness_duplicates() {
+    #[cfg(miri)]
+    const COUNT: usize = 100;
+    #[cfg(not(miri))]
     const COUNT: usize = 10_000;
 
     let (s, r) = bounded::<()>(0);
@@ -517,6 +539,9 @@
 
 #[test]
 fn channel_through_channel() {
+    #[cfg(miri)]
+    const COUNT: usize = 100;
+    #[cfg(not(miri))]
     const COUNT: usize = 1000;
 
     type T = Box<dyn Any + Send>;