1
Fork 0

Auto merge of #96622 - JohnTitor:rollup-8hckgaj, r=JohnTitor

Rollup of 7 pull requests

Successful merges:

 - #94126 (Classify BinaryHeap & LinkedList unit tests as such)
 - #96222 (Clarify docs for `from_raw_parts` on `Vec` and `String`)
 - #96499 (Make it possible to write doctests for bootstrap)
 - #96567 (Fix docs for u32 and i32 logs func)
 - #96568 (std::fmt: Various fixes and improvements to documentation)
 - #96571 (Add a bathroom stall to weird expressions test)
 - #96610 (Update browser-ui-test version to 0.9.0)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2022-05-02 03:28:14 +00:00
commit f6cbc92e2a
14 changed files with 756 additions and 723 deletions

View file

@ -155,6 +155,9 @@ use crate::vec::{self, AsVecIntoIter, Vec};
use super::SpecExtend;
#[cfg(test)]
mod tests;
/// A priority queue implemented with a binary heap.
///
/// This will be a max-heap.

View file

@ -1,5 +1,5 @@
use std::collections::binary_heap::{Drain, PeekMut};
use std::collections::BinaryHeap;
use super::*;
use crate::boxed::Box;
use std::iter::TrustedLen;
use std::panic::{catch_unwind, AssertUnwindSafe};
use std::sync::atomic::{AtomicU32, Ordering};

View file

@ -1,10 +1,55 @@
use super::*;
use crate::vec::Vec;
use std::panic::{catch_unwind, AssertUnwindSafe};
use std::thread;
use std::vec::Vec;
use rand::{thread_rng, RngCore};
#[test]
fn test_basic() {
let mut m = LinkedList::<Box<_>>::new();
assert_eq!(m.pop_front(), None);
assert_eq!(m.pop_back(), None);
assert_eq!(m.pop_front(), None);
m.push_front(box 1);
assert_eq!(m.pop_front(), Some(box 1));
m.push_back(box 2);
m.push_back(box 3);
assert_eq!(m.len(), 2);
assert_eq!(m.pop_front(), Some(box 2));
assert_eq!(m.pop_front(), Some(box 3));
assert_eq!(m.len(), 0);
assert_eq!(m.pop_front(), None);
m.push_back(box 1);
m.push_back(box 3);
m.push_back(box 5);
m.push_back(box 7);
assert_eq!(m.pop_front(), Some(box 1));
let mut n = LinkedList::new();
n.push_front(2);
n.push_front(3);
{
assert_eq!(n.front().unwrap(), &3);
let x = n.front_mut().unwrap();
assert_eq!(*x, 3);
*x = 0;
}
{
assert_eq!(n.back().unwrap(), &2);
let y = n.back_mut().unwrap();
assert_eq!(*y, 2);
*y = 1;
}
assert_eq!(n.pop_front(), Some(0));
assert_eq!(n.pop_front(), Some(1));
}
fn generate_test() -> LinkedList<i32> {
list_from(&[0, 1, 2, 3, 4, 5, 6])
}
fn list_from<T: Clone>(v: &[T]) -> LinkedList<T> {
v.iter().cloned().collect()
}
@ -110,6 +155,123 @@ fn test_append() {
check_links(&n);
}
#[test]
fn test_iterator() {
let m = generate_test();
for (i, elt) in m.iter().enumerate() {
assert_eq!(i as i32, *elt);
}
let mut n = LinkedList::new();
assert_eq!(n.iter().next(), None);
n.push_front(4);
let mut it = n.iter();
assert_eq!(it.size_hint(), (1, Some(1)));
assert_eq!(it.next().unwrap(), &4);
assert_eq!(it.size_hint(), (0, Some(0)));
assert_eq!(it.next(), None);
}
#[test]
fn test_iterator_clone() {
let mut n = LinkedList::new();
n.push_back(2);
n.push_back(3);
n.push_back(4);
let mut it = n.iter();
it.next();
let mut jt = it.clone();
assert_eq!(it.next(), jt.next());
assert_eq!(it.next_back(), jt.next_back());
assert_eq!(it.next(), jt.next());
}
#[test]
fn test_iterator_double_end() {
let mut n = LinkedList::new();
assert_eq!(n.iter().next(), None);
n.push_front(4);
n.push_front(5);
n.push_front(6);
let mut it = n.iter();
assert_eq!(it.size_hint(), (3, Some(3)));
assert_eq!(it.next().unwrap(), &6);
assert_eq!(it.size_hint(), (2, Some(2)));
assert_eq!(it.next_back().unwrap(), &4);
assert_eq!(it.size_hint(), (1, Some(1)));
assert_eq!(it.next_back().unwrap(), &5);
assert_eq!(it.next_back(), None);
assert_eq!(it.next(), None);
}
#[test]
fn test_rev_iter() {
let m = generate_test();
for (i, elt) in m.iter().rev().enumerate() {
assert_eq!((6 - i) as i32, *elt);
}
let mut n = LinkedList::new();
assert_eq!(n.iter().rev().next(), None);
n.push_front(4);
let mut it = n.iter().rev();
assert_eq!(it.size_hint(), (1, Some(1)));
assert_eq!(it.next().unwrap(), &4);
assert_eq!(it.size_hint(), (0, Some(0)));
assert_eq!(it.next(), None);
}
#[test]
fn test_mut_iter() {
let mut m = generate_test();
let mut len = m.len();
for (i, elt) in m.iter_mut().enumerate() {
assert_eq!(i as i32, *elt);
len -= 1;
}
assert_eq!(len, 0);
let mut n = LinkedList::new();
assert!(n.iter_mut().next().is_none());
n.push_front(4);
n.push_back(5);
let mut it = n.iter_mut();
assert_eq!(it.size_hint(), (2, Some(2)));
assert!(it.next().is_some());
assert!(it.next().is_some());
assert_eq!(it.size_hint(), (0, Some(0)));
assert!(it.next().is_none());
}
#[test]
fn test_iterator_mut_double_end() {
let mut n = LinkedList::new();
assert!(n.iter_mut().next_back().is_none());
n.push_front(4);
n.push_front(5);
n.push_front(6);
let mut it = n.iter_mut();
assert_eq!(it.size_hint(), (3, Some(3)));
assert_eq!(*it.next().unwrap(), 6);
assert_eq!(it.size_hint(), (2, Some(2)));
assert_eq!(*it.next_back().unwrap(), 4);
assert_eq!(it.size_hint(), (1, Some(1)));
assert_eq!(*it.next_back().unwrap(), 5);
assert!(it.next_back().is_none());
assert!(it.next().is_none());
}
#[test]
fn test_mut_rev_iter() {
let mut m = generate_test();
for (i, elt) in m.iter_mut().rev().enumerate() {
assert_eq!((6 - i) as i32, *elt);
}
let mut n = LinkedList::new();
assert!(n.iter_mut().rev().next().is_none());
n.push_front(4);
let mut it = n.iter_mut().rev();
assert!(it.next().is_some());
assert!(it.next().is_none());
}
#[test]
fn test_clone_from() {
// Short cloned from long
@ -168,13 +330,60 @@ fn test_send() {
}
#[test]
fn test_fuzz() {
for _ in 0..25 {
fuzz_test(3);
fuzz_test(16);
#[cfg(not(miri))] // Miri is too slow
fuzz_test(189);
}
fn test_eq() {
let mut n = list_from(&[]);
let mut m = list_from(&[]);
assert!(n == m);
n.push_front(1);
assert!(n != m);
m.push_back(1);
assert!(n == m);
let n = list_from(&[2, 3, 4]);
let m = list_from(&[1, 2, 3]);
assert!(n != m);
}
#[test]
fn test_ord() {
let n = list_from(&[]);
let m = list_from(&[1, 2, 3]);
assert!(n < m);
assert!(m > n);
assert!(n <= n);
assert!(n >= n);
}
#[test]
fn test_ord_nan() {
let nan = 0.0f64 / 0.0;
let n = list_from(&[nan]);
let m = list_from(&[nan]);
assert!(!(n < m));
assert!(!(n > m));
assert!(!(n <= m));
assert!(!(n >= m));
let n = list_from(&[nan]);
let one = list_from(&[1.0f64]);
assert!(!(n < one));
assert!(!(n > one));
assert!(!(n <= one));
assert!(!(n >= one));
let u = list_from(&[1.0f64, 2.0, nan]);
let v = list_from(&[1.0f64, 2.0, 3.0]);
assert!(!(u < v));
assert!(!(u > v));
assert!(!(u <= v));
assert!(!(u >= v));
let s = list_from(&[1.0f64, 2.0, 4.0, 2.0]);
let t = list_from(&[1.0f64, 2.0, 3.0, 2.0]);
assert!(!(s < t));
assert!(s > one);
assert!(!(s <= one));
assert!(s >= one);
}
#[test]
@ -215,6 +424,62 @@ fn test_split_off() {
}
}
#[test]
fn test_split_off_2() {
// singleton
{
let mut m = LinkedList::new();
m.push_back(1);
let p = m.split_off(0);
assert_eq!(m.len(), 0);
assert_eq!(p.len(), 1);
assert_eq!(p.back(), Some(&1));
assert_eq!(p.front(), Some(&1));
}
// not singleton, forwards
{
let u = vec![1, 2, 3, 4, 5];
let mut m = list_from(&u);
let mut n = m.split_off(2);
assert_eq!(m.len(), 2);
assert_eq!(n.len(), 3);
for elt in 1..3 {
assert_eq!(m.pop_front(), Some(elt));
}
for elt in 3..6 {
assert_eq!(n.pop_front(), Some(elt));
}
}
// not singleton, backwards
{
let u = vec![1, 2, 3, 4, 5];
let mut m = list_from(&u);
let mut n = m.split_off(4);
assert_eq!(m.len(), 4);
assert_eq!(n.len(), 1);
for elt in 1..5 {
assert_eq!(m.pop_front(), Some(elt));
}
for elt in 5..6 {
assert_eq!(n.pop_front(), Some(elt));
}
}
// no-op on the last index
{
let mut m = LinkedList::new();
m.push_back(1);
let p = m.split_off(1);
assert_eq!(m.len(), 1);
assert_eq!(p.len(), 0);
assert_eq!(m.back(), Some(&1));
assert_eq!(m.front(), Some(&1));
}
}
fn fuzz_test(sz: i32) {
let mut m: LinkedList<_> = LinkedList::new();
let mut v = vec![];
@ -253,6 +518,25 @@ fn fuzz_test(sz: i32) {
assert_eq!(i, v.len());
}
#[test]
fn test_fuzz() {
for _ in 0..25 {
fuzz_test(3);
fuzz_test(16);
#[cfg(not(miri))] // Miri is too slow
fuzz_test(189);
}
}
#[test]
fn test_show() {
let list: LinkedList<_> = (0..10).collect();
assert_eq!(format!("{list:?}"), "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]");
let list: LinkedList<_> = ["just", "one", "test", "more"].into_iter().collect();
assert_eq!(format!("{list:?}"), "[\"just\", \"one\", \"test\", \"more\"]");
}
#[test]
fn drain_filter_test() {
let mut m: LinkedList<u32> = LinkedList::new();
@ -475,3 +759,398 @@ fn test_cursor_pop_front_back() {
assert_eq!(c.current(), None);
assert_eq!(c.index, 2);
}
#[test]
fn test_extend_ref() {
let mut a = LinkedList::new();
a.push_back(1);
a.extend(&[2, 3, 4]);
assert_eq!(a.len(), 4);
assert_eq!(a, list_from(&[1, 2, 3, 4]));
let mut b = LinkedList::new();
b.push_back(5);
b.push_back(6);
a.extend(&b);
assert_eq!(a.len(), 6);
assert_eq!(a, list_from(&[1, 2, 3, 4, 5, 6]));
}
#[test]
fn test_extend() {
let mut a = LinkedList::new();
a.push_back(1);
a.extend(vec![2, 3, 4]); // uses iterator
assert_eq!(a.len(), 4);
assert!(a.iter().eq(&[1, 2, 3, 4]));
let b: LinkedList<_> = [5, 6, 7].into_iter().collect();
a.extend(b); // specializes to `append`
assert_eq!(a.len(), 7);
assert!(a.iter().eq(&[1, 2, 3, 4, 5, 6, 7]));
}
#[test]
fn test_contains() {
let mut l = LinkedList::new();
l.extend(&[2, 3, 4]);
assert!(l.contains(&3));
assert!(!l.contains(&1));
l.clear();
assert!(!l.contains(&3));
}
#[test]
fn drain_filter_empty() {
let mut list: LinkedList<i32> = LinkedList::new();
{
let mut iter = list.drain_filter(|_| true);
assert_eq!(iter.size_hint(), (0, Some(0)));
assert_eq!(iter.next(), None);
assert_eq!(iter.size_hint(), (0, Some(0)));
assert_eq!(iter.next(), None);
assert_eq!(iter.size_hint(), (0, Some(0)));
}
assert_eq!(list.len(), 0);
assert_eq!(list.into_iter().collect::<Vec<_>>(), vec![]);
}
#[test]
fn drain_filter_zst() {
let mut list: LinkedList<_> = [(), (), (), (), ()].into_iter().collect();
let initial_len = list.len();
let mut count = 0;
{
let mut iter = list.drain_filter(|_| true);
assert_eq!(iter.size_hint(), (0, Some(initial_len)));
while let Some(_) = iter.next() {
count += 1;
assert_eq!(iter.size_hint(), (0, Some(initial_len - count)));
}
assert_eq!(iter.size_hint(), (0, Some(0)));
assert_eq!(iter.next(), None);
assert_eq!(iter.size_hint(), (0, Some(0)));
}
assert_eq!(count, initial_len);
assert_eq!(list.len(), 0);
assert_eq!(list.into_iter().collect::<Vec<_>>(), vec![]);
}
#[test]
fn drain_filter_false() {
let mut list: LinkedList<_> = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].into_iter().collect();
let initial_len = list.len();
let mut count = 0;
{
let mut iter = list.drain_filter(|_| false);
assert_eq!(iter.size_hint(), (0, Some(initial_len)));
for _ in iter.by_ref() {
count += 1;
}
assert_eq!(iter.size_hint(), (0, Some(0)));
assert_eq!(iter.next(), None);
assert_eq!(iter.size_hint(), (0, Some(0)));
}
assert_eq!(count, 0);
assert_eq!(list.len(), initial_len);
assert_eq!(list.into_iter().collect::<Vec<_>>(), vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
}
#[test]
fn drain_filter_true() {
let mut list: LinkedList<_> = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].into_iter().collect();
let initial_len = list.len();
let mut count = 0;
{
let mut iter = list.drain_filter(|_| true);
assert_eq!(iter.size_hint(), (0, Some(initial_len)));
while let Some(_) = iter.next() {
count += 1;
assert_eq!(iter.size_hint(), (0, Some(initial_len - count)));
}
assert_eq!(iter.size_hint(), (0, Some(0)));
assert_eq!(iter.next(), None);
assert_eq!(iter.size_hint(), (0, Some(0)));
}
assert_eq!(count, initial_len);
assert_eq!(list.len(), 0);
assert_eq!(list.into_iter().collect::<Vec<_>>(), vec![]);
}
#[test]
fn drain_filter_complex() {
{
// [+xxx++++++xxxxx++++x+x++]
let mut list = [
1, 2, 4, 6, 7, 9, 11, 13, 15, 17, 18, 20, 22, 24, 26, 27, 29, 31, 33, 34, 35, 36, 37,
39,
]
.into_iter()
.collect::<LinkedList<_>>();
let removed = list.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>();
assert_eq!(removed.len(), 10);
assert_eq!(removed, vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]);
assert_eq!(list.len(), 14);
assert_eq!(
list.into_iter().collect::<Vec<_>>(),
vec![1, 7, 9, 11, 13, 15, 17, 27, 29, 31, 33, 35, 37, 39]
);
}
{
// [xxx++++++xxxxx++++x+x++]
let mut list =
[2, 4, 6, 7, 9, 11, 13, 15, 17, 18, 20, 22, 24, 26, 27, 29, 31, 33, 34, 35, 36, 37, 39]
.into_iter()
.collect::<LinkedList<_>>();
let removed = list.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>();
assert_eq!(removed.len(), 10);
assert_eq!(removed, vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]);
assert_eq!(list.len(), 13);
assert_eq!(
list.into_iter().collect::<Vec<_>>(),
vec![7, 9, 11, 13, 15, 17, 27, 29, 31, 33, 35, 37, 39]
);
}
{
// [xxx++++++xxxxx++++x+x]
let mut list =
[2, 4, 6, 7, 9, 11, 13, 15, 17, 18, 20, 22, 24, 26, 27, 29, 31, 33, 34, 35, 36]
.into_iter()
.collect::<LinkedList<_>>();
let removed = list.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>();
assert_eq!(removed.len(), 10);
assert_eq!(removed, vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]);
assert_eq!(list.len(), 11);
assert_eq!(
list.into_iter().collect::<Vec<_>>(),
vec![7, 9, 11, 13, 15, 17, 27, 29, 31, 33, 35]
);
}
{
// [xxxxxxxxxx+++++++++++]
let mut list = [2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
.into_iter()
.collect::<LinkedList<_>>();
let removed = list.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>();
assert_eq!(removed.len(), 10);
assert_eq!(removed, vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20]);
assert_eq!(list.len(), 10);
assert_eq!(list.into_iter().collect::<Vec<_>>(), vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19]);
}
{
// [+++++++++++xxxxxxxxxx]
let mut list = [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
.into_iter()
.collect::<LinkedList<_>>();
let removed = list.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>();
assert_eq!(removed.len(), 10);
assert_eq!(removed, vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20]);
assert_eq!(list.len(), 10);
assert_eq!(list.into_iter().collect::<Vec<_>>(), vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19]);
}
}
#[test]
fn drain_filter_drop_panic_leak() {
static mut DROPS: i32 = 0;
struct D(bool);
impl Drop for D {
fn drop(&mut self) {
unsafe {
DROPS += 1;
}
if self.0 {
panic!("panic in `drop`");
}
}
}
let mut q = LinkedList::new();
q.push_back(D(false));
q.push_back(D(false));
q.push_back(D(false));
q.push_back(D(false));
q.push_back(D(false));
q.push_front(D(false));
q.push_front(D(true));
q.push_front(D(false));
catch_unwind(AssertUnwindSafe(|| drop(q.drain_filter(|_| true)))).ok();
assert_eq!(unsafe { DROPS }, 8);
assert!(q.is_empty());
}
#[test]
fn drain_filter_pred_panic_leak() {
static mut DROPS: i32 = 0;
#[derive(Debug)]
struct D(u32);
impl Drop for D {
fn drop(&mut self) {
unsafe {
DROPS += 1;
}
}
}
let mut q = LinkedList::new();
q.push_back(D(3));
q.push_back(D(4));
q.push_back(D(5));
q.push_back(D(6));
q.push_back(D(7));
q.push_front(D(2));
q.push_front(D(1));
q.push_front(D(0));
catch_unwind(AssertUnwindSafe(|| {
drop(q.drain_filter(|item| if item.0 >= 2 { panic!() } else { true }))
}))
.ok();
assert_eq!(unsafe { DROPS }, 2); // 0 and 1
assert_eq!(q.len(), 6);
}
#[test]
fn test_drop() {
static mut DROPS: i32 = 0;
struct Elem;
impl Drop for Elem {
fn drop(&mut self) {
unsafe {
DROPS += 1;
}
}
}
let mut ring = LinkedList::new();
ring.push_back(Elem);
ring.push_front(Elem);
ring.push_back(Elem);
ring.push_front(Elem);
drop(ring);
assert_eq!(unsafe { DROPS }, 4);
}
#[test]
fn test_drop_with_pop() {
static mut DROPS: i32 = 0;
struct Elem;
impl Drop for Elem {
fn drop(&mut self) {
unsafe {
DROPS += 1;
}
}
}
let mut ring = LinkedList::new();
ring.push_back(Elem);
ring.push_front(Elem);
ring.push_back(Elem);
ring.push_front(Elem);
drop(ring.pop_back());
drop(ring.pop_front());
assert_eq!(unsafe { DROPS }, 2);
drop(ring);
assert_eq!(unsafe { DROPS }, 4);
}
#[test]
fn test_drop_clear() {
static mut DROPS: i32 = 0;
struct Elem;
impl Drop for Elem {
fn drop(&mut self) {
unsafe {
DROPS += 1;
}
}
}
let mut ring = LinkedList::new();
ring.push_back(Elem);
ring.push_front(Elem);
ring.push_back(Elem);
ring.push_front(Elem);
ring.clear();
assert_eq!(unsafe { DROPS }, 4);
drop(ring);
assert_eq!(unsafe { DROPS }, 4);
}
#[test]
fn test_drop_panic() {
static mut DROPS: i32 = 0;
struct D(bool);
impl Drop for D {
fn drop(&mut self) {
unsafe {
DROPS += 1;
}
if self.0 {
panic!("panic in `drop`");
}
}
}
let mut q = LinkedList::new();
q.push_back(D(false));
q.push_back(D(false));
q.push_back(D(false));
q.push_back(D(false));
q.push_back(D(false));
q.push_front(D(false));
q.push_front(D(false));
q.push_front(D(true));
catch_unwind(move || drop(q)).ok();
assert_eq!(unsafe { DROPS }, 8);
}

View file

@ -221,10 +221,12 @@
//!
//! 3. An asterisk `.*`:
//!
//! `.*` means that this `{...}` is associated with *two* format inputs rather than one: the
//! first input holds the `usize` precision, and the second holds the value to print. Note that
//! in this case, if one uses the format string `{<arg>:<spec>.*}`, then the `<arg>` part refers
//! to the *value* to print, and the `precision` must come in the input preceding `<arg>`.
//! `.*` means that this `{...}` is associated with *two* format inputs rather than one:
//! - If a format string in the fashion of `{:<spec>.*}` is used, then the first input holds
//! the `usize` precision, and the second holds the value to print.
//! - If a format string in the fashion of `{<arg>:<spec>.*}` is used, then the `<arg>` part
//! refers to the value to print, and the `precision` is taken like it was specified with an
//! omitted positional parameter (`{}` instead of `{<arg>:}`).
//!
//! For example, the following calls all print the same thing `Hello x is 0.01000`:
//!
@ -238,15 +240,19 @@
//! // Hello {arg 0 ("x")} is {arg 2 (0.01) with precision specified in arg 1 (5)}
//! println!("Hello {0} is {2:.1$}", "x", 5, 0.01);
//!
//! // Hello {next arg ("x")} is {second of next two args (0.01) with precision
//! // specified in first of next two args (5)}
//! // Hello {next arg -> arg 0 ("x")} is {second of next two args -> arg 2 (0.01) with precision
//! // specified in first of next two args -> arg 1 (5)}
//! println!("Hello {} is {:.*}", "x", 5, 0.01);
//!
//! // Hello {next arg ("x")} is {arg 2 (0.01) with precision
//! // specified in its predecessor (5)}
//! // Hello {arg 1 ("x")} is {arg 2 (0.01) with precision
//! // specified in next arg -> arg 0 (5)}
//! println!("Hello {1} is {2:.*}", 5, "x", 0.01);
//!
//! // Hello {next arg -> arg 0 ("x")} is {arg 2 (0.01) with precision
//! // specified in next arg -> arg 1 (5)}
//! println!("Hello {} is {2:.*}", "x", 5, 0.01);
//!
//! // Hello {next arg ("x")} is {arg "number" (0.01) with precision specified
//! // Hello {next arg -> arg 0 ("x")} is {arg "number" (0.01) with precision specified
//! // in arg "prec" (5)}
//! println!("Hello {} is {number:.prec$}", "x", prec = 5, number = 0.01);
//! ```
@ -304,7 +310,7 @@
//! ```text
//! format_string := text [ maybe_format text ] *
//! maybe_format := '{' '{' | '}' '}' | format
//! format := '{' [ argument ] [ ':' format_spec ] '}'
//! format := '{' [ argument ] [ ':' format_spec ] [ ws ] * '}'
//! argument := integer | identifier
//!
//! format_spec := [[fill]align][sign]['#']['0'][width]['.' precision]type
@ -317,7 +323,12 @@
//! count := parameter | integer
//! parameter := argument '$'
//! ```
//! In the above grammar, `text` must not contain any `'{'` or `'}'` characters.
//! In the above grammar,
//! - `text` must not contain any `'{'` or `'}'` characters,
//! - `ws` is any character for which [`char::is_whitespace`] returns `true`, has no semantic
//! meaning and is completely optional,
//! - `integer` is a decimal integer that may contain leading zeroes and
//! - `identifier` is an `IDENTIFIER_OR_KEYWORD` (not an `IDENTIFIER`) as defined by the [Rust language reference](https://doc.rust-lang.org/reference/identifiers.html).
//!
//! # Formatting traits
//!
@ -358,9 +369,9 @@
//! ```
//!
//! Your type will be passed as `self` by-reference, and then the function
//! should emit output into the `f.buf` stream. It is up to each format trait
//! implementation to correctly adhere to the requested formatting parameters.
//! The values of these parameters will be listed in the fields of the
//! should emit output into the Formatter `f` which implements `fmt::Write`. It is up to each
//! format trait implementation to correctly adhere to the requested formatting parameters.
//! The values of these parameters can be accessed with methods of the
//! [`Formatter`] struct. In order to help with this, the [`Formatter`] struct also
//! provides some helper methods.
//!
@ -449,7 +460,7 @@
//!
//! ```ignore (only-for-syntax-highlight)
//! format! // described above
//! write! // first argument is a &mut io::Write, the destination
//! write! // first argument is either a &mut io::Write or a &mut fmt::Write, the destination
//! writeln! // same as write but appends a newline
//! print! // the format string is printed to the standard output
//! println! // same as print but appends a newline
@ -460,11 +471,11 @@
//!
//! ### `write!`
//!
//! This and [`writeln!`] are two macros which are used to emit the format string
//! [`write!`] and [`writeln!`] are two macros which are used to emit the format string
//! to a specified stream. This is used to prevent intermediate allocations of
//! format strings and instead directly write the output. Under the hood, this
//! function is actually invoking the [`write_fmt`] function defined on the
//! [`std::io::Write`] trait. Example usage is:
//! [`std::io::Write`] and the [`std::fmt::Write`] trait. Example usage is:
//!
//! ```
//! # #![allow(unused_must_use)]
@ -491,7 +502,7 @@
//!
//! ### `format_args!`
//!
//! This is a curious macro used to safely pass around
//! [`format_args!`] is a curious macro used to safely pass around
//! an opaque object describing the format string. This object
//! does not require any heap allocations to create, and it only
//! references information on the stack. Under the hood, all of
@ -529,10 +540,12 @@
//! [`to_string`]: crate::string::ToString::to_string "ToString::to_string"
//! [`write_fmt`]: ../../std/io/trait.Write.html#method.write_fmt
//! [`std::io::Write`]: ../../std/io/trait.Write.html
//! [`std::fmt::Write`]: ../../std/fmt/trait.Write.html
//! [`print!`]: ../../std/macro.print.html "print!"
//! [`println!`]: ../../std/macro.println.html "println!"
//! [`eprint!`]: ../../std/macro.eprint.html "eprint!"
//! [`eprintln!`]: ../../std/macro.eprintln.html "eprintln!"
//! [`format_args!`]: ../../std/macro.format_args.html "format_args!"
//! [`fmt::Arguments`]: Arguments "fmt::Arguments"
//! [`format`]: format() "fmt::format"

View file

@ -770,7 +770,10 @@ impl String {
/// * The first `length` bytes at `buf` need to be valid UTF-8.
///
/// Violating these may cause problems like corrupting the allocator's
/// internal data structures.
/// internal data structures. For example, it is normally **not** safe to
/// build a `String` from a pointer to a C `char` array containing UTF-8
/// _unless_ you are certain that array was originally allocated by the
/// Rust standard library's allocator.
///
/// The ownership of `buf` is effectively transferred to the
/// `String` which may then deallocate, reallocate or change the

View file

@ -489,8 +489,10 @@ impl<T> Vec<T> {
/// * `length` needs to be less than or equal to `capacity`.
///
/// Violating these may cause problems like corrupting the allocator's
/// internal data structures. For example it is **not** safe
/// to build a `Vec<u8>` from a pointer to a C `char` array with length `size_t`.
/// internal data structures. For example it is normally **not** safe
/// to build a `Vec<u8>` from a pointer to a C `char` array with length
/// `size_t`, doing so is only safe if the array was initially allocated by
/// a `Vec` or `String`.
/// It's also not safe to build one from a `Vec<u16>` and its length, because
/// the allocator cares about the alignment, and these two types have different
/// alignments. The buffer was allocated with alignment 2 (for `u16`), but after

View file

@ -47,7 +47,6 @@ use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
mod arc;
mod binary_heap;
mod borrow;
mod boxed;
mod btree_set_hash;

View file

@ -1,241 +1,4 @@
use std::collections::LinkedList;
use std::panic::{catch_unwind, AssertUnwindSafe};
#[test]
fn test_basic() {
let mut m = LinkedList::<Box<_>>::new();
assert_eq!(m.pop_front(), None);
assert_eq!(m.pop_back(), None);
assert_eq!(m.pop_front(), None);
m.push_front(box 1);
assert_eq!(m.pop_front(), Some(box 1));
m.push_back(box 2);
m.push_back(box 3);
assert_eq!(m.len(), 2);
assert_eq!(m.pop_front(), Some(box 2));
assert_eq!(m.pop_front(), Some(box 3));
assert_eq!(m.len(), 0);
assert_eq!(m.pop_front(), None);
m.push_back(box 1);
m.push_back(box 3);
m.push_back(box 5);
m.push_back(box 7);
assert_eq!(m.pop_front(), Some(box 1));
let mut n = LinkedList::new();
n.push_front(2);
n.push_front(3);
{
assert_eq!(n.front().unwrap(), &3);
let x = n.front_mut().unwrap();
assert_eq!(*x, 3);
*x = 0;
}
{
assert_eq!(n.back().unwrap(), &2);
let y = n.back_mut().unwrap();
assert_eq!(*y, 2);
*y = 1;
}
assert_eq!(n.pop_front(), Some(0));
assert_eq!(n.pop_front(), Some(1));
}
fn generate_test() -> LinkedList<i32> {
list_from(&[0, 1, 2, 3, 4, 5, 6])
}
fn list_from<T: Clone>(v: &[T]) -> LinkedList<T> {
v.iter().cloned().collect()
}
#[test]
fn test_split_off() {
// singleton
{
let mut m = LinkedList::new();
m.push_back(1);
let p = m.split_off(0);
assert_eq!(m.len(), 0);
assert_eq!(p.len(), 1);
assert_eq!(p.back(), Some(&1));
assert_eq!(p.front(), Some(&1));
}
// not singleton, forwards
{
let u = vec![1, 2, 3, 4, 5];
let mut m = list_from(&u);
let mut n = m.split_off(2);
assert_eq!(m.len(), 2);
assert_eq!(n.len(), 3);
for elt in 1..3 {
assert_eq!(m.pop_front(), Some(elt));
}
for elt in 3..6 {
assert_eq!(n.pop_front(), Some(elt));
}
}
// not singleton, backwards
{
let u = vec![1, 2, 3, 4, 5];
let mut m = list_from(&u);
let mut n = m.split_off(4);
assert_eq!(m.len(), 4);
assert_eq!(n.len(), 1);
for elt in 1..5 {
assert_eq!(m.pop_front(), Some(elt));
}
for elt in 5..6 {
assert_eq!(n.pop_front(), Some(elt));
}
}
// no-op on the last index
{
let mut m = LinkedList::new();
m.push_back(1);
let p = m.split_off(1);
assert_eq!(m.len(), 1);
assert_eq!(p.len(), 0);
assert_eq!(m.back(), Some(&1));
assert_eq!(m.front(), Some(&1));
}
}
#[test]
fn test_iterator() {
let m = generate_test();
for (i, elt) in m.iter().enumerate() {
assert_eq!(i as i32, *elt);
}
let mut n = LinkedList::new();
assert_eq!(n.iter().next(), None);
n.push_front(4);
let mut it = n.iter();
assert_eq!(it.size_hint(), (1, Some(1)));
assert_eq!(it.next().unwrap(), &4);
assert_eq!(it.size_hint(), (0, Some(0)));
assert_eq!(it.next(), None);
}
#[test]
fn test_iterator_clone() {
let mut n = LinkedList::new();
n.push_back(2);
n.push_back(3);
n.push_back(4);
let mut it = n.iter();
it.next();
let mut jt = it.clone();
assert_eq!(it.next(), jt.next());
assert_eq!(it.next_back(), jt.next_back());
assert_eq!(it.next(), jt.next());
}
#[test]
fn test_iterator_double_end() {
let mut n = LinkedList::new();
assert_eq!(n.iter().next(), None);
n.push_front(4);
n.push_front(5);
n.push_front(6);
let mut it = n.iter();
assert_eq!(it.size_hint(), (3, Some(3)));
assert_eq!(it.next().unwrap(), &6);
assert_eq!(it.size_hint(), (2, Some(2)));
assert_eq!(it.next_back().unwrap(), &4);
assert_eq!(it.size_hint(), (1, Some(1)));
assert_eq!(it.next_back().unwrap(), &5);
assert_eq!(it.next_back(), None);
assert_eq!(it.next(), None);
}
#[test]
fn test_rev_iter() {
let m = generate_test();
for (i, elt) in m.iter().rev().enumerate() {
assert_eq!((6 - i) as i32, *elt);
}
let mut n = LinkedList::new();
assert_eq!(n.iter().rev().next(), None);
n.push_front(4);
let mut it = n.iter().rev();
assert_eq!(it.size_hint(), (1, Some(1)));
assert_eq!(it.next().unwrap(), &4);
assert_eq!(it.size_hint(), (0, Some(0)));
assert_eq!(it.next(), None);
}
#[test]
fn test_mut_iter() {
let mut m = generate_test();
let mut len = m.len();
for (i, elt) in m.iter_mut().enumerate() {
assert_eq!(i as i32, *elt);
len -= 1;
}
assert_eq!(len, 0);
let mut n = LinkedList::new();
assert!(n.iter_mut().next().is_none());
n.push_front(4);
n.push_back(5);
let mut it = n.iter_mut();
assert_eq!(it.size_hint(), (2, Some(2)));
assert!(it.next().is_some());
assert!(it.next().is_some());
assert_eq!(it.size_hint(), (0, Some(0)));
assert!(it.next().is_none());
}
#[test]
fn test_iterator_mut_double_end() {
let mut n = LinkedList::new();
assert!(n.iter_mut().next_back().is_none());
n.push_front(4);
n.push_front(5);
n.push_front(6);
let mut it = n.iter_mut();
assert_eq!(it.size_hint(), (3, Some(3)));
assert_eq!(*it.next().unwrap(), 6);
assert_eq!(it.size_hint(), (2, Some(2)));
assert_eq!(*it.next_back().unwrap(), 4);
assert_eq!(it.size_hint(), (1, Some(1)));
assert_eq!(*it.next_back().unwrap(), 5);
assert!(it.next_back().is_none());
assert!(it.next().is_none());
}
#[test]
fn test_mut_rev_iter() {
let mut m = generate_test();
for (i, elt) in m.iter_mut().rev().enumerate() {
assert_eq!((6 - i) as i32, *elt);
}
let mut n = LinkedList::new();
assert!(n.iter_mut().rev().next().is_none());
n.push_front(4);
let mut it = n.iter_mut().rev();
assert!(it.next().is_some());
assert!(it.next().is_none());
}
#[test]
fn test_eq() {
let mut n = list_from(&[]);
let mut m = list_from(&[]);
assert!(n == m);
n.push_front(1);
assert!(n != m);
m.push_back(1);
assert!(n == m);
let n = list_from(&[2, 3, 4]);
let m = list_from(&[1, 2, 3]);
assert!(n != m);
}
#[test]
fn test_hash() {
@ -256,449 +19,3 @@ fn test_hash() {
assert!(hash(&x) == hash(&y));
}
#[test]
fn test_ord() {
let n = list_from(&[]);
let m = list_from(&[1, 2, 3]);
assert!(n < m);
assert!(m > n);
assert!(n <= n);
assert!(n >= n);
}
#[test]
fn test_ord_nan() {
let nan = 0.0f64 / 0.0;
let n = list_from(&[nan]);
let m = list_from(&[nan]);
assert!(!(n < m));
assert!(!(n > m));
assert!(!(n <= m));
assert!(!(n >= m));
let n = list_from(&[nan]);
let one = list_from(&[1.0f64]);
assert!(!(n < one));
assert!(!(n > one));
assert!(!(n <= one));
assert!(!(n >= one));
let u = list_from(&[1.0f64, 2.0, nan]);
let v = list_from(&[1.0f64, 2.0, 3.0]);
assert!(!(u < v));
assert!(!(u > v));
assert!(!(u <= v));
assert!(!(u >= v));
let s = list_from(&[1.0f64, 2.0, 4.0, 2.0]);
let t = list_from(&[1.0f64, 2.0, 3.0, 2.0]);
assert!(!(s < t));
assert!(s > one);
assert!(!(s <= one));
assert!(s >= one);
}
#[test]
fn test_show() {
let list: LinkedList<_> = (0..10).collect();
assert_eq!(format!("{list:?}"), "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]");
let list: LinkedList<_> = ["just", "one", "test", "more"].into_iter().collect();
assert_eq!(format!("{list:?}"), "[\"just\", \"one\", \"test\", \"more\"]");
}
#[test]
fn test_extend_ref() {
let mut a = LinkedList::new();
a.push_back(1);
a.extend(&[2, 3, 4]);
assert_eq!(a.len(), 4);
assert_eq!(a, list_from(&[1, 2, 3, 4]));
let mut b = LinkedList::new();
b.push_back(5);
b.push_back(6);
a.extend(&b);
assert_eq!(a.len(), 6);
assert_eq!(a, list_from(&[1, 2, 3, 4, 5, 6]));
}
#[test]
fn test_extend() {
let mut a = LinkedList::new();
a.push_back(1);
a.extend(vec![2, 3, 4]); // uses iterator
assert_eq!(a.len(), 4);
assert!(a.iter().eq(&[1, 2, 3, 4]));
let b: LinkedList<_> = [5, 6, 7].into_iter().collect();
a.extend(b); // specializes to `append`
assert_eq!(a.len(), 7);
assert!(a.iter().eq(&[1, 2, 3, 4, 5, 6, 7]));
}
#[test]
fn test_contains() {
let mut l = LinkedList::new();
l.extend(&[2, 3, 4]);
assert!(l.contains(&3));
assert!(!l.contains(&1));
l.clear();
assert!(!l.contains(&3));
}
#[test]
fn drain_filter_empty() {
let mut list: LinkedList<i32> = LinkedList::new();
{
let mut iter = list.drain_filter(|_| true);
assert_eq!(iter.size_hint(), (0, Some(0)));
assert_eq!(iter.next(), None);
assert_eq!(iter.size_hint(), (0, Some(0)));
assert_eq!(iter.next(), None);
assert_eq!(iter.size_hint(), (0, Some(0)));
}
assert_eq!(list.len(), 0);
assert_eq!(list.into_iter().collect::<Vec<_>>(), vec![]);
}
#[test]
fn drain_filter_zst() {
let mut list: LinkedList<_> = [(), (), (), (), ()].into_iter().collect();
let initial_len = list.len();
let mut count = 0;
{
let mut iter = list.drain_filter(|_| true);
assert_eq!(iter.size_hint(), (0, Some(initial_len)));
while let Some(_) = iter.next() {
count += 1;
assert_eq!(iter.size_hint(), (0, Some(initial_len - count)));
}
assert_eq!(iter.size_hint(), (0, Some(0)));
assert_eq!(iter.next(), None);
assert_eq!(iter.size_hint(), (0, Some(0)));
}
assert_eq!(count, initial_len);
assert_eq!(list.len(), 0);
assert_eq!(list.into_iter().collect::<Vec<_>>(), vec![]);
}
#[test]
fn drain_filter_false() {
let mut list: LinkedList<_> = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].into_iter().collect();
let initial_len = list.len();
let mut count = 0;
{
let mut iter = list.drain_filter(|_| false);
assert_eq!(iter.size_hint(), (0, Some(initial_len)));
for _ in iter.by_ref() {
count += 1;
}
assert_eq!(iter.size_hint(), (0, Some(0)));
assert_eq!(iter.next(), None);
assert_eq!(iter.size_hint(), (0, Some(0)));
}
assert_eq!(count, 0);
assert_eq!(list.len(), initial_len);
assert_eq!(list.into_iter().collect::<Vec<_>>(), vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
}
#[test]
fn drain_filter_true() {
let mut list: LinkedList<_> = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].into_iter().collect();
let initial_len = list.len();
let mut count = 0;
{
let mut iter = list.drain_filter(|_| true);
assert_eq!(iter.size_hint(), (0, Some(initial_len)));
while let Some(_) = iter.next() {
count += 1;
assert_eq!(iter.size_hint(), (0, Some(initial_len - count)));
}
assert_eq!(iter.size_hint(), (0, Some(0)));
assert_eq!(iter.next(), None);
assert_eq!(iter.size_hint(), (0, Some(0)));
}
assert_eq!(count, initial_len);
assert_eq!(list.len(), 0);
assert_eq!(list.into_iter().collect::<Vec<_>>(), vec![]);
}
#[test]
fn drain_filter_complex() {
{
// [+xxx++++++xxxxx++++x+x++]
let mut list = [
1, 2, 4, 6, 7, 9, 11, 13, 15, 17, 18, 20, 22, 24, 26, 27, 29, 31, 33, 34, 35, 36, 37,
39,
]
.into_iter()
.collect::<LinkedList<_>>();
let removed = list.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>();
assert_eq!(removed.len(), 10);
assert_eq!(removed, vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]);
assert_eq!(list.len(), 14);
assert_eq!(
list.into_iter().collect::<Vec<_>>(),
vec![1, 7, 9, 11, 13, 15, 17, 27, 29, 31, 33, 35, 37, 39]
);
}
{
// [xxx++++++xxxxx++++x+x++]
let mut list =
[2, 4, 6, 7, 9, 11, 13, 15, 17, 18, 20, 22, 24, 26, 27, 29, 31, 33, 34, 35, 36, 37, 39]
.into_iter()
.collect::<LinkedList<_>>();
let removed = list.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>();
assert_eq!(removed.len(), 10);
assert_eq!(removed, vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]);
assert_eq!(list.len(), 13);
assert_eq!(
list.into_iter().collect::<Vec<_>>(),
vec![7, 9, 11, 13, 15, 17, 27, 29, 31, 33, 35, 37, 39]
);
}
{
// [xxx++++++xxxxx++++x+x]
let mut list =
[2, 4, 6, 7, 9, 11, 13, 15, 17, 18, 20, 22, 24, 26, 27, 29, 31, 33, 34, 35, 36]
.into_iter()
.collect::<LinkedList<_>>();
let removed = list.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>();
assert_eq!(removed.len(), 10);
assert_eq!(removed, vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]);
assert_eq!(list.len(), 11);
assert_eq!(
list.into_iter().collect::<Vec<_>>(),
vec![7, 9, 11, 13, 15, 17, 27, 29, 31, 33, 35]
);
}
{
// [xxxxxxxxxx+++++++++++]
let mut list = [2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
.into_iter()
.collect::<LinkedList<_>>();
let removed = list.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>();
assert_eq!(removed.len(), 10);
assert_eq!(removed, vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20]);
assert_eq!(list.len(), 10);
assert_eq!(list.into_iter().collect::<Vec<_>>(), vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19]);
}
{
// [+++++++++++xxxxxxxxxx]
let mut list = [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
.into_iter()
.collect::<LinkedList<_>>();
let removed = list.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>();
assert_eq!(removed.len(), 10);
assert_eq!(removed, vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20]);
assert_eq!(list.len(), 10);
assert_eq!(list.into_iter().collect::<Vec<_>>(), vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19]);
}
}
#[test]
fn drain_filter_drop_panic_leak() {
static mut DROPS: i32 = 0;
struct D(bool);
impl Drop for D {
fn drop(&mut self) {
unsafe {
DROPS += 1;
}
if self.0 {
panic!("panic in `drop`");
}
}
}
let mut q = LinkedList::new();
q.push_back(D(false));
q.push_back(D(false));
q.push_back(D(false));
q.push_back(D(false));
q.push_back(D(false));
q.push_front(D(false));
q.push_front(D(true));
q.push_front(D(false));
catch_unwind(AssertUnwindSafe(|| drop(q.drain_filter(|_| true)))).ok();
assert_eq!(unsafe { DROPS }, 8);
assert!(q.is_empty());
}
#[test]
fn drain_filter_pred_panic_leak() {
static mut DROPS: i32 = 0;
#[derive(Debug)]
struct D(u32);
impl Drop for D {
fn drop(&mut self) {
unsafe {
DROPS += 1;
}
}
}
let mut q = LinkedList::new();
q.push_back(D(3));
q.push_back(D(4));
q.push_back(D(5));
q.push_back(D(6));
q.push_back(D(7));
q.push_front(D(2));
q.push_front(D(1));
q.push_front(D(0));
catch_unwind(AssertUnwindSafe(|| {
drop(q.drain_filter(|item| if item.0 >= 2 { panic!() } else { true }))
}))
.ok();
assert_eq!(unsafe { DROPS }, 2); // 0 and 1
assert_eq!(q.len(), 6);
}
#[test]
fn test_drop() {
static mut DROPS: i32 = 0;
struct Elem;
impl Drop for Elem {
fn drop(&mut self) {
unsafe {
DROPS += 1;
}
}
}
let mut ring = LinkedList::new();
ring.push_back(Elem);
ring.push_front(Elem);
ring.push_back(Elem);
ring.push_front(Elem);
drop(ring);
assert_eq!(unsafe { DROPS }, 4);
}
#[test]
fn test_drop_with_pop() {
static mut DROPS: i32 = 0;
struct Elem;
impl Drop for Elem {
fn drop(&mut self) {
unsafe {
DROPS += 1;
}
}
}
let mut ring = LinkedList::new();
ring.push_back(Elem);
ring.push_front(Elem);
ring.push_back(Elem);
ring.push_front(Elem);
drop(ring.pop_back());
drop(ring.pop_front());
assert_eq!(unsafe { DROPS }, 2);
drop(ring);
assert_eq!(unsafe { DROPS }, 4);
}
#[test]
fn test_drop_clear() {
static mut DROPS: i32 = 0;
struct Elem;
impl Drop for Elem {
fn drop(&mut self) {
unsafe {
DROPS += 1;
}
}
}
let mut ring = LinkedList::new();
ring.push_back(Elem);
ring.push_front(Elem);
ring.push_back(Elem);
ring.push_front(Elem);
ring.clear();
assert_eq!(unsafe { DROPS }, 4);
drop(ring);
assert_eq!(unsafe { DROPS }, 4);
}
#[test]
fn test_drop_panic() {
static mut DROPS: i32 = 0;
struct D(bool);
impl Drop for D {
fn drop(&mut self) {
unsafe {
DROPS += 1;
}
if self.0 {
panic!("panic in `drop`");
}
}
}
let mut q = LinkedList::new();
q.push_back(D(false));
q.push_back(D(false));
q.push_back(D(false));
q.push_back(D(false));
q.push_back(D(false));
q.push_front(D(false));
q.push_front(D(false));
q.push_front(D(true));
catch_unwind(move || drop(q)).ok();
assert_eq!(unsafe { DROPS }, 8);
}

View file

@ -2189,7 +2189,7 @@ macro_rules! int_impl {
///
/// # Panics
///
/// When the number is zero, or if the base is not at least 2; it
/// When the number is negative, zero, or if the base is not at least 2; it
/// panics in debug mode and the return value is 0 in release
/// mode.
///
@ -2223,7 +2223,7 @@ macro_rules! int_impl {
///
/// # Panics
///
/// When the number is zero it panics in debug mode and the return value
/// When the number is negative or zero it panics in debug mode and the return value
/// is 0 in release mode.
///
/// # Examples
@ -2256,7 +2256,7 @@ macro_rules! int_impl {
///
/// # Panics
///
/// When the number is zero it panics in debug mode and the return value
/// When the number is negative or zero it panics in debug mode and the return value
/// is 0 in release mode.
///
/// # Example

View file

@ -689,7 +689,7 @@ macro_rules! uint_impl {
///
/// # Panics
///
/// When the number is negative, zero, or if the base is not at least 2;
/// When the number is zero, or if the base is not at least 2;
/// it panics in debug mode and the return value is 0 in release mode.
///
/// # Examples
@ -722,7 +722,7 @@ macro_rules! uint_impl {
///
/// # Panics
///
/// When the number is negative or zero it panics in debug mode and
/// When the number is zero it panics in debug mode and
/// the return value is 0 in release mode.
///
/// # Examples
@ -755,7 +755,7 @@ macro_rules! uint_impl {
///
/// # Panics
///
/// When the number is negative or zero it panics in debug mode and the
/// When the number is zero it panics in debug mode and the
/// return value is 0 in release mode.
///
/// # Example

View file

@ -2359,6 +2359,7 @@ impl Step for Bootstrap {
.env("RUSTFLAGS", "-Cdebuginfo=2")
.env("CARGO_TARGET_DIR", builder.out.join("bootstrap"))
.env("RUSTC_BOOTSTRAP", "1")
.env("RUSTDOC", builder.rustdoc(builder.compiler(0, builder.build.build)))
.env("RUSTC", &builder.initial_rustc);
if let Some(flags) = option_env!("RUSTFLAGS") {
// Use the same rustc flags for testing as for "normal" compilation,
@ -2369,6 +2370,16 @@ impl Step for Bootstrap {
if !builder.fail_fast {
cmd.arg("--no-fail-fast");
}
match builder.doc_tests {
DocTests::Only => {
cmd.arg("--doc");
}
DocTests::No => {
cmd.args(&["--lib", "--bins", "--examples", "--tests", "--benches"]);
}
DocTests::Yes => {}
}
cmd.arg("--").args(&builder.config.cmd.test_args());
// rustbuild tests are racy on directory creation so just run them one at a time.
// Since there's not many this shouldn't be a problem.

View file

@ -164,6 +164,12 @@ fn monkey_barrel() {
assert_eq!(val, ());
}
fn bathroom_stall() {
let mut i = 1;
matches!(2, _|_|_|_|_|_ if (i+=1) != (i+=1));
assert_eq!(i, 13);
}
pub fn main() {
strange();
funny();
@ -183,4 +189,5 @@ pub fn main() {
i_yield();
match_nested_if();
monkey_barrel();
bathroom_stall();
}

View file

@ -138,7 +138,6 @@ async function main(argv) {
try {
// This is more convenient that setting fields one by one.
let args = [
"--no-screenshot-comparison",
"--variable", "DOC_PATH", opts["doc_folder"],
];
if (opts["debug"]) {