Auto merge of #66917 - Centril:rollup-xj2enik, r=Centril

Rollup of 9 pull requests

Successful merges:

 - #66503 (More useful test error messages on should_panic(expected=...) mismatch)
 - #66662 (Miri: run panic-catching tests in liballoc)
 - #66679 (Improve lifetime errors with implicit trait object lifetimes)
 - #66726 (Use recursion_limit for const eval stack limit)
 - #66790 (Do `min_const_fn` checks for `SetDiscriminant`s target)
 - #66832 (const_prop: detect and avoid catching Miri errors that require allocation)
 - #66880 (Add long error code explanation message for E0203)
 - #66890 (Format liballoc with rustfmt)
 - #66896 (pass Queries to compiler callbacks)

Failed merges:

r? @ghost
This commit is contained in:
bors 2019-12-01 06:00:33 +00:00
commit 4007d4ef26
47 changed files with 660 additions and 634 deletions

View File

@ -1,15 +1,15 @@
use super::*; use super::*;
extern crate test; extern crate test;
use test::Bencher;
use crate::boxed::Box; use crate::boxed::Box;
use test::Bencher;
#[test] #[test]
fn allocate_zeroed() { fn allocate_zeroed() {
unsafe { unsafe {
let layout = Layout::from_size_align(1024, 1).unwrap(); let layout = Layout::from_size_align(1024, 1).unwrap();
let ptr = Global.alloc_zeroed(layout.clone()) let ptr =
.unwrap_or_else(|_| handle_alloc_error(layout)); Global.alloc_zeroed(layout.clone()).unwrap_or_else(|_| handle_alloc_error(layout));
let mut i = ptr.cast::<u8>().as_ptr(); let mut i = ptr.cast::<u8>().as_ptr();
let end = i.add(layout.size()); let end = i.add(layout.size());

View File

@ -1,12 +1,12 @@
use std::collections::BTreeMap;
use std::iter::Iterator; use std::iter::Iterator;
use std::vec::Vec; use std::vec::Vec;
use std::collections::BTreeMap;
use rand::{Rng, seq::SliceRandom, thread_rng}; use rand::{seq::SliceRandom, thread_rng, Rng};
use test::{Bencher, black_box}; use test::{black_box, Bencher};
macro_rules! map_insert_rand_bench { macro_rules! map_insert_rand_bench {
($name: ident, $n: expr, $map: ident) => ( ($name: ident, $n: expr, $map: ident) => {
#[bench] #[bench]
pub fn $name(b: &mut Bencher) { pub fn $name(b: &mut Bencher) {
let n: usize = $n; let n: usize = $n;
@ -27,11 +27,11 @@ macro_rules! map_insert_rand_bench {
}); });
black_box(map); black_box(map);
} }
) };
} }
macro_rules! map_insert_seq_bench { macro_rules! map_insert_seq_bench {
($name: ident, $n: expr, $map: ident) => ( ($name: ident, $n: expr, $map: ident) => {
#[bench] #[bench]
pub fn $name(b: &mut Bencher) { pub fn $name(b: &mut Bencher) {
let mut map = $map::new(); let mut map = $map::new();
@ -50,11 +50,11 @@ macro_rules! map_insert_seq_bench {
}); });
black_box(map); black_box(map);
} }
) };
} }
macro_rules! map_find_rand_bench { macro_rules! map_find_rand_bench {
($name: ident, $n: expr, $map: ident) => ( ($name: ident, $n: expr, $map: ident) => {
#[bench] #[bench]
pub fn $name(b: &mut Bencher) { pub fn $name(b: &mut Bencher) {
let mut map = $map::new(); let mut map = $map::new();
@ -78,11 +78,11 @@ macro_rules! map_find_rand_bench {
black_box(t); black_box(t);
}) })
} }
) };
} }
macro_rules! map_find_seq_bench { macro_rules! map_find_seq_bench {
($name: ident, $n: expr, $map: ident) => ( ($name: ident, $n: expr, $map: ident) => {
#[bench] #[bench]
pub fn $name(b: &mut Bencher) { pub fn $name(b: &mut Bencher) {
let mut map = $map::new(); let mut map = $map::new();
@ -101,20 +101,20 @@ macro_rules! map_find_seq_bench {
black_box(x); black_box(x);
}) })
} }
) };
} }
map_insert_rand_bench!{insert_rand_100, 100, BTreeMap} map_insert_rand_bench! {insert_rand_100, 100, BTreeMap}
map_insert_rand_bench!{insert_rand_10_000, 10_000, BTreeMap} map_insert_rand_bench! {insert_rand_10_000, 10_000, BTreeMap}
map_insert_seq_bench!{insert_seq_100, 100, BTreeMap} map_insert_seq_bench! {insert_seq_100, 100, BTreeMap}
map_insert_seq_bench!{insert_seq_10_000, 10_000, BTreeMap} map_insert_seq_bench! {insert_seq_10_000, 10_000, BTreeMap}
map_find_rand_bench!{find_rand_100, 100, BTreeMap} map_find_rand_bench! {find_rand_100, 100, BTreeMap}
map_find_rand_bench!{find_rand_10_000, 10_000, BTreeMap} map_find_rand_bench! {find_rand_10_000, 10_000, BTreeMap}
map_find_seq_bench!{find_seq_100, 100, BTreeMap} map_find_seq_bench! {find_seq_100, 100, BTreeMap}
map_find_seq_bench!{find_seq_10_000, 10_000, BTreeMap} map_find_seq_bench! {find_seq_10_000, 10_000, BTreeMap}
fn bench_iter(b: &mut Bencher, size: i32) { fn bench_iter(b: &mut Bencher, size: i32) {
let mut map = BTreeMap::<i32, i32>::new(); let mut map = BTreeMap::<i32, i32>::new();

View File

@ -1,9 +1,9 @@
use std::{mem, ptr}; use std::{mem, ptr};
use rand::distributions::{Alphanumeric, Standard};
use rand::{thread_rng, Rng, SeedableRng}; use rand::{thread_rng, Rng, SeedableRng};
use rand::distributions::{Standard, Alphanumeric};
use rand_xorshift::XorShiftRng; use rand_xorshift::XorShiftRng;
use test::{Bencher, black_box}; use test::{black_box, Bencher};
#[bench] #[bench]
fn iterator(b: &mut Bencher) { fn iterator(b: &mut Bencher) {
@ -239,7 +239,7 @@ macro_rules! sort {
b.iter(|| v.clone().$f()); b.iter(|| v.clone().$f());
b.bytes = $len * mem::size_of_val(&$gen(1)[0]) as u64; b.bytes = $len * mem::size_of_val(&$gen(1)[0]) as u64;
} }
} };
} }
macro_rules! sort_strings { macro_rules! sort_strings {
@ -251,7 +251,7 @@ macro_rules! sort_strings {
b.iter(|| v.clone().$f()); b.iter(|| v.clone().$f());
b.bytes = $len * mem::size_of::<&str>() as u64; b.bytes = $len * mem::size_of::<&str>() as u64;
} }
} };
} }
macro_rules! sort_expensive { macro_rules! sort_expensive {
@ -273,7 +273,7 @@ macro_rules! sort_expensive {
}); });
b.bytes = $len * mem::size_of_val(&$gen(1)[0]) as u64; b.bytes = $len * mem::size_of_val(&$gen(1)[0]) as u64;
} }
} };
} }
macro_rules! sort_lexicographic { macro_rules! sort_lexicographic {
@ -284,7 +284,7 @@ macro_rules! sort_lexicographic {
b.iter(|| v.clone().$f(|x| x.to_string())); b.iter(|| v.clone().$f(|x| x.to_string()));
b.bytes = $len * mem::size_of_val(&$gen(1)[0]) as u64; b.bytes = $len * mem::size_of_val(&$gen(1)[0]) as u64;
} }
} };
} }
sort!(sort, sort_small_ascending, gen_ascending, 10); sort!(sort, sort_small_ascending, gen_ascending, 10);
@ -325,24 +325,25 @@ macro_rules! reverse {
fn $name(b: &mut Bencher) { fn $name(b: &mut Bencher) {
// odd length and offset by 1 to be as unaligned as possible // odd length and offset by 1 to be as unaligned as possible
let n = 0xFFFFF; let n = 0xFFFFF;
let mut v: Vec<_> = let mut v: Vec<_> = (0..1 + (n / mem::size_of::<$ty>() as u64)).map($f).collect();
(0..1+(n / mem::size_of::<$ty>() as u64))
.map($f)
.collect();
b.iter(|| black_box(&mut v[1..]).reverse()); b.iter(|| black_box(&mut v[1..]).reverse());
b.bytes = n; b.bytes = n;
} }
} };
} }
reverse!(reverse_u8, u8, |x| x as u8); reverse!(reverse_u8, u8, |x| x as u8);
reverse!(reverse_u16, u16, |x| x as u16); reverse!(reverse_u16, u16, |x| x as u16);
reverse!(reverse_u8x3, [u8;3], |x| [x as u8, (x>>8) as u8, (x>>16) as u8]); reverse!(reverse_u8x3, [u8; 3], |x| [x as u8, (x >> 8) as u8, (x >> 16) as u8]);
reverse!(reverse_u32, u32, |x| x as u32); reverse!(reverse_u32, u32, |x| x as u32);
reverse!(reverse_u64, u64, |x| x as u64); reverse!(reverse_u64, u64, |x| x as u64);
reverse!(reverse_u128, u128, |x| x as u128); reverse!(reverse_u128, u128, |x| x as u128);
#[repr(simd)] struct F64x4(f64, f64, f64, f64); #[repr(simd)]
reverse!(reverse_simd_f64x4, F64x4, |x| { let x = x as f64; F64x4(x,x,x,x) }); struct F64x4(f64, f64, f64, f64);
reverse!(reverse_simd_f64x4, F64x4, |x| {
let x = x as f64;
F64x4(x, x, x, x)
});
macro_rules! rotate { macro_rules! rotate {
($name:ident, $gen:expr, $len:expr, $mid:expr) => { ($name:ident, $gen:expr, $len:expr, $mid:expr) => {
@ -350,32 +351,32 @@ macro_rules! rotate {
fn $name(b: &mut Bencher) { fn $name(b: &mut Bencher) {
let size = mem::size_of_val(&$gen(1)[0]); let size = mem::size_of_val(&$gen(1)[0]);
let mut v = $gen($len * 8 / size); let mut v = $gen($len * 8 / size);
b.iter(|| black_box(&mut v).rotate_left(($mid*8+size-1)/size)); b.iter(|| black_box(&mut v).rotate_left(($mid * 8 + size - 1) / size));
b.bytes = (v.len() * size) as u64; b.bytes = (v.len() * size) as u64;
} }
} };
} }
rotate!(rotate_tiny_by1, gen_random, 16, 1); rotate!(rotate_tiny_by1, gen_random, 16, 1);
rotate!(rotate_tiny_half, gen_random, 16, 16/2); rotate!(rotate_tiny_half, gen_random, 16, 16 / 2);
rotate!(rotate_tiny_half_plus_one, gen_random, 16, 16/2+1); rotate!(rotate_tiny_half_plus_one, gen_random, 16, 16 / 2 + 1);
rotate!(rotate_medium_by1, gen_random, 9158, 1); rotate!(rotate_medium_by1, gen_random, 9158, 1);
rotate!(rotate_medium_by727_u64, gen_random, 9158, 727); rotate!(rotate_medium_by727_u64, gen_random, 9158, 727);
rotate!(rotate_medium_by727_bytes, gen_random_bytes, 9158, 727); rotate!(rotate_medium_by727_bytes, gen_random_bytes, 9158, 727);
rotate!(rotate_medium_by727_strings, gen_strings, 9158, 727); rotate!(rotate_medium_by727_strings, gen_strings, 9158, 727);
rotate!(rotate_medium_half, gen_random, 9158, 9158/2); rotate!(rotate_medium_half, gen_random, 9158, 9158 / 2);
rotate!(rotate_medium_half_plus_one, gen_random, 9158, 9158/2+1); rotate!(rotate_medium_half_plus_one, gen_random, 9158, 9158 / 2 + 1);
// Intended to use more RAM than the machine has cache // Intended to use more RAM than the machine has cache
rotate!(rotate_huge_by1, gen_random, 5*1024*1024, 1); rotate!(rotate_huge_by1, gen_random, 5 * 1024 * 1024, 1);
rotate!(rotate_huge_by9199_u64, gen_random, 5*1024*1024, 9199); rotate!(rotate_huge_by9199_u64, gen_random, 5 * 1024 * 1024, 9199);
rotate!(rotate_huge_by9199_bytes, gen_random_bytes, 5*1024*1024, 9199); rotate!(rotate_huge_by9199_bytes, gen_random_bytes, 5 * 1024 * 1024, 9199);
rotate!(rotate_huge_by9199_strings, gen_strings, 5*1024*1024, 9199); rotate!(rotate_huge_by9199_strings, gen_strings, 5 * 1024 * 1024, 9199);
rotate!(rotate_huge_by9199_big, gen_big_random, 5*1024*1024, 9199); rotate!(rotate_huge_by9199_big, gen_big_random, 5 * 1024 * 1024, 9199);
rotate!(rotate_huge_by1234577_u64, gen_random, 5*1024*1024, 1234577); rotate!(rotate_huge_by1234577_u64, gen_random, 5 * 1024 * 1024, 1234577);
rotate!(rotate_huge_by1234577_bytes, gen_random_bytes, 5*1024*1024, 1234577); rotate!(rotate_huge_by1234577_bytes, gen_random_bytes, 5 * 1024 * 1024, 1234577);
rotate!(rotate_huge_by1234577_strings, gen_strings, 5*1024*1024, 1234577); rotate!(rotate_huge_by1234577_strings, gen_strings, 5 * 1024 * 1024, 1234577);
rotate!(rotate_huge_by1234577_big, gen_big_random, 5*1024*1024, 1234577); rotate!(rotate_huge_by1234577_big, gen_big_random, 5 * 1024 * 1024, 1234577);
rotate!(rotate_huge_half, gen_random, 5*1024*1024, 5*1024*1024/2); rotate!(rotate_huge_half, gen_random, 5 * 1024 * 1024, 5 * 1024 * 1024 / 2);
rotate!(rotate_huge_half_plus_one, gen_random, 5*1024*1024, 5*1024*1024/2+1); rotate!(rotate_huge_half_plus_one, gen_random, 5 * 1024 * 1024, 5 * 1024 * 1024 / 2 + 1);

View File

@ -1,4 +1,4 @@
use test::{Bencher, black_box}; use test::{black_box, Bencher};
#[bench] #[bench]
fn char_iterator(b: &mut Bencher) { fn char_iterator(b: &mut Bencher) {
@ -12,7 +12,9 @@ fn char_iterator_for(b: &mut Bencher) {
let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
b.iter(|| { b.iter(|| {
for ch in s.chars() { black_box(ch); } for ch in s.chars() {
black_box(ch);
}
}); });
} }
@ -40,7 +42,9 @@ fn char_iterator_rev_for(b: &mut Bencher) {
let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
b.iter(|| { b.iter(|| {
for ch in s.chars().rev() { black_box(ch); } for ch in s.chars().rev() {
black_box(ch);
}
}); });
} }
@ -79,7 +83,9 @@ fn split_ascii(b: &mut Bencher) {
fn split_extern_fn(b: &mut Bencher) { fn split_extern_fn(b: &mut Bencher) {
let s = "Mary had a little lamb, Little lamb, little-lamb."; let s = "Mary had a little lamb, Little lamb, little-lamb.";
let len = s.split(' ').count(); let len = s.split(' ').count();
fn pred(c: char) -> bool { c == ' ' } fn pred(c: char) -> bool {
c == ' '
}
b.iter(|| assert_eq!(s.split(pred).count(), len)); b.iter(|| assert_eq!(s.split(pred).count(), len));
} }
@ -185,16 +191,19 @@ fn bench_contains_equal(b: &mut Bencher) {
}) })
} }
macro_rules! make_test_inner { macro_rules! make_test_inner {
($s:ident, $code:expr, $name:ident, $str:expr, $iters:expr) => { ($s:ident, $code:expr, $name:ident, $str:expr, $iters:expr) => {
#[bench] #[bench]
fn $name(bencher: &mut Bencher) { fn $name(bencher: &mut Bencher) {
let mut $s = $str; let mut $s = $str;
black_box(&mut $s); black_box(&mut $s);
bencher.iter(|| for _ in 0..$iters { black_box($code); }); bencher.iter(|| {
for _ in 0..$iters {
black_box($code);
}
});
} }
} };
} }
macro_rules! make_test { macro_rules! make_test {
@ -261,15 +270,9 @@ make_test!(match_indices_a_str, s, s.match_indices("a").count());
make_test!(split_a_str, s, s.split("a").count()); make_test!(split_a_str, s, s.split("a").count());
make_test!(trim_ascii_char, s, { make_test!(trim_ascii_char, s, { s.trim_matches(|c: char| c.is_ascii()) });
s.trim_matches(|c: char| c.is_ascii()) make_test!(trim_start_ascii_char, s, { s.trim_start_matches(|c: char| c.is_ascii()) });
}); make_test!(trim_end_ascii_char, s, { s.trim_end_matches(|c: char| c.is_ascii()) });
make_test!(trim_start_ascii_char, s, {
s.trim_start_matches(|c: char| c.is_ascii())
});
make_test!(trim_end_ascii_char, s, {
s.trim_end_matches(|c: char| c.is_ascii())
});
make_test!(find_underscore_char, s, s.find('_')); make_test!(find_underscore_char, s, s.find('_'));
make_test!(rfind_underscore_char, s, s.rfind('_')); make_test!(rfind_underscore_char, s, s.rfind('_'));

View File

@ -1,5 +1,5 @@
use std::collections::VecDeque; use std::collections::VecDeque;
use test::{Bencher, black_box}; use test::{black_box, Bencher};
#[bench] #[bench]
fn bench_new(b: &mut Bencher) { fn bench_new(b: &mut Bencher) {

View File

@ -30,8 +30,5 @@ fn main() {
assert!(BENCH_N % 2 == 0); assert!(BENCH_N % 2 == 0);
let median = (durations[(l / 2) - 1] + durations[l / 2]) / 2; let median = (durations[(l / 2) - 1] + durations[l / 2]) / 2;
println!( println!("\ncustom-bench vec_deque_append {:?} ns/iter\n", median.as_nanos());
"\ncustom-bench vec_deque_append {:?} ns/iter\n",
median.as_nanos()
);
} }

View File

@ -1,6 +1,6 @@
pub mod map;
mod node; mod node;
mod search; mod search;
pub mod map;
pub mod set; pub mod set;
#[doc(hidden)] #[doc(hidden)]

View File

@ -1,21 +1,23 @@
use core::borrow::Borrow; use core::borrow::Borrow;
use core::cmp::Ordering; use core::cmp::Ordering;
use super::node::{Handle, NodeRef, marker, ForceResult::*}; use super::node::{marker, ForceResult::*, Handle, NodeRef};
use SearchResult::*; use SearchResult::*;
pub enum SearchResult<BorrowType, K, V, FoundType, GoDownType> { pub enum SearchResult<BorrowType, K, V, FoundType, GoDownType> {
Found(Handle<NodeRef<BorrowType, K, V, FoundType>, marker::KV>), Found(Handle<NodeRef<BorrowType, K, V, FoundType>, marker::KV>),
GoDown(Handle<NodeRef<BorrowType, K, V, GoDownType>, marker::Edge>) GoDown(Handle<NodeRef<BorrowType, K, V, GoDownType>, marker::Edge>),
} }
pub fn search_tree<BorrowType, K, V, Q: ?Sized>( pub fn search_tree<BorrowType, K, V, Q: ?Sized>(
mut node: NodeRef<BorrowType, K, V, marker::LeafOrInternal>, mut node: NodeRef<BorrowType, K, V, marker::LeafOrInternal>,
key: &Q key: &Q,
) -> SearchResult<BorrowType, K, V, marker::LeafOrInternal, marker::Leaf> ) -> SearchResult<BorrowType, K, V, marker::LeafOrInternal, marker::Leaf>
where Q: Ord, K: Borrow<Q> { where
Q: Ord,
K: Borrow<Q>,
{
loop { loop {
match search_node(node, key) { match search_node(node, key) {
Found(handle) => return Found(handle), Found(handle) => return Found(handle),
@ -25,38 +27,38 @@ pub fn search_tree<BorrowType, K, V, Q: ?Sized>(
node = internal.descend(); node = internal.descend();
continue; continue;
} }
} },
} }
} }
} }
pub fn search_node<BorrowType, K, V, Type, Q: ?Sized>( pub fn search_node<BorrowType, K, V, Type, Q: ?Sized>(
node: NodeRef<BorrowType, K, V, Type>, node: NodeRef<BorrowType, K, V, Type>,
key: &Q key: &Q,
) -> SearchResult<BorrowType, K, V, Type, Type> ) -> SearchResult<BorrowType, K, V, Type, Type>
where Q: Ord, K: Borrow<Q> { where
Q: Ord,
K: Borrow<Q>,
{
match search_linear(&node, key) { match search_linear(&node, key) {
(idx, true) => Found( (idx, true) => Found(Handle::new_kv(node, idx)),
Handle::new_kv(node, idx) (idx, false) => SearchResult::GoDown(Handle::new_edge(node, idx)),
),
(idx, false) => SearchResult::GoDown(
Handle::new_edge(node, idx)
)
} }
} }
pub fn search_linear<BorrowType, K, V, Type, Q: ?Sized>( pub fn search_linear<BorrowType, K, V, Type, Q: ?Sized>(
node: &NodeRef<BorrowType, K, V, Type>, node: &NodeRef<BorrowType, K, V, Type>,
key: &Q key: &Q,
) -> (usize, bool) ) -> (usize, bool)
where Q: Ord, K: Borrow<Q> { where
Q: Ord,
K: Borrow<Q>,
{
for (i, k) in node.keys().iter().enumerate() { for (i, k) in node.keys().iter().enumerate() {
match key.cmp(k.borrow()) { match key.cmp(k.borrow()) {
Ordering::Greater => {}, Ordering::Greater => {}
Ordering::Equal => return (i, true), Ordering::Equal => return (i, true),
Ordering::Less => return (i, false) Ordering::Less => return (i, false),
} }
} }
(node.keys().len(), false) (node.keys().len(), false)

View File

@ -177,8 +177,7 @@ fn test_insert_prev() {
} }
check_links(&m); check_links(&m);
assert_eq!(m.len(), 3 + len * 2); assert_eq!(m.len(), 3 + len * 2);
assert_eq!(m.into_iter().collect::<Vec<_>>(), assert_eq!(m.into_iter().collect::<Vec<_>>(), [-2, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1]);
[-2, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1]);
} }
#[test] #[test]
@ -187,13 +186,13 @@ fn test_insert_prev() {
fn test_send() { fn test_send() {
let n = list_from(&[1, 2, 3]); let n = list_from(&[1, 2, 3]);
thread::spawn(move || { thread::spawn(move || {
check_links(&n); check_links(&n);
let a: &[_] = &[&1, &2, &3]; let a: &[_] = &[&1, &2, &3];
assert_eq!(a, &*n.iter().collect::<Vec<_>>()); assert_eq!(a, &*n.iter().collect::<Vec<_>>());
}) })
.join() .join()
.ok() .ok()
.unwrap(); .unwrap();
} }
#[test] #[test]

View File

@ -66,11 +66,8 @@ fn test_swap_front_back_remove() {
let final_len = usable_cap / 2; let final_len = usable_cap / 2;
for len in 0..final_len { for len in 0..final_len {
let expected: VecDeque<_> = if back { let expected: VecDeque<_> =
(0..len).collect() if back { (0..len).collect() } else { (0..len).rev().collect() };
} else {
(0..len).rev().collect()
};
for tail_pos in 0..usable_cap { for tail_pos in 0..usable_cap {
tester.tail = tail_pos; tester.tail = tail_pos;
tester.head = tail_pos; tester.head = tail_pos;
@ -111,7 +108,6 @@ fn test_insert() {
// this test isn't covering what it wants to // this test isn't covering what it wants to
let cap = tester.capacity(); let cap = tester.capacity();
// len is the length *after* insertion // len is the length *after* insertion
for len in 1..cap { for len in 1..cap {
// 0, 1, 2, .., len - 1 // 0, 1, 2, .., len - 1
@ -198,9 +194,7 @@ fn test_drain() {
assert!(tester.head < tester.cap()); assert!(tester.head < tester.cap());
// We should see the correct values in the VecDeque // We should see the correct values in the VecDeque
let expected: VecDeque<_> = (0..drain_start) let expected: VecDeque<_> = (0..drain_start).chain(drain_end..len).collect();
.chain(drain_end..len)
.collect();
assert_eq!(expected, tester); assert_eq!(expected, tester);
} }
} }

View File

@ -516,24 +516,24 @@
#[unstable(feature = "fmt_internals", issue = "0")] #[unstable(feature = "fmt_internals", issue = "0")]
pub use core::fmt::rt; pub use core::fmt::rt;
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "fmt_flags_align", since = "1.28.0")]
pub use core::fmt::{Formatter, Result, Write}; pub use core::fmt::Alignment;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::fmt::{Binary, Octal};
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::fmt::{Debug, Display};
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::fmt::{LowerHex, Pointer, UpperHex};
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::fmt::{LowerExp, UpperExp};
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub use core::fmt::Error; pub use core::fmt::Error;
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub use core::fmt::{write, ArgumentV1, Arguments}; pub use core::fmt::{write, ArgumentV1, Arguments};
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub use core::fmt::{Binary, Octal};
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::fmt::{Debug, Display};
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::fmt::{DebugList, DebugMap, DebugSet, DebugStruct, DebugTuple}; pub use core::fmt::{DebugList, DebugMap, DebugSet, DebugStruct, DebugTuple};
#[stable(feature = "fmt_flags_align", since = "1.28.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub use core::fmt::{Alignment}; pub use core::fmt::{Formatter, Result, Write};
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::fmt::{LowerExp, UpperExp};
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::fmt::{LowerHex, Pointer, UpperHex};
use crate::string; use crate::string;
@ -568,8 +568,6 @@ use crate::string;
pub fn format(args: Arguments<'_>) -> string::String { pub fn format(args: Arguments<'_>) -> string::String {
let capacity = args.estimated_capacity(); let capacity = args.estimated_capacity();
let mut output = string::String::with_capacity(capacity); let mut output = string::String::with_capacity(capacity);
output output.write_fmt(args).expect("a formatting trait implementation returned an error");
.write_fmt(args)
.expect("a formatting trait implementation returned an error");
output output
} }

View File

@ -4,7 +4,11 @@
#![unstable(feature = "alloc_prelude", issue = "58935")] #![unstable(feature = "alloc_prelude", issue = "58935")]
#[unstable(feature = "alloc_prelude", issue = "58935")] pub use crate::borrow::ToOwned; #[unstable(feature = "alloc_prelude", issue = "58935")]
#[unstable(feature = "alloc_prelude", issue = "58935")] pub use crate::boxed::Box; pub use crate::borrow::ToOwned;
#[unstable(feature = "alloc_prelude", issue = "58935")] pub use crate::string::{String, ToString}; #[unstable(feature = "alloc_prelude", issue = "58935")]
#[unstable(feature = "alloc_prelude", issue = "58935")] pub use crate::vec::Vec; pub use crate::boxed::Box;
#[unstable(feature = "alloc_prelude", issue = "58935")]
pub use crate::string::{String, ToString};
#[unstable(feature = "alloc_prelude", issue = "58935")]
pub use crate::vec::Vec;

View File

@ -16,7 +16,9 @@ fn allocator_param() {
// A dumb allocator that consumes a fixed amount of fuel // A dumb allocator that consumes a fixed amount of fuel
// before allocation attempts start failing. // before allocation attempts start failing.
struct BoundedAlloc { fuel: usize } struct BoundedAlloc {
fuel: usize,
}
unsafe impl Alloc for BoundedAlloc { unsafe impl Alloc for BoundedAlloc {
unsafe fn alloc(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr> { unsafe fn alloc(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr> {
let size = layout.size(); let size = layout.size();
@ -24,7 +26,10 @@ fn allocator_param() {
return Err(AllocErr); return Err(AllocErr);
} }
match Global.alloc(layout) { match Global.alloc(layout) {
ok @ Ok(_) => { self.fuel -= size; ok } ok @ Ok(_) => {
self.fuel -= size;
ok
}
err @ Err(_) => err, err @ Err(_) => err,
} }
} }

View File

@ -82,7 +82,6 @@
//! [`.chunks`]: ../../std/primitive.slice.html#method.chunks //! [`.chunks`]: ../../std/primitive.slice.html#method.chunks
//! [`.windows`]: ../../std/primitive.slice.html#method.windows //! [`.windows`]: ../../std/primitive.slice.html#method.windows
#![stable(feature = "rust1", since = "1.0.0")] #![stable(feature = "rust1", since = "1.0.0")]
// Many of the usings in this module are only used in the test configuration. // Many of the usings in this module are only used in the test configuration.
// It's cleaner to just turn off the unused_imports warning than to fix them. // It's cleaner to just turn off the unused_imports warning than to fix them.
#![cfg_attr(test, allow(unused_imports, dead_code))] #![cfg_attr(test, allow(unused_imports, dead_code))]
@ -91,32 +90,32 @@ use core::borrow::{Borrow, BorrowMut};
use core::cmp::Ordering::{self, Less}; use core::cmp::Ordering::{self, Less};
use core::mem::{self, size_of}; use core::mem::{self, size_of};
use core::ptr; use core::ptr;
use core::{u8, u16, u32}; use core::{u16, u32, u8};
use crate::borrow::ToOwned; use crate::borrow::ToOwned;
use crate::boxed::Box; use crate::boxed::Box;
use crate::vec::Vec; use crate::vec::Vec;
#[stable(feature = "slice_get_slice", since = "1.28.0")]
pub use core::slice::SliceIndex;
#[stable(feature = "from_ref", since = "1.28.0")]
pub use core::slice::{from_mut, from_ref};
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::slice::{from_raw_parts, from_raw_parts_mut};
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub use core::slice::{Chunks, Windows}; pub use core::slice::{Chunks, Windows};
#[stable(feature = "chunks_exact", since = "1.31.0")]
pub use core::slice::{ChunksExact, ChunksExactMut};
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::slice::{ChunksMut, Split, SplitMut};
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub use core::slice::{Iter, IterMut}; pub use core::slice::{Iter, IterMut};
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rchunks", since = "1.31.0")]
pub use core::slice::{SplitMut, ChunksMut, Split}; pub use core::slice::{RChunks, RChunksExact, RChunksExactMut, RChunksMut};
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::slice::{SplitN, RSplitN, SplitNMut, RSplitNMut};
#[stable(feature = "slice_rsplit", since = "1.27.0")] #[stable(feature = "slice_rsplit", since = "1.27.0")]
pub use core::slice::{RSplit, RSplitMut}; pub use core::slice::{RSplit, RSplitMut};
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub use core::slice::{from_raw_parts, from_raw_parts_mut}; pub use core::slice::{RSplitN, RSplitNMut, SplitN, SplitNMut};
#[stable(feature = "from_ref", since = "1.28.0")]
pub use core::slice::{from_ref, from_mut};
#[stable(feature = "slice_get_slice", since = "1.28.0")]
pub use core::slice::SliceIndex;
#[stable(feature = "chunks_exact", since = "1.31.0")]
pub use core::slice::{ChunksExact, ChunksExactMut};
#[stable(feature = "rchunks", since = "1.31.0")]
pub use core::slice::{RChunks, RChunksMut, RChunksExact, RChunksExactMut};
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Basic slice extension methods // Basic slice extension methods
@ -138,9 +137,9 @@ pub use hack::to_vec;
// `test_permutations` test // `test_permutations` test
mod hack { mod hack {
use crate::boxed::Box; use crate::boxed::Box;
use crate::vec::Vec;
#[cfg(test)] #[cfg(test)]
use crate::string::ToString; use crate::string::ToString;
use crate::vec::Vec;
pub fn into_vec<T>(b: Box<[T]>) -> Vec<T> { pub fn into_vec<T>(b: Box<[T]>) -> Vec<T> {
unsafe { unsafe {
@ -153,7 +152,8 @@ mod hack {
#[inline] #[inline]
pub fn to_vec<T>(s: &[T]) -> Vec<T> pub fn to_vec<T>(s: &[T]) -> Vec<T>
where T: Clone where
T: Clone,
{ {
let mut vector = Vec::with_capacity(s.len()); let mut vector = Vec::with_capacity(s.len());
vector.extend_from_slice(s); vector.extend_from_slice(s);
@ -193,7 +193,8 @@ impl<T> [T] {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn sort(&mut self) pub fn sort(&mut self)
where T: Ord where
T: Ord,
{ {
merge_sort(self, |a, b| a.lt(b)); merge_sort(self, |a, b| a.lt(b));
} }
@ -246,7 +247,8 @@ impl<T> [T] {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn sort_by<F>(&mut self, mut compare: F) pub fn sort_by<F>(&mut self, mut compare: F)
where F: FnMut(&T, &T) -> Ordering where
F: FnMut(&T, &T) -> Ordering,
{ {
merge_sort(self, |a, b| compare(a, b) == Less); merge_sort(self, |a, b| compare(a, b) == Less);
} }
@ -285,7 +287,9 @@ impl<T> [T] {
#[stable(feature = "slice_sort_by_key", since = "1.7.0")] #[stable(feature = "slice_sort_by_key", since = "1.7.0")]
#[inline] #[inline]
pub fn sort_by_key<K, F>(&mut self, mut f: F) pub fn sort_by_key<K, F>(&mut self, mut f: F)
where F: FnMut(&T) -> K, K: Ord where
F: FnMut(&T) -> K,
K: Ord,
{ {
merge_sort(self, |a, b| f(a).lt(&f(b))); merge_sort(self, |a, b| f(a).lt(&f(b)));
} }
@ -325,11 +329,13 @@ impl<T> [T] {
#[stable(feature = "slice_sort_by_cached_key", since = "1.34.0")] #[stable(feature = "slice_sort_by_cached_key", since = "1.34.0")]
#[inline] #[inline]
pub fn sort_by_cached_key<K, F>(&mut self, f: F) pub fn sort_by_cached_key<K, F>(&mut self, f: F)
where F: FnMut(&T) -> K, K: Ord where
F: FnMut(&T) -> K,
K: Ord,
{ {
// Helper macro for indexing our vector by the smallest possible type, to reduce allocation. // Helper macro for indexing our vector by the smallest possible type, to reduce allocation.
macro_rules! sort_by_key { macro_rules! sort_by_key {
($t:ty, $slice:ident, $f:ident) => ({ ($t:ty, $slice:ident, $f:ident) => {{
let mut indices: Vec<_> = let mut indices: Vec<_> =
$slice.iter().map($f).enumerate().map(|(i, k)| (k, i as $t)).collect(); $slice.iter().map($f).enumerate().map(|(i, k)| (k, i as $t)).collect();
// The elements of `indices` are unique, as they are indexed, so any sort will be // The elements of `indices` are unique, as they are indexed, so any sort will be
@ -344,19 +350,27 @@ impl<T> [T] {
indices[i].1 = index; indices[i].1 = index;
$slice.swap(i, index as usize); $slice.swap(i, index as usize);
} }
}) }};
} }
let sz_u8 = mem::size_of::<(K, u8)>(); let sz_u8 = mem::size_of::<(K, u8)>();
let sz_u16 = mem::size_of::<(K, u16)>(); let sz_u16 = mem::size_of::<(K, u16)>();
let sz_u32 = mem::size_of::<(K, u32)>(); let sz_u32 = mem::size_of::<(K, u32)>();
let sz_usize = mem::size_of::<(K, usize)>(); let sz_usize = mem::size_of::<(K, usize)>();
let len = self.len(); let len = self.len();
if len < 2 { return } if len < 2 {
if sz_u8 < sz_u16 && len <= ( u8::MAX as usize) { return sort_by_key!( u8, self, f) } return;
if sz_u16 < sz_u32 && len <= (u16::MAX as usize) { return sort_by_key!(u16, self, f) } }
if sz_u32 < sz_usize && len <= (u32::MAX as usize) { return sort_by_key!(u32, self, f) } if sz_u8 < sz_u16 && len <= (u8::MAX as usize) {
return sort_by_key!(u8, self, f);
}
if sz_u16 < sz_u32 && len <= (u16::MAX as usize) {
return sort_by_key!(u16, self, f);
}
if sz_u32 < sz_usize && len <= (u32::MAX as usize) {
return sort_by_key!(u32, self, f);
}
sort_by_key!(usize, self, f) sort_by_key!(usize, self, f)
} }
@ -373,7 +387,8 @@ impl<T> [T] {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn to_vec(&self) -> Vec<T> pub fn to_vec(&self) -> Vec<T>
where T: Clone where
T: Clone,
{ {
// N.B., see the `hack` module in this file for more details. // N.B., see the `hack` module in this file for more details.
hack::to_vec(self) hack::to_vec(self)
@ -421,7 +436,10 @@ impl<T> [T] {
/// b"0123456789abcdef".repeat(usize::max_value()); /// b"0123456789abcdef".repeat(usize::max_value());
/// ``` /// ```
#[stable(feature = "repeat_generic_slice", since = "1.40.0")] #[stable(feature = "repeat_generic_slice", since = "1.40.0")]
pub fn repeat(&self, n: usize) -> Vec<T> where T: Copy { pub fn repeat(&self, n: usize) -> Vec<T>
where
T: Copy,
{
if n == 0 { if n == 0 {
return Vec::new(); return Vec::new();
} }
@ -486,7 +504,8 @@ impl<T> [T] {
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn concat<Item: ?Sized>(&self) -> <Self as Concat<Item>>::Output pub fn concat<Item: ?Sized>(&self) -> <Self as Concat<Item>>::Output
where Self: Concat<Item> where
Self: Concat<Item>,
{ {
Concat::concat(self) Concat::concat(self)
} }
@ -503,7 +522,8 @@ impl<T> [T] {
/// ``` /// ```
#[stable(feature = "rename_connect_to_join", since = "1.3.0")] #[stable(feature = "rename_connect_to_join", since = "1.3.0")]
pub fn join<Separator>(&self, sep: Separator) -> <Self as Join<Separator>>::Output pub fn join<Separator>(&self, sep: Separator) -> <Self as Join<Separator>>::Output
where Self: Join<Separator> where
Self: Join<Separator>,
{ {
Join::join(self, sep) Join::join(self, sep)
} }
@ -521,11 +541,11 @@ impl<T> [T] {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[rustc_deprecated(since = "1.3.0", reason = "renamed to join")] #[rustc_deprecated(since = "1.3.0", reason = "renamed to join")]
pub fn connect<Separator>(&self, sep: Separator) -> <Self as Join<Separator>>::Output pub fn connect<Separator>(&self, sep: Separator) -> <Self as Join<Separator>>::Output
where Self: Join<Separator> where
Self: Join<Separator>,
{ {
Join::join(self, sep) Join::join(self, sep)
} }
} }
#[lang = "slice_u8_alloc"] #[lang = "slice_u8_alloc"]
@ -668,8 +688,8 @@ impl<T: Clone, V: Borrow<[T]>> Join<&[T]> for [V] {
Some(first) => first, Some(first) => first,
None => return vec![], None => return vec![],
}; };
let size = slice.iter().map(|v| v.borrow().len()).sum::<usize>() + let size =
sep.len() * (slice.len() - 1); slice.iter().map(|v| v.borrow().len()).sum::<usize>() + sep.len() * (slice.len() - 1);
let mut result = Vec::with_capacity(size); let mut result = Vec::with_capacity(size);
result.extend_from_slice(first.borrow()); result.extend_from_slice(first.borrow());
@ -734,7 +754,8 @@ impl<T: Clone> ToOwned for [T] {
/// ///
/// This is the integral subroutine of insertion sort. /// This is the integral subroutine of insertion sort.
fn insert_head<T, F>(v: &mut [T], is_less: &mut F) fn insert_head<T, F>(v: &mut [T], is_less: &mut F)
where F: FnMut(&T, &T) -> bool where
F: FnMut(&T, &T) -> bool,
{ {
if v.len() >= 2 && is_less(&v[1], &v[0]) { if v.len() >= 2 && is_less(&v[1], &v[0]) {
unsafe { unsafe {
@ -767,10 +788,7 @@ fn insert_head<T, F>(v: &mut [T], is_less: &mut F)
// If `is_less` panics at any point during the process, `hole` will get dropped and // If `is_less` panics at any point during the process, `hole` will get dropped and
// fill the hole in `v` with `tmp`, thus ensuring that `v` still holds every object it // fill the hole in `v` with `tmp`, thus ensuring that `v` still holds every object it
// initially held exactly once. // initially held exactly once.
let mut hole = InsertionHole { let mut hole = InsertionHole { src: &mut *tmp, dest: &mut v[1] };
src: &mut *tmp,
dest: &mut v[1],
};
ptr::copy_nonoverlapping(&v[1], &mut v[0], 1); ptr::copy_nonoverlapping(&v[1], &mut v[0], 1);
for i in 2..v.len() { for i in 2..v.len() {
@ -792,7 +810,9 @@ fn insert_head<T, F>(v: &mut [T], is_less: &mut F)
impl<T> Drop for InsertionHole<T> { impl<T> Drop for InsertionHole<T> {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { ptr::copy_nonoverlapping(self.src, self.dest, 1); } unsafe {
ptr::copy_nonoverlapping(self.src, self.dest, 1);
}
} }
} }
} }
@ -805,7 +825,8 @@ fn insert_head<T, F>(v: &mut [T], is_less: &mut F)
/// The two slices must be non-empty and `mid` must be in bounds. Buffer `buf` must be long enough /// The two slices must be non-empty and `mid` must be in bounds. Buffer `buf` must be long enough
/// to hold a copy of the shorter slice. Also, `T` must not be a zero-sized type. /// to hold a copy of the shorter slice. Also, `T` must not be a zero-sized type.
unsafe fn merge<T, F>(v: &mut [T], mid: usize, buf: *mut T, is_less: &mut F) unsafe fn merge<T, F>(v: &mut [T], mid: usize, buf: *mut T, is_less: &mut F)
where F: FnMut(&T, &T) -> bool where
F: FnMut(&T, &T) -> bool,
{ {
let len = v.len(); let len = v.len();
let v = v.as_mut_ptr(); let v = v.as_mut_ptr();
@ -834,11 +855,7 @@ unsafe fn merge<T, F>(v: &mut [T], mid: usize, buf: *mut T, is_less: &mut F)
if mid <= len - mid { if mid <= len - mid {
// The left run is shorter. // The left run is shorter.
ptr::copy_nonoverlapping(v, buf, mid); ptr::copy_nonoverlapping(v, buf, mid);
hole = MergeHole { hole = MergeHole { start: buf, end: buf.add(mid), dest: v };
start: buf,
end: buf.add(mid),
dest: v,
};
// Initially, these pointers point to the beginnings of their arrays. // Initially, these pointers point to the beginnings of their arrays.
let left = &mut hole.start; let left = &mut hole.start;
@ -858,11 +875,7 @@ unsafe fn merge<T, F>(v: &mut [T], mid: usize, buf: *mut T, is_less: &mut F)
} else { } else {
// The right run is shorter. // The right run is shorter.
ptr::copy_nonoverlapping(v_mid, buf, len - mid); ptr::copy_nonoverlapping(v_mid, buf, len - mid);
hole = MergeHole { hole = MergeHole { start: buf, end: buf.add(len - mid), dest: v_mid };
start: buf,
end: buf.add(len - mid),
dest: v_mid,
};
// Initially, these pointers point past the ends of their arrays. // Initially, these pointers point past the ends of their arrays.
let left = &mut hole.dest; let left = &mut hole.dest;
@ -905,7 +918,9 @@ unsafe fn merge<T, F>(v: &mut [T], mid: usize, buf: *mut T, is_less: &mut F)
fn drop(&mut self) { fn drop(&mut self) {
// `T` is not a zero-sized type, so it's okay to divide by its size. // `T` is not a zero-sized type, so it's okay to divide by its size.
let len = (self.end as usize - self.start as usize) / mem::size_of::<T>(); let len = (self.end as usize - self.start as usize) / mem::size_of::<T>();
unsafe { ptr::copy_nonoverlapping(self.start, self.dest, len); } unsafe {
ptr::copy_nonoverlapping(self.start, self.dest, len);
}
} }
} }
} }
@ -923,7 +938,8 @@ unsafe fn merge<T, F>(v: &mut [T], mid: usize, buf: *mut T, is_less: &mut F)
/// ///
/// The invariants ensure that the total running time is `O(n log n)` worst-case. /// The invariants ensure that the total running time is `O(n log n)` worst-case.
fn merge_sort<T, F>(v: &mut [T], mut is_less: F) fn merge_sort<T, F>(v: &mut [T], mut is_less: F)
where F: FnMut(&T, &T) -> bool where
F: FnMut(&T, &T) -> bool,
{ {
// Slices of up to this length get sorted using insertion sort. // Slices of up to this length get sorted using insertion sort.
const MAX_INSERTION: usize = 20; const MAX_INSERTION: usize = 20;
@ -940,7 +956,7 @@ fn merge_sort<T, F>(v: &mut [T], mut is_less: F)
// Short arrays get sorted in-place via insertion sort to avoid allocations. // Short arrays get sorted in-place via insertion sort to avoid allocations.
if len <= MAX_INSERTION { if len <= MAX_INSERTION {
if len >= 2 { if len >= 2 {
for i in (0..len-1).rev() { for i in (0..len - 1).rev() {
insert_head(&mut v[i..], &mut is_less); insert_head(&mut v[i..], &mut is_less);
} }
} }
@ -966,14 +982,13 @@ fn merge_sort<T, F>(v: &mut [T], mut is_less: F)
start -= 1; start -= 1;
unsafe { unsafe {
if is_less(v.get_unchecked(start + 1), v.get_unchecked(start)) { if is_less(v.get_unchecked(start + 1), v.get_unchecked(start)) {
while start > 0 && is_less(v.get_unchecked(start), while start > 0 && is_less(v.get_unchecked(start), v.get_unchecked(start - 1)) {
v.get_unchecked(start - 1)) {
start -= 1; start -= 1;
} }
v[start..end].reverse(); v[start..end].reverse();
} else { } else {
while start > 0 && !is_less(v.get_unchecked(start), while start > 0 && !is_less(v.get_unchecked(start), v.get_unchecked(start - 1))
v.get_unchecked(start - 1)) { {
start -= 1; start -= 1;
} }
} }
@ -988,10 +1003,7 @@ fn merge_sort<T, F>(v: &mut [T], mut is_less: F)
} }
// Push this run onto the stack. // Push this run onto the stack.
runs.push(Run { runs.push(Run { start, len: end - start });
start,
len: end - start,
});
end = start; end = start;
// Merge some pairs of adjacent runs to satisfy the invariants. // Merge some pairs of adjacent runs to satisfy the invariants.
@ -999,13 +1011,14 @@ fn merge_sort<T, F>(v: &mut [T], mut is_less: F)
let left = runs[r + 1]; let left = runs[r + 1];
let right = runs[r]; let right = runs[r];
unsafe { unsafe {
merge(&mut v[left.start .. right.start + right.len], left.len, buf.as_mut_ptr(), merge(
&mut is_less); &mut v[left.start..right.start + right.len],
left.len,
buf.as_mut_ptr(),
&mut is_less,
);
} }
runs[r] = Run { runs[r] = Run { start: left.start, len: left.len + right.len };
start: left.start,
len: left.len + right.len,
};
runs.remove(r + 1); runs.remove(r + 1);
} }
} }
@ -1030,15 +1043,13 @@ fn merge_sort<T, F>(v: &mut [T], mut is_less: F)
#[inline] #[inline]
fn collapse(runs: &[Run]) -> Option<usize> { fn collapse(runs: &[Run]) -> Option<usize> {
let n = runs.len(); let n = runs.len();
if n >= 2 && (runs[n - 1].start == 0 || if n >= 2
runs[n - 2].len <= runs[n - 1].len || && (runs[n - 1].start == 0
(n >= 3 && runs[n - 3].len <= runs[n - 2].len + runs[n - 1].len) || || runs[n - 2].len <= runs[n - 1].len
(n >= 4 && runs[n - 4].len <= runs[n - 3].len + runs[n - 2].len)) { || (n >= 3 && runs[n - 3].len <= runs[n - 2].len + runs[n - 1].len)
if n >= 3 && runs[n - 3].len < runs[n - 1].len { || (n >= 4 && runs[n - 4].len <= runs[n - 3].len + runs[n - 2].len))
Some(n - 3) {
} else { if n >= 3 && runs[n - 3].len < runs[n - 1].len { Some(n - 3) } else { Some(n - 2) }
Some(n - 2)
}
} else { } else {
None None
} }

View File

@ -1,12 +1,12 @@
//! Test for `boxed` mod. //! Test for `boxed` mod.
use core::any::Any; use core::any::Any;
use core::convert::TryInto;
use core::ops::Deref;
use core::result::Result::{Err, Ok};
use core::clone::Clone; use core::clone::Clone;
use core::convert::TryInto;
use core::f64; use core::f64;
use core::i64; use core::i64;
use core::ops::Deref;
use core::result::Result::{Err, Ok};
use std::boxed::Box; use std::boxed::Box;

View File

@ -1,9 +1,9 @@
use std::any::Any; use std::any::Any;
use std::sync::{Arc, Weak};
use std::cell::RefCell; use std::cell::RefCell;
use std::cmp::PartialEq; use std::cmp::PartialEq;
use std::iter::TrustedLen; use std::iter::TrustedLen;
use std::mem; use std::mem;
use std::sync::{Arc, Weak};
#[test] #[test]
fn uninhabited() { fn uninhabited() {
@ -12,7 +12,7 @@ fn uninhabited() {
a = a.clone(); a = a.clone();
assert!(a.upgrade().is_none()); assert!(a.upgrade().is_none());
let mut a: Weak<dyn Any> = a; // Unsizing let mut a: Weak<dyn Any> = a; // Unsizing
a = a.clone(); a = a.clone();
assert!(a.upgrade().is_none()); assert!(a.upgrade().is_none());
} }
@ -20,8 +20,8 @@ fn uninhabited() {
#[test] #[test]
fn slice() { fn slice() {
let a: Arc<[u32; 3]> = Arc::new([3, 2, 1]); let a: Arc<[u32; 3]> = Arc::new([3, 2, 1]);
let a: Arc<[u32]> = a; // Unsizing let a: Arc<[u32]> = a; // Unsizing
let b: Arc<[u32]> = Arc::from(&[3, 2, 1][..]); // Conversion let b: Arc<[u32]> = Arc::from(&[3, 2, 1][..]); // Conversion
assert_eq!(a, b); assert_eq!(a, b);
// Exercise is_dangling() with a DST // Exercise is_dangling() with a DST
@ -33,7 +33,7 @@ fn slice() {
#[test] #[test]
fn trait_object() { fn trait_object() {
let a: Arc<u32> = Arc::new(4); let a: Arc<u32> = Arc::new(4);
let a: Arc<dyn Any> = a; // Unsizing let a: Arc<dyn Any> = a; // Unsizing
// Exercise is_dangling() with a DST // Exercise is_dangling() with a DST
let mut a = Arc::downgrade(&a); let mut a = Arc::downgrade(&a);
@ -43,7 +43,7 @@ fn trait_object() {
let mut b = Weak::<u32>::new(); let mut b = Weak::<u32>::new();
b = b.clone(); b = b.clone();
assert!(b.upgrade().is_none()); assert!(b.upgrade().is_none());
let mut b: Weak<dyn Any> = b; // Unsizing let mut b: Weak<dyn Any> = b; // Unsizing
b = b.clone(); b = b.clone();
assert!(b.upgrade().is_none()); assert!(b.upgrade().is_none());
} }
@ -57,7 +57,7 @@ fn float_nan_ne() {
#[test] #[test]
fn partial_eq() { fn partial_eq() {
struct TestPEq (RefCell<usize>); struct TestPEq(RefCell<usize>);
impl PartialEq for TestPEq { impl PartialEq for TestPEq {
fn eq(&self, other: &TestPEq) -> bool { fn eq(&self, other: &TestPEq) -> bool {
*self.0.borrow_mut() += 1; *self.0.borrow_mut() += 1;
@ -74,7 +74,7 @@ fn partial_eq() {
#[test] #[test]
fn eq() { fn eq() {
#[derive(Eq)] #[derive(Eq)]
struct TestEq (RefCell<usize>); struct TestEq(RefCell<usize>);
impl PartialEq for TestEq { impl PartialEq for TestEq {
fn eq(&self, other: &TestEq) -> bool { fn eq(&self, other: &TestEq) -> bool {
*self.0.borrow_mut() += 1; *self.0.borrow_mut() += 1;
@ -160,13 +160,10 @@ fn shared_from_iter_trustedlen_normal() {
fn shared_from_iter_trustedlen_panic() { fn shared_from_iter_trustedlen_panic() {
// Exercise the `TrustedLen` implementation when `size_hint()` matches // Exercise the `TrustedLen` implementation when `size_hint()` matches
// `(_, Some(exact_len))` but where `.next()` drops before the last iteration. // `(_, Some(exact_len))` but where `.next()` drops before the last iteration.
let iter = (0..SHARED_ITER_MAX) let iter = (0..SHARED_ITER_MAX).map(|val| match val {
.map(|val| { 98 => panic!("I've almost got 99 problems."),
match val { _ => Box::new(val),
98 => panic!("I've almost got 99 problems."), });
_ => Box::new(val),
}
});
assert_trusted_len(&iter); assert_trusted_len(&iter);
let _ = iter.collect::<Rc<[_]>>(); let _ = iter.collect::<Rc<[_]>>();
@ -193,16 +190,8 @@ fn shared_from_iter_trustedlen_no_fuse() {
} }
} }
let vec = vec![ let vec = vec![Some(Box::new(42)), Some(Box::new(24)), None, Some(Box::new(12))];
Some(Box::new(42)),
Some(Box::new(24)),
None,
Some(Box::new(12)),
];
let iter = Iter(vec.into_iter()); let iter = Iter(vec.into_iter());
assert_trusted_len(&iter); assert_trusted_len(&iter);
assert_eq!( assert_eq!(&[Box::new(42), Box::new(24)], &*iter.collect::<Rc<[_]>>());
&[Box::new(42), Box::new(24)],
&*iter.collect::<Rc<[_]>>()
);
} }

View File

@ -347,7 +347,7 @@ fn assert_covariance() {
// Destructors must be called exactly once per element. // Destructors must be called exactly once per element.
// FIXME: re-enable emscripten once it can unwind again // FIXME: re-enable emscripten once it can unwind again
#[test] #[test]
#[cfg(not(any(miri, target_os = "emscripten")))] // Miri does not support catching panics #[cfg(not(target_os = "emscripten"))]
fn panic_safe() { fn panic_safe() {
use std::cmp; use std::cmp;
use std::panic::{self, AssertUnwindSafe}; use std::panic::{self, AssertUnwindSafe};
@ -376,7 +376,10 @@ fn panic_safe() {
} }
let mut rng = thread_rng(); let mut rng = thread_rng();
const DATASZ: usize = 32; const DATASZ: usize = 32;
#[cfg(not(miri))] // Miri is too slow
const NTEST: usize = 10; const NTEST: usize = 10;
#[cfg(miri)]
const NTEST: usize = 1;
// don't use 0 in the data -- we want to catch the zeroed-out case. // don't use 0 in the data -- we want to catch the zeroed-out case.
let data = (1..=DATASZ).collect::<Vec<_>>(); let data = (1..=DATASZ).collect::<Vec<_>>();

View File

@ -1,5 +1,5 @@
use std::ptr::NonNull;
use std::mem::MaybeUninit; use std::mem::MaybeUninit;
use std::ptr::NonNull;
#[test] #[test]
fn unitialized_zero_size_box() { fn unitialized_zero_size_box() {

View File

@ -11,12 +11,7 @@ struct DeterministicRng {
impl DeterministicRng { impl DeterministicRng {
fn new() -> Self { fn new() -> Self {
DeterministicRng { DeterministicRng { x: 0x193a6754, y: 0xa8a7d469, z: 0x97830e05, w: 0x113ba7bb }
x: 0x193a6754,
y: 0xa8a7d469,
z: 0x97830e05,
w: 0x113ba7bb,
}
} }
fn next(&mut self) -> u32 { fn next(&mut self) -> u32 {

View File

@ -102,7 +102,6 @@ fn test_split_off() {
assert_eq!(m.back(), Some(&1)); assert_eq!(m.back(), Some(&1));
assert_eq!(m.front(), Some(&1)); assert_eq!(m.front(), Some(&1));
} }
} }
#[test] #[test]
@ -305,8 +304,7 @@ fn test_show() {
assert_eq!(format!("{:?}", list), "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]"); assert_eq!(format!("{:?}", list), "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]");
let list: LinkedList<_> = vec!["just", "one", "test", "more"].iter().cloned().collect(); let list: LinkedList<_> = vec!["just", "one", "test", "more"].iter().cloned().collect();
assert_eq!(format!("{:?}", list), assert_eq!(format!("{:?}", list), "[\"just\", \"one\", \"test\", \"more\"]");
"[\"just\", \"one\", \"test\", \"more\"]");
} }
#[test] #[test]
@ -446,19 +444,14 @@ fn drain_filter_true() {
#[test] #[test]
fn drain_filter_complex() { fn drain_filter_complex() {
{
{ // [+xxx++++++xxxxx++++x+x++] // [+xxx++++++xxxxx++++x+x++]
let mut list = vec![ let mut list = vec![
1, 1, 2, 4, 6, 7, 9, 11, 13, 15, 17, 18, 20, 22, 24, 26, 27, 29, 31, 33, 34, 35, 36, 37,
2, 4, 6, 39,
7, 9, 11, 13, 15, 17, ]
18, 20, 22, 24, 26, .into_iter()
27, 29, 31, 33, .collect::<LinkedList<_>>();
34,
35,
36,
37, 39
].into_iter().collect::<LinkedList<_>>();
let removed = list.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>(); let removed = list.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>();
assert_eq!(removed.len(), 10); assert_eq!(removed.len(), 10);
@ -471,17 +464,13 @@ fn drain_filter_complex() {
); );
} }
{ // [xxx++++++xxxxx++++x+x++] {
// [xxx++++++xxxxx++++x+x++]
let mut list = vec![ let mut list = vec![
2, 4, 6, 2, 4, 6, 7, 9, 11, 13, 15, 17, 18, 20, 22, 24, 26, 27, 29, 31, 33, 34, 35, 36, 37, 39,
7, 9, 11, 13, 15, 17, ]
18, 20, 22, 24, 26, .into_iter()
27, 29, 31, 33, .collect::<LinkedList<_>>();
34,
35,
36,
37, 39
].into_iter().collect::<LinkedList<_>>();
let removed = list.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>(); let removed = list.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>();
assert_eq!(removed.len(), 10); assert_eq!(removed.len(), 10);
@ -494,16 +483,12 @@ fn drain_filter_complex() {
); );
} }
{ // [xxx++++++xxxxx++++x+x] {
let mut list = vec![ // [xxx++++++xxxxx++++x+x]
2, 4, 6, let mut list =
7, 9, 11, 13, 15, 17, vec![2, 4, 6, 7, 9, 11, 13, 15, 17, 18, 20, 22, 24, 26, 27, 29, 31, 33, 34, 35, 36]
18, 20, 22, 24, 26, .into_iter()
27, 29, 31, 33, .collect::<LinkedList<_>>();
34,
35,
36
].into_iter().collect::<LinkedList<_>>();
let removed = list.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>(); let removed = list.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>();
assert_eq!(removed.len(), 10); assert_eq!(removed.len(), 10);
@ -516,11 +501,11 @@ fn drain_filter_complex() {
); );
} }
{ // [xxxxxxxxxx+++++++++++] {
let mut list = vec![ // [xxxxxxxxxx+++++++++++]
2, 4, 6, 8, 10, 12, 14, 16, 18, 20, let mut list = vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
1, 3, 5, 7, 9, 11, 13, 15, 17, 19 .into_iter()
].into_iter().collect::<LinkedList<_>>(); .collect::<LinkedList<_>>();
let removed = list.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>(); let removed = list.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>();
assert_eq!(removed.len(), 10); assert_eq!(removed.len(), 10);
@ -530,11 +515,11 @@ fn drain_filter_complex() {
assert_eq!(list.into_iter().collect::<Vec<_>>(), vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19]); assert_eq!(list.into_iter().collect::<Vec<_>>(), vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19]);
} }
{ // [+++++++++++xxxxxxxxxx] {
let mut list = vec![ // [+++++++++++xxxxxxxxxx]
1, 3, 5, 7, 9, 11, 13, 15, 17, 19, let mut list = vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
2, 4, 6, 8, 10, 12, 14, 16, 18, 20 .into_iter()
].into_iter().collect::<LinkedList<_>>(); .collect::<LinkedList<_>>();
let removed = list.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>(); let removed = list.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>();
assert_eq!(removed.len(), 10); assert_eq!(removed.len(), 10);

View File

@ -1,9 +1,9 @@
use std::any::Any; use std::any::Any;
use std::rc::{Rc, Weak};
use std::cell::RefCell; use std::cell::RefCell;
use std::cmp::PartialEq; use std::cmp::PartialEq;
use std::mem;
use std::iter::TrustedLen; use std::iter::TrustedLen;
use std::mem;
use std::rc::{Rc, Weak};
#[test] #[test]
fn uninhabited() { fn uninhabited() {
@ -12,7 +12,7 @@ fn uninhabited() {
a = a.clone(); a = a.clone();
assert!(a.upgrade().is_none()); assert!(a.upgrade().is_none());
let mut a: Weak<dyn Any> = a; // Unsizing let mut a: Weak<dyn Any> = a; // Unsizing
a = a.clone(); a = a.clone();
assert!(a.upgrade().is_none()); assert!(a.upgrade().is_none());
} }
@ -20,8 +20,8 @@ fn uninhabited() {
#[test] #[test]
fn slice() { fn slice() {
let a: Rc<[u32; 3]> = Rc::new([3, 2, 1]); let a: Rc<[u32; 3]> = Rc::new([3, 2, 1]);
let a: Rc<[u32]> = a; // Unsizing let a: Rc<[u32]> = a; // Unsizing
let b: Rc<[u32]> = Rc::from(&[3, 2, 1][..]); // Conversion let b: Rc<[u32]> = Rc::from(&[3, 2, 1][..]); // Conversion
assert_eq!(a, b); assert_eq!(a, b);
// Exercise is_dangling() with a DST // Exercise is_dangling() with a DST
@ -33,7 +33,7 @@ fn slice() {
#[test] #[test]
fn trait_object() { fn trait_object() {
let a: Rc<u32> = Rc::new(4); let a: Rc<u32> = Rc::new(4);
let a: Rc<dyn Any> = a; // Unsizing let a: Rc<dyn Any> = a; // Unsizing
// Exercise is_dangling() with a DST // Exercise is_dangling() with a DST
let mut a = Rc::downgrade(&a); let mut a = Rc::downgrade(&a);
@ -43,7 +43,7 @@ fn trait_object() {
let mut b = Weak::<u32>::new(); let mut b = Weak::<u32>::new();
b = b.clone(); b = b.clone();
assert!(b.upgrade().is_none()); assert!(b.upgrade().is_none());
let mut b: Weak<dyn Any> = b; // Unsizing let mut b: Weak<dyn Any> = b; // Unsizing
b = b.clone(); b = b.clone();
assert!(b.upgrade().is_none()); assert!(b.upgrade().is_none());
} }
@ -57,7 +57,7 @@ fn float_nan_ne() {
#[test] #[test]
fn partial_eq() { fn partial_eq() {
struct TestPEq (RefCell<usize>); struct TestPEq(RefCell<usize>);
impl PartialEq for TestPEq { impl PartialEq for TestPEq {
fn eq(&self, other: &TestPEq) -> bool { fn eq(&self, other: &TestPEq) -> bool {
*self.0.borrow_mut() += 1; *self.0.borrow_mut() += 1;
@ -74,7 +74,7 @@ fn partial_eq() {
#[test] #[test]
fn eq() { fn eq() {
#[derive(Eq)] #[derive(Eq)]
struct TestEq (RefCell<usize>); struct TestEq(RefCell<usize>);
impl PartialEq for TestEq { impl PartialEq for TestEq {
fn eq(&self, other: &TestEq) -> bool { fn eq(&self, other: &TestEq) -> bool {
*self.0.borrow_mut() += 1; *self.0.borrow_mut() += 1;
@ -156,13 +156,10 @@ fn shared_from_iter_trustedlen_normal() {
fn shared_from_iter_trustedlen_panic() { fn shared_from_iter_trustedlen_panic() {
// Exercise the `TrustedLen` implementation when `size_hint()` matches // Exercise the `TrustedLen` implementation when `size_hint()` matches
// `(_, Some(exact_len))` but where `.next()` drops before the last iteration. // `(_, Some(exact_len))` but where `.next()` drops before the last iteration.
let iter = (0..SHARED_ITER_MAX) let iter = (0..SHARED_ITER_MAX).map(|val| match val {
.map(|val| { 98 => panic!("I've almost got 99 problems."),
match val { _ => Box::new(val),
98 => panic!("I've almost got 99 problems."), });
_ => Box::new(val),
}
});
assert_trusted_len(&iter); assert_trusted_len(&iter);
let _ = iter.collect::<Rc<[_]>>(); let _ = iter.collect::<Rc<[_]>>();
@ -189,16 +186,8 @@ fn shared_from_iter_trustedlen_no_fuse() {
} }
} }
let vec = vec![ let vec = vec![Some(Box::new(42)), Some(Box::new(24)), None, Some(Box::new(12))];
Some(Box::new(42)),
Some(Box::new(24)),
None,
Some(Box::new(12)),
];
let iter = Iter(vec.into_iter()); let iter = Iter(vec.into_iter());
assert_trusted_len(&iter); assert_trusted_len(&iter);
assert_eq!( assert_eq!(&[Box::new(42), Box::new(24)], &*iter.collect::<Rc<[_]>>());
&[Box::new(42), Box::new(24)],
&*iter.collect::<Rc<[_]>>()
);
} }

View File

@ -4,7 +4,6 @@ use std::mem;
use std::panic; use std::panic;
use std::rc::Rc; use std::rc::Rc;
use std::sync::atomic::{Ordering::Relaxed, AtomicUsize}; use std::sync::atomic::{Ordering::Relaxed, AtomicUsize};
use std::thread;
use rand::{Rng, RngCore, thread_rng}; use rand::{Rng, RngCore, thread_rng};
use rand::seq::SliceRandom; use rand::seq::SliceRandom;
@ -1406,11 +1405,9 @@ fn test_box_slice_clone() {
#[test] #[test]
#[allow(unused_must_use)] // here, we care about the side effects of `.clone()` #[allow(unused_must_use)] // here, we care about the side effects of `.clone()`
#[cfg_attr(target_os = "emscripten", ignore)] #[cfg_attr(target_os = "emscripten", ignore)]
#[cfg(not(miri))] // Miri does not support threads
fn test_box_slice_clone_panics() { fn test_box_slice_clone_panics() {
use std::sync::Arc; use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::atomic::{AtomicUsize, Ordering};
use std::thread::spawn;
struct Canary { struct Canary {
count: Arc<AtomicUsize>, count: Arc<AtomicUsize>,
@ -1446,7 +1443,7 @@ fn test_box_slice_clone_panics() {
panics: true, panics: true,
}; };
spawn(move || { std::panic::catch_unwind(move || {
// When xs is dropped, +5. // When xs is dropped, +5.
let xs = vec![canary.clone(), canary.clone(), canary.clone(), panic, canary] let xs = vec![canary.clone(), canary.clone(), canary.clone(), panic, canary]
.into_boxed_slice(); .into_boxed_slice();
@ -1454,7 +1451,6 @@ fn test_box_slice_clone_panics() {
// When panic is cloned, +3. // When panic is cloned, +3.
xs.clone(); xs.clone();
}) })
.join()
.unwrap_err(); .unwrap_err();
// Total = 8 // Total = 8
@ -1566,7 +1562,7 @@ macro_rules! test {
} }
let v = $input.to_owned(); let v = $input.to_owned();
let _ = thread::spawn(move || { let _ = std::panic::catch_unwind(move || {
let mut v = v; let mut v = v;
let mut panic_countdown = panic_countdown; let mut panic_countdown = panic_countdown;
v.$func(|a, b| { v.$func(|a, b| {
@ -1577,7 +1573,7 @@ macro_rules! test {
panic_countdown -= 1; panic_countdown -= 1;
a.cmp(b) a.cmp(b)
}) })
}).join(); });
// Check that the number of things dropped is exactly // Check that the number of things dropped is exactly
// what we expect (i.e., the contents of `v`). // what we expect (i.e., the contents of `v`).
@ -1598,7 +1594,6 @@ thread_local!(static SILENCE_PANIC: Cell<bool> = Cell::new(false));
#[test] #[test]
#[cfg_attr(target_os = "emscripten", ignore)] // no threads #[cfg_attr(target_os = "emscripten", ignore)] // no threads
#[cfg(not(miri))] // Miri does not support threads
fn panic_safe() { fn panic_safe() {
let prev = panic::take_hook(); let prev = panic::take_hook();
panic::set_hook(Box::new(move |info| { panic::set_hook(Box::new(move |info| {
@ -1609,8 +1604,18 @@ fn panic_safe() {
let mut rng = thread_rng(); let mut rng = thread_rng();
for len in (1..20).chain(70..MAX_LEN) { #[cfg(not(miri))] // Miri is too slow
for &modulus in &[5, 20, 50] { let lens = (1..20).chain(70..MAX_LEN);
#[cfg(not(miri))] // Miri is too slow
let moduli = &[5, 20, 50];
#[cfg(miri)]
let lens = (1..13);
#[cfg(miri)]
let moduli = &[10];
for len in lens {
for &modulus in moduli {
for &has_runs in &[false, true] { for &has_runs in &[false, true] {
let mut input = (0..len) let mut input = (0..len)
.map(|id| { .map(|id| {
@ -1643,6 +1648,9 @@ fn panic_safe() {
} }
} }
} }
// Set default panic hook again.
drop(panic::take_hook());
} }
#[test] #[test]

View File

@ -944,10 +944,9 @@ fn drain_filter_complex() {
} }
} }
// Miri does not support catching panics
// FIXME: re-enable emscripten once it can unwind again // FIXME: re-enable emscripten once it can unwind again
#[test] #[test]
#[cfg(not(any(miri, target_os = "emscripten")))] #[cfg(not(target_os = "emscripten"))]
fn drain_filter_consumed_panic() { fn drain_filter_consumed_panic() {
use std::rc::Rc; use std::rc::Rc;
use std::sync::Mutex; use std::sync::Mutex;
@ -999,7 +998,7 @@ fn drain_filter_consumed_panic() {
// FIXME: Re-enable emscripten once it can catch panics // FIXME: Re-enable emscripten once it can catch panics
#[test] #[test]
#[cfg(not(any(miri, target_os = "emscripten")))] // Miri does not support catching panics #[cfg(not(target_os = "emscripten"))]
fn drain_filter_unconsumed_panic() { fn drain_filter_unconsumed_panic() {
use std::rc::Rc; use std::rc::Rc;
use std::sync::Mutex; use std::sync::Mutex;

View File

@ -1,8 +1,8 @@
use std::fmt::Debug;
use std::collections::{VecDeque, vec_deque::Drain};
use std::collections::TryReserveError::*; use std::collections::TryReserveError::*;
use std::collections::{vec_deque::Drain, VecDeque};
use std::fmt::Debug;
use std::mem::size_of; use std::mem::size_of;
use std::{usize, isize}; use std::{isize, usize};
use crate::hash; use crate::hash;
@ -148,34 +148,20 @@ fn test_param_taggy() {
#[test] #[test]
fn test_param_taggypar() { fn test_param_taggypar() {
test_parameterized::<Taggypar<i32>>(Onepar::<i32>(1), test_parameterized::<Taggypar<i32>>(
Twopar::<i32>(1, 2), Onepar::<i32>(1),
Threepar::<i32>(1, 2, 3), Twopar::<i32>(1, 2),
Twopar::<i32>(17, 42)); Threepar::<i32>(1, 2, 3),
Twopar::<i32>(17, 42),
);
} }
#[test] #[test]
fn test_param_reccy() { fn test_param_reccy() {
let reccy1 = RecCy { let reccy1 = RecCy { x: 1, y: 2, t: One(1) };
x: 1, let reccy2 = RecCy { x: 345, y: 2, t: Two(1, 2) };
y: 2, let reccy3 = RecCy { x: 1, y: 777, t: Three(1, 2, 3) };
t: One(1), let reccy4 = RecCy { x: 19, y: 252, t: Two(17, 42) };
};
let reccy2 = RecCy {
x: 345,
y: 2,
t: Two(1, 2),
};
let reccy3 = RecCy {
x: 1,
y: 777,
t: Three(1, 2, 3),
};
let reccy4 = RecCy {
x: 19,
y: 252,
t: Two(17, 42),
};
test_parameterized::<RecCy>(reccy1, reccy2, reccy3, reccy4); test_parameterized::<RecCy>(reccy1, reccy2, reccy3, reccy4);
} }
@ -320,8 +306,7 @@ fn test_mut_rev_iter_wrap() {
assert_eq!(d.pop_front(), Some(1)); assert_eq!(d.pop_front(), Some(1));
d.push_back(4); d.push_back(4);
assert_eq!(d.iter_mut().rev().map(|x| *x).collect::<Vec<_>>(), assert_eq!(d.iter_mut().rev().map(|x| *x).collect::<Vec<_>>(), vec![4, 3, 2]);
vec![4, 3, 2]);
} }
#[test] #[test]
@ -372,7 +357,6 @@ fn test_mut_rev_iter() {
#[test] #[test]
fn test_into_iter() { fn test_into_iter() {
// Empty iter // Empty iter
{ {
let d: VecDeque<i32> = VecDeque::new(); let d: VecDeque<i32> = VecDeque::new();
@ -431,7 +415,6 @@ fn test_into_iter() {
#[test] #[test]
fn test_drain() { fn test_drain() {
// Empty iter // Empty iter
{ {
let mut d: VecDeque<i32> = VecDeque::new(); let mut d: VecDeque<i32> = VecDeque::new();
@ -650,12 +633,8 @@ fn test_show() {
let ringbuf: VecDeque<_> = (0..10).collect(); let ringbuf: VecDeque<_> = (0..10).collect();
assert_eq!(format!("{:?}", ringbuf), "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]"); assert_eq!(format!("{:?}", ringbuf), "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]");
let ringbuf: VecDeque<_> = vec!["just", "one", "test", "more"] let ringbuf: VecDeque<_> = vec!["just", "one", "test", "more"].iter().cloned().collect();
.iter() assert_eq!(format!("{:?}", ringbuf), "[\"just\", \"one\", \"test\", \"more\"]");
.cloned()
.collect();
assert_eq!(format!("{:?}", ringbuf),
"[\"just\", \"one\", \"test\", \"more\"]");
} }
#[test] #[test]
@ -955,7 +934,6 @@ fn test_append_permutations() {
// doesn't pop more values than are pushed // doesn't pop more values than are pushed
for src_pop_back in 0..(src_push_back + src_push_front) { for src_pop_back in 0..(src_push_back + src_push_front) {
for src_pop_front in 0..(src_push_back + src_push_front - src_pop_back) { for src_pop_front in 0..(src_push_back + src_push_front - src_pop_back) {
let src = construct_vec_deque( let src = construct_vec_deque(
src_push_back, src_push_back,
src_pop_back, src_pop_back,
@ -966,8 +944,8 @@ fn test_append_permutations() {
for dst_push_back in 0..MAX { for dst_push_back in 0..MAX {
for dst_push_front in 0..MAX { for dst_push_front in 0..MAX {
for dst_pop_back in 0..(dst_push_back + dst_push_front) { for dst_pop_back in 0..(dst_push_back + dst_push_front) {
for dst_pop_front for dst_pop_front in
in 0..(dst_push_back + dst_push_front - dst_pop_back) 0..(dst_push_back + dst_push_front - dst_pop_back)
{ {
let mut dst = construct_vec_deque( let mut dst = construct_vec_deque(
dst_push_back, dst_push_back,
@ -1124,7 +1102,6 @@ fn test_reserve_exact_2() {
#[test] #[test]
#[cfg(not(miri))] // Miri does not support signalling OOM #[cfg(not(miri))] // Miri does not support signalling OOM
fn test_try_reserve() { fn test_try_reserve() {
// These are the interesting cases: // These are the interesting cases:
// * exactly isize::MAX should never trigger a CapacityOverflow (can be OOM) // * exactly isize::MAX should never trigger a CapacityOverflow (can be OOM)
// * > isize::MAX should always fail // * > isize::MAX should always fail
@ -1158,22 +1135,27 @@ fn test_try_reserve() {
if guards_against_isize { if guards_against_isize {
// Check isize::MAX + 1 does count as overflow // Check isize::MAX + 1 does count as overflow
if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_CAP + 1) { if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_CAP + 1) {
} else { panic!("isize::MAX + 1 should trigger an overflow!") } } else {
panic!("isize::MAX + 1 should trigger an overflow!")
}
// Check usize::MAX does count as overflow // Check usize::MAX does count as overflow
if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_USIZE) { if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_USIZE) {
} else { panic!("usize::MAX should trigger an overflow!") } } else {
panic!("usize::MAX should trigger an overflow!")
}
} else { } else {
// Check isize::MAX is an OOM // Check isize::MAX is an OOM
// VecDeque starts with capacity 7, always adds 1 to the capacity // VecDeque starts with capacity 7, always adds 1 to the capacity
// and also rounds the number to next power of 2 so this is the // and also rounds the number to next power of 2 so this is the
// furthest we can go without triggering CapacityOverflow // furthest we can go without triggering CapacityOverflow
if let Err(AllocError { .. }) = empty_bytes.try_reserve(MAX_CAP) { if let Err(AllocError { .. }) = empty_bytes.try_reserve(MAX_CAP) {
} else { panic!("isize::MAX + 1 should trigger an OOM!") } } else {
panic!("isize::MAX + 1 should trigger an OOM!")
}
} }
} }
{ {
// Same basic idea, but with non-zero len // Same basic idea, but with non-zero len
let mut ten_bytes: VecDeque<u8> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10].into_iter().collect(); let mut ten_bytes: VecDeque<u8> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10].into_iter().collect();
@ -1186,33 +1168,42 @@ fn test_try_reserve() {
} }
if guards_against_isize { if guards_against_isize {
if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 9) { if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 9) {
} else { panic!("isize::MAX + 1 should trigger an overflow!"); } } else {
panic!("isize::MAX + 1 should trigger an overflow!");
}
} else { } else {
if let Err(AllocError { .. }) = ten_bytes.try_reserve(MAX_CAP - 9) { if let Err(AllocError { .. }) = ten_bytes.try_reserve(MAX_CAP - 9) {
} else { panic!("isize::MAX + 1 should trigger an OOM!") } } else {
panic!("isize::MAX + 1 should trigger an OOM!")
}
} }
// Should always overflow in the add-to-len // Should always overflow in the add-to-len
if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_USIZE) { if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_USIZE) {
} else { panic!("usize::MAX should trigger an overflow!") } } else {
panic!("usize::MAX should trigger an overflow!")
}
} }
{ {
// Same basic idea, but with interesting type size // Same basic idea, but with interesting type size
let mut ten_u32s: VecDeque<u32> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10].into_iter().collect(); let mut ten_u32s: VecDeque<u32> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10].into_iter().collect();
if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_CAP/4 - 10) { if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_CAP / 4 - 10) {
panic!("isize::MAX shouldn't trigger an overflow!"); panic!("isize::MAX shouldn't trigger an overflow!");
} }
if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_CAP/4 - 10) { if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_CAP / 4 - 10) {
panic!("isize::MAX shouldn't trigger an overflow!"); panic!("isize::MAX shouldn't trigger an overflow!");
} }
if guards_against_isize { if guards_against_isize {
if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_CAP/4 - 9) { if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_CAP / 4 - 9) {
} else { panic!("isize::MAX + 1 should trigger an overflow!"); } } else {
panic!("isize::MAX + 1 should trigger an overflow!");
}
} else { } else {
if let Err(AllocError { .. }) = ten_u32s.try_reserve(MAX_CAP/4 - 9) { if let Err(AllocError { .. }) = ten_u32s.try_reserve(MAX_CAP / 4 - 9) {
} else { panic!("isize::MAX + 1 should trigger an OOM!") } } else {
panic!("isize::MAX + 1 should trigger an OOM!")
}
} }
// Should fail in the mul-by-size // Should fail in the mul-by-size
if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_USIZE - 20) { if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_USIZE - 20) {
@ -1220,13 +1211,11 @@ fn test_try_reserve() {
panic!("usize::MAX should trigger an overflow!"); panic!("usize::MAX should trigger an overflow!");
} }
} }
} }
#[test] #[test]
#[cfg(not(miri))] // Miri does not support signalling OOM #[cfg(not(miri))] // Miri does not support signalling OOM
fn test_try_reserve_exact() { fn test_try_reserve_exact() {
// This is exactly the same as test_try_reserve with the method changed. // This is exactly the same as test_try_reserve with the method changed.
// See that test for comments. // See that test for comments.
@ -1247,21 +1236,26 @@ fn test_try_reserve_exact() {
if guards_against_isize { if guards_against_isize {
if let Err(CapacityOverflow) = empty_bytes.try_reserve_exact(MAX_CAP + 1) { if let Err(CapacityOverflow) = empty_bytes.try_reserve_exact(MAX_CAP + 1) {
} else { panic!("isize::MAX + 1 should trigger an overflow!") } } else {
panic!("isize::MAX + 1 should trigger an overflow!")
}
if let Err(CapacityOverflow) = empty_bytes.try_reserve_exact(MAX_USIZE) { if let Err(CapacityOverflow) = empty_bytes.try_reserve_exact(MAX_USIZE) {
} else { panic!("usize::MAX should trigger an overflow!") } } else {
panic!("usize::MAX should trigger an overflow!")
}
} else { } else {
// Check isize::MAX is an OOM // Check isize::MAX is an OOM
// VecDeque starts with capacity 7, always adds 1 to the capacity // VecDeque starts with capacity 7, always adds 1 to the capacity
// and also rounds the number to next power of 2 so this is the // and also rounds the number to next power of 2 so this is the
// furthest we can go without triggering CapacityOverflow // furthest we can go without triggering CapacityOverflow
if let Err(AllocError { .. }) = empty_bytes.try_reserve_exact(MAX_CAP) { if let Err(AllocError { .. }) = empty_bytes.try_reserve_exact(MAX_CAP) {
} else { panic!("isize::MAX + 1 should trigger an OOM!") } } else {
panic!("isize::MAX + 1 should trigger an OOM!")
}
} }
} }
{ {
let mut ten_bytes: VecDeque<u8> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10].into_iter().collect(); let mut ten_bytes: VecDeque<u8> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10].into_iter().collect();
@ -1273,36 +1267,46 @@ fn test_try_reserve_exact() {
} }
if guards_against_isize { if guards_against_isize {
if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 9) { if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 9) {
} else { panic!("isize::MAX + 1 should trigger an overflow!"); } } else {
panic!("isize::MAX + 1 should trigger an overflow!");
}
} else { } else {
if let Err(AllocError { .. }) = ten_bytes.try_reserve_exact(MAX_CAP - 9) { if let Err(AllocError { .. }) = ten_bytes.try_reserve_exact(MAX_CAP - 9) {
} else { panic!("isize::MAX + 1 should trigger an OOM!") } } else {
panic!("isize::MAX + 1 should trigger an OOM!")
}
} }
if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_USIZE) { if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_USIZE) {
} else { panic!("usize::MAX should trigger an overflow!") } } else {
panic!("usize::MAX should trigger an overflow!")
}
} }
{ {
let mut ten_u32s: VecDeque<u32> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10].into_iter().collect(); let mut ten_u32s: VecDeque<u32> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10].into_iter().collect();
if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 10) { if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_CAP / 4 - 10) {
panic!("isize::MAX shouldn't trigger an overflow!"); panic!("isize::MAX shouldn't trigger an overflow!");
} }
if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 10) { if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_CAP / 4 - 10) {
panic!("isize::MAX shouldn't trigger an overflow!"); panic!("isize::MAX shouldn't trigger an overflow!");
} }
if guards_against_isize { if guards_against_isize {
if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 9) { if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_CAP / 4 - 9) {
} else { panic!("isize::MAX + 1 should trigger an overflow!"); } } else {
panic!("isize::MAX + 1 should trigger an overflow!");
}
} else { } else {
if let Err(AllocError { .. }) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 9) { if let Err(AllocError { .. }) = ten_u32s.try_reserve_exact(MAX_CAP / 4 - 9) {
} else { panic!("isize::MAX + 1 should trigger an OOM!") } } else {
panic!("isize::MAX + 1 should trigger an OOM!")
}
} }
if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_USIZE - 20) { if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_USIZE - 20) {
} else { panic!("usize::MAX should trigger an overflow!") } } else {
panic!("usize::MAX should trigger an overflow!")
}
} }
} }
#[test] #[test]
@ -1404,9 +1408,8 @@ fn test_rotate_right_parts() {
#[test] #[test]
fn test_rotate_left_random() { fn test_rotate_left_random() {
let shifts = [ let shifts = [
6, 1, 0, 11, 12, 1, 11, 7, 9, 3, 6, 1, 6, 1, 0, 11, 12, 1, 11, 7, 9, 3, 6, 1, 4, 0, 5, 1, 3, 1, 12, 8, 3, 1, 11, 11, 9, 4, 12, 3,
4, 0, 5, 1, 3, 1, 12, 8, 3, 1, 11, 11, 12, 9, 11, 1, 7, 9, 7, 2,
9, 4, 12, 3, 12, 9, 11, 1, 7, 9, 7, 2,
]; ];
let n = 12; let n = 12;
let mut v: VecDeque<_> = (0..n).collect(); let mut v: VecDeque<_> = (0..n).collect();
@ -1423,9 +1426,8 @@ fn test_rotate_left_random() {
#[test] #[test]
fn test_rotate_right_random() { fn test_rotate_right_random() {
let shifts = [ let shifts = [
6, 1, 0, 11, 12, 1, 11, 7, 9, 3, 6, 1, 6, 1, 0, 11, 12, 1, 11, 7, 9, 3, 6, 1, 4, 0, 5, 1, 3, 1, 12, 8, 3, 1, 11, 11, 9, 4, 12, 3,
4, 0, 5, 1, 3, 1, 12, 8, 3, 1, 11, 11, 12, 9, 11, 1, 7, 9, 7, 2,
9, 4, 12, 3, 12, 9, 11, 1, 7, 9, 7, 2,
]; ];
let n = 12; let n = 12;
let mut v: VecDeque<_> = (0..n).collect(); let mut v: VecDeque<_> = (0..n).collect();
@ -1447,8 +1449,7 @@ fn test_try_fold_empty() {
#[test] #[test]
fn test_try_fold_none() { fn test_try_fold_none() {
let v: VecDeque<u32> = (0..12).collect(); let v: VecDeque<u32> = (0..12).collect();
assert_eq!(None, v.into_iter().try_fold(0, |a, b| assert_eq!(None, v.into_iter().try_fold(0, |a, b| if b < 11 { Some(a + b) } else { None }));
if b < 11 { Some(a + b) } else { None }));
} }
#[test] #[test]
@ -1463,7 +1464,6 @@ fn test_try_fold_unit() {
assert_eq!(Some(()), v.into_iter().try_fold((), |(), ()| Some(()))); assert_eq!(Some(()), v.into_iter().try_fold((), |(), ()| Some(())));
} }
#[test] #[test]
fn test_try_fold_unit_none() { fn test_try_fold_unit_none() {
let v: std::collections::VecDeque<()> = [(); 10].iter().cloned().collect(); let v: std::collections::VecDeque<()> = [(); 10].iter().cloned().collect();
@ -1534,7 +1534,7 @@ fn test_try_rfold_rotated() {
#[test] #[test]
fn test_try_rfold_moves_iter() { fn test_try_rfold_moves_iter() {
let v : VecDeque<_> = [10, 20, 30, 40, 100, 60, 70, 80, 90].iter().collect(); let v: VecDeque<_> = [10, 20, 30, 40, 100, 60, 70, 80, 90].iter().collect();
let mut iter = v.into_iter(); let mut iter = v.into_iter();
assert_eq!(iter.try_rfold(0_i8, |acc, &x| acc.checked_add(x)), None); assert_eq!(iter.try_rfold(0_i8, |acc, &x| acc.checked_add(x)), None);
assert_eq!(iter.next_back(), Some(&70)); assert_eq!(iter.next_back(), Some(&70));

View File

@ -44,14 +44,14 @@ CloneTypeFoldableImpls! {
pub type ConstEvalRawResult<'tcx> = Result<RawConst<'tcx>, ErrorHandled>; pub type ConstEvalRawResult<'tcx> = Result<RawConst<'tcx>, ErrorHandled>;
pub type ConstEvalResult<'tcx> = Result<&'tcx ty::Const<'tcx>, ErrorHandled>; pub type ConstEvalResult<'tcx> = Result<&'tcx ty::Const<'tcx>, ErrorHandled>;
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)] #[derive(Clone, Debug)]
pub struct ConstEvalErr<'tcx> { pub struct ConstEvalErr<'tcx> {
pub span: Span, pub span: Span,
pub error: crate::mir::interpret::InterpError<'tcx>, pub error: crate::mir::interpret::InterpError<'tcx>,
pub stacktrace: Vec<FrameInfo<'tcx>>, pub stacktrace: Vec<FrameInfo<'tcx>>,
} }
#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)] #[derive(Clone, Debug)]
pub struct FrameInfo<'tcx> { pub struct FrameInfo<'tcx> {
/// This span is in the caller. /// This span is in the caller.
pub call_site: Span, pub call_site: Span,
@ -331,7 +331,7 @@ impl<O: fmt::Debug> fmt::Debug for PanicInfo<O> {
/// Error information for when the program we executed turned out not to actually be a valid /// Error information for when the program we executed turned out not to actually be a valid
/// program. This cannot happen in stand-alone Miri, but it can happen during CTFE/ConstProp /// program. This cannot happen in stand-alone Miri, but it can happen during CTFE/ConstProp
/// where we work on generic code or execution does not have all information available. /// where we work on generic code or execution does not have all information available.
#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)] #[derive(Clone, HashStable)]
pub enum InvalidProgramInfo<'tcx> { pub enum InvalidProgramInfo<'tcx> {
/// Resolution can fail if we are in a too generic context. /// Resolution can fail if we are in a too generic context.
TooGeneric, TooGeneric,
@ -361,7 +361,7 @@ impl fmt::Debug for InvalidProgramInfo<'tcx> {
} }
/// Error information for when the program caused Undefined Behavior. /// Error information for when the program caused Undefined Behavior.
#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)] #[derive(Clone, HashStable)]
pub enum UndefinedBehaviorInfo { pub enum UndefinedBehaviorInfo {
/// Free-form case. Only for errors that are never caught! /// Free-form case. Only for errors that are never caught!
Ub(String), Ub(String),
@ -394,11 +394,15 @@ impl fmt::Debug for UndefinedBehaviorInfo {
/// ///
/// Currently, we also use this as fall-back error kind for errors that have not been /// Currently, we also use this as fall-back error kind for errors that have not been
/// categorized yet. /// categorized yet.
#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)] #[derive(Clone, HashStable)]
pub enum UnsupportedOpInfo<'tcx> { pub enum UnsupportedOpInfo<'tcx> {
/// Free-form case. Only for errors that are never caught! /// Free-form case. Only for errors that are never caught!
Unsupported(String), Unsupported(String),
/// When const-prop encounters a situation it does not support, it raises this error.
/// This must not allocate for performance reasons.
ConstPropUnsupported(&'tcx str),
// -- Everything below is not categorized yet -- // -- Everything below is not categorized yet --
FunctionAbiMismatch(Abi, Abi), FunctionAbiMismatch(Abi, Abi),
FunctionArgMismatch(Ty<'tcx>, Ty<'tcx>), FunctionArgMismatch(Ty<'tcx>, Ty<'tcx>),
@ -559,13 +563,15 @@ impl fmt::Debug for UnsupportedOpInfo<'tcx> {
not a power of two"), not a power of two"),
Unsupported(ref msg) => Unsupported(ref msg) =>
write!(f, "{}", msg), write!(f, "{}", msg),
ConstPropUnsupported(ref msg) =>
write!(f, "Constant propagation encountered an unsupported situation: {}", msg),
} }
} }
} }
/// Error information for when the program exhausted the resources granted to it /// Error information for when the program exhausted the resources granted to it
/// by the interpreter. /// by the interpreter.
#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)] #[derive(Clone, HashStable)]
pub enum ResourceExhaustionInfo { pub enum ResourceExhaustionInfo {
/// The stack grew too big. /// The stack grew too big.
StackFrameLimitReached, StackFrameLimitReached,
@ -586,7 +592,7 @@ impl fmt::Debug for ResourceExhaustionInfo {
} }
} }
#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)] #[derive(Clone, HashStable)]
pub enum InterpError<'tcx> { pub enum InterpError<'tcx> {
/// The program panicked. /// The program panicked.
Panic(PanicInfo<u64>), Panic(PanicInfo<u64>),

View File

@ -94,9 +94,6 @@ pub struct Session {
/// The maximum length of types during monomorphization. /// The maximum length of types during monomorphization.
pub type_length_limit: Once<usize>, pub type_length_limit: Once<usize>,
/// The maximum number of stackframes allowed in const eval.
pub const_eval_stack_frame_limit: usize,
/// Map from imported macro spans (which consist of /// Map from imported macro spans (which consist of
/// the localized span for the macro body) to the /// the localized span for the macro body) to the
/// macro name and definition span in the source crate. /// macro name and definition span in the source crate.
@ -1158,7 +1155,6 @@ fn build_session_(
features: Once::new(), features: Once::new(),
recursion_limit: Once::new(), recursion_limit: Once::new(),
type_length_limit: Once::new(), type_length_limit: Once::new(),
const_eval_stack_frame_limit: 100,
imported_macro_spans: OneThread::new(RefCell::new(FxHashMap::default())), imported_macro_spans: OneThread::new(RefCell::new(FxHashMap::default())),
incr_comp_session: OneThread::new(RefCell::new(IncrCompSession::NotInitialized)), incr_comp_session: OneThread::new(RefCell::new(IncrCompSession::NotInitialized)),
cgu_reuse_tracker, cgu_reuse_tracker,

View File

@ -69,7 +69,7 @@ pub enum BoundRegion {
impl BoundRegion { impl BoundRegion {
pub fn is_named(&self) -> bool { pub fn is_named(&self) -> bool {
match *self { match *self {
BoundRegion::BrNamed(..) => true, BoundRegion::BrNamed(_, name) => name != kw::UnderscoreLifetime,
_ => false, _ => false,
} }
} }

View File

@ -41,7 +41,7 @@ use rustc::util::common::{set_time_depth, time, print_time_passes_entry, ErrorRe
use rustc_metadata::locator; use rustc_metadata::locator;
use rustc_codegen_utils::codegen_backend::CodegenBackend; use rustc_codegen_utils::codegen_backend::CodegenBackend;
use errors::{PResult, registry::Registry}; use errors::{PResult, registry::Registry};
use rustc_interface::interface; use rustc_interface::{interface, Queries};
use rustc_interface::util::get_codegen_sysroot; use rustc_interface::util::get_codegen_sysroot;
use rustc_data_structures::sync::SeqCst; use rustc_data_structures::sync::SeqCst;
use rustc_feature::{find_gated_cfg, UnstableFeatures}; use rustc_feature::{find_gated_cfg, UnstableFeatures};
@ -98,17 +98,29 @@ pub trait Callbacks {
fn config(&mut self, _config: &mut interface::Config) {} fn config(&mut self, _config: &mut interface::Config) {}
/// Called after parsing. Return value instructs the compiler whether to /// Called after parsing. Return value instructs the compiler whether to
/// continue the compilation afterwards (defaults to `Compilation::Continue`) /// continue the compilation afterwards (defaults to `Compilation::Continue`)
fn after_parsing(&mut self, _compiler: &interface::Compiler) -> Compilation { fn after_parsing<'tcx>(
&mut self,
_compiler: &interface::Compiler,
_queries: &'tcx Queries<'tcx>,
) -> Compilation {
Compilation::Continue Compilation::Continue
} }
/// Called after expansion. Return value instructs the compiler whether to /// Called after expansion. Return value instructs the compiler whether to
/// continue the compilation afterwards (defaults to `Compilation::Continue`) /// continue the compilation afterwards (defaults to `Compilation::Continue`)
fn after_expansion(&mut self, _compiler: &interface::Compiler) -> Compilation { fn after_expansion<'tcx>(
&mut self,
_compiler: &interface::Compiler,
_queries: &'tcx Queries<'tcx>,
) -> Compilation {
Compilation::Continue Compilation::Continue
} }
/// Called after analysis. Return value instructs the compiler whether to /// Called after analysis. Return value instructs the compiler whether to
/// continue the compilation afterwards (defaults to `Compilation::Continue`) /// continue the compilation afterwards (defaults to `Compilation::Continue`)
fn after_analysis(&mut self, _compiler: &interface::Compiler) -> Compilation { fn after_analysis<'tcx>(
&mut self,
_compiler: &interface::Compiler,
_queries: &'tcx Queries<'tcx>,
) -> Compilation {
Compilation::Continue Compilation::Continue
} }
} }
@ -312,7 +324,7 @@ pub fn run_compiler(
return early_exit(); return early_exit();
} }
if callbacks.after_parsing(compiler) == Compilation::Stop { if callbacks.after_parsing(compiler, queries) == Compilation::Stop {
return early_exit(); return early_exit();
} }
@ -333,7 +345,7 @@ pub fn run_compiler(
} }
queries.expansion()?; queries.expansion()?;
if callbacks.after_expansion(compiler) == Compilation::Stop { if callbacks.after_expansion(compiler, queries) == Compilation::Stop {
return early_exit(); return early_exit();
} }
@ -382,7 +394,7 @@ pub fn run_compiler(
queries.global_ctxt()?.peek_mut().enter(|tcx| tcx.analysis(LOCAL_CRATE))?; queries.global_ctxt()?.peek_mut().enter(|tcx| tcx.analysis(LOCAL_CRATE))?;
if callbacks.after_analysis(compiler) == Compilation::Stop { if callbacks.after_analysis(compiler, queries) == Compilation::Stop {
return early_exit(); return early_exit();
} }

View File

@ -107,6 +107,7 @@ E0199: include_str!("./error_codes/E0199.md"),
E0200: include_str!("./error_codes/E0200.md"), E0200: include_str!("./error_codes/E0200.md"),
E0201: include_str!("./error_codes/E0201.md"), E0201: include_str!("./error_codes/E0201.md"),
E0202: include_str!("./error_codes/E0202.md"), E0202: include_str!("./error_codes/E0202.md"),
E0203: include_str!("./error_codes/E0203.md"),
E0204: include_str!("./error_codes/E0204.md"), E0204: include_str!("./error_codes/E0204.md"),
E0205: include_str!("./error_codes/E0205.md"), E0205: include_str!("./error_codes/E0205.md"),
E0206: include_str!("./error_codes/E0206.md"), E0206: include_str!("./error_codes/E0206.md"),
@ -446,8 +447,6 @@ E0745: include_str!("./error_codes/E0745.md"),
// E0190, // deprecated: can only cast a &-pointer to an &-object // E0190, // deprecated: can only cast a &-pointer to an &-object
// E0194, // merged into E0403 // E0194, // merged into E0403
// E0196, // cannot determine a type for this closure // E0196, // cannot determine a type for this closure
E0203, // type parameter has more than one relaxed default bound,
// and only one is supported
E0208, E0208,
// E0209, // builtin traits can only be implemented on structs or enums // E0209, // builtin traits can only be implemented on structs or enums
E0212, // cannot extract an associated type from a higher-ranked trait bound E0212, // cannot extract an associated type from a higher-ranked trait bound

View File

@ -0,0 +1,18 @@
Having multiple relaxed default bounds is unsupported.
Erroneous code example:
```compile_fail,E0203
struct Bad<T: ?Sized + ?Send>{
inner: T
}
```
Here the type `T` cannot have a relaxed bound for multiple default traits
(`Sized` and `Send`). This can be fixed by only using one relaxed bound.
```
struct Good<T: ?Sized>{
inner: T
}
```

View File

@ -18,6 +18,7 @@ pub mod util;
mod proc_macro_decls; mod proc_macro_decls;
pub use interface::{run_compiler, Config}; pub use interface::{run_compiler, Config};
pub use queries::Queries;
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;

View File

@ -78,17 +78,7 @@ impl OutlivesSuggestionBuilder<'a> {
match name.source { match name.source {
RegionNameSource::NamedEarlyBoundRegion(..) RegionNameSource::NamedEarlyBoundRegion(..)
| RegionNameSource::NamedFreeRegion(..) | RegionNameSource::NamedFreeRegion(..)
| RegionNameSource::Static => { | RegionNameSource::Static => true,
// FIXME: This is a bit hacky. We should ideally have a semantic way for checking
// if the name is `'_`...
if name.name().with(|name| name != "'_") {
debug!("Region {:?} is suggestable", name);
true
} else {
debug!("Region {:?} is NOT suggestable", name);
false
}
}
// Don't give suggestions for upvars, closure return types, or other unnamable // Don't give suggestions for upvars, closure return types, or other unnamable
// regions. // regions.
@ -98,7 +88,8 @@ impl OutlivesSuggestionBuilder<'a> {
| RegionNameSource::MatchedAdtAndSegment(..) | RegionNameSource::MatchedAdtAndSegment(..)
| RegionNameSource::AnonRegionFromUpvar(..) | RegionNameSource::AnonRegionFromUpvar(..)
| RegionNameSource::AnonRegionFromOutput(..) | RegionNameSource::AnonRegionFromOutput(..)
| RegionNameSource::AnonRegionFromYieldTy(..) => { | RegionNameSource::AnonRegionFromYieldTy(..)
| RegionNameSource::AnonRegionFromAsyncFn(..) => {
debug!("Region {:?} is NOT suggestable", name); debug!("Region {:?} is NOT suggestable", name);
false false
} }

View File

@ -13,13 +13,13 @@ use rustc::hir::def_id::DefId;
use rustc::infer::InferCtxt; use rustc::infer::InferCtxt;
use rustc::mir::{Local, Body}; use rustc::mir::{Local, Body};
use rustc::ty::subst::{SubstsRef, GenericArgKind}; use rustc::ty::subst::{SubstsRef, GenericArgKind};
use rustc::ty::{self, RegionKind, RegionVid, Ty, TyCtxt}; use rustc::ty::{self, RegionVid, Ty, TyCtxt};
use rustc::ty::print::RegionHighlightMode; use rustc::ty::print::RegionHighlightMode;
use rustc_index::vec::IndexVec; use rustc_index::vec::IndexVec;
use rustc_errors::DiagnosticBuilder; use rustc_errors::DiagnosticBuilder;
use syntax::symbol::kw; use syntax::symbol::kw;
use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashMap;
use syntax_pos::{Span, symbol::Symbol}; use syntax_pos::{Span, symbol::Symbol, DUMMY_SP};
/// A name for a particular region used in emitting diagnostics. This name could be a generated /// A name for a particular region used in emitting diagnostics. This name could be a generated
/// name like `'1`, a name used by the user like `'a`, or a name like `'static`. /// name like `'1`, a name used by the user like `'a`, or a name like `'static`.
@ -55,7 +55,10 @@ crate enum RegionNameSource {
AnonRegionFromUpvar(Span, String), AnonRegionFromUpvar(Span, String),
/// The region corresponding to the return type of a closure. /// The region corresponding to the return type of a closure.
AnonRegionFromOutput(Span, String, String), AnonRegionFromOutput(Span, String, String),
/// The region from a type yielded by a generator.
AnonRegionFromYieldTy(Span, String), AnonRegionFromYieldTy(Span, String),
/// An anonymous region from an async fn.
AnonRegionFromAsyncFn(Span),
} }
/// Records region names that have been assigned before so that we can use the same ones in later /// Records region names that have been assigned before so that we can use the same ones in later
@ -113,14 +116,11 @@ impl RegionName {
RegionNameSource::MatchedAdtAndSegment(..) | RegionNameSource::MatchedAdtAndSegment(..) |
RegionNameSource::AnonRegionFromUpvar(..) | RegionNameSource::AnonRegionFromUpvar(..) |
RegionNameSource::AnonRegionFromOutput(..) | RegionNameSource::AnonRegionFromOutput(..) |
RegionNameSource::AnonRegionFromYieldTy(..) => false, RegionNameSource::AnonRegionFromYieldTy(..) |
RegionNameSource::AnonRegionFromAsyncFn(..) => false,
} }
} }
crate fn name(&self) -> Symbol {
self.name
}
crate fn highlight_region_name(&self, diag: &mut DiagnosticBuilder<'_>) { crate fn highlight_region_name(&self, diag: &mut DiagnosticBuilder<'_>) {
match &self.source { match &self.source {
RegionNameSource::NamedFreeRegion(span) RegionNameSource::NamedFreeRegion(span)
@ -137,7 +137,8 @@ impl RegionName {
RegionNameSource::CannotMatchHirTy(span, type_name) => { RegionNameSource::CannotMatchHirTy(span, type_name) => {
diag.span_label(*span, format!("has type `{}`", type_name)); diag.span_label(*span, format!("has type `{}`", type_name));
} }
RegionNameSource::MatchedHirTy(span) => { RegionNameSource::MatchedHirTy(span) |
RegionNameSource::AnonRegionFromAsyncFn(span) => {
diag.span_label( diag.span_label(
*span, *span,
format!("let's call the lifetime of this reference `{}`", self), format!("let's call the lifetime of this reference `{}`", self),
@ -270,7 +271,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
match error_region { match error_region {
ty::ReEarlyBound(ebr) => { ty::ReEarlyBound(ebr) => {
if ebr.has_name() { if ebr.has_name() {
let span = self.get_named_span(tcx, error_region, ebr.name); let span = tcx.hir().span_if_local(ebr.def_id).unwrap_or(DUMMY_SP);
Some(RegionName { Some(RegionName {
name: ebr.name, name: ebr.name,
source: RegionNameSource::NamedEarlyBoundRegion(span), source: RegionNameSource::NamedEarlyBoundRegion(span),
@ -286,12 +287,30 @@ impl<'tcx> RegionInferenceContext<'tcx> {
}), }),
ty::ReFree(free_region) => match free_region.bound_region { ty::ReFree(free_region) => match free_region.bound_region {
ty::BoundRegion::BrNamed(_, name) => { ty::BoundRegion::BrNamed(region_def_id, name) => {
let span = self.get_named_span(tcx, error_region, name); // Get the span to point to, even if we don't use the name.
Some(RegionName { let span = tcx.hir().span_if_local(region_def_id).unwrap_or(DUMMY_SP);
name, debug!("bound region named: {:?}, is_named: {:?}",
source: RegionNameSource::NamedFreeRegion(span), name, free_region.bound_region.is_named());
})
if free_region.bound_region.is_named() {
// A named region that is actually named.
Some(RegionName {
name,
source: RegionNameSource::NamedFreeRegion(span),
})
} else {
// If we spuriously thought that the region is named, we should let the
// system generate a true name for error messages. Currently this can
// happen if we have an elided name in an async fn for example: the
// compiler will generate a region named `'_`, but reporting such a name is
// not actually useful, so we synthesize a name for it instead.
let name = renctx.synthesize_region_name();
Some(RegionName {
name,
source: RegionNameSource::AnonRegionFromAsyncFn(span),
})
}
} }
ty::BoundRegion::BrEnv => { ty::BoundRegion::BrEnv => {
@ -350,40 +369,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
} }
} }
/// Gets a span of a named region to provide context for error messages that
/// mention that span, for example:
///
/// ```
/// |
/// | fn two_regions<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
/// | -- -- lifetime `'b` defined here
/// | |
/// | lifetime `'a` defined here
/// |
/// | with_signature(cell, t, |cell, t| require(cell, t));
/// | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must
/// | outlive `'a`
/// ```
fn get_named_span(
&self,
tcx: TyCtxt<'tcx>,
error_region: &RegionKind,
name: Symbol,
) -> Span {
let scope = error_region.free_region_binding_scope(tcx);
let node = tcx.hir().as_local_hir_id(scope).unwrap_or(hir::DUMMY_HIR_ID);
let span = tcx.sess.source_map().def_span(tcx.hir().span(node));
if let Some(param) = tcx.hir()
.get_generics(scope)
.and_then(|generics| generics.get_named(name))
{
param.span
} else {
span
}
}
/// Finds an argument that contains `fr` and label it with a fully /// Finds an argument that contains `fr` and label it with a fully
/// elaborated type, returning something like `'1`. Result looks /// elaborated type, returning something like `'1`. Result looks
/// like: /// like:

View File

@ -548,7 +548,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
info!("ENTERING({}) {}", self.cur_frame(), self.frame().instance); info!("ENTERING({}) {}", self.cur_frame(), self.frame().instance);
if self.stack.len() > self.tcx.sess.const_eval_stack_frame_limit { if self.stack.len() > *self.tcx.sess.recursion_limit.get() {
throw_exhaust!(StackFrameLimitReached) throw_exhaust!(StackFrameLimitReached)
} else { } else {
Ok(()) Ok(())

View File

@ -560,7 +560,7 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> {
trace!("visit_statement: statement={:?} location={:?}", statement, location); trace!("visit_statement: statement={:?} location={:?}", statement, location);
match statement.kind { match statement.kind {
StatementKind::Assign(..) => { StatementKind::Assign(..) | StatementKind::SetDiscriminant { .. } => {
self.super_statement(statement, location); self.super_statement(statement, location);
} }
StatementKind::FakeRead(FakeReadCause::ForMatchedPlace, _) => { StatementKind::FakeRead(FakeReadCause::ForMatchedPlace, _) => {
@ -568,7 +568,6 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> {
} }
// FIXME(eddyb) should these really do nothing? // FIXME(eddyb) should these really do nothing?
StatementKind::FakeRead(..) | StatementKind::FakeRead(..) |
StatementKind::SetDiscriminant { .. } |
StatementKind::StorageLive(_) | StatementKind::StorageLive(_) |
StatementKind::StorageDead(_) | StatementKind::StorageDead(_) |
StatementKind::InlineAsm {..} | StatementKind::InlineAsm {..} |

View File

@ -168,14 +168,14 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine {
_ret: Option<(PlaceTy<'tcx>, BasicBlock)>, _ret: Option<(PlaceTy<'tcx>, BasicBlock)>,
_unwind: Option<BasicBlock> _unwind: Option<BasicBlock>
) -> InterpResult<'tcx> { ) -> InterpResult<'tcx> {
throw_unsup_format!("calling intrinsics isn't supported in ConstProp"); throw_unsup!(ConstPropUnsupported("calling intrinsics isn't supported in ConstProp"));
} }
fn ptr_to_int( fn ptr_to_int(
_mem: &Memory<'mir, 'tcx, Self>, _mem: &Memory<'mir, 'tcx, Self>,
_ptr: Pointer, _ptr: Pointer,
) -> InterpResult<'tcx, u64> { ) -> InterpResult<'tcx, u64> {
throw_unsup_format!("ptr-to-int casts aren't supported in ConstProp"); throw_unsup!(ConstPropUnsupported("ptr-to-int casts aren't supported in ConstProp"));
} }
fn binary_ptr_op( fn binary_ptr_op(
@ -185,7 +185,8 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine {
_right: ImmTy<'tcx>, _right: ImmTy<'tcx>,
) -> InterpResult<'tcx, (Scalar, bool, Ty<'tcx>)> { ) -> InterpResult<'tcx, (Scalar, bool, Ty<'tcx>)> {
// We can't do this because aliasing of memory can differ between const eval and llvm // We can't do this because aliasing of memory can differ between const eval and llvm
throw_unsup_format!("pointer arithmetic or comparisons aren't supported in ConstProp"); throw_unsup!(ConstPropUnsupported("pointer arithmetic or comparisons aren't supported \
in ConstProp"));
} }
fn find_foreign_static( fn find_foreign_static(
@ -218,7 +219,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine {
_ecx: &mut InterpCx<'mir, 'tcx, Self>, _ecx: &mut InterpCx<'mir, 'tcx, Self>,
_dest: PlaceTy<'tcx>, _dest: PlaceTy<'tcx>,
) -> InterpResult<'tcx> { ) -> InterpResult<'tcx> {
throw_unsup_format!("can't const prop `box` keyword"); throw_unsup!(ConstPropUnsupported("can't const prop `box` keyword"));
} }
fn access_local( fn access_local(
@ -229,7 +230,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine {
let l = &frame.locals[local]; let l = &frame.locals[local];
if l.value == LocalValue::Uninitialized { if l.value == LocalValue::Uninitialized {
throw_unsup_format!("tried to access an uninitialized local"); throw_unsup!(ConstPropUnsupported("tried to access an uninitialized local"));
} }
l.access() l.access()
@ -241,7 +242,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine {
// if the static allocation is mutable or if it has relocations (it may be legal to mutate // if the static allocation is mutable or if it has relocations (it may be legal to mutate
// the memory behind that in the future), then we can't const prop it // the memory behind that in the future), then we can't const prop it
if allocation.mutability == Mutability::Mutable || allocation.relocations().len() > 0 { if allocation.mutability == Mutability::Mutable || allocation.relocations().len() > 0 {
throw_unsup_format!("can't eval mutable statics in ConstProp"); throw_unsup!(ConstPropUnsupported("can't eval mutable statics in ConstProp"));
} }
Ok(()) Ok(())
@ -389,9 +390,26 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
let r = match f(self) { let r = match f(self) {
Ok(val) => Some(val), Ok(val) => Some(val),
Err(error) => { Err(error) => {
use rustc::mir::interpret::InterpError::*; use rustc::mir::interpret::{
UnsupportedOpInfo,
UndefinedBehaviorInfo,
InterpError::*
};
match error.kind { match error.kind {
Exit(_) => bug!("the CTFE program cannot exit"), Exit(_) => bug!("the CTFE program cannot exit"),
// Some error shouldn't come up because creating them causes
// an allocation, which we should avoid. When that happens,
// dedicated error variants should be introduced instead.
// Only test this in debug builds though to avoid disruptions.
Unsupported(UnsupportedOpInfo::Unsupported(_))
| Unsupported(UnsupportedOpInfo::ValidationFailure(_))
| UndefinedBehavior(UndefinedBehaviorInfo::Ub(_))
| UndefinedBehavior(UndefinedBehaviorInfo::UbExperimental(_))
if cfg!(debug_assertions) => {
bug!("const-prop encountered allocating error: {:?}", error.kind);
}
Unsupported(_) Unsupported(_)
| UndefinedBehavior(_) | UndefinedBehavior(_)
| InvalidProgram(_) | InvalidProgram(_)

View File

@ -225,7 +225,7 @@ fn check_statement(
StatementKind::FakeRead(_, place) => check_place(tcx, place, span, def_id, body), StatementKind::FakeRead(_, place) => check_place(tcx, place, span, def_id, body),
// just an assignment // just an assignment
StatementKind::SetDiscriminant { .. } => Ok(()), StatementKind::SetDiscriminant { place, .. } => check_place(tcx, place, span, def_id, body),
| StatementKind::InlineAsm { .. } => { | StatementKind::InlineAsm { .. } => {
Err((span, "cannot use inline assembly in const fn".into())) Err((span, "cannot use inline assembly in const fn".into()))

View File

@ -37,22 +37,30 @@ pub fn calc_result<'a>(
let result = match (&desc.should_panic, task_result) { let result = match (&desc.should_panic, task_result) {
(&ShouldPanic::No, Ok(())) | (&ShouldPanic::Yes, Err(_)) => TestResult::TrOk, (&ShouldPanic::No, Ok(())) | (&ShouldPanic::Yes, Err(_)) => TestResult::TrOk,
(&ShouldPanic::YesWithMessage(msg), Err(ref err)) => { (&ShouldPanic::YesWithMessage(msg), Err(ref err)) => {
if err let maybe_panic_str = err
.downcast_ref::<String>() .downcast_ref::<String>()
.map(|e| &**e) .map(|e| &**e)
.or_else(|| err.downcast_ref::<&'static str>().map(|e| *e)) .or_else(|| err.downcast_ref::<&'static str>().map(|e| *e));
.map(|e| e.contains(msg))
.unwrap_or(false) if maybe_panic_str.map(|e| e.contains(msg)).unwrap_or(false) {
{
TestResult::TrOk TestResult::TrOk
} else if desc.allow_fail {
TestResult::TrAllowedFail
} else if let Some(panic_str) = maybe_panic_str {
TestResult::TrFailedMsg(format!(
r#"panic did not contain expected string
panic message: `{:?}`,
expected substring: `{:?}`"#,
panic_str, msg
))
} else { } else {
if desc.allow_fail { TestResult::TrFailedMsg(format!(
TestResult::TrAllowedFail r#"expected panic with string value,
} else { found non-string value: `{:?}`
TestResult::TrFailedMsg( expected substring: `{:?}`"#,
format!("panic did not include expected string '{}'", msg) (**err).type_id(),
) msg
} ))
} }
} }
(&ShouldPanic::Yes, Ok(())) => { (&ShouldPanic::Yes, Ok(())) => {

View File

@ -15,6 +15,7 @@ use crate::{
// TestType, TrFailedMsg, TrIgnored, TrOk, // TestType, TrFailedMsg, TrIgnored, TrOk,
}, },
}; };
use std::any::TypeId;
use std::sync::mpsc::channel; use std::sync::mpsc::channel;
use std::time::Duration; use std::time::Duration;
@ -84,7 +85,7 @@ pub fn do_not_run_ignored_tests() {
let (tx, rx) = channel(); let (tx, rx) = channel();
run_test(&TestOpts::new(), false, desc, RunStrategy::InProcess, tx, Concurrent::No); run_test(&TestOpts::new(), false, desc, RunStrategy::InProcess, tx, Concurrent::No);
let result = rx.recv().unwrap().result; let result = rx.recv().unwrap().result;
assert!(result != TrOk); assert_ne!(result, TrOk);
} }
#[test] #[test]
@ -103,7 +104,7 @@ pub fn ignored_tests_result_in_ignored() {
let (tx, rx) = channel(); let (tx, rx) = channel();
run_test(&TestOpts::new(), false, desc, RunStrategy::InProcess, tx, Concurrent::No); run_test(&TestOpts::new(), false, desc, RunStrategy::InProcess, tx, Concurrent::No);
let result = rx.recv().unwrap().result; let result = rx.recv().unwrap().result;
assert!(result == TrIgnored); assert_eq!(result, TrIgnored);
} }
// FIXME: Re-enable emscripten once it can catch panics again (introduced by #65251) // FIXME: Re-enable emscripten once it can catch panics again (introduced by #65251)
@ -126,7 +127,7 @@ fn test_should_panic() {
let (tx, rx) = channel(); let (tx, rx) = channel();
run_test(&TestOpts::new(), false, desc, RunStrategy::InProcess, tx, Concurrent::No); run_test(&TestOpts::new(), false, desc, RunStrategy::InProcess, tx, Concurrent::No);
let result = rx.recv().unwrap().result; let result = rx.recv().unwrap().result;
assert!(result == TrOk); assert_eq!(result, TrOk);
} }
// FIXME: Re-enable emscripten once it can catch panics again (introduced by #65251) // FIXME: Re-enable emscripten once it can catch panics again (introduced by #65251)
@ -149,7 +150,7 @@ fn test_should_panic_good_message() {
let (tx, rx) = channel(); let (tx, rx) = channel();
run_test(&TestOpts::new(), false, desc, RunStrategy::InProcess, tx, Concurrent::No); run_test(&TestOpts::new(), false, desc, RunStrategy::InProcess, tx, Concurrent::No);
let result = rx.recv().unwrap().result; let result = rx.recv().unwrap().result;
assert!(result == TrOk); assert_eq!(result, TrOk);
} }
// FIXME: Re-enable emscripten once it can catch panics again (introduced by #65251) // FIXME: Re-enable emscripten once it can catch panics again (introduced by #65251)
@ -161,7 +162,9 @@ fn test_should_panic_bad_message() {
panic!("an error message"); panic!("an error message");
} }
let expected = "foobar"; let expected = "foobar";
let failed_msg = "panic did not include expected string"; let failed_msg = r#"panic did not contain expected string
panic message: `"an error message"`,
expected substring: `"foobar"`"#;
let desc = TestDescAndFn { let desc = TestDescAndFn {
desc: TestDesc { desc: TestDesc {
name: StaticTestName("whatever"), name: StaticTestName("whatever"),
@ -175,7 +178,35 @@ fn test_should_panic_bad_message() {
let (tx, rx) = channel(); let (tx, rx) = channel();
run_test(&TestOpts::new(), false, desc, RunStrategy::InProcess, tx, Concurrent::No); run_test(&TestOpts::new(), false, desc, RunStrategy::InProcess, tx, Concurrent::No);
let result = rx.recv().unwrap().result; let result = rx.recv().unwrap().result;
assert!(result == TrFailedMsg(format!("{} '{}'", failed_msg, expected))); assert_eq!(result, TrFailedMsg(failed_msg.to_string()));
}
// FIXME: Re-enable emscripten once it can catch panics again (introduced by #65251)
#[test]
#[cfg(not(target_os = "emscripten"))]
fn test_should_panic_non_string_message_type() {
use crate::tests::TrFailedMsg;
fn f() {
panic!(1i32);
}
let expected = "foobar";
let failed_msg = format!(r#"expected panic with string value,
found non-string value: `{:?}`
expected substring: `"foobar"`"#, TypeId::of::<i32>());
let desc = TestDescAndFn {
desc: TestDesc {
name: StaticTestName("whatever"),
ignore: false,
should_panic: ShouldPanic::YesWithMessage(expected),
allow_fail: false,
test_type: TestType::Unknown,
},
testfn: DynTestFn(Box::new(f)),
};
let (tx, rx) = channel();
run_test(&TestOpts::new(), false, desc, RunStrategy::InProcess, tx, Concurrent::No);
let result = rx.recv().unwrap().result;
assert_eq!(result, TrFailedMsg(failed_msg));
} }
// FIXME: Re-enable emscripten once it can catch panics again (introduced by #65251) // FIXME: Re-enable emscripten once it can catch panics again (introduced by #65251)
@ -196,7 +227,7 @@ fn test_should_panic_but_succeeds() {
let (tx, rx) = channel(); let (tx, rx) = channel();
run_test(&TestOpts::new(), false, desc, RunStrategy::InProcess, tx, Concurrent::No); run_test(&TestOpts::new(), false, desc, RunStrategy::InProcess, tx, Concurrent::No);
let result = rx.recv().unwrap().result; let result = rx.recv().unwrap().result;
assert!(result == TrFailedMsg("test did not panic as expected".to_string())); assert_eq!(result, TrFailedMsg("test did not panic as expected".to_string()));
} }
fn report_time_test_template(report_time: bool) -> Option<TestExecTime> { fn report_time_test_template(report_time: bool) -> Option<TestExecTime> {
@ -570,7 +601,7 @@ pub fn sort_tests() {
]; ];
for (a, b) in expected.iter().zip(filtered) { for (a, b) in expected.iter().zip(filtered) {
assert!(*a == b.desc.name.to_string()); assert_eq!(*a, b.desc.name.to_string());
} }
} }

View File

@ -12,12 +12,12 @@ error: lifetime may not live long enough
LL | async fn do_sth<'a>( LL | async fn do_sth<'a>(
| -- lifetime `'a` defined here | -- lifetime `'a` defined here
LL | &'a self, foo: &dyn Foo LL | &'a self, foo: &dyn Foo
| - lifetime `'_` defined here | - let's call the lifetime of this reference `'1`
LL | ) -> &dyn Foo LL | ) -> &dyn Foo
LL | / { LL | / {
LL | | foo LL | | foo
LL | | } LL | | }
| |_____^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'_` | |_____^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1`
error: aborting due to 2 previous errors error: aborting due to 2 previous errors

View File

@ -42,3 +42,4 @@ LL | struct S5<T>(*const T) where T: ?Trait<'static> + ?Sized;
error: aborting due to 6 previous errors error: aborting due to 6 previous errors
For more information about this error, try `rustc --explain E0203`.

View File

@ -2,11 +2,11 @@ error: lifetime may not live long enough
--> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:48 --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:48
| |
LL | async fn f(self: Pin<&Self>) -> impl Clone { self } LL | async fn f(self: Pin<&Self>) -> impl Clone { self }
| - ^^^^^^^^ returning this value requires that `'_` must outlive `'static` | - ^^^^^^^^ returning this value requires that `'1` must outlive `'static`
| | | |
| lifetime `'_` defined here | let's call the lifetime of this reference `'1`
| |
help: to allow this `impl Trait` to capture borrowed data with lifetime `'_`, add `'_` as a constraint help: to allow this `impl Trait` to capture borrowed data with lifetime `'1`, add `'_` as a constraint
| |
LL | async fn f(self: Pin<&Self>) -> impl Clone + '_ { self } LL | async fn f(self: Pin<&Self>) -> impl Clone + '_ { self }
| ^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^

View File

@ -10,19 +10,19 @@ error: lifetime may not live long enough
--> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:8:52 --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:8:52
| |
LL | async fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f } LL | async fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f }
| - ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` | - - ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
| | | | |
| lifetime `'_` defined here | | let's call the lifetime of this reference `'1`
| lifetime `'_` defined here | let's call the lifetime of this reference `'2`
error: lifetime may not live long enough error: lifetime may not live long enough
--> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:11:75 --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:11:75
| |
LL | async fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) } LL | async fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) }
| - ^^^^^^^^^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` | - - ^^^^^^^^^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
| | | | |
| lifetime `'_` defined here | | let's call the lifetime of this reference `'1`
| lifetime `'_` defined here | let's call the lifetime of this reference `'2`
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:17:58 --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:17:58
@ -36,8 +36,9 @@ error: lifetime may not live long enough
--> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:17:64 --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:17:64
| |
LL | async fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg } LL | async fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg }
| -- - lifetime `'_` defined here ^^^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'a` | -- - ^^^ function was supposed to return data with lifetime `'1` but it is returning data with lifetime `'a`
| | | | |
| | let's call the lifetime of this reference `'1`
| lifetime `'a` defined here | lifetime `'a` defined here
error: aborting due to 5 previous errors error: aborting due to 5 previous errors

View File

@ -10,12 +10,11 @@ error: lifetime may not live long enough
--> $DIR/lt-ref-self-async.rs:13:9 --> $DIR/lt-ref-self-async.rs:13:9
| |
LL | async fn ref_self(&self, f: &u32) -> &u32 { LL | async fn ref_self(&self, f: &u32) -> &u32 {
| - | - - let's call the lifetime of this reference `'1`
| | | |
| lifetime `'_` defined here | let's call the lifetime of this reference `'2`
| lifetime `'_` defined here
LL | f LL | f
| ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> $DIR/lt-ref-self-async.rs:18:48 --> $DIR/lt-ref-self-async.rs:18:48
@ -29,12 +28,11 @@ error: lifetime may not live long enough
--> $DIR/lt-ref-self-async.rs:19:9 --> $DIR/lt-ref-self-async.rs:19:9
| |
LL | async fn ref_Self(self: &Self, f: &u32) -> &u32 { LL | async fn ref_Self(self: &Self, f: &u32) -> &u32 {
| - | - - let's call the lifetime of this reference `'1`
| | | |
| lifetime `'_` defined here | let's call the lifetime of this reference `'2`
| lifetime `'_` defined here
LL | f LL | f
| ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> $DIR/lt-ref-self-async.rs:22:57 --> $DIR/lt-ref-self-async.rs:22:57
@ -48,12 +46,11 @@ error: lifetime may not live long enough
--> $DIR/lt-ref-self-async.rs:23:9 --> $DIR/lt-ref-self-async.rs:23:9
| |
LL | async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 { LL | async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
| - | - - let's call the lifetime of this reference `'1`
| | | |
| lifetime `'_` defined here | let's call the lifetime of this reference `'2`
| lifetime `'_` defined here
LL | f LL | f
| ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> $DIR/lt-ref-self-async.rs:26:57 --> $DIR/lt-ref-self-async.rs:26:57
@ -67,12 +64,11 @@ error: lifetime may not live long enough
--> $DIR/lt-ref-self-async.rs:27:9 --> $DIR/lt-ref-self-async.rs:27:9
| |
LL | async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 { LL | async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
| - | - - let's call the lifetime of this reference `'1`
| | | |
| lifetime `'_` defined here | let's call the lifetime of this reference `'2`
| lifetime `'_` defined here
LL | f LL | f
| ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> $DIR/lt-ref-self-async.rs:30:66 --> $DIR/lt-ref-self-async.rs:30:66
@ -86,12 +82,11 @@ error: lifetime may not live long enough
--> $DIR/lt-ref-self-async.rs:31:9 --> $DIR/lt-ref-self-async.rs:31:9
| |
LL | async fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 { LL | async fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
| - | - - let's call the lifetime of this reference `'1`
| | | |
| lifetime `'_` defined here | let's call the lifetime of this reference `'2`
| lifetime `'_` defined here
LL | f LL | f
| ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> $DIR/lt-ref-self-async.rs:34:62 --> $DIR/lt-ref-self-async.rs:34:62
@ -105,12 +100,11 @@ error: lifetime may not live long enough
--> $DIR/lt-ref-self-async.rs:35:9 --> $DIR/lt-ref-self-async.rs:35:9
| |
LL | async fn box_pin_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 { LL | async fn box_pin_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
| - | - - let's call the lifetime of this reference `'1`
| | | |
| lifetime `'_` defined here | let's call the lifetime of this reference `'2`
| lifetime `'_` defined here
LL | f LL | f
| ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: aborting due to 12 previous errors error: aborting due to 12 previous errors

View File

@ -10,12 +10,11 @@ error: lifetime may not live long enough
--> $DIR/ref-mut-self-async.rs:13:9 --> $DIR/ref-mut-self-async.rs:13:9
| |
LL | async fn ref_self(&mut self, f: &u32) -> &u32 { LL | async fn ref_self(&mut self, f: &u32) -> &u32 {
| - | - - let's call the lifetime of this reference `'1`
| | | |
| lifetime `'_` defined here | let's call the lifetime of this reference `'2`
| lifetime `'_` defined here
LL | f LL | f
| ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> $DIR/ref-mut-self-async.rs:18:52 --> $DIR/ref-mut-self-async.rs:18:52
@ -29,12 +28,11 @@ error: lifetime may not live long enough
--> $DIR/ref-mut-self-async.rs:19:9 --> $DIR/ref-mut-self-async.rs:19:9
| |
LL | async fn ref_Self(self: &mut Self, f: &u32) -> &u32 { LL | async fn ref_Self(self: &mut Self, f: &u32) -> &u32 {
| - | - - let's call the lifetime of this reference `'1`
| | | |
| lifetime `'_` defined here | let's call the lifetime of this reference `'2`
| lifetime `'_` defined here
LL | f LL | f
| ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> $DIR/ref-mut-self-async.rs:22:61 --> $DIR/ref-mut-self-async.rs:22:61
@ -48,12 +46,11 @@ error: lifetime may not live long enough
--> $DIR/ref-mut-self-async.rs:23:9 --> $DIR/ref-mut-self-async.rs:23:9
| |
LL | async fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 { LL | async fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 {
| - | - - let's call the lifetime of this reference `'1`
| | | |
| lifetime `'_` defined here | let's call the lifetime of this reference `'2`
| lifetime `'_` defined here
LL | f LL | f
| ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> $DIR/ref-mut-self-async.rs:26:61 --> $DIR/ref-mut-self-async.rs:26:61
@ -67,12 +64,11 @@ error: lifetime may not live long enough
--> $DIR/ref-mut-self-async.rs:27:9 --> $DIR/ref-mut-self-async.rs:27:9
| |
LL | async fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 { LL | async fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 {
| - | - - let's call the lifetime of this reference `'1`
| | | |
| lifetime `'_` defined here | let's call the lifetime of this reference `'2`
| lifetime `'_` defined here
LL | f LL | f
| ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> $DIR/ref-mut-self-async.rs:30:70 --> $DIR/ref-mut-self-async.rs:30:70
@ -86,12 +82,11 @@ error: lifetime may not live long enough
--> $DIR/ref-mut-self-async.rs:31:9 --> $DIR/ref-mut-self-async.rs:31:9
| |
LL | async fn box_box_ref_Self(self: Box<Box<&mut Self>>, f: &u32) -> &u32 { LL | async fn box_box_ref_Self(self: Box<Box<&mut Self>>, f: &u32) -> &u32 {
| - | - - let's call the lifetime of this reference `'1`
| | | |
| lifetime `'_` defined here | let's call the lifetime of this reference `'2`
| lifetime `'_` defined here
LL | f LL | f
| ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> $DIR/ref-mut-self-async.rs:34:70 --> $DIR/ref-mut-self-async.rs:34:70
@ -105,12 +100,11 @@ error: lifetime may not live long enough
--> $DIR/ref-mut-self-async.rs:35:9 --> $DIR/ref-mut-self-async.rs:35:9
| |
LL | async fn box_pin_ref_Self(self: Box<Pin<&mut Self>>, f: &u32) -> &u32 { LL | async fn box_pin_ref_Self(self: Box<Pin<&mut Self>>, f: &u32) -> &u32 {
| - | - - let's call the lifetime of this reference `'1`
| | | |
| lifetime `'_` defined here | let's call the lifetime of this reference `'2`
| lifetime `'_` defined here
LL | f LL | f
| ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: aborting due to 12 previous errors error: aborting due to 12 previous errors

View File

@ -10,12 +10,11 @@ error: lifetime may not live long enough
--> $DIR/ref-mut-struct-async.rs:13:9 --> $DIR/ref-mut-struct-async.rs:13:9
| |
LL | async fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 { LL | async fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 {
| - | - - let's call the lifetime of this reference `'1`
| | | |
| lifetime `'_` defined here | let's call the lifetime of this reference `'2`
| lifetime `'_` defined here
LL | f LL | f
| ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> $DIR/ref-mut-struct-async.rs:16:65 --> $DIR/ref-mut-struct-async.rs:16:65
@ -29,12 +28,11 @@ error: lifetime may not live long enough
--> $DIR/ref-mut-struct-async.rs:17:9 --> $DIR/ref-mut-struct-async.rs:17:9
| |
LL | async fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 { LL | async fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 {
| - | - - let's call the lifetime of this reference `'1`
| | | |
| lifetime `'_` defined here | let's call the lifetime of this reference `'2`
| lifetime `'_` defined here
LL | f LL | f
| ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> $DIR/ref-mut-struct-async.rs:20:65 --> $DIR/ref-mut-struct-async.rs:20:65
@ -48,12 +46,11 @@ error: lifetime may not live long enough
--> $DIR/ref-mut-struct-async.rs:21:9 --> $DIR/ref-mut-struct-async.rs:21:9
| |
LL | async fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 { LL | async fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 {
| - | - - let's call the lifetime of this reference `'1`
| | | |
| lifetime `'_` defined here | let's call the lifetime of this reference `'2`
| lifetime `'_` defined here
LL | f LL | f
| ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> $DIR/ref-mut-struct-async.rs:24:74 --> $DIR/ref-mut-struct-async.rs:24:74
@ -67,12 +64,11 @@ error: lifetime may not live long enough
--> $DIR/ref-mut-struct-async.rs:25:9 --> $DIR/ref-mut-struct-async.rs:25:9
| |
LL | async fn box_box_ref_Struct(self: Box<Box<&mut Struct>>, f: &u32) -> &u32 { LL | async fn box_box_ref_Struct(self: Box<Box<&mut Struct>>, f: &u32) -> &u32 {
| - | - - let's call the lifetime of this reference `'1`
| | | |
| lifetime `'_` defined here | let's call the lifetime of this reference `'2`
| lifetime `'_` defined here
LL | f LL | f
| ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> $DIR/ref-mut-struct-async.rs:28:74 --> $DIR/ref-mut-struct-async.rs:28:74
@ -86,12 +82,11 @@ error: lifetime may not live long enough
--> $DIR/ref-mut-struct-async.rs:29:9 --> $DIR/ref-mut-struct-async.rs:29:9
| |
LL | async fn box_pin_ref_Struct(self: Box<Pin<&mut Struct>>, f: &u32) -> &u32 { LL | async fn box_pin_ref_Struct(self: Box<Pin<&mut Struct>>, f: &u32) -> &u32 {
| - | - - let's call the lifetime of this reference `'1`
| | | |
| lifetime `'_` defined here | let's call the lifetime of this reference `'2`
| lifetime `'_` defined here
LL | f LL | f
| ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: aborting due to 10 previous errors error: aborting due to 10 previous errors

View File

@ -10,12 +10,11 @@ error: lifetime may not live long enough
--> $DIR/ref-struct-async.rs:13:9 --> $DIR/ref-struct-async.rs:13:9
| |
LL | async fn ref_Struct(self: &Struct, f: &u32) -> &u32 { LL | async fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
| - | - - let's call the lifetime of this reference `'1`
| | | |
| lifetime `'_` defined here | let's call the lifetime of this reference `'2`
| lifetime `'_` defined here
LL | f LL | f
| ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> $DIR/ref-struct-async.rs:16:61 --> $DIR/ref-struct-async.rs:16:61
@ -29,12 +28,11 @@ error: lifetime may not live long enough
--> $DIR/ref-struct-async.rs:17:9 --> $DIR/ref-struct-async.rs:17:9
| |
LL | async fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 { LL | async fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 {
| - | - - let's call the lifetime of this reference `'1`
| | | |
| lifetime `'_` defined here | let's call the lifetime of this reference `'2`
| lifetime `'_` defined here
LL | f LL | f
| ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> $DIR/ref-struct-async.rs:20:61 --> $DIR/ref-struct-async.rs:20:61
@ -48,12 +46,11 @@ error: lifetime may not live long enough
--> $DIR/ref-struct-async.rs:21:9 --> $DIR/ref-struct-async.rs:21:9
| |
LL | async fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 { LL | async fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 {
| - | - - let's call the lifetime of this reference `'1`
| | | |
| lifetime `'_` defined here | let's call the lifetime of this reference `'2`
| lifetime `'_` defined here
LL | f LL | f
| ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> $DIR/ref-struct-async.rs:24:70 --> $DIR/ref-struct-async.rs:24:70
@ -67,12 +64,11 @@ error: lifetime may not live long enough
--> $DIR/ref-struct-async.rs:25:9 --> $DIR/ref-struct-async.rs:25:9
| |
LL | async fn box_box_ref_Struct(self: Box<Box<&Struct>>, f: &u32) -> &u32 { LL | async fn box_box_ref_Struct(self: Box<Box<&Struct>>, f: &u32) -> &u32 {
| - | - - let's call the lifetime of this reference `'1`
| | | |
| lifetime `'_` defined here | let's call the lifetime of this reference `'2`
| lifetime `'_` defined here
LL | f LL | f
| ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> $DIR/ref-struct-async.rs:28:66 --> $DIR/ref-struct-async.rs:28:66
@ -86,12 +82,11 @@ error: lifetime may not live long enough
--> $DIR/ref-struct-async.rs:29:9 --> $DIR/ref-struct-async.rs:29:9
| |
LL | async fn box_pin_Struct(self: Box<Pin<&Struct>>, f: &u32) -> &u32 { LL | async fn box_pin_Struct(self: Box<Pin<&Struct>>, f: &u32) -> &u32 {
| - | - - let's call the lifetime of this reference `'1`
| | | |
| lifetime `'_` defined here | let's call the lifetime of this reference `'2`
| lifetime `'_` defined here
LL | f LL | f
| ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: aborting due to 10 previous errors error: aborting due to 10 previous errors