mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
Auto merge of #70884 - Dylan-DPC:rollup-r3raqdf, r=jonas-schievink
Rollup of 5 pull requests Successful merges: - #70201 (Small tweaks in ToOwned::clone_into) - #70762 (Miri leak check: memory reachable through globals is not leaked) - #70846 (Keep codegen units unmerged when building compiler builtins) - #70854 (Use assoc int submodules) - #70857 (Don't import integer and float modules, use assoc consts 2) Failed merges: r? @ghost
This commit is contained in:
commit
42abbd8878
@ -1 +1 @@
|
|||||||
Subproject commit 411197b0e77590c967e37e8f6ec681abd359afe8
|
Subproject commit 6eb24d6e9c0773d4aee68ed5fca121ce3cdf676a
|
@ -1 +1 @@
|
|||||||
Subproject commit edd2a7e687358712608896730c083cb76c7b401a
|
Subproject commit a6638463efc7631bc0e8dc67ccd256d4e1b61f1a
|
@ -608,7 +608,7 @@ unsafe impl<#[may_dangle] T, A: AllocRef> Drop for RawVec<T, A> {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn alloc_guard(alloc_size: usize) -> Result<(), TryReserveError> {
|
fn alloc_guard(alloc_size: usize) -> Result<(), TryReserveError> {
|
||||||
if mem::size_of::<usize>() < 8 && alloc_size > core::isize::MAX as usize {
|
if mem::size_of::<usize>() < 8 && alloc_size > isize::MAX as usize {
|
||||||
Err(CapacityOverflow)
|
Err(CapacityOverflow)
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -733,14 +733,14 @@ impl<T: Clone> ToOwned for [T] {
|
|||||||
fn clone_into(&self, target: &mut Vec<T>) {
|
fn clone_into(&self, target: &mut Vec<T>) {
|
||||||
// drop anything in target that will not be overwritten
|
// drop anything in target that will not be overwritten
|
||||||
target.truncate(self.len());
|
target.truncate(self.len());
|
||||||
let len = target.len();
|
|
||||||
|
|
||||||
// reuse the contained values' allocations/resources.
|
|
||||||
target.clone_from_slice(&self[..len]);
|
|
||||||
|
|
||||||
// target.len <= self.len due to the truncate above, so the
|
// target.len <= self.len due to the truncate above, so the
|
||||||
// slice here is always in-bounds.
|
// slices here are always in-bounds.
|
||||||
target.extend_from_slice(&self[len..]);
|
let (init, tail) = self.split_at(target.len());
|
||||||
|
|
||||||
|
// reuse the contained values' allocations/resources.
|
||||||
|
target.clone_from_slice(init);
|
||||||
|
target.extend_from_slice(tail);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ fn trait_object() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn float_nan_ne() {
|
fn float_nan_ne() {
|
||||||
let x = Arc::new(std::f32::NAN);
|
let x = Arc::new(f32::NAN);
|
||||||
assert!(x != x);
|
assert!(x != x);
|
||||||
assert!(!(x == x));
|
assert!(!(x == x));
|
||||||
}
|
}
|
||||||
|
@ -475,7 +475,7 @@ fn test_range_large() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_range_inclusive_max_value() {
|
fn test_range_inclusive_max_value() {
|
||||||
let max = std::usize::MAX;
|
let max = usize::MAX;
|
||||||
let map: BTreeMap<_, _> = vec![(max, 0)].into_iter().collect();
|
let map: BTreeMap<_, _> = vec![(max, 0)].into_iter().collect();
|
||||||
|
|
||||||
assert_eq!(map.range(max..=max).collect::<Vec<_>>(), &[(&max, &0)]);
|
assert_eq!(map.range(max..=max).collect::<Vec<_>>(), &[(&max, &0)]);
|
||||||
|
@ -50,7 +50,7 @@ fn trait_object() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn float_nan_ne() {
|
fn float_nan_ne() {
|
||||||
let x = Rc::new(std::f32::NAN);
|
let x = Rc::new(f32::NAN);
|
||||||
assert!(x != x);
|
assert!(x != x);
|
||||||
assert!(!(x == x));
|
assert!(!(x == x));
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
use std::f64;
|
|
||||||
use test::Bencher;
|
use test::Bencher;
|
||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
|
@ -5,7 +5,6 @@ mod strategy {
|
|||||||
|
|
||||||
use core::num::flt2dec::MAX_SIG_DIGITS;
|
use core::num::flt2dec::MAX_SIG_DIGITS;
|
||||||
use core::num::flt2dec::{decode, DecodableFloat, Decoded, FullDecoded};
|
use core::num::flt2dec::{decode, DecodableFloat, Decoded, FullDecoded};
|
||||||
use std::f64;
|
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::vec::Vec;
|
use std::vec::Vec;
|
||||||
use test::Bencher;
|
use test::Bencher;
|
||||||
|
@ -76,7 +76,6 @@ fn test_cmp_by() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_partial_cmp_by() {
|
fn test_partial_cmp_by() {
|
||||||
use core::cmp::Ordering;
|
use core::cmp::Ordering;
|
||||||
use core::f64;
|
|
||||||
|
|
||||||
let f = |x: i32, y: i32| (x * x).partial_cmp(&y);
|
let f = |x: i32, y: i32| (x * x).partial_cmp(&y);
|
||||||
let xs = || [1, 2, 3, 4].iter().copied();
|
let xs = || [1, 2, 3, 4].iter().copied();
|
||||||
@ -2894,7 +2893,7 @@ fn test_is_sorted() {
|
|||||||
assert!(![1, 3, 2].iter().is_sorted());
|
assert!(![1, 3, 2].iter().is_sorted());
|
||||||
assert!([0].iter().is_sorted());
|
assert!([0].iter().is_sorted());
|
||||||
assert!(std::iter::empty::<i32>().is_sorted());
|
assert!(std::iter::empty::<i32>().is_sorted());
|
||||||
assert!(![0.0, 1.0, std::f32::NAN].iter().is_sorted());
|
assert!(![0.0, 1.0, f32::NAN].iter().is_sorted());
|
||||||
assert!([-2, -1, 0, 3].iter().is_sorted());
|
assert!([-2, -1, 0, 3].iter().is_sorted());
|
||||||
assert!(![-2i32, -1, 0, 3].iter().is_sorted_by_key(|n| n.abs()));
|
assert!(![-2i32, -1, 0, 3].iter().is_sorted_by_key(|n| n.abs()));
|
||||||
assert!(!["c", "bb", "aaa"].iter().is_sorted());
|
assert!(!["c", "bb", "aaa"].iter().is_sorted());
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
use core::num::dec2flt::rawfp::RawFloat;
|
use core::num::dec2flt::rawfp::RawFloat;
|
||||||
use core::num::dec2flt::rawfp::{fp_to_float, next_float, prev_float, round_normal};
|
use core::num::dec2flt::rawfp::{fp_to_float, next_float, prev_float, round_normal};
|
||||||
use core::num::diy_float::Fp;
|
use core::num::diy_float::Fp;
|
||||||
use std::f32;
|
|
||||||
use std::f64;
|
|
||||||
|
|
||||||
fn integer_decode(f: f64) -> (u64, i16, i8) {
|
fn integer_decode(f: f64) -> (u64, i16, i8) {
|
||||||
RawFloat::integer_decode(f)
|
RawFloat::integer_decode(f)
|
||||||
|
@ -205,8 +205,6 @@ test_impl_from! { test_u32f64, u32, f64 }
|
|||||||
// Float -> Float
|
// Float -> Float
|
||||||
#[test]
|
#[test]
|
||||||
fn test_f32f64() {
|
fn test_f32f64() {
|
||||||
use core::f32;
|
|
||||||
|
|
||||||
let max: f64 = f32::MAX.into();
|
let max: f64 = f32::MAX.into();
|
||||||
assert_eq!(max as f32, f32::MAX);
|
assert_eq!(max as f32, f32::MAX);
|
||||||
assert!(max.is_normal());
|
assert!(max.is_normal());
|
||||||
@ -704,5 +702,5 @@ macro_rules! test_float {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
test_float!(f32, f32, ::core::f32::INFINITY, ::core::f32::NEG_INFINITY, ::core::f32::NAN);
|
test_float!(f32, f32, f32::INFINITY, f32::NEG_INFINITY, f32::NAN);
|
||||||
test_float!(f64, f64, ::core::f64::INFINITY, ::core::f64::NEG_INFINITY, ::core::f64::NAN);
|
test_float!(f64, f64, f64::INFINITY, f64::NEG_INFINITY, f64::NAN);
|
||||||
|
@ -61,25 +61,23 @@ fn test_range_inclusive() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_range_is_empty() {
|
fn test_range_is_empty() {
|
||||||
use core::f32::*;
|
|
||||||
|
|
||||||
assert!(!(0.0..10.0).is_empty());
|
assert!(!(0.0..10.0).is_empty());
|
||||||
assert!((-0.0..0.0).is_empty());
|
assert!((-0.0..0.0).is_empty());
|
||||||
assert!((10.0..0.0).is_empty());
|
assert!((10.0..0.0).is_empty());
|
||||||
|
|
||||||
assert!(!(NEG_INFINITY..INFINITY).is_empty());
|
assert!(!(f32::NEG_INFINITY..f32::INFINITY).is_empty());
|
||||||
assert!((EPSILON..NAN).is_empty());
|
assert!((f32::EPSILON..f32::NAN).is_empty());
|
||||||
assert!((NAN..EPSILON).is_empty());
|
assert!((f32::NAN..f32::EPSILON).is_empty());
|
||||||
assert!((NAN..NAN).is_empty());
|
assert!((f32::NAN..f32::NAN).is_empty());
|
||||||
|
|
||||||
assert!(!(0.0..=10.0).is_empty());
|
assert!(!(0.0..=10.0).is_empty());
|
||||||
assert!(!(-0.0..=0.0).is_empty());
|
assert!(!(-0.0..=0.0).is_empty());
|
||||||
assert!((10.0..=0.0).is_empty());
|
assert!((10.0..=0.0).is_empty());
|
||||||
|
|
||||||
assert!(!(NEG_INFINITY..=INFINITY).is_empty());
|
assert!(!(f32::NEG_INFINITY..=f32::INFINITY).is_empty());
|
||||||
assert!((EPSILON..=NAN).is_empty());
|
assert!((f32::EPSILON..=f32::NAN).is_empty());
|
||||||
assert!((NAN..=EPSILON).is_empty());
|
assert!((f32::NAN..=f32::EPSILON).is_empty());
|
||||||
assert!((NAN..=NAN).is_empty());
|
assert!((f32::NAN..=f32::NAN).is_empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -1108,14 +1108,14 @@ mod slice_index {
|
|||||||
|
|
||||||
// note: using 0 specifically ensures that the result of overflowing is 0..0,
|
// note: using 0 specifically ensures that the result of overflowing is 0..0,
|
||||||
// so that `get` doesn't simply return None for the wrong reason.
|
// so that `get` doesn't simply return None for the wrong reason.
|
||||||
bad: data[0 ..= ::std::usize::MAX];
|
bad: data[0 ..= usize::MAX];
|
||||||
message: "maximum usize";
|
message: "maximum usize";
|
||||||
}
|
}
|
||||||
|
|
||||||
in mod rangetoinclusive_overflow {
|
in mod rangetoinclusive_overflow {
|
||||||
data: [0, 1];
|
data: [0, 1];
|
||||||
|
|
||||||
bad: data[..= ::std::usize::MAX];
|
bad: data[..= usize::MAX];
|
||||||
message: "maximum usize";
|
message: "maximum usize";
|
||||||
}
|
}
|
||||||
} // panic_cases!
|
} // panic_cases!
|
||||||
@ -1709,7 +1709,7 @@ fn test_is_sorted() {
|
|||||||
assert!(![1, 3, 2].is_sorted());
|
assert!(![1, 3, 2].is_sorted());
|
||||||
assert!([0].is_sorted());
|
assert!([0].is_sorted());
|
||||||
assert!(empty.is_sorted());
|
assert!(empty.is_sorted());
|
||||||
assert!(![0.0, 1.0, std::f32::NAN].is_sorted());
|
assert!(![0.0, 1.0, f32::NAN].is_sorted());
|
||||||
assert!([-2, -1, 0, 3].is_sorted());
|
assert!([-2, -1, 0, 3].is_sorted());
|
||||||
assert!(![-2i32, -1, 0, 3].is_sorted_by_key(|n| n.abs()));
|
assert!(![-2i32, -1, 0, 3].is_sorted_by_key(|n| n.abs()));
|
||||||
assert!(!["c", "bb", "aaa"].is_sorted());
|
assert!(!["c", "bb", "aaa"].is_sorted());
|
||||||
|
@ -14,7 +14,7 @@ fn creation() {
|
|||||||
#[test]
|
#[test]
|
||||||
#[should_panic]
|
#[should_panic]
|
||||||
fn new_overflow() {
|
fn new_overflow() {
|
||||||
let _ = Duration::new(::core::u64::MAX, 1_000_000_000);
|
let _ = Duration::new(u64::MAX, 1_000_000_000);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -86,7 +86,7 @@ fn checked_add() {
|
|||||||
Duration::new(0, 500_000_000).checked_add(Duration::new(0, 500_000_001)),
|
Duration::new(0, 500_000_000).checked_add(Duration::new(0, 500_000_001)),
|
||||||
Some(Duration::new(1, 1))
|
Some(Duration::new(1, 1))
|
||||||
);
|
);
|
||||||
assert_eq!(Duration::new(1, 0).checked_add(Duration::new(::core::u64::MAX, 0)), None);
|
assert_eq!(Duration::new(1, 0).checked_add(Duration::new(u64::MAX, 0)), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -133,7 +133,7 @@ fn checked_mul() {
|
|||||||
assert_eq!(Duration::new(1, 1).checked_mul(3), Some(Duration::new(3, 3)));
|
assert_eq!(Duration::new(1, 1).checked_mul(3), Some(Duration::new(3, 3)));
|
||||||
assert_eq!(Duration::new(0, 500_000_001).checked_mul(4), Some(Duration::new(2, 4)));
|
assert_eq!(Duration::new(0, 500_000_001).checked_mul(4), Some(Duration::new(2, 4)));
|
||||||
assert_eq!(Duration::new(0, 500_000_001).checked_mul(4000), Some(Duration::new(2000, 4000)));
|
assert_eq!(Duration::new(0, 500_000_001).checked_mul(4000), Some(Duration::new(2000, 4000)));
|
||||||
assert_eq!(Duration::new(::core::u64::MAX - 1, 0).checked_mul(2), None);
|
assert_eq!(Duration::new(u64::MAX - 1, 0).checked_mul(2), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
use std::cmp::Ordering::{Equal, Greater, Less};
|
use std::cmp::Ordering::{Equal, Greater, Less};
|
||||||
use std::f64::NAN;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_clone() {
|
fn test_clone() {
|
||||||
@ -34,12 +33,12 @@ fn test_partial_ord() {
|
|||||||
assert!(big >= small);
|
assert!(big >= small);
|
||||||
assert!(big >= big);
|
assert!(big >= big);
|
||||||
|
|
||||||
assert!(!((1.0f64, 2.0f64) < (NAN, 3.0)));
|
assert!(!((1.0f64, 2.0f64) < (f64::NAN, 3.0)));
|
||||||
assert!(!((1.0f64, 2.0f64) <= (NAN, 3.0)));
|
assert!(!((1.0f64, 2.0f64) <= (f64::NAN, 3.0)));
|
||||||
assert!(!((1.0f64, 2.0f64) > (NAN, 3.0)));
|
assert!(!((1.0f64, 2.0f64) > (f64::NAN, 3.0)));
|
||||||
assert!(!((1.0f64, 2.0f64) >= (NAN, 3.0)));
|
assert!(!((1.0f64, 2.0f64) >= (f64::NAN, 3.0)));
|
||||||
assert!(((1.0f64, 2.0f64) < (2.0, NAN)));
|
assert!(((1.0f64, 2.0f64) < (2.0, f64::NAN)));
|
||||||
assert!(!((2.0f64, 2.0f64) < (2.0, NAN)));
|
assert!(!((2.0f64, 2.0f64) < (2.0, f64::NAN)));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -1528,7 +1528,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const CODEGEN_WORKER_ID: usize = ::std::usize::MAX;
|
pub const CODEGEN_WORKER_ID: usize = usize::MAX;
|
||||||
|
|
||||||
/// `FatalError` is explicitly not `Send`.
|
/// `FatalError` is explicitly not `Send`.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
|
@ -507,7 +507,7 @@ fn get_argc_argv<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const CODEGEN_WORKER_ID: usize = ::std::usize::MAX;
|
pub const CODEGEN_WORKER_ID: usize = usize::MAX;
|
||||||
|
|
||||||
pub fn codegen_crate<B: ExtraBackendMethods>(
|
pub fn codegen_crate<B: ExtraBackendMethods>(
|
||||||
backend: B,
|
backend: B,
|
||||||
|
@ -1361,7 +1361,7 @@ impl EmitterWriter {
|
|||||||
let mut multilines = FxHashMap::default();
|
let mut multilines = FxHashMap::default();
|
||||||
|
|
||||||
// Get the left-side margin to remove it
|
// Get the left-side margin to remove it
|
||||||
let mut whitespace_margin = std::usize::MAX;
|
let mut whitespace_margin = usize::MAX;
|
||||||
for line_idx in 0..annotated_file.lines.len() {
|
for line_idx in 0..annotated_file.lines.len() {
|
||||||
let file = annotated_file.file.clone();
|
let file = annotated_file.file.clone();
|
||||||
let line = &annotated_file.lines[line_idx];
|
let line = &annotated_file.lines[line_idx];
|
||||||
@ -1373,19 +1373,19 @@ impl EmitterWriter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if whitespace_margin == std::usize::MAX {
|
if whitespace_margin == usize::MAX {
|
||||||
whitespace_margin = 0;
|
whitespace_margin = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Left-most column any visible span points at.
|
// Left-most column any visible span points at.
|
||||||
let mut span_left_margin = std::usize::MAX;
|
let mut span_left_margin = usize::MAX;
|
||||||
for line in &annotated_file.lines {
|
for line in &annotated_file.lines {
|
||||||
for ann in &line.annotations {
|
for ann in &line.annotations {
|
||||||
span_left_margin = min(span_left_margin, ann.start_col);
|
span_left_margin = min(span_left_margin, ann.start_col);
|
||||||
span_left_margin = min(span_left_margin, ann.end_col);
|
span_left_margin = min(span_left_margin, ann.end_col);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if span_left_margin == std::usize::MAX {
|
if span_left_margin == usize::MAX {
|
||||||
span_left_margin = 0;
|
span_left_margin = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1421,7 +1421,7 @@ impl EmitterWriter {
|
|||||||
} else {
|
} else {
|
||||||
termize::dimensions()
|
termize::dimensions()
|
||||||
.map(|(w, _)| w.saturating_sub(code_offset))
|
.map(|(w, _)| w.saturating_sub(code_offset))
|
||||||
.unwrap_or(std::usize::MAX)
|
.unwrap_or(usize::MAX)
|
||||||
};
|
};
|
||||||
|
|
||||||
let margin = Margin::new(
|
let margin = Margin::new(
|
||||||
|
@ -307,7 +307,7 @@ impl<'a, T: Idx> BitIter<'a, T> {
|
|||||||
// additional state about whether we have started.
|
// additional state about whether we have started.
|
||||||
BitIter {
|
BitIter {
|
||||||
word: 0,
|
word: 0,
|
||||||
offset: std::usize::MAX - (WORD_BITS - 1),
|
offset: usize::MAX - (WORD_BITS - 1),
|
||||||
iter: words.iter(),
|
iter: words.iter(),
|
||||||
marker: PhantomData,
|
marker: PhantomData,
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,7 @@ pub trait AllocMap<K: Hash + Eq, V> {
|
|||||||
where
|
where
|
||||||
K: Borrow<Q>;
|
K: Borrow<Q>;
|
||||||
|
|
||||||
/// Returns data based the keys and values in the map.
|
/// Returns data based on the keys and values in the map.
|
||||||
fn filter_map_collect<T>(&self, f: impl FnMut(&K, &V) -> Option<T>) -> Vec<T>;
|
fn filter_map_collect<T>(&self, f: impl FnMut(&K, &V) -> Option<T>) -> Vec<T>;
|
||||||
|
|
||||||
/// Returns a reference to entry `k`. If no such entry exists, call
|
/// Returns a reference to entry `k`. If no such entry exists, call
|
||||||
@ -79,7 +79,7 @@ pub trait AllocMap<K: Hash + Eq, V> {
|
|||||||
/// and some use case dependent behaviour can instead be applied.
|
/// and some use case dependent behaviour can instead be applied.
|
||||||
pub trait Machine<'mir, 'tcx>: Sized {
|
pub trait Machine<'mir, 'tcx>: Sized {
|
||||||
/// Additional memory kinds a machine wishes to distinguish from the builtin ones
|
/// Additional memory kinds a machine wishes to distinguish from the builtin ones
|
||||||
type MemoryKind: ::std::fmt::Debug + MayLeak + Eq + 'static;
|
type MemoryKind: ::std::fmt::Debug + ::std::fmt::Display + MayLeak + Eq + 'static;
|
||||||
|
|
||||||
/// Tag tracked alongside every pointer. This is used to implement "Stacked Borrows"
|
/// Tag tracked alongside every pointer. This is used to implement "Stacked Borrows"
|
||||||
/// <https://www.ralfj.de/blog/2018/08/07/stacked-borrows.html>.
|
/// <https://www.ralfj.de/blog/2018/08/07/stacked-borrows.html>.
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
use std::fmt;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
|
||||||
use rustc_ast::ast::Mutability;
|
use rustc_ast::ast::Mutability;
|
||||||
@ -20,6 +21,7 @@ use super::{
|
|||||||
AllocId, AllocMap, Allocation, AllocationExtra, CheckInAllocMsg, ErrorHandled, GlobalAlloc,
|
AllocId, AllocMap, Allocation, AllocationExtra, CheckInAllocMsg, ErrorHandled, GlobalAlloc,
|
||||||
GlobalId, InterpResult, Machine, MayLeak, Pointer, PointerArithmetic, Scalar,
|
GlobalId, InterpResult, Machine, MayLeak, Pointer, PointerArithmetic, Scalar,
|
||||||
};
|
};
|
||||||
|
use crate::util::pretty;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Copy, Clone)]
|
#[derive(Debug, PartialEq, Copy, Clone)]
|
||||||
pub enum MemoryKind<T> {
|
pub enum MemoryKind<T> {
|
||||||
@ -45,6 +47,17 @@ impl<T: MayLeak> MayLeak for MemoryKind<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: fmt::Display> fmt::Display for MemoryKind<T> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
MemoryKind::Stack => write!(f, "stack variable"),
|
||||||
|
MemoryKind::Vtable => write!(f, "vtable"),
|
||||||
|
MemoryKind::CallerLocation => write!(f, "caller location"),
|
||||||
|
MemoryKind::Machine(m) => write!(f, "{}", m),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Used by `get_size_and_align` to indicate whether the allocation needs to be live.
|
/// Used by `get_size_and_align` to indicate whether the allocation needs to be live.
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub enum AllocCheck {
|
pub enum AllocCheck {
|
||||||
@ -258,7 +271,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
|
|||||||
|
|
||||||
if alloc_kind != kind {
|
if alloc_kind != kind {
|
||||||
throw_ub_format!(
|
throw_ub_format!(
|
||||||
"deallocating `{:?}` memory using `{:?}` deallocation operation",
|
"deallocating {} memory using {} deallocation operation",
|
||||||
alloc_kind,
|
alloc_kind,
|
||||||
kind
|
kind
|
||||||
);
|
);
|
||||||
@ -644,81 +657,90 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
|
|||||||
self.dump_allocs(vec![id]);
|
self.dump_allocs(vec![id]);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dump_alloc_helper<Tag, Extra>(
|
|
||||||
&self,
|
|
||||||
allocs_seen: &mut FxHashSet<AllocId>,
|
|
||||||
allocs_to_print: &mut VecDeque<AllocId>,
|
|
||||||
alloc: &Allocation<Tag, Extra>,
|
|
||||||
) {
|
|
||||||
for &(_, (_, target_id)) in alloc.relocations().iter() {
|
|
||||||
if allocs_seen.insert(target_id) {
|
|
||||||
allocs_to_print.push_back(target_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
crate::util::pretty::write_allocation(self.tcx.tcx, alloc, &mut std::io::stderr(), "")
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Print a list of allocations and all allocations they point to, recursively.
|
/// Print a list of allocations and all allocations they point to, recursively.
|
||||||
/// This prints directly to stderr, ignoring RUSTC_LOG! It is up to the caller to
|
/// This prints directly to stderr, ignoring RUSTC_LOG! It is up to the caller to
|
||||||
/// control for this.
|
/// control for this.
|
||||||
pub fn dump_allocs(&self, mut allocs: Vec<AllocId>) {
|
pub fn dump_allocs(&self, mut allocs: Vec<AllocId>) {
|
||||||
|
// Cannot be a closure because it is generic in `Tag`, `Extra`.
|
||||||
|
fn write_allocation_track_relocs<'tcx, Tag, Extra>(
|
||||||
|
tcx: TyCtxtAt<'tcx>,
|
||||||
|
allocs_to_print: &mut VecDeque<AllocId>,
|
||||||
|
alloc: &Allocation<Tag, Extra>,
|
||||||
|
) {
|
||||||
|
for &(_, target_id) in alloc.relocations().values() {
|
||||||
|
allocs_to_print.push_back(target_id);
|
||||||
|
}
|
||||||
|
pretty::write_allocation(tcx.tcx, alloc, &mut std::io::stderr()).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
allocs.sort();
|
allocs.sort();
|
||||||
allocs.dedup();
|
allocs.dedup();
|
||||||
let mut allocs_to_print = VecDeque::from(allocs);
|
let mut allocs_to_print = VecDeque::from(allocs);
|
||||||
let mut allocs_seen = FxHashSet::default();
|
// `allocs_printed` contains all allocations that we have already printed.
|
||||||
|
let mut allocs_printed = FxHashSet::default();
|
||||||
|
|
||||||
while let Some(id) = allocs_to_print.pop_front() {
|
while let Some(id) = allocs_to_print.pop_front() {
|
||||||
eprint!("Alloc {:<5}: ", id);
|
if !allocs_printed.insert(id) {
|
||||||
fn msg<Tag, Extra>(alloc: &Allocation<Tag, Extra>, extra: &str) {
|
// Already printed, so skip this.
|
||||||
eprintln!(
|
continue;
|
||||||
"({} bytes, alignment {}){}",
|
}
|
||||||
alloc.size.bytes(),
|
|
||||||
alloc.align.bytes(),
|
|
||||||
extra
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
// normal alloc?
|
eprint!("{}", id);
|
||||||
match self.alloc_map.get_or(id, || Err(())) {
|
match self.alloc_map.get(id) {
|
||||||
Ok((kind, alloc)) => {
|
Some(&(kind, ref alloc)) => {
|
||||||
match kind {
|
// normal alloc
|
||||||
MemoryKind::Stack => msg(alloc, " (stack)"),
|
eprint!(" ({}, ", kind);
|
||||||
MemoryKind::Vtable => msg(alloc, " (vtable)"),
|
write_allocation_track_relocs(self.tcx, &mut allocs_to_print, alloc);
|
||||||
MemoryKind::CallerLocation => msg(alloc, " (caller_location)"),
|
|
||||||
MemoryKind::Machine(m) => msg(alloc, &format!(" ({:?})", m)),
|
|
||||||
};
|
|
||||||
self.dump_alloc_helper(&mut allocs_seen, &mut allocs_to_print, alloc);
|
|
||||||
}
|
}
|
||||||
Err(()) => {
|
None => {
|
||||||
// global alloc?
|
// global alloc
|
||||||
match self.tcx.alloc_map.lock().get(id) {
|
match self.tcx.alloc_map.lock().get(id) {
|
||||||
Some(GlobalAlloc::Memory(alloc)) => {
|
Some(GlobalAlloc::Memory(alloc)) => {
|
||||||
msg(alloc, " (immutable)");
|
eprint!(" (unchanged global, ");
|
||||||
self.dump_alloc_helper(&mut allocs_seen, &mut allocs_to_print, alloc);
|
write_allocation_track_relocs(self.tcx, &mut allocs_to_print, alloc);
|
||||||
}
|
}
|
||||||
Some(GlobalAlloc::Function(func)) => {
|
Some(GlobalAlloc::Function(func)) => {
|
||||||
eprintln!("{}", func);
|
eprint!(" (fn: {})", func);
|
||||||
}
|
}
|
||||||
Some(GlobalAlloc::Static(did)) => {
|
Some(GlobalAlloc::Static(did)) => {
|
||||||
eprintln!("{:?}", did);
|
eprint!(" (static: {})", self.tcx.def_path_str(did));
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
eprintln!("(deallocated)");
|
eprint!(" (deallocated)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
eprintln!();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn leak_report(&self) -> usize {
|
pub fn leak_report(&self) -> usize {
|
||||||
let leaks: Vec<_> = self
|
// Collect the set of allocations that are *reachable* from `Global` allocations.
|
||||||
.alloc_map
|
let reachable = {
|
||||||
.filter_map_collect(|&id, &(kind, _)| if kind.may_leak() { None } else { Some(id) });
|
let mut reachable = FxHashSet::default();
|
||||||
|
let global_kind = M::GLOBAL_KIND.map(MemoryKind::Machine);
|
||||||
|
let mut todo: Vec<_> = self.alloc_map.filter_map_collect(move |&id, &(kind, _)| {
|
||||||
|
if Some(kind) == global_kind { Some(id) } else { None }
|
||||||
|
});
|
||||||
|
while let Some(id) = todo.pop() {
|
||||||
|
if reachable.insert(id) {
|
||||||
|
// This is a new allocation, add its relocations to `todo`.
|
||||||
|
if let Some((_, alloc)) = self.alloc_map.get(id) {
|
||||||
|
todo.extend(alloc.relocations().values().map(|&(_, target_id)| target_id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
reachable
|
||||||
|
};
|
||||||
|
|
||||||
|
// All allocations that are *not* `reachable` and *not* `may_leak` are considered leaking.
|
||||||
|
let leaks: Vec<_> = self.alloc_map.filter_map_collect(|&id, &(kind, _)| {
|
||||||
|
if kind.may_leak() || reachable.contains(&id) { None } else { Some(id) }
|
||||||
|
});
|
||||||
let n = leaks.len();
|
let n = leaks.len();
|
||||||
if n > 0 {
|
if n > 0 {
|
||||||
eprintln!("### LEAK REPORT ###");
|
eprintln!("The following memory was leaked:");
|
||||||
self.dump_allocs(leaks);
|
self.dump_allocs(leaks);
|
||||||
}
|
}
|
||||||
n
|
n
|
||||||
|
@ -455,11 +455,18 @@ fn default_visibility(tcx: TyCtxt<'_>, id: DefId, is_generic: bool) -> Visibilit
|
|||||||
fn merge_codegen_units<'tcx>(
|
fn merge_codegen_units<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
initial_partitioning: &mut PreInliningPartitioning<'tcx>,
|
initial_partitioning: &mut PreInliningPartitioning<'tcx>,
|
||||||
target_cgu_count: usize,
|
mut target_cgu_count: usize,
|
||||||
) {
|
) {
|
||||||
assert!(target_cgu_count >= 1);
|
assert!(target_cgu_count >= 1);
|
||||||
let codegen_units = &mut initial_partitioning.codegen_units;
|
let codegen_units = &mut initial_partitioning.codegen_units;
|
||||||
|
|
||||||
|
if tcx.is_compiler_builtins(LOCAL_CRATE) {
|
||||||
|
// Compiler builtins require some degree of control over how mono items
|
||||||
|
// are partitioned into compilation units. Provide it by keeping the
|
||||||
|
// original partitioning when compiling the compiler builtins crate.
|
||||||
|
target_cgu_count = codegen_units.len();
|
||||||
|
}
|
||||||
|
|
||||||
// Note that at this point in time the `codegen_units` here may not be in a
|
// Note that at this point in time the `codegen_units` here may not be in a
|
||||||
// deterministic order (but we know they're deterministically the same set).
|
// deterministic order (but we know they're deterministically the same set).
|
||||||
// We want this merging to produce a deterministic ordering of codegen units
|
// We want this merging to produce a deterministic ordering of codegen units
|
||||||
|
@ -567,26 +567,21 @@ pub fn write_allocations<'tcx>(
|
|||||||
}
|
}
|
||||||
let mut visitor = CollectAllocIds(Default::default());
|
let mut visitor = CollectAllocIds(Default::default());
|
||||||
body.visit_with(&mut visitor);
|
body.visit_with(&mut visitor);
|
||||||
|
// `seen` contains all seen allocations, including the ones we have *not* printed yet.
|
||||||
|
// The protocol is to first `insert` into `seen`, and only if that returns `true`
|
||||||
|
// then push to `todo`.
|
||||||
let mut seen = visitor.0;
|
let mut seen = visitor.0;
|
||||||
let mut todo: Vec<_> = seen.iter().copied().collect();
|
let mut todo: Vec<_> = seen.iter().copied().collect();
|
||||||
while let Some(id) = todo.pop() {
|
while let Some(id) = todo.pop() {
|
||||||
let mut write_header_and_allocation =
|
let mut write_allocation_track_relocs =
|
||||||
|w: &mut dyn Write, alloc: &Allocation| -> io::Result<()> {
|
|w: &mut dyn Write, alloc: &Allocation| -> io::Result<()> {
|
||||||
write!(w, "size: {}, align: {})", alloc.size.bytes(), alloc.align.bytes())?;
|
// `.rev()` because we are popping them from the back of the `todo` vector.
|
||||||
if alloc.size == Size::ZERO {
|
for id in alloc_ids_from_alloc(alloc).rev() {
|
||||||
write!(w, " {{}}")?;
|
if seen.insert(id) {
|
||||||
} else {
|
todo.push(id);
|
||||||
writeln!(w, " {{")?;
|
|
||||||
write_allocation(tcx, alloc, w, " ")?;
|
|
||||||
write!(w, "}}")?;
|
|
||||||
// `.rev()` because we are popping them from the back of the `todo` vector.
|
|
||||||
for id in alloc_ids_from_alloc(alloc).rev() {
|
|
||||||
if seen.insert(id) {
|
|
||||||
todo.push(id);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
write_allocation(tcx, alloc, w)
|
||||||
};
|
};
|
||||||
write!(w, "\n{}", id)?;
|
write!(w, "\n{}", id)?;
|
||||||
let alloc = tcx.alloc_map.lock().get(id);
|
let alloc = tcx.alloc_map.lock().get(id);
|
||||||
@ -599,7 +594,7 @@ pub fn write_allocations<'tcx>(
|
|||||||
match tcx.const_eval_poly(did) {
|
match tcx.const_eval_poly(did) {
|
||||||
Ok(ConstValue::ByRef { alloc, .. }) => {
|
Ok(ConstValue::ByRef { alloc, .. }) => {
|
||||||
write!(w, " (static: {}, ", tcx.def_path_str(did))?;
|
write!(w, " (static: {}, ", tcx.def_path_str(did))?;
|
||||||
write_header_and_allocation(w, alloc)?;
|
write_allocation_track_relocs(w, alloc)?;
|
||||||
}
|
}
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
span_bug!(tcx.def_span(did), " static item without `ByRef` initializer")
|
span_bug!(tcx.def_span(did), " static item without `ByRef` initializer")
|
||||||
@ -616,15 +611,46 @@ pub fn write_allocations<'tcx>(
|
|||||||
}
|
}
|
||||||
Some(GlobalAlloc::Memory(alloc)) => {
|
Some(GlobalAlloc::Memory(alloc)) => {
|
||||||
write!(w, " (")?;
|
write!(w, " (")?;
|
||||||
write_header_and_allocation(w, alloc)?
|
write_allocation_track_relocs(w, alloc)?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
writeln!(w)?;
|
writeln!(w)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Dumps the size and metadata and content of an allocation to the given writer.
|
||||||
|
/// The expectation is that the caller first prints other relevant metadata, so the exact
|
||||||
|
/// format of this function is (*without* leading or trailing newline):
|
||||||
|
/// ```
|
||||||
|
/// size: {}, align: {}) {
|
||||||
|
/// <bytes>
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// The byte format is similar to how hex editors print bytes. Each line starts with the address of
|
||||||
|
/// the start of the line, followed by all bytes in hex format (space separated).
|
||||||
|
/// If the allocation is small enough to fit into a single line, no start address is given.
|
||||||
|
/// After the hex dump, an ascii dump follows, replacing all unprintable characters (control
|
||||||
|
/// characters or characters whose value is larger than 127) with a `.`
|
||||||
|
/// This also prints relocations adequately.
|
||||||
|
pub fn write_allocation<Tag, Extra>(
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
alloc: &Allocation<Tag, Extra>,
|
||||||
|
w: &mut dyn Write,
|
||||||
|
) -> io::Result<()> {
|
||||||
|
write!(w, "size: {}, align: {})", alloc.size.bytes(), alloc.align.bytes())?;
|
||||||
|
if alloc.size == Size::ZERO {
|
||||||
|
// We are done.
|
||||||
|
return write!(w, " {{}}");
|
||||||
|
}
|
||||||
|
// Write allocation bytes.
|
||||||
|
writeln!(w, " {{")?;
|
||||||
|
write_allocation_bytes(tcx, alloc, w, " ")?;
|
||||||
|
write!(w, "}}")?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn write_allocation_endline(w: &mut dyn Write, ascii: &str) -> io::Result<()> {
|
fn write_allocation_endline(w: &mut dyn Write, ascii: &str) -> io::Result<()> {
|
||||||
for _ in 0..(BYTES_PER_LINE - ascii.chars().count()) {
|
for _ in 0..(BYTES_PER_LINE - ascii.chars().count()) {
|
||||||
write!(w, " ")?;
|
write!(w, " ")?;
|
||||||
@ -649,18 +675,10 @@ fn write_allocation_newline(
|
|||||||
Ok(line_start)
|
Ok(line_start)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Dumps the bytes of an allocation to the given writer. This also prints relocations instead of
|
|
||||||
/// the raw bytes where applicable.
|
|
||||||
/// The byte format is similar to how hex editors print bytes. Each line starts with the address of
|
|
||||||
/// the start of the line, followed by all bytes in hex format (space separated).
|
|
||||||
/// If the allocation is small enough to fit into a single line, no start address is given.
|
|
||||||
/// After the hex dump, an ascii dump follows, replacing all unprintable characters (control
|
|
||||||
/// characters or characters whose value is larger than 127) with a `.`
|
|
||||||
///
|
|
||||||
/// The `prefix` argument allows callers to add an arbitrary prefix before each line (even if there
|
/// The `prefix` argument allows callers to add an arbitrary prefix before each line (even if there
|
||||||
/// is only one line). Note that your prefix should contain a trailing space as the lines are
|
/// is only one line). Note that your prefix should contain a trailing space as the lines are
|
||||||
/// printed directly after it.
|
/// printed directly after it.
|
||||||
pub fn write_allocation<Tag, Extra>(
|
fn write_allocation_bytes<Tag, Extra>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
alloc: &Allocation<Tag, Extra>,
|
alloc: &Allocation<Tag, Extra>,
|
||||||
w: &mut dyn Write,
|
w: &mut dyn Write,
|
||||||
|
@ -612,7 +612,7 @@ fn receiver_is_dispatchable<'tcx>(
|
|||||||
// FIXME(mikeyhew) this is a total hack. Once object_safe_for_dispatch is stabilized, we can
|
// FIXME(mikeyhew) this is a total hack. Once object_safe_for_dispatch is stabilized, we can
|
||||||
// replace this with `dyn Trait`
|
// replace this with `dyn Trait`
|
||||||
let unsized_self_ty: Ty<'tcx> =
|
let unsized_self_ty: Ty<'tcx> =
|
||||||
tcx.mk_ty_param(::std::u32::MAX, Symbol::intern("RustaceansAreAwesome"));
|
tcx.mk_ty_param(u32::MAX, Symbol::intern("RustaceansAreAwesome"));
|
||||||
|
|
||||||
// `Receiver[Self => U]`
|
// `Receiver[Self => U]`
|
||||||
let unsized_receiver_ty =
|
let unsized_receiver_ty =
|
||||||
|
@ -3650,11 +3650,7 @@ struct ProvisionalEvaluation {
|
|||||||
|
|
||||||
impl<'tcx> Default for ProvisionalEvaluationCache<'tcx> {
|
impl<'tcx> Default for ProvisionalEvaluationCache<'tcx> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self { dfn: Cell::new(0), reached_depth: Cell::new(usize::MAX), map: Default::default() }
|
||||||
dfn: Cell::new(0),
|
|
||||||
reached_depth: Cell::new(std::usize::MAX),
|
|
||||||
map: Default::default(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3753,7 +3749,7 @@ impl<'tcx> ProvisionalEvaluationCache<'tcx> {
|
|||||||
op(fresh_trait_ref, eval.result);
|
op(fresh_trait_ref, eval.result);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.reached_depth.set(std::usize::MAX);
|
self.reached_depth.set(usize::MAX);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2620,13 +2620,13 @@ fn check_link_ordinal(tcx: TyCtxt<'_>, attr: &ast::Attribute) -> Option<usize> {
|
|||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
if let Some(Lit { kind: LitKind::Int(ordinal, LitIntType::Unsuffixed), .. }) = sole_meta_list {
|
if let Some(Lit { kind: LitKind::Int(ordinal, LitIntType::Unsuffixed), .. }) = sole_meta_list {
|
||||||
if *ordinal <= std::usize::MAX as u128 {
|
if *ordinal <= usize::MAX as u128 {
|
||||||
Some(*ordinal as usize)
|
Some(*ordinal as usize)
|
||||||
} else {
|
} else {
|
||||||
let msg = format!("ordinal value in `link_ordinal` is too large: `{}`", &ordinal);
|
let msg = format!("ordinal value in `link_ordinal` is too large: `{}`", &ordinal);
|
||||||
tcx.sess
|
tcx.sess
|
||||||
.struct_span_err(attr.span, &msg)
|
.struct_span_err(attr.span, &msg)
|
||||||
.note("the value may not exceed `std::usize::MAX`")
|
.note("the value may not exceed `usize::MAX`")
|
||||||
.emit();
|
.emit();
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -198,7 +198,7 @@ use std::num::FpCategory as Fp;
|
|||||||
use std::ops::Index;
|
use std::ops::Index;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::string;
|
use std::string;
|
||||||
use std::{char, f64, fmt, str};
|
use std::{char, fmt, str};
|
||||||
|
|
||||||
use crate::Encodable;
|
use crate::Encodable;
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ fn test_unit() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_u8() {
|
fn test_u8() {
|
||||||
let mut vec = vec![];
|
let mut vec = vec![];
|
||||||
for i in ::std::u8::MIN..::std::u8::MAX {
|
for i in u8::MIN..u8::MAX {
|
||||||
vec.push(i);
|
vec.push(i);
|
||||||
}
|
}
|
||||||
check_round_trip(vec);
|
check_round_trip(vec);
|
||||||
@ -61,30 +61,30 @@ fn test_u8() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_u16() {
|
fn test_u16() {
|
||||||
for i in ::std::u16::MIN..::std::u16::MAX {
|
for i in u16::MIN..u16::MAX {
|
||||||
check_round_trip(vec![1, 2, 3, i, i, i]);
|
check_round_trip(vec![1, 2, 3, i, i, i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_u32() {
|
fn test_u32() {
|
||||||
check_round_trip(vec![1, 2, 3, ::std::u32::MIN, 0, 1, ::std::u32::MAX, 2, 1]);
|
check_round_trip(vec![1, 2, 3, u32::MIN, 0, 1, u32::MAX, 2, 1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_u64() {
|
fn test_u64() {
|
||||||
check_round_trip(vec![1, 2, 3, ::std::u64::MIN, 0, 1, ::std::u64::MAX, 2, 1]);
|
check_round_trip(vec![1, 2, 3, u64::MIN, 0, 1, u64::MAX, 2, 1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_usize() {
|
fn test_usize() {
|
||||||
check_round_trip(vec![1, 2, 3, ::std::usize::MIN, 0, 1, ::std::usize::MAX, 2, 1]);
|
check_round_trip(vec![1, 2, 3, usize::MIN, 0, 1, usize::MAX, 2, 1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_i8() {
|
fn test_i8() {
|
||||||
let mut vec = vec![];
|
let mut vec = vec![];
|
||||||
for i in ::std::i8::MIN..::std::i8::MAX {
|
for i in i8::MIN..i8::MAX {
|
||||||
vec.push(i);
|
vec.push(i);
|
||||||
}
|
}
|
||||||
check_round_trip(vec);
|
check_round_trip(vec);
|
||||||
@ -92,24 +92,24 @@ fn test_i8() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_i16() {
|
fn test_i16() {
|
||||||
for i in ::std::i16::MIN..::std::i16::MAX {
|
for i in i16::MIN..i16::MAX {
|
||||||
check_round_trip(vec![-1, 2, -3, i, i, i, 2]);
|
check_round_trip(vec![-1, 2, -3, i, i, i, 2]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_i32() {
|
fn test_i32() {
|
||||||
check_round_trip(vec![-1, 2, -3, ::std::i32::MIN, 0, 1, ::std::i32::MAX, 2, 1]);
|
check_round_trip(vec![-1, 2, -3, i32::MIN, 0, 1, i32::MAX, 2, 1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_i64() {
|
fn test_i64() {
|
||||||
check_round_trip(vec![-1, 2, -3, ::std::i64::MIN, 0, 1, ::std::i64::MAX, 2, 1]);
|
check_round_trip(vec![-1, 2, -3, i64::MIN, 0, 1, i64::MAX, 2, 1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_isize() {
|
fn test_isize() {
|
||||||
check_round_trip(vec![-1, 2, -3, ::std::isize::MIN, 0, 1, ::std::isize::MAX, 2, 1]);
|
check_round_trip(vec![-1, 2, -3, isize::MIN, 0, 1, isize::MAX, 2, 1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -2617,7 +2617,6 @@ mod test_map {
|
|||||||
use crate::cell::RefCell;
|
use crate::cell::RefCell;
|
||||||
use rand::{thread_rng, Rng};
|
use rand::{thread_rng, Rng};
|
||||||
use realstd::collections::TryReserveError::*;
|
use realstd::collections::TryReserveError::*;
|
||||||
use realstd::usize;
|
|
||||||
|
|
||||||
// https://github.com/rust-lang/rust/issues/62301
|
// https://github.com/rust-lang/rust/issues/62301
|
||||||
fn _assert_hashmap_is_unwind_safe() {
|
fn _assert_hashmap_is_unwind_safe() {
|
||||||
|
@ -1329,6 +1329,12 @@ impl ToOwned for CStr {
|
|||||||
fn to_owned(&self) -> CString {
|
fn to_owned(&self) -> CString {
|
||||||
CString { inner: self.to_bytes_with_nul().into() }
|
CString { inner: self.to_bytes_with_nul().into() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn clone_into(&self, target: &mut CString) {
|
||||||
|
let mut b = Vec::from(mem::take(&mut target.inner));
|
||||||
|
self.to_bytes_with_nul().clone_into(&mut b);
|
||||||
|
target.inner = b.into_boxed_slice();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "cstring_asref", since = "1.7.0")]
|
#[stable(feature = "cstring_asref", since = "1.7.0")]
|
||||||
@ -1510,6 +1516,17 @@ mod tests {
|
|||||||
assert_eq!(boxed.to_bytes_with_nul(), &[0]);
|
assert_eq!(boxed.to_bytes_with_nul(), &[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_c_str_clone_into() {
|
||||||
|
let mut c_string = CString::new("lorem").unwrap();
|
||||||
|
let c_ptr = c_string.as_ptr();
|
||||||
|
let c_str = CStr::from_bytes_with_nul(b"ipsum\0").unwrap();
|
||||||
|
c_str.clone_into(&mut c_string);
|
||||||
|
assert_eq!(c_str, c_string.as_c_str());
|
||||||
|
// The exact same size shouldn't have needed to move its allocation
|
||||||
|
assert_eq!(c_ptr, c_string.as_ptr());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn into_rc() {
|
fn into_rc() {
|
||||||
let orig: &[u8] = b"Hello, world!\0";
|
let orig: &[u8] = b"Hello, world!\0";
|
||||||
|
@ -1120,8 +1120,7 @@ impl ToOwned for OsStr {
|
|||||||
self.to_os_string()
|
self.to_os_string()
|
||||||
}
|
}
|
||||||
fn clone_into(&self, target: &mut OsString) {
|
fn clone_into(&self, target: &mut OsString) {
|
||||||
target.clear();
|
self.inner.clone_into(&mut target.inner)
|
||||||
target.push(self);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,6 +159,10 @@ impl Slice {
|
|||||||
Buf { inner: buf }
|
Buf { inner: buf }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn clone_into(&self, buf: &mut Buf) {
|
||||||
|
self.inner.clone_into(&mut buf.inner)
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn into_box(&self) -> Box<Slice> {
|
pub fn into_box(&self) -> Box<Slice> {
|
||||||
unsafe { mem::transmute(self.inner.into_box()) }
|
unsafe { mem::transmute(self.inner.into_box()) }
|
||||||
|
@ -173,6 +173,10 @@ impl Slice {
|
|||||||
Buf { inner: self.inner.to_vec() }
|
Buf { inner: self.inner.to_vec() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn clone_into(&self, buf: &mut Buf) {
|
||||||
|
self.inner.clone_into(&mut buf.inner)
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn into_box(&self) -> Box<Slice> {
|
pub fn into_box(&self) -> Box<Slice> {
|
||||||
let boxed: Box<[u8]> = self.inner.into();
|
let boxed: Box<[u8]> = self.inner.into();
|
||||||
|
@ -613,6 +613,10 @@ impl Wtf8 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn clone_into(&self, buf: &mut Wtf8Buf) {
|
||||||
|
self.bytes.clone_into(&mut buf.bytes)
|
||||||
|
}
|
||||||
|
|
||||||
/// Boxes this `Wtf8`.
|
/// Boxes this `Wtf8`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn into_box(&self) -> Box<Wtf8> {
|
pub fn into_box(&self) -> Box<Wtf8> {
|
||||||
|
@ -2,7 +2,6 @@ use super::*;
|
|||||||
|
|
||||||
extern crate test;
|
extern crate test;
|
||||||
use self::test::test::Bencher;
|
use self::test::test::Bencher;
|
||||||
use std::f64;
|
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
|
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit abe96ca3b87fcca6aa1dfcefd40d8c8d92d2e673
|
Subproject commit 1a577bd78e84e357e29c5336ff8beb432873046b
|
40
src/test/codegen-units/partitioning/compiler-builtins.rs
Normal file
40
src/test/codegen-units/partitioning/compiler-builtins.rs
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
// Verifies that during compiler_builtins compilation the codegen units are kept
|
||||||
|
// unmerged. Even when only a single codegen unit is requested with -Ccodegen-units=1.
|
||||||
|
//
|
||||||
|
// compile-flags: -Zprint-mono-items=eager -Ccodegen-units=1
|
||||||
|
|
||||||
|
#![compiler_builtins]
|
||||||
|
#![crate_type="lib"]
|
||||||
|
#![feature(compiler_builtins)]
|
||||||
|
|
||||||
|
mod atomics {
|
||||||
|
//~ MONO_ITEM fn compiler_builtins::atomics[0]::sync_1[0] @@ compiler_builtins-cgu.0[External]
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn sync_1() {}
|
||||||
|
|
||||||
|
//~ MONO_ITEM fn compiler_builtins::atomics[0]::sync_2[0] @@ compiler_builtins-cgu.0[External]
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn sync_2() {}
|
||||||
|
|
||||||
|
//~ MONO_ITEM fn compiler_builtins::atomics[0]::sync_3[0] @@ compiler_builtins-cgu.0[External]
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn sync_3() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod x {
|
||||||
|
//~ MONO_ITEM fn compiler_builtins::x[0]::x[0] @@ compiler_builtins-cgu.1[External]
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn x() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod y {
|
||||||
|
//~ MONO_ITEM fn compiler_builtins::y[0]::y[0] @@ compiler_builtins-cgu.2[External]
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn y() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod z {
|
||||||
|
//~ MONO_ITEM fn compiler_builtins::z[0]::z[0] @@ compiler_builtins-cgu.3[External]
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn z() {}
|
||||||
|
}
|
@ -12,7 +12,7 @@ error: ordinal value in `link_ordinal` is too large: `18446744073709551616`
|
|||||||
LL | #[link_ordinal(18446744073709551616)]
|
LL | #[link_ordinal(18446744073709551616)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: the value may not exceed `std::usize::MAX`
|
= note: the value may not exceed `usize::MAX`
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user