Bug 1671170 - Downgrade smallvec to 1.3. r=markh

See https://github.com/servo/rust-smallvec/issues/243 and the PRs in the
comments.

Differential Revision: https://phabricator.services.mozilla.com/D98802
This commit is contained in:
Emilio Cobos Álvarez 2020-12-05 17:12:44 +00:00
parent 62dc874ef0
commit 80b8ba4acd
23 changed files with 966 additions and 4654 deletions

24
Cargo.lock generated
View File

@ -617,15 +617,6 @@ dependencies = [
"unicode-width",
]
[[package]]
name = "cloudabi"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4344512281c643ae7638bbabc3af17a11307803ec8f0fcad9fae512a8bf36467"
dependencies = [
"bitflags",
]
[[package]]
name = "cmake"
version = "0.1.29"
@ -3678,12 +3669,11 @@ dependencies = [
[[package]]
name = "parking_lot_core"
version = "0.8.0"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c361aa727dd08437f2f1447be8b59a33b0edd15e0fcee698f935613d9efbca9b"
checksum = "d7c6d9b8427445284a09c55be860a15855ab580a417ccad9da88f5a06787ced0"
dependencies = [
"cfg-if 0.1.10",
"cloudabi",
"cfg-if 1.0.0",
"instant",
"libc",
"redox_syscall",
@ -4356,9 +4346,9 @@ checksum = "5d79b4b604167921892e84afbbaad9d5ad74e091bf6c511d9dbfb0593f09fabd"
[[package]]
name = "rusqlite"
version = "0.24.1"
version = "0.24.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e3d4791ab5517217f51216a84a688b53c1ebf7988736469c538d02f46ddba68"
checksum = "d5f38ee71cbab2c827ec0ac24e76f82eca723cee92c509a65f67dee393c25112"
dependencies = [
"bitflags",
"fallible-iterator",
@ -4709,9 +4699,9 @@ checksum = "797a4eaffb90d896f29698d45676f9f940a71936d7574996a7df54593ba209fa"
[[package]]
name = "smallvec"
version = "1.4.2"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fbee7696b84bbf3d89a1c2eccff0850e3047ed46bfcd2e92c29a2d074d57e252"
checksum = "05720e22615919e4734f6a99ceae50d00226c3c5aca406e102ebc33298214e0a"
dependencies = [
"serde",
]

View File

@ -66,7 +66,8 @@ servo_arc = { path = "../servo_arc" }
servo_atoms = {path = "../atoms", optional = true}
servo_config = {path = "../config", optional = true}
smallbitvec = "2.3.0"
smallvec = "1.0"
# See https://github.com/servo/rust-smallvec/issues/243
smallvec = "=1.3"
static_prefs = { path = "../../../modules/libpref/init/static_prefs" }
string_cache = { version = "0.8", optional = true }
style_derive = {path = "../style_derive"}

View File

@ -1 +0,0 @@
{"files":{"Cargo.toml":"8f287443ede083f9f2816bccdd6a23f0b58e70337315c06a34a9ae06029242d1","cloudabi.rs":"5660f8ac289098a3fc9b39df2c8ec1f218bbbd8a98ec38b17f24a1dd8fbc0bdb"},"package":"4344512281c643ae7638bbabc3af17a11307803ec8f0fcad9fae512a8bf36467"}

View File

@ -1,32 +0,0 @@
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
#
# 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
#
# 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)
[package]
edition = "2018"
name = "cloudabi"
version = "0.1.0"
authors = ["Nuxi (https://nuxi.nl/) and contributors"]
description = "Low level interface to CloudABI. Contains all syscalls and related types."
homepage = "https://cloudabi.org/"
documentation = "https://docs.rs/cloudabi/"
keywords = ["cloudabi"]
license = "BSD-2-Clause"
repository = "https://github.com/nuxinl/cloudabi"
[lib]
path = "cloudabi.rs"
[dependencies.bitflags]
version = "1.2.1"
optional = true
[features]
default = ["bitflags"]

File diff suppressed because it is too large Load Diff

View File

@ -1 +1 @@
{"files":{"Cargo.toml":"f1e6b94b0b13664976a1ebeef3163f4560077e17b9254593f7c566c653fbcc93","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"c9a75f18b9ab2927829a208fc6aa2cf4e63b8420887ba29cdb265d6619ae82d5","src/lib.rs":"058dddad16d91c8d0160fa2a78bb5f7c2f801f2fd9770fc387c5843395bf0379","src/parking_lot.rs":"586fa7ff7ee77c19dcea83310135709f0beda3a3395c4b305217b67e83e6b410","src/spinwait.rs":"d568d8a81f9144ec4c4a139dc934d7d04ee1656a4a221eb548742fe7aba09ab1","src/thread_parker/cloudabi.rs":"dba5efaf7538c3d8731e9ef9aa41bb48aaa1721c61acb64eb224b38edf12b663","src/thread_parker/generic.rs":"574aecb3c325012b683eca4135441ec73f44c33cc9955aa05db24d7e4c991cd7","src/thread_parker/linux.rs":"4a2c76b3dc09301ceb73d904460f49d91bc1a2492cc123ee26ca22ece3faae79","src/thread_parker/mod.rs":"347fe878b616ec69eeffc188475920b47b3d802756565d32e004fc342eea771f","src/thread_parker/redox.rs":"91ca107c4edffa57e87294cadec3b6010b584fb272c044e2557c925dbcb90f6a","src/thread_parker/sgx.rs":"898ced116fb7b0ac077b5977b5bcac610f1d55beffb613ec73e083b1ef09cc28","src/thread_parker/unix.rs":"8ff84ab0a629e8891b663226c8867ae4bb0fc63f0b3504e85b4583e7bf73a589","src/thread_parker/wasm.rs":"903b7eec240cdbe8a23467f6b41d042d93b35755bd1763be02f9cc55756c4aec","src/thread_parker/wasm_atomic.rs":"85f2d7e9982ef64f077fc6ee2e10f81027d556b08c5618e86913c137571e377e","src/thread_parker/windows/keyed_event.rs":"fc1cf4e592d814c4c949217d91317ec2afb6048430abebb3cea2e8487b369734","src/thread_parker/windows/mod.rs":"c99a3871e69800452a56928a9e870530b7f48a563a4d3efe6184103147899f0c","src/thread_parker/windows/waitaddress.rs":"8e037df2a5692905e2bc2d4ea955295ab92bcc7e26eea0bb7a4eaac9ce657321","src/util.rs":"285e6133150645525f2ca1ece41f6d35bad4e7c5e08b42b20c99d2a97e04a974","src/word_lock.rs":"2c030aedb340ae8ca564365206452c298fe29986d005d6a40e808c9760f91c95"},"package":"c361aa727dd08437f2f1447be8b59a33b0edd15e0fcee698f935613d9efbca9b"}
{"files":{"Cargo.toml":"5c6baed932139022eb9544cb9b2ea8434bd1dc4add567257bbc0245f52efaa85","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"c9a75f18b9ab2927829a208fc6aa2cf4e63b8420887ba29cdb265d6619ae82d5","src/lib.rs":"7baf09034aafc28f7dbb1550cdde89221e4eb5dfda51b55aeb652ee8710c715d","src/parking_lot.rs":"58125667bd78399e8753b6bd8acef84f180f369f0bc174c573887176bab9f9d3","src/spinwait.rs":"d568d8a81f9144ec4c4a139dc934d7d04ee1656a4a221eb548742fe7aba09ab1","src/thread_parker/generic.rs":"574aecb3c325012b683eca4135441ec73f44c33cc9955aa05db24d7e4c991cd7","src/thread_parker/linux.rs":"4a2c76b3dc09301ceb73d904460f49d91bc1a2492cc123ee26ca22ece3faae79","src/thread_parker/mod.rs":"9c675b7690bbde62e88d946fad218623d423edccff4e01e8e52b116d815c695c","src/thread_parker/redox.rs":"91ca107c4edffa57e87294cadec3b6010b584fb272c044e2557c925dbcb90f6a","src/thread_parker/sgx.rs":"898ced116fb7b0ac077b5977b5bcac610f1d55beffb613ec73e083b1ef09cc28","src/thread_parker/unix.rs":"8ff84ab0a629e8891b663226c8867ae4bb0fc63f0b3504e85b4583e7bf73a589","src/thread_parker/wasm.rs":"903b7eec240cdbe8a23467f6b41d042d93b35755bd1763be02f9cc55756c4aec","src/thread_parker/wasm_atomic.rs":"cf761157803256b18205e747bc99e30b18d5410c27121fa9595e12cb51bb6bef","src/thread_parker/windows/keyed_event.rs":"fc1cf4e592d814c4c949217d91317ec2afb6048430abebb3cea2e8487b369734","src/thread_parker/windows/mod.rs":"c99a3871e69800452a56928a9e870530b7f48a563a4d3efe6184103147899f0c","src/thread_parker/windows/waitaddress.rs":"8e037df2a5692905e2bc2d4ea955295ab92bcc7e26eea0bb7a4eaac9ce657321","src/util.rs":"285e6133150645525f2ca1ece41f6d35bad4e7c5e08b42b20c99d2a97e04a974","src/word_lock.rs":"2c030aedb340ae8ca564365206452c298fe29986d005d6a40e808c9760f91c95"},"package":"d7c6d9b8427445284a09c55be860a15855ab580a417ccad9da88f5a06787ced0"}

View File

@ -13,7 +13,7 @@
[package]
edition = "2018"
name = "parking_lot_core"
version = "0.8.0"
version = "0.8.1"
authors = ["Amanieu d'Antras <amanieu@gmail.com>"]
description = "An advanced API for creating custom synchronization primitives."
keywords = ["mutex", "condvar", "rwlock", "once", "thread"]
@ -25,7 +25,7 @@ version = "0.3.49"
optional = true
[dependencies.cfg-if]
version = "0.1.10"
version = "1.0.0"
[dependencies.instant]
version = "0.1.4"
@ -35,7 +35,7 @@ version = "0.5.1"
optional = true
[dependencies.smallvec]
version = "1.4.0"
version = "1.0"
[dependencies.thread-id]
version = "3.3.0"
@ -44,8 +44,6 @@ optional = true
[features]
deadlock_detection = ["petgraph", "thread-id", "backtrace"]
nightly = []
[target."cfg(target_os = \"cloudabi\")".dependencies.cloudabi]
version = "0.1.0"
[target."cfg(target_os = \"redox\")".dependencies.redox_syscall]
version = "0.1.56"
[target."cfg(unix)".dependencies.libc]

View File

@ -51,10 +51,6 @@
),
feature(stdsimd)
)]
#![cfg_attr(
all(feature = "nightly", target_os = "cloudabi",),
feature(thread_local)
)]
mod parking_lot;
mod spinwait;

View File

@ -7,7 +7,6 @@
use crate::thread_parker::{ThreadParker, ThreadParkerT, UnparkHandleT};
use crate::util::UncheckedOptionExt;
use crate::word_lock::WordLock;
use cfg_if::cfg_if;
use core::{
cell::{Cell, UnsafeCell},
ptr,
@ -17,46 +16,6 @@ use instant::Instant;
use smallvec::SmallVec;
use std::time::Duration;
cfg_if! {
if #[cfg(all(
target_arch = "wasm32",
target_os = "unknown",
target_vendor = "unknown"
))] {
use core::ops::Add;
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
struct DummyInstant(Duration);
impl DummyInstant {
pub fn now() -> DummyInstant {
DummyInstant::zero()
}
const fn zero() -> DummyInstant {
DummyInstant(Duration::from_secs(0))
}
}
impl Add<Duration> for DummyInstant {
type Output = DummyInstant;
fn add(self, _rhs: Duration) -> DummyInstant {
DummyInstant::zero()
}
}
// Use dummy implementation for `Instant` on `wasm32`. The reason for this is
// that `Instant::now()` will always panic because time is currently not implemented
// on wasm32-unknown-unknown.
// See https://github.com/rust-lang/rust/blob/master/src/libstd/sys/wasm/time.rs
type InstantType = DummyInstant;
} else {
// Otherwise use `instant::Instant`
type InstantType = Instant;
}
}
static NUM_THREADS: AtomicUsize = AtomicUsize::new(0);
/// Holds the pointer to the currently active `HashTable`.
@ -88,7 +47,7 @@ impl HashTable {
let new_size = (num_threads * LOAD_FACTOR).next_power_of_two();
let hash_bits = 0usize.leading_zeros() - new_size.leading_zeros() - 1;
let now = InstantType::now();
let now = Instant::now();
let mut entries = Vec::with_capacity(new_size);
for i in 0..new_size {
// We must ensure the seed is not zero
@ -118,7 +77,7 @@ struct Bucket {
impl Bucket {
#[inline]
pub fn new(timeout: InstantType, seed: u32) -> Self {
pub fn new(timeout: Instant, seed: u32) -> Self {
Self {
mutex: WordLock::new(),
queue_head: Cell::new(ptr::null()),
@ -130,7 +89,7 @@ impl Bucket {
struct FairTimeout {
// Next time at which point be_fair should be set
timeout: InstantType,
timeout: Instant,
// the PRNG state for calculating the next timeout
seed: u32,
@ -138,14 +97,14 @@ struct FairTimeout {
impl FairTimeout {
#[inline]
fn new(timeout: InstantType, seed: u32) -> FairTimeout {
fn new(timeout: Instant, seed: u32) -> FairTimeout {
FairTimeout { timeout, seed }
}
// Determine whether we should force a fair unlock, and update the timeout
#[inline]
fn should_timeout(&mut self) -> bool {
let now = InstantType::now();
let now = Instant::now();
if now > self.timeout {
// Time between 0 and 1ms.
let nanos = self.gen_u32() % 1_000_000;

View File

@ -1,305 +0,0 @@
// Copyright 2016 Amanieu d'Antras
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.
use cloudabi as abi;
use core::{
cell::Cell,
mem::{self, MaybeUninit},
sync::atomic::{AtomicU32, Ordering},
};
use instant::Instant;
use std::{convert::TryFrom, thread};
extern "C" {
#[thread_local]
static __pthread_thread_id: abi::tid;
}
struct Lock {
lock: AtomicU32,
}
impl Lock {
pub fn new() -> Self {
Lock {
lock: AtomicU32::new(abi::LOCK_UNLOCKED.0),
}
}
/// # Safety
///
/// See `Lock::lock`.
unsafe fn try_lock(&self) -> Option<LockGuard> {
// Attempt to acquire the lock.
if let Err(old) = self.lock.compare_exchange(
abi::LOCK_UNLOCKED.0,
__pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
Ordering::Acquire,
Ordering::Relaxed,
) {
// Failure. Crash upon recursive acquisition.
debug_assert_ne!(
old & !abi::LOCK_KERNEL_MANAGED.0,
__pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
"Attempted to recursive write-lock a lock",
);
None
} else {
Some(LockGuard { lock: &self.lock })
}
}
/// # Safety
///
/// This method is unsafe because the `LockGuard` has a raw pointer into this `Lock`
/// that it will access on drop to unlock the lock. So make sure the `LockGuard` goes
/// out of scope before the `Lock` it came from moves or goes out of scope.
pub unsafe fn lock(&self) -> LockGuard {
self.try_lock().unwrap_or_else(|| {
// Call into the kernel to acquire a write lock.
let subscription = abi::subscription {
r#type: abi::eventtype::LOCK_WRLOCK,
union: abi::subscription_union {
lock: abi::subscription_lock {
lock: self.ptr(),
lock_scope: abi::scope::PRIVATE,
},
},
..mem::zeroed()
};
let mut event = MaybeUninit::<abi::event>::uninit();
let mut nevents: usize = 0;
let ret = abi::poll(&subscription, event.as_mut_ptr(), 1, &mut nevents);
debug_assert_eq!(ret, abi::errno::SUCCESS);
debug_assert_eq!(event.assume_init().error, abi::errno::SUCCESS);
LockGuard { lock: &self.lock }
})
}
fn ptr(&self) -> *mut abi::lock {
&self.lock as *const AtomicU32 as *mut abi::lock
}
}
struct LockGuard {
lock: *const AtomicU32,
}
impl LockGuard {
fn ptr(&self) -> *mut abi::lock {
self.lock as *mut abi::lock
}
}
impl Drop for LockGuard {
fn drop(&mut self) {
let lock = unsafe { &*self.lock };
debug_assert_eq!(
lock.load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0,
unsafe { __pthread_thread_id.0 } | abi::LOCK_WRLOCKED.0,
"This lock is not write-locked by this thread"
);
if !lock
.compare_exchange(
unsafe { __pthread_thread_id.0 } | abi::LOCK_WRLOCKED.0,
abi::LOCK_UNLOCKED.0,
Ordering::Release,
Ordering::Relaxed,
)
.is_ok()
{
// Lock is managed by kernelspace. Call into the kernel
// to unblock waiting threads.
let ret = unsafe { abi::lock_unlock(self.lock as *mut abi::lock, abi::scope::PRIVATE) };
debug_assert_eq!(ret, abi::errno::SUCCESS);
}
}
}
struct Condvar {
condvar: AtomicU32,
}
impl Condvar {
pub fn new() -> Self {
Condvar {
condvar: AtomicU32::new(abi::CONDVAR_HAS_NO_WAITERS.0),
}
}
pub fn wait(&self, lock: &LockGuard) {
unsafe {
let subscription = abi::subscription {
r#type: abi::eventtype::CONDVAR,
union: abi::subscription_union {
condvar: abi::subscription_condvar {
condvar: self.ptr(),
condvar_scope: abi::scope::PRIVATE,
lock: lock.ptr(),
lock_scope: abi::scope::PRIVATE,
},
},
..mem::zeroed()
};
let mut event = MaybeUninit::<abi::event>::uninit();
let mut nevents: usize = 0;
let ret = abi::poll(&subscription, event.as_mut_ptr(), 1, &mut nevents);
debug_assert_eq!(ret, abi::errno::SUCCESS);
debug_assert_eq!(event.assume_init().error, abi::errno::SUCCESS);
}
}
/// Waits for a signal on the condvar.
/// Returns false if it times out before anyone notified us.
pub fn wait_timeout(&self, lock: &LockGuard, timeout: abi::timestamp) -> bool {
unsafe {
let subscriptions = [
abi::subscription {
r#type: abi::eventtype::CONDVAR,
union: abi::subscription_union {
condvar: abi::subscription_condvar {
condvar: self.ptr(),
condvar_scope: abi::scope::PRIVATE,
lock: lock.ptr(),
lock_scope: abi::scope::PRIVATE,
},
},
..mem::zeroed()
},
abi::subscription {
r#type: abi::eventtype::CLOCK,
union: abi::subscription_union {
clock: abi::subscription_clock {
clock_id: abi::clockid::MONOTONIC,
timeout,
..mem::zeroed()
},
},
..mem::zeroed()
},
];
let mut events = MaybeUninit::<[abi::event; 2]>::uninit();
let mut nevents: usize = 0;
let ret = abi::poll(
subscriptions.as_ptr(),
events.as_mut_ptr() as *mut _,
2,
&mut nevents,
);
debug_assert_eq!(ret, abi::errno::SUCCESS);
let events = events.assume_init();
for i in 0..nevents {
debug_assert_eq!(events[i].error, abi::errno::SUCCESS);
if events[i].r#type == abi::eventtype::CONDVAR {
return true;
}
}
}
false
}
pub fn notify(&self) {
let ret = unsafe { abi::condvar_signal(self.ptr(), abi::scope::PRIVATE, 1) };
debug_assert_eq!(ret, abi::errno::SUCCESS);
}
fn ptr(&self) -> *mut abi::condvar {
&self.condvar as *const AtomicU32 as *mut abi::condvar
}
}
// Helper type for putting a thread to sleep until some other thread wakes it up
pub struct ThreadParker {
should_park: Cell<bool>,
lock: Lock,
condvar: Condvar,
}
impl super::ThreadParkerT for ThreadParker {
type UnparkHandle = UnparkHandle;
const IS_CHEAP_TO_CONSTRUCT: bool = true;
fn new() -> ThreadParker {
ThreadParker {
should_park: Cell::new(false),
lock: Lock::new(),
condvar: Condvar::new(),
}
}
unsafe fn prepare_park(&self) {
self.should_park.set(true);
}
unsafe fn timed_out(&self) -> bool {
// We need to grab the lock here because another thread may be
// concurrently executing UnparkHandle::unpark, which is done without
// holding the queue lock.
let _guard = self.lock.lock();
self.should_park.get()
}
unsafe fn park(&self) {
let guard = self.lock.lock();
while self.should_park.get() {
self.condvar.wait(&guard);
}
}
unsafe fn park_until(&self, timeout: Instant) -> bool {
let guard = self.lock.lock();
while self.should_park.get() {
if let Some(duration_left) = timeout.checked_duration_since(Instant::now()) {
if let Ok(nanos_left) = abi::timestamp::try_from(duration_left.as_nanos()) {
self.condvar.wait_timeout(&guard, nanos_left);
} else {
// remaining timeout overflows an abi::timestamp. Sleep indefinitely
self.condvar.wait(&guard);
}
} else {
// We timed out
return false;
}
}
true
}
unsafe fn unpark_lock(&self) -> UnparkHandle {
let _lock_guard = self.lock.lock();
UnparkHandle {
thread_parker: self,
_lock_guard,
}
}
}
pub struct UnparkHandle {
thread_parker: *const ThreadParker,
_lock_guard: LockGuard,
}
impl super::UnparkHandleT for UnparkHandle {
unsafe fn unpark(self) {
(*self.thread_parker).should_park.set(false);
// We notify while holding the lock here to avoid races with the target
// thread. In particular, the thread could exit after we unlock the
// mutex, which would make the condvar access invalid memory.
(*self.thread_parker).condvar.notify();
}
}
#[inline]
pub fn thread_yield() {
thread::yield_now();
}

View File

@ -76,9 +76,6 @@ cfg_if! {
} else if #[cfg(target_arch = "wasm32")] {
#[path = "wasm.rs"]
mod imp;
} else if #[cfg(all(feature = "nightly", target_os = "cloudabi"))] {
#[path = "cloudabi.rs"]
mod imp;
} else {
#[path = "generic.rs"]
mod imp;

View File

@ -5,13 +5,41 @@
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.
use cfg_if::cfg_if;
use core::{
arch::wasm32,
sync::atomic::{AtomicI32, Ordering},
};
use instant::Instant;
use std::time::Duration;
use std::{convert::TryFrom, thread};
cfg_if! {
if #[cfg(all(
target_arch = "wasm32",
target_os = "unknown",
target_vendor = "unknown"
))] {
// This function serves as a polyfill for `Instant::checked_duration_since`, which is
// currently not implemented for wasm32-unknown-unknown.
// TODO: Remove this shim once it
fn checked_duration_since_now(other: Instant) -> Option<Duration> {
let now = Instant::now();
if other < now {
None
} else {
Some(other.duration_since(now))
}
}
} else {
// If we are not targeting wasm32, we can use the native `checked_duration_since`.
fn checked_duration_since_now(timeout: Instant) -> Option<Duration> {
timeout.checked_duration_since(Instant::now())
}
}
}
// Helper type for putting a thread to sleep until some other thread wakes it up
pub struct ThreadParker {
parked: AtomicI32,
@ -45,7 +73,7 @@ impl super::ThreadParkerT for ThreadParker {
#[inline]
unsafe fn park(&self) {
while self.parked.load(Ordering::Acquire) == PARKED {
let r = unsafe { wasm32::i32_atomic_wait(self.ptr(), PARKED, -1) };
let r = wasm32::memory_atomic_wait32(self.ptr(), PARKED, -1);
// we should have either woken up (0) or got a not-equal due to a
// race (1). We should never time out (2)
debug_assert!(r == 0 || r == 1);
@ -55,9 +83,9 @@ impl super::ThreadParkerT for ThreadParker {
#[inline]
unsafe fn park_until(&self, timeout: Instant) -> bool {
while self.parked.load(Ordering::Acquire) == PARKED {
if let Some(left) = timeout.checked_duration_since(Instant::now()) {
if let Some(left) = checked_duration_since_now(timeout) {
let nanos_left = i64::try_from(left.as_nanos()).unwrap_or(i64::max_value());
let r = unsafe { wasm32::i32_atomic_wait(self.ptr(), PARKED, nanos_left) };
let r = wasm32::memory_atomic_wait32(self.ptr(), PARKED, nanos_left);
debug_assert!(r == 0 || r == 1 || r == 2);
} else {
return false;
@ -86,7 +114,7 @@ pub struct UnparkHandle(*mut i32);
impl super::UnparkHandleT for UnparkHandle {
#[inline]
unsafe fn unpark(self) {
let num_notified = unsafe { wasm32::atomic_notify(self.0 as *mut i32, 1) };
let num_notified = wasm32::memory_atomic_notify(self.0 as *mut i32, 1);
debug_assert!(num_notified == 0 || num_notified == 1);
}
}

View File

@ -1 +1 @@
{"files":{"Cargo.toml":"56285617b69a9e2ea1d922620fb2ba960cb487fcececd016ef41dcb9c850f53a","Changelog.md":"34c6aa9cde3eb6b2803ec1072368ae412eac2da7c8a770ab2bd643a3fa1f9c5d","LICENSE":"6e93da4b8f1e937ae6addcac29c06bac66358611488c17fd1f46c6fa485f519c","README.md":"1730524868f2391f2501f3e8f1516e4cc63dc5e93b4d7dfb211ad8f3de460dac","appveyor.yml":"0bcc97462ce19ea2d7018b5a0f322d4d0ffc085a31cd18abe540ede05c770ff2","benches/cache.rs":"30459d8d7f65dd684909a53590f9be32e2e545a0775cd93ee0ce85dd08410955","benches/exec.rs":"cb7feb1738d4565c8265538a95a869a99ca360ed20c68bb69e84bd31ecbce094","clippy.toml":"98f90bbe52849b3078daeccfbe87aec1c08d02b94a453a15149a1fcccb7cafd0","codecov.yml":"17e6a8fa616f9a9f46ce420761ad15ddf0d8b5fb64c75c04365e5f269ab60ee5","publish-ghp-docs.sh":"3e2c59e09ce377c46a62511aa17389e6bf824c17d2fc5a818409ede40ba64c23","src/backup.rs":"00ee47c6b3d96393e68a3c9467e61f4082613bdd7e06607ef8b9238b62122de2","src/blob/mod.rs":"a8ea454a6bb31becd8b83e10c32c2e19a5a2fbb91cdfbd9fb0ec8525a162b2a7","src/blob/pos_io.rs":"6a41d298789ba7b2efa339f7cfcefef4162d39daf0400ca4fd3849f2f9534c45","src/busy.rs":"1308fbb2a09940207e59e6730d84165e262d95409ee11d434e4e846bb327caac","src/cache.rs":"024aac5c2a955fe60e54871a5ffd0d4fe56410398d2f2202c53f13c425533820","src/collation.rs":"1871a5d1973aedeaf8db52ab635702d77cc7a958d604f307cb498b5060db0d8e","src/column.rs":"7e7c7d5532202eaed6d453cb4cc3f46e3901f0528c5f1c83bfa08a0fd3d87264","src/config.rs":"70620f037d79bbb59ce4fff406b4aff4333cc14901dab8a6deeb4715d30ebc63","src/context.rs":"7550b77ccc1362ebbefa85e51ad70bf3d4e7d4f7817fcaac8cf34300962b7c33","src/error.rs":"dd7ab850c864aabd7bed4988955e652bff00546c20c16e3fe9ed471a655fb684","src/functions.rs":"ed50aacc01f1087ba7af347c0d46ee443360932dbdc539583cbf8b59a221bfdb","src/hooks.rs":"3ca1bcc9ba80f41c003331d779f1116c5c83daaf2bc5740fd0feb56710babce1","src/inner_connection.rs":"844a609bde6131ca13dd1a496181b405ae4f6a79766721adec01c3cf75e82c2a","src/lib.rs":"cd4c916eb8e1fbcc8eff2435b136e7f3723e7d62a691758018ee6e2bbf4678c5","src/limits.rs":"75d339cf1f21c744f42f339dcfccf44e149bd2d1294ad0fe412b0792d9c809ab","src/load_extension_guard.rs":"cd349613067410fa4be811d7522fc50004fbc48feb050c19f80a097ab919f9fb","src/pragma.rs":"f6820bcccd50ef804be09f348069208a2bc227de6959c0e3d9ac42b9c4c3e454","src/raw_statement.rs":"40864c284d9b29842831e92ca92eecf6ac77e5f166b43fc55043e62405e9e190","src/row.rs":"5f0e20ec6bbe9e6c5bce80e34bb76ba06b3abf54ef42755394f144ed1ad2e0c9","src/session.rs":"a4730dd21a0dd880d6cff46236fd3c7ad5ad5de4f607203c13062011162f3029","src/statement.rs":"32e3df655ff71ae0415539c6d79197f8e21315a583bfcad39906e0f8da4abc38","src/trace.rs":"686f46f9b27c9d446aaeff2eae0e8346177cedc48859c1fdac7453386797fe6e","src/transaction.rs":"41c5b8b0355401cace43996d311065a8e05846cb40a15d043f51bdd9e0606ffb","src/types/chrono.rs":"1d6aebb7b8efc6038ec30c95d91cee7a16c826bf5a78aca1bc75c86349e17c83","src/types/from_sql.rs":"3508835cf9a7eba0628dbd0bbbe06783f6fe57e5e8469ca51b288f139cd73436","src/types/mod.rs":"77ef2a40101d7864a651fa601e84ecda0ad441723e6c16dedd5329f4cbe8de84","src/types/serde_json.rs":"a3f11fd63cf5f3ffc9e89134dd3d139ac275aff1948d315b1eb1673d81e8fe95","src/types/time.rs":"f4ce83e8368274cf67677a5b67133adfaf0adef5c600574dd34e2e68da102754","src/types/to_sql.rs":"8544f6c9c6a0676bd75375ddba234d051d9dcf28829f49e3dbb39534142b7981","src/types/url.rs":"b476ca2386a4cc4e8ac500f870993c0445abe91754d4e004bfd19a1b95b53816","src/types/value.rs":"1bc28c99b215bf74821feef60544d5bfbedfcde99590f229d8336e0fc75354f8","src/types/value_ref.rs":"6fb2f5bfb268a90794bfc4aeda41182c7cead0292c84ff56d5141a4825ff1bae","src/unlock_notify.rs":"cf2a91e6484454fc3174be546a7f80934fd40f5be51d174db6a5674e93c9ec4a","src/util/mod.rs":"330b1822393003003e4c890df183eb88e3cfe9d566c8325fb421426811a54193","src/util/param_cache.rs":"efb480749cd74c09aeca28be074050e3a9aed7c8ed1371ca562342cba9c408dd","src/util/small_cstr.rs":"5ec10de6708837c09a67d12a7c503fc2856e933b318f8776ee2b4a6b2ce6cd83","src/util/sqlite_string.rs":"b35a4fac5962d47e0efa1b488d3447997de138aca8e99be8f5073fcbf2081664","src/version.rs":"6df3d88ff62b1f4c46692b515a16d1f02ff27732a3e371788566e6a75d5c1d4d","src/vtab/array.rs":"485d2b441b01d26a8f6a59130c85970afd627e1b953b52434964835f8b6a2aef","src/vtab/csvtab.rs":"1a4b70bdb3cb1eaeee80caded133278280f760bda2eac7ca9185448e121f32ca","src/vtab/mod.rs":"24119ac8328b8aaaf8d75c59e60820055af87dc56db153dabcb3b14113a5e50a","src/vtab/series.rs":"6b6f1c13c3d453ae726721fd09bb51c90a4252d4e662c503d7b0398812e772b7","test.csv":"3f5649d7b9f80468999b80d4d0e747c6f4f1bba80ade792689eeb4359dc1834a","tests/config_log.rs":"e786bb1a0ca1b560788b24a2091e7d294753a7bee8a39f0e6037b435809267df","tests/deny_single_threaded_sqlite_config.rs":"586ee163d42d886d88ae319cb2184c021bdf9f6da9a8325d799ba10ddeadcbe0","tests/vtab.rs":"0bb466e5ad5f96443ed5ef7f7252656dc5d3c6c3cc44d179195f654190065c04"},"package":"7e3d4791ab5517217f51216a84a688b53c1ebf7988736469c538d02f46ddba68"}
{"files":{"Cargo.toml":"a68dc0863956a747f6526f566355c2f176dc1f0e522742ee1b4fe83f56dce905","Changelog.md":"34c6aa9cde3eb6b2803ec1072368ae412eac2da7c8a770ab2bd643a3fa1f9c5d","LICENSE":"6e93da4b8f1e937ae6addcac29c06bac66358611488c17fd1f46c6fa485f519c","README.md":"2265be99f12cc6805897266a26fb27227e4bb226293f3952de6edc4e2e47b8ef","appveyor.yml":"0bcc97462ce19ea2d7018b5a0f322d4d0ffc085a31cd18abe540ede05c770ff2","benches/cache.rs":"30459d8d7f65dd684909a53590f9be32e2e545a0775cd93ee0ce85dd08410955","benches/exec.rs":"cb7feb1738d4565c8265538a95a869a99ca360ed20c68bb69e84bd31ecbce094","clippy.toml":"98f90bbe52849b3078daeccfbe87aec1c08d02b94a453a15149a1fcccb7cafd0","codecov.yml":"17e6a8fa616f9a9f46ce420761ad15ddf0d8b5fb64c75c04365e5f269ab60ee5","publish-ghp-docs.sh":"3e2c59e09ce377c46a62511aa17389e6bf824c17d2fc5a818409ede40ba64c23","src/backup.rs":"00ee47c6b3d96393e68a3c9467e61f4082613bdd7e06607ef8b9238b62122de2","src/blob/mod.rs":"a8ea454a6bb31becd8b83e10c32c2e19a5a2fbb91cdfbd9fb0ec8525a162b2a7","src/blob/pos_io.rs":"6a41d298789ba7b2efa339f7cfcefef4162d39daf0400ca4fd3849f2f9534c45","src/busy.rs":"1308fbb2a09940207e59e6730d84165e262d95409ee11d434e4e846bb327caac","src/cache.rs":"024aac5c2a955fe60e54871a5ffd0d4fe56410398d2f2202c53f13c425533820","src/collation.rs":"1871a5d1973aedeaf8db52ab635702d77cc7a958d604f307cb498b5060db0d8e","src/column.rs":"7e7c7d5532202eaed6d453cb4cc3f46e3901f0528c5f1c83bfa08a0fd3d87264","src/config.rs":"70620f037d79bbb59ce4fff406b4aff4333cc14901dab8a6deeb4715d30ebc63","src/context.rs":"7550b77ccc1362ebbefa85e51ad70bf3d4e7d4f7817fcaac8cf34300962b7c33","src/error.rs":"dd7ab850c864aabd7bed4988955e652bff00546c20c16e3fe9ed471a655fb684","src/functions.rs":"ed50aacc01f1087ba7af347c0d46ee443360932dbdc539583cbf8b59a221bfdb","src/hooks.rs":"3ca1bcc9ba80f41c003331d779f1116c5c83daaf2bc5740fd0feb56710babce1","src/inner_connection.rs":"844a609bde6131ca13dd1a496181b405ae4f6a79766721adec01c3cf75e82c2a","src/lib.rs":"cd4c916eb8e1fbcc8eff2435b136e7f3723e7d62a691758018ee6e2bbf4678c5","src/limits.rs":"75d339cf1f21c744f42f339dcfccf44e149bd2d1294ad0fe412b0792d9c809ab","src/load_extension_guard.rs":"cd349613067410fa4be811d7522fc50004fbc48feb050c19f80a097ab919f9fb","src/pragma.rs":"f6820bcccd50ef804be09f348069208a2bc227de6959c0e3d9ac42b9c4c3e454","src/raw_statement.rs":"40864c284d9b29842831e92ca92eecf6ac77e5f166b43fc55043e62405e9e190","src/row.rs":"5f0e20ec6bbe9e6c5bce80e34bb76ba06b3abf54ef42755394f144ed1ad2e0c9","src/session.rs":"a4730dd21a0dd880d6cff46236fd3c7ad5ad5de4f607203c13062011162f3029","src/statement.rs":"32e3df655ff71ae0415539c6d79197f8e21315a583bfcad39906e0f8da4abc38","src/trace.rs":"686f46f9b27c9d446aaeff2eae0e8346177cedc48859c1fdac7453386797fe6e","src/transaction.rs":"41c5b8b0355401cace43996d311065a8e05846cb40a15d043f51bdd9e0606ffb","src/types/chrono.rs":"1d6aebb7b8efc6038ec30c95d91cee7a16c826bf5a78aca1bc75c86349e17c83","src/types/from_sql.rs":"3508835cf9a7eba0628dbd0bbbe06783f6fe57e5e8469ca51b288f139cd73436","src/types/mod.rs":"77ef2a40101d7864a651fa601e84ecda0ad441723e6c16dedd5329f4cbe8de84","src/types/serde_json.rs":"a3f11fd63cf5f3ffc9e89134dd3d139ac275aff1948d315b1eb1673d81e8fe95","src/types/time.rs":"f4ce83e8368274cf67677a5b67133adfaf0adef5c600574dd34e2e68da102754","src/types/to_sql.rs":"8544f6c9c6a0676bd75375ddba234d051d9dcf28829f49e3dbb39534142b7981","src/types/url.rs":"b476ca2386a4cc4e8ac500f870993c0445abe91754d4e004bfd19a1b95b53816","src/types/value.rs":"1bc28c99b215bf74821feef60544d5bfbedfcde99590f229d8336e0fc75354f8","src/types/value_ref.rs":"6fb2f5bfb268a90794bfc4aeda41182c7cead0292c84ff56d5141a4825ff1bae","src/unlock_notify.rs":"cf2a91e6484454fc3174be546a7f80934fd40f5be51d174db6a5674e93c9ec4a","src/util/mod.rs":"330b1822393003003e4c890df183eb88e3cfe9d566c8325fb421426811a54193","src/util/param_cache.rs":"efb480749cd74c09aeca28be074050e3a9aed7c8ed1371ca562342cba9c408dd","src/util/small_cstr.rs":"5ec10de6708837c09a67d12a7c503fc2856e933b318f8776ee2b4a6b2ce6cd83","src/util/sqlite_string.rs":"b35a4fac5962d47e0efa1b488d3447997de138aca8e99be8f5073fcbf2081664","src/version.rs":"6df3d88ff62b1f4c46692b515a16d1f02ff27732a3e371788566e6a75d5c1d4d","src/vtab/array.rs":"485d2b441b01d26a8f6a59130c85970afd627e1b953b52434964835f8b6a2aef","src/vtab/csvtab.rs":"1a4b70bdb3cb1eaeee80caded133278280f760bda2eac7ca9185448e121f32ca","src/vtab/mod.rs":"24119ac8328b8aaaf8d75c59e60820055af87dc56db153dabcb3b14113a5e50a","src/vtab/series.rs":"6b6f1c13c3d453ae726721fd09bb51c90a4252d4e662c503d7b0398812e772b7","test.csv":"3f5649d7b9f80468999b80d4d0e747c6f4f1bba80ade792689eeb4359dc1834a","tests/config_log.rs":"e786bb1a0ca1b560788b24a2091e7d294753a7bee8a39f0e6037b435809267df","tests/deny_single_threaded_sqlite_config.rs":"586ee163d42d886d88ae319cb2184c021bdf9f6da9a8325d799ba10ddeadcbe0","tests/vtab.rs":"0bb466e5ad5f96443ed5ef7f7252656dc5d3c6c3cc44d179195f654190065c04"},"package":"d5f38ee71cbab2c827ec0ac24e76f82eca723cee92c509a65f67dee393c25112"}

View File

@ -13,7 +13,7 @@
[package]
edition = "2018"
name = "rusqlite"
version = "0.24.1"
version = "0.24.2"
authors = ["The rusqlite developers"]
description = "Ergonomic wrapper for SQLite"
documentation = "http://docs.rs/rusqlite/"
@ -92,7 +92,7 @@ version = "1.0"
optional = true
[dependencies.smallvec]
version = "1.4"
version = "1.0"
[dependencies.time]
version = "0.2"

View File

@ -123,7 +123,7 @@ You can adjust this behavior in a number of ways:
0.20.0). This is probably the simplest solution to any build problems. You can enable this by adding the following in your `Cargo.toml` file:
```toml
[dependencies.rusqlite]
version = "0.24.1"
version = "0.24.2"
features = ["bundled"]
```
* You can set the `SQLITE3_LIB_DIR` to point to directory containing the SQLite

View File

@ -1 +1 @@
{"files":{"Cargo.toml":"13560b491e0ed99fe7d16ecef0f728bc57058c007563170d7d644f3bb2433fff","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0b28172679e0009b655da42797c03fd163a3379d5cfa67ba1f1655e974a2a1a9","README.md":"a01127c37308457e8d396b176fb790846be0978c173be3f13260b62efcef011b","benches/bench.rs":"7425b60d83d01a0bcedb5855ec8652fb1089194da5b5d8f7d7d9072c8ea9d133","scripts/run_miri.sh":"0d0b8c54c73fa9da1217d29ed0984f8328dd9fb61bb5a02db44458c360cdc3c4","src/lib.rs":"bb8aef09a9c7a43d225dfd99063261b89ebd6835ced4e2dfe696f1c3eaf9b9d2","src/specialization.rs":"46433586203399251cba496d67b88d34e1be3c2b591986b77463513da1c66471","src/tests.rs":"1c4763444139813d335d33f9eda8b8b719da60a2b13ddcb44e1a6cc278c319cc","tests/macro.rs":"22ad4f6f104a599fdcba19cad8834105b8656b212fb6c7573a427d447f5db14f"},"package":"fbee7696b84bbf3d89a1c2eccff0850e3047ed46bfcd2e92c29a2d074d57e252"}
{"files":{"Cargo.toml":"45e745963490153700d8392f914b159019420aa81d8ae80241771769199cf65b","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0b28172679e0009b655da42797c03fd163a3379d5cfa67ba1f1655e974a2a1a9","README.md":"a01127c37308457e8d396b176fb790846be0978c173be3f13260b62efcef011b","benches/bench.rs":"9dca7122a3dcb2c099e49807e4d3b8f01d9220e2b3db0a54e9901ee74392866f","lib.rs":"45aa4cd721dd8e649b79c443b9d12b8ff0f9e4dd4188e604b2d6b36b8ceb1c71","scripts/run_miri.sh":"2e83d153efc16cbc3c41589e306faa0624c8b9a0feecea3baae6e34f4563ac42","specialization.rs":"46433586203399251cba496d67b88d34e1be3c2b591986b77463513da1c66471"},"package":"05720e22615919e4734f6a99ceae50d00226c3c5aca406e102ebc33298214e0a"}

View File

@ -13,8 +13,8 @@
[package]
edition = "2018"
name = "smallvec"
version = "1.4.2"
authors = ["The Servo Project Developers"]
version = "1.3.0"
authors = ["Simon Sapin <simon.sapin@exyr.org>"]
description = "'Small vector' optimization: store up to a small number of items on the stack"
documentation = "https://docs.rs/smallvec/"
readme = "README.md"
@ -22,10 +22,13 @@ keywords = ["small", "vec", "vector", "stack", "no_std"]
categories = ["data-structures"]
license = "MIT/Apache-2.0"
repository = "https://github.com/servo/rust-smallvec"
[lib]
name = "smallvec"
path = "lib.rs"
[dependencies.serde]
version = "1"
optional = true
default-features = false
[dev-dependencies.bincode]
version = "1.0.1"

View File

@ -1,5 +1,4 @@
#![feature(test)]
#![allow(deprecated)]
#[macro_use]
extern crate smallvec;

File diff suppressed because it is too large Load Diff

View File

@ -16,6 +16,6 @@ rustup default "$MIRI_NIGHTLY"
rustup component add miri
cargo miri setup
cargo miri test --verbose
cargo miri test --verbose --features union
cargo miri test --verbose --all-features
cargo miri test --verbose -- -Zmiri-ignore-leaks
cargo miri test --verbose --features union -- -Zmiri-ignore-leaks
cargo miri test --verbose --all-features -- -Zmiri-ignore-leaks

View File

@ -1,907 +0,0 @@
use crate::{smallvec, SmallVec};
use std::iter::FromIterator;
use alloc::borrow::ToOwned;
use alloc::boxed::Box;
use alloc::rc::Rc;
use alloc::{vec, vec::Vec};
#[test]
pub fn test_zero() {
let mut v = SmallVec::<[_; 0]>::new();
assert!(!v.spilled());
v.push(0usize);
assert!(v.spilled());
assert_eq!(&*v, &[0]);
}
// We heap allocate all these strings so that double frees will show up under valgrind.
#[test]
pub fn test_inline() {
let mut v = SmallVec::<[_; 16]>::new();
v.push("hello".to_owned());
v.push("there".to_owned());
assert_eq!(&*v, &["hello".to_owned(), "there".to_owned(),][..]);
}
#[test]
pub fn test_spill() {
let mut v = SmallVec::<[_; 2]>::new();
v.push("hello".to_owned());
assert_eq!(v[0], "hello");
v.push("there".to_owned());
v.push("burma".to_owned());
assert_eq!(v[0], "hello");
v.push("shave".to_owned());
assert_eq!(
&*v,
&[
"hello".to_owned(),
"there".to_owned(),
"burma".to_owned(),
"shave".to_owned(),
][..]
);
}
#[test]
pub fn test_double_spill() {
let mut v = SmallVec::<[_; 2]>::new();
v.push("hello".to_owned());
v.push("there".to_owned());
v.push("burma".to_owned());
v.push("shave".to_owned());
v.push("hello".to_owned());
v.push("there".to_owned());
v.push("burma".to_owned());
v.push("shave".to_owned());
assert_eq!(
&*v,
&[
"hello".to_owned(),
"there".to_owned(),
"burma".to_owned(),
"shave".to_owned(),
"hello".to_owned(),
"there".to_owned(),
"burma".to_owned(),
"shave".to_owned(),
][..]
);
}
/// https://github.com/servo/rust-smallvec/issues/4
#[test]
fn issue_4() {
SmallVec::<[Box<u32>; 2]>::new();
}
/// https://github.com/servo/rust-smallvec/issues/5
#[test]
fn issue_5() {
assert!(Some(SmallVec::<[&u32; 2]>::new()).is_some());
}
#[test]
fn test_with_capacity() {
let v: SmallVec<[u8; 3]> = SmallVec::with_capacity(1);
assert!(v.is_empty());
assert!(!v.spilled());
assert_eq!(v.capacity(), 3);
let v: SmallVec<[u8; 3]> = SmallVec::with_capacity(10);
assert!(v.is_empty());
assert!(v.spilled());
assert_eq!(v.capacity(), 10);
}
#[test]
fn drain() {
let mut v: SmallVec<[u8; 2]> = SmallVec::new();
v.push(3);
assert_eq!(v.drain(..).collect::<Vec<_>>(), &[3]);
// spilling the vec
v.push(3);
v.push(4);
v.push(5);
let old_capacity = v.capacity();
assert_eq!(v.drain(1..).collect::<Vec<_>>(), &[4, 5]);
// drain should not change the capacity
assert_eq!(v.capacity(), old_capacity);
}
#[test]
fn drain_rev() {
let mut v: SmallVec<[u8; 2]> = SmallVec::new();
v.push(3);
assert_eq!(v.drain(..).rev().collect::<Vec<_>>(), &[3]);
// spilling the vec
v.push(3);
v.push(4);
v.push(5);
assert_eq!(v.drain(..).rev().collect::<Vec<_>>(), &[5, 4, 3]);
}
#[test]
fn drain_forget() {
let mut v: SmallVec<[u8; 1]> = smallvec![0, 1, 2, 3, 4, 5, 6, 7];
std::mem::forget(v.drain(2..5));
assert_eq!(v.len(), 2);
}
#[test]
fn into_iter() {
let mut v: SmallVec<[u8; 2]> = SmallVec::new();
v.push(3);
assert_eq!(v.into_iter().collect::<Vec<_>>(), &[3]);
// spilling the vec
let mut v: SmallVec<[u8; 2]> = SmallVec::new();
v.push(3);
v.push(4);
v.push(5);
assert_eq!(v.into_iter().collect::<Vec<_>>(), &[3, 4, 5]);
}
#[test]
fn into_iter_rev() {
let mut v: SmallVec<[u8; 2]> = SmallVec::new();
v.push(3);
assert_eq!(v.into_iter().rev().collect::<Vec<_>>(), &[3]);
// spilling the vec
let mut v: SmallVec<[u8; 2]> = SmallVec::new();
v.push(3);
v.push(4);
v.push(5);
assert_eq!(v.into_iter().rev().collect::<Vec<_>>(), &[5, 4, 3]);
}
#[test]
fn into_iter_drop() {
use std::cell::Cell;
struct DropCounter<'a>(&'a Cell<i32>);
impl<'a> Drop for DropCounter<'a> {
fn drop(&mut self) {
self.0.set(self.0.get() + 1);
}
}
{
let cell = Cell::new(0);
let mut v: SmallVec<[DropCounter<'_>; 2]> = SmallVec::new();
v.push(DropCounter(&cell));
v.into_iter();
assert_eq!(cell.get(), 1);
}
{
let cell = Cell::new(0);
let mut v: SmallVec<[DropCounter<'_>; 2]> = SmallVec::new();
v.push(DropCounter(&cell));
v.push(DropCounter(&cell));
assert!(v.into_iter().next().is_some());
assert_eq!(cell.get(), 2);
}
{
let cell = Cell::new(0);
let mut v: SmallVec<[DropCounter<'_>; 2]> = SmallVec::new();
v.push(DropCounter(&cell));
v.push(DropCounter(&cell));
v.push(DropCounter(&cell));
assert!(v.into_iter().next().is_some());
assert_eq!(cell.get(), 3);
}
{
let cell = Cell::new(0);
let mut v: SmallVec<[DropCounter<'_>; 2]> = SmallVec::new();
v.push(DropCounter(&cell));
v.push(DropCounter(&cell));
v.push(DropCounter(&cell));
{
let mut it = v.into_iter();
assert!(it.next().is_some());
assert!(it.next_back().is_some());
}
assert_eq!(cell.get(), 3);
}
}
#[test]
fn test_capacity() {
let mut v: SmallVec<[u8; 2]> = SmallVec::new();
v.reserve(1);
assert_eq!(v.capacity(), 2);
assert!(!v.spilled());
v.reserve_exact(0x100);
assert!(v.capacity() >= 0x100);
v.push(0);
v.push(1);
v.push(2);
v.push(3);
v.shrink_to_fit();
assert!(v.capacity() < 0x100);
}
#[test]
fn test_truncate() {
let mut v: SmallVec<[Box<u8>; 8]> = SmallVec::new();
for x in 0..8 {
v.push(Box::new(x));
}
v.truncate(4);
assert_eq!(v.len(), 4);
assert!(!v.spilled());
assert_eq!(*v.swap_remove(1), 1);
assert_eq!(*v.remove(1), 3);
v.insert(1, Box::new(3));
assert_eq!(&v.iter().map(|v| **v).collect::<Vec<_>>(), &[0, 3, 2]);
}
#[test]
fn test_insert_many() {
let mut v: SmallVec<[u8; 8]> = SmallVec::new();
for x in 0..4 {
v.push(x);
}
assert_eq!(v.len(), 4);
v.insert_many(1, [5, 6].iter().cloned());
assert_eq!(
&v.iter().map(|v| *v).collect::<Vec<_>>(),
&[0, 5, 6, 1, 2, 3]
);
}
struct MockHintIter<T: Iterator> {
x: T,
hint: usize,
}
impl<T: Iterator> Iterator for MockHintIter<T> {
type Item = T::Item;
fn next(&mut self) -> Option<Self::Item> {
self.x.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.hint, None)
}
}
#[test]
fn test_insert_many_short_hint() {
let mut v: SmallVec<[u8; 8]> = SmallVec::new();
for x in 0..4 {
v.push(x);
}
assert_eq!(v.len(), 4);
v.insert_many(
1,
MockHintIter {
x: [5, 6].iter().cloned(),
hint: 5,
},
);
assert_eq!(
&v.iter().map(|v| *v).collect::<Vec<_>>(),
&[0, 5, 6, 1, 2, 3]
);
}
#[test]
fn test_insert_many_long_hint() {
let mut v: SmallVec<[u8; 8]> = SmallVec::new();
for x in 0..4 {
v.push(x);
}
assert_eq!(v.len(), 4);
v.insert_many(
1,
MockHintIter {
x: [5, 6].iter().cloned(),
hint: 1,
},
);
assert_eq!(
&v.iter().map(|v| *v).collect::<Vec<_>>(),
&[0, 5, 6, 1, 2, 3]
);
}
// https://github.com/servo/rust-smallvec/issues/96
mod insert_many_panic {
use crate::{smallvec, SmallVec};
use alloc::boxed::Box;
struct PanicOnDoubleDrop {
dropped: Box<bool>,
}
impl PanicOnDoubleDrop {
fn new() -> Self {
Self {
dropped: Box::new(false),
}
}
}
impl Drop for PanicOnDoubleDrop {
fn drop(&mut self) {
assert!(!*self.dropped, "already dropped");
*self.dropped = true;
}
}
/// Claims to yield `hint` items, but actually yields `count`, then panics.
struct BadIter {
hint: usize,
count: usize,
}
impl Iterator for BadIter {
type Item = PanicOnDoubleDrop;
fn size_hint(&self) -> (usize, Option<usize>) {
(self.hint, None)
}
fn next(&mut self) -> Option<Self::Item> {
if self.count == 0 {
panic!()
}
self.count -= 1;
Some(PanicOnDoubleDrop::new())
}
}
#[test]
fn panic_early_at_start() {
let mut vec: SmallVec<[PanicOnDoubleDrop; 0]> =
smallvec![PanicOnDoubleDrop::new(), PanicOnDoubleDrop::new(),];
let result = ::std::panic::catch_unwind(move || {
vec.insert_many(0, BadIter { hint: 1, count: 0 });
});
assert!(result.is_err());
}
#[test]
fn panic_early_in_middle() {
let mut vec: SmallVec<[PanicOnDoubleDrop; 0]> =
smallvec![PanicOnDoubleDrop::new(), PanicOnDoubleDrop::new(),];
let result = ::std::panic::catch_unwind(move || {
vec.insert_many(1, BadIter { hint: 4, count: 2 });
});
assert!(result.is_err());
}
#[test]
fn panic_early_at_end() {
let mut vec: SmallVec<[PanicOnDoubleDrop; 0]> =
smallvec![PanicOnDoubleDrop::new(), PanicOnDoubleDrop::new(),];
let result = ::std::panic::catch_unwind(move || {
vec.insert_many(2, BadIter { hint: 3, count: 1 });
});
assert!(result.is_err());
}
#[test]
fn panic_late_at_start() {
let mut vec: SmallVec<[PanicOnDoubleDrop; 0]> =
smallvec![PanicOnDoubleDrop::new(), PanicOnDoubleDrop::new(),];
let result = ::std::panic::catch_unwind(move || {
vec.insert_many(0, BadIter { hint: 3, count: 5 });
});
assert!(result.is_err());
}
#[test]
fn panic_late_at_end() {
let mut vec: SmallVec<[PanicOnDoubleDrop; 0]> =
smallvec![PanicOnDoubleDrop::new(), PanicOnDoubleDrop::new(),];
let result = ::std::panic::catch_unwind(move || {
vec.insert_many(2, BadIter { hint: 3, count: 5 });
});
assert!(result.is_err());
}
}
#[test]
#[should_panic]
fn test_invalid_grow() {
let mut v: SmallVec<[u8; 8]> = SmallVec::new();
v.extend(0..8);
v.grow(5);
}
#[test]
fn test_insert_from_slice() {
let mut v: SmallVec<[u8; 8]> = SmallVec::new();
for x in 0..4 {
v.push(x);
}
assert_eq!(v.len(), 4);
v.insert_from_slice(1, &[5, 6]);
assert_eq!(
&v.iter().map(|v| *v).collect::<Vec<_>>(),
&[0, 5, 6, 1, 2, 3]
);
}
#[test]
fn test_extend_from_slice() {
let mut v: SmallVec<[u8; 8]> = SmallVec::new();
for x in 0..4 {
v.push(x);
}
assert_eq!(v.len(), 4);
v.extend_from_slice(&[5, 6]);
assert_eq!(
&v.iter().map(|v| *v).collect::<Vec<_>>(),
&[0, 1, 2, 3, 5, 6]
);
}
#[test]
#[should_panic]
fn test_drop_panic_smallvec() {
// This test should only panic once, and not double panic,
// which would mean a double drop
struct DropPanic;
impl Drop for DropPanic {
fn drop(&mut self) {
panic!("drop");
}
}
let mut v = SmallVec::<[_; 1]>::new();
v.push(DropPanic);
}
#[test]
fn test_eq() {
let mut a: SmallVec<[u32; 2]> = SmallVec::new();
let mut b: SmallVec<[u32; 2]> = SmallVec::new();
let mut c: SmallVec<[u32; 2]> = SmallVec::new();
// a = [1, 2]
a.push(1);
a.push(2);
// b = [1, 2]
b.push(1);
b.push(2);
// c = [3, 4]
c.push(3);
c.push(4);
assert!(a == b);
assert!(a != c);
}
#[test]
fn test_ord() {
let mut a: SmallVec<[u32; 2]> = SmallVec::new();
let mut b: SmallVec<[u32; 2]> = SmallVec::new();
let mut c: SmallVec<[u32; 2]> = SmallVec::new();
// a = [1]
a.push(1);
// b = [1, 1]
b.push(1);
b.push(1);
// c = [1, 2]
c.push(1);
c.push(2);
assert!(a < b);
assert!(b > a);
assert!(b < c);
assert!(c > b);
}
#[test]
fn test_hash() {
use std::collections::hash_map::DefaultHasher;
use std::hash::Hash;
{
let mut a: SmallVec<[u32; 2]> = SmallVec::new();
let b = [1, 2];
a.extend(b.iter().cloned());
let mut hasher = DefaultHasher::new();
assert_eq!(a.hash(&mut hasher), b.hash(&mut hasher));
}
{
let mut a: SmallVec<[u32; 2]> = SmallVec::new();
let b = [1, 2, 11, 12];
a.extend(b.iter().cloned());
let mut hasher = DefaultHasher::new();
assert_eq!(a.hash(&mut hasher), b.hash(&mut hasher));
}
}
#[test]
fn test_as_ref() {
let mut a: SmallVec<[u32; 2]> = SmallVec::new();
a.push(1);
assert_eq!(a.as_ref(), [1]);
a.push(2);
assert_eq!(a.as_ref(), [1, 2]);
a.push(3);
assert_eq!(a.as_ref(), [1, 2, 3]);
}
#[test]
fn test_as_mut() {
let mut a: SmallVec<[u32; 2]> = SmallVec::new();
a.push(1);
assert_eq!(a.as_mut(), [1]);
a.push(2);
assert_eq!(a.as_mut(), [1, 2]);
a.push(3);
assert_eq!(a.as_mut(), [1, 2, 3]);
a.as_mut()[1] = 4;
assert_eq!(a.as_mut(), [1, 4, 3]);
}
#[test]
fn test_borrow() {
use std::borrow::Borrow;
let mut a: SmallVec<[u32; 2]> = SmallVec::new();
a.push(1);
assert_eq!(a.borrow(), [1]);
a.push(2);
assert_eq!(a.borrow(), [1, 2]);
a.push(3);
assert_eq!(a.borrow(), [1, 2, 3]);
}
#[test]
fn test_borrow_mut() {
use std::borrow::BorrowMut;
let mut a: SmallVec<[u32; 2]> = SmallVec::new();
a.push(1);
assert_eq!(a.borrow_mut(), [1]);
a.push(2);
assert_eq!(a.borrow_mut(), [1, 2]);
a.push(3);
assert_eq!(a.borrow_mut(), [1, 2, 3]);
BorrowMut::<[u32]>::borrow_mut(&mut a)[1] = 4;
assert_eq!(a.borrow_mut(), [1, 4, 3]);
}
#[test]
fn test_from() {
assert_eq!(&SmallVec::<[u32; 2]>::from(&[1][..])[..], [1]);
assert_eq!(&SmallVec::<[u32; 2]>::from(&[1, 2, 3][..])[..], [1, 2, 3]);
let vec = vec![];
let small_vec: SmallVec<[u8; 3]> = SmallVec::from(vec);
assert_eq!(&*small_vec, &[]);
drop(small_vec);
let vec = vec![1, 2, 3, 4, 5];
let small_vec: SmallVec<[u8; 3]> = SmallVec::from(vec);
assert_eq!(&*small_vec, &[1, 2, 3, 4, 5]);
drop(small_vec);
let vec = vec![1, 2, 3, 4, 5];
let small_vec: SmallVec<[u8; 1]> = SmallVec::from(vec);
assert_eq!(&*small_vec, &[1, 2, 3, 4, 5]);
drop(small_vec);
let array = [1];
let small_vec: SmallVec<[u8; 1]> = SmallVec::from(array);
assert_eq!(&*small_vec, &[1]);
drop(small_vec);
let array = [99; 128];
let small_vec: SmallVec<[u8; 128]> = SmallVec::from(array);
assert_eq!(&*small_vec, vec![99u8; 128].as_slice());
drop(small_vec);
}
#[test]
fn test_from_slice() {
assert_eq!(&SmallVec::<[u32; 2]>::from_slice(&[1][..])[..], [1]);
assert_eq!(
&SmallVec::<[u32; 2]>::from_slice(&[1, 2, 3][..])[..],
[1, 2, 3]
);
}
#[test]
fn test_exact_size_iterator() {
let mut vec = SmallVec::<[u32; 2]>::from(&[1, 2, 3][..]);
assert_eq!(vec.clone().into_iter().len(), 3);
assert_eq!(vec.drain(..2).len(), 2);
assert_eq!(vec.into_iter().len(), 1);
}
#[test]
fn test_into_iter_as_slice() {
let vec = SmallVec::<[u32; 2]>::from(&[1, 2, 3][..]);
let mut iter = vec.clone().into_iter();
assert_eq!(iter.as_slice(), &[1, 2, 3]);
assert_eq!(iter.as_mut_slice(), &[1, 2, 3]);
iter.next();
assert_eq!(iter.as_slice(), &[2, 3]);
assert_eq!(iter.as_mut_slice(), &[2, 3]);
iter.next_back();
assert_eq!(iter.as_slice(), &[2]);
assert_eq!(iter.as_mut_slice(), &[2]);
}
#[test]
fn test_into_iter_clone() {
// Test that the cloned iterator yields identical elements and that it owns its own copy
// (i.e. no use after move errors).
let mut iter = SmallVec::<[u8; 2]>::from_iter(0..3).into_iter();
let mut clone_iter = iter.clone();
while let Some(x) = iter.next() {
assert_eq!(x, clone_iter.next().unwrap());
}
assert_eq!(clone_iter.next(), None);
}
#[test]
fn test_into_iter_clone_partially_consumed_iterator() {
// Test that the cloned iterator only contains the remaining elements of the original iterator.
let mut iter = SmallVec::<[u8; 2]>::from_iter(0..3).into_iter().skip(1);
let mut clone_iter = iter.clone();
while let Some(x) = iter.next() {
assert_eq!(x, clone_iter.next().unwrap());
}
assert_eq!(clone_iter.next(), None);
}
#[test]
fn test_into_iter_clone_empty_smallvec() {
let mut iter = SmallVec::<[u8; 2]>::new().into_iter();
let mut clone_iter = iter.clone();
assert_eq!(iter.next(), None);
assert_eq!(clone_iter.next(), None);
}
#[test]
fn shrink_to_fit_unspill() {
let mut vec = SmallVec::<[u8; 2]>::from_iter(0..3);
vec.pop();
assert!(vec.spilled());
vec.shrink_to_fit();
assert!(!vec.spilled(), "shrink_to_fit will un-spill if possible");
}
#[test]
fn test_into_vec() {
let vec = SmallVec::<[u8; 2]>::from_iter(0..2);
assert_eq!(vec.into_vec(), vec![0, 1]);
let vec = SmallVec::<[u8; 2]>::from_iter(0..3);
assert_eq!(vec.into_vec(), vec![0, 1, 2]);
}
#[test]
fn test_into_inner() {
let vec = SmallVec::<[u8; 2]>::from_iter(0..2);
assert_eq!(vec.into_inner(), Ok([0, 1]));
let vec = SmallVec::<[u8; 2]>::from_iter(0..1);
assert_eq!(vec.clone().into_inner(), Err(vec));
let vec = SmallVec::<[u8; 2]>::from_iter(0..3);
assert_eq!(vec.clone().into_inner(), Err(vec));
}
#[test]
fn test_from_vec() {
let vec = vec![];
let small_vec: SmallVec<[u8; 3]> = SmallVec::from_vec(vec);
assert_eq!(&*small_vec, &[]);
drop(small_vec);
let vec = vec![];
let small_vec: SmallVec<[u8; 1]> = SmallVec::from_vec(vec);
assert_eq!(&*small_vec, &[]);
drop(small_vec);
let vec = vec![1];
let small_vec: SmallVec<[u8; 3]> = SmallVec::from_vec(vec);
assert_eq!(&*small_vec, &[1]);
drop(small_vec);
let vec = vec![1, 2, 3];
let small_vec: SmallVec<[u8; 3]> = SmallVec::from_vec(vec);
assert_eq!(&*small_vec, &[1, 2, 3]);
drop(small_vec);
let vec = vec![1, 2, 3, 4, 5];
let small_vec: SmallVec<[u8; 3]> = SmallVec::from_vec(vec);
assert_eq!(&*small_vec, &[1, 2, 3, 4, 5]);
drop(small_vec);
let vec = vec![1, 2, 3, 4, 5];
let small_vec: SmallVec<[u8; 1]> = SmallVec::from_vec(vec);
assert_eq!(&*small_vec, &[1, 2, 3, 4, 5]);
drop(small_vec);
}
#[test]
fn test_retain() {
// Test inline data storate
let mut sv: SmallVec<[i32; 5]> = SmallVec::from_slice(&[1, 2, 3, 3, 4]);
sv.retain(|&mut i| i != 3);
assert_eq!(sv.pop(), Some(4));
assert_eq!(sv.pop(), Some(2));
assert_eq!(sv.pop(), Some(1));
assert_eq!(sv.pop(), None);
// Test spilled data storage
let mut sv: SmallVec<[i32; 3]> = SmallVec::from_slice(&[1, 2, 3, 3, 4]);
sv.retain(|&mut i| i != 3);
assert_eq!(sv.pop(), Some(4));
assert_eq!(sv.pop(), Some(2));
assert_eq!(sv.pop(), Some(1));
assert_eq!(sv.pop(), None);
// Test that drop implementations are called for inline.
let one = Rc::new(1);
let mut sv: SmallVec<[Rc<i32>; 3]> = SmallVec::new();
sv.push(Rc::clone(&one));
assert_eq!(Rc::strong_count(&one), 2);
sv.retain(|_| false);
assert_eq!(Rc::strong_count(&one), 1);
// Test that drop implementations are called for spilled data.
let mut sv: SmallVec<[Rc<i32>; 1]> = SmallVec::new();
sv.push(Rc::clone(&one));
sv.push(Rc::new(2));
assert_eq!(Rc::strong_count(&one), 2);
sv.retain(|_| false);
assert_eq!(Rc::strong_count(&one), 1);
}
#[test]
fn test_dedup() {
let mut dupes: SmallVec<[i32; 5]> = SmallVec::from_slice(&[1, 1, 2, 3, 3]);
dupes.dedup();
assert_eq!(&*dupes, &[1, 2, 3]);
let mut empty: SmallVec<[i32; 5]> = SmallVec::new();
empty.dedup();
assert!(empty.is_empty());
let mut all_ones: SmallVec<[i32; 5]> = SmallVec::from_slice(&[1, 1, 1, 1, 1]);
all_ones.dedup();
assert_eq!(all_ones.len(), 1);
let mut no_dupes: SmallVec<[i32; 5]> = SmallVec::from_slice(&[1, 2, 3, 4, 5]);
no_dupes.dedup();
assert_eq!(no_dupes.len(), 5);
}
#[test]
fn test_resize() {
let mut v: SmallVec<[i32; 8]> = SmallVec::new();
v.push(1);
v.resize(5, 0);
assert_eq!(v[..], [1, 0, 0, 0, 0][..]);
v.resize(2, -1);
assert_eq!(v[..], [1, 0][..]);
}
#[cfg(feature = "write")]
#[test]
fn test_write() {
use std::io::Write;
let data = [1, 2, 3, 4, 5];
let mut small_vec: SmallVec<[u8; 2]> = SmallVec::new();
let len = small_vec.write(&data[..]).unwrap();
assert_eq!(len, 5);
assert_eq!(small_vec.as_ref(), data.as_ref());
let mut small_vec: SmallVec<[u8; 2]> = SmallVec::new();
small_vec.write_all(&data[..]).unwrap();
assert_eq!(small_vec.as_ref(), data.as_ref());
}
#[cfg(feature = "serde")]
extern crate bincode;
#[cfg(feature = "serde")]
#[test]
fn test_serde() {
use self::bincode::{config, deserialize};
let mut small_vec: SmallVec<[i32; 2]> = SmallVec::new();
small_vec.push(1);
let encoded = config().limit(100).serialize(&small_vec).unwrap();
let decoded: SmallVec<[i32; 2]> = deserialize(&encoded).unwrap();
assert_eq!(small_vec, decoded);
small_vec.push(2);
// Spill the vec
small_vec.push(3);
small_vec.push(4);
// Check again after spilling.
let encoded = config().limit(100).serialize(&small_vec).unwrap();
let decoded: SmallVec<[i32; 2]> = deserialize(&encoded).unwrap();
assert_eq!(small_vec, decoded);
}
#[test]
fn grow_to_shrink() {
let mut v: SmallVec<[u8; 2]> = SmallVec::new();
v.push(1);
v.push(2);
v.push(3);
assert!(v.spilled());
v.clear();
// Shrink to inline.
v.grow(2);
assert!(!v.spilled());
assert_eq!(v.capacity(), 2);
assert_eq!(v.len(), 0);
v.push(4);
assert_eq!(v[..], [4]);
}
#[test]
fn resumable_extend() {
let s = "a b c";
// This iterator yields: (Some('a'), None, Some('b'), None, Some('c')), None
let it = s
.chars()
.scan(0, |_, ch| if ch.is_whitespace() { None } else { Some(ch) });
let mut v: SmallVec<[char; 4]> = SmallVec::new();
v.extend(it);
assert_eq!(v[..], ['a']);
}
// #139
#[test]
fn uninhabited() {
enum Void {}
let _sv = SmallVec::<[Void; 8]>::new();
}
#[test]
fn grow_spilled_same_size() {
let mut v: SmallVec<[u8; 2]> = SmallVec::new();
v.push(0);
v.push(1);
v.push(2);
assert!(v.spilled());
assert_eq!(v.capacity(), 4);
// grow with the same capacity
v.grow(4);
assert_eq!(v.capacity(), 4);
assert_eq!(v[..], [0, 1, 2]);
}
#[cfg(feature = "const_generics")]
#[test]
fn const_generics() {
let _v = SmallVec::<[i32; 987]>::default();
}
#[test]
fn empty_macro() {
let _v: SmallVec<[u8; 1]> = smallvec![];
}
#[test]
fn zero_size_items() {
SmallVec::<[(); 0]>::new().push(());
}

View File

@ -1,24 +0,0 @@
/// This file tests `smallvec!` without actually having the macro in scope.
/// This forces any recursion to use a `$crate` prefix to reliably find itself.
#[test]
fn smallvec() {
let mut vec: smallvec::SmallVec<[i32; 2]>;
macro_rules! check {
($init:tt) => {
vec = smallvec::smallvec! $init;
assert_eq!(*vec, *vec! $init);
}
}
check!([0; 0]);
check!([1; 1]);
check!([2; 2]);
check!([3; 3]);
check!([]);
check!([1]);
check!([1, 2]);
check!([1, 2, 3]);
}