Auto merge of #32112 - alexcrichton:fix-issues, r=aturon
std: Fix tracking issues and clean deprecated APIs This PR fixes up a number of discrepancies found with tracking issues (some closed, some needed new ones, etc), and also cleans out all pre-1.8 deprecated APIs. The big beast here was dealing with `std::dynamic_lib`, and via many applications of a large hammer it's now out of the standard library.
This commit is contained in:
commit
a2c56de764
@ -11,7 +11,6 @@
|
||||
#![crate_type = "bin"]
|
||||
|
||||
#![feature(box_syntax)]
|
||||
#![feature(dynamic_lib)]
|
||||
#![feature(libc)]
|
||||
#![feature(rustc_private)]
|
||||
#![feature(str_char)]
|
||||
|
@ -8,9 +8,8 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![allow(deprecated)]
|
||||
|
||||
use std::dynamic_lib::DynamicLibrary;
|
||||
use std::env;
|
||||
use std::ffi::OsString;
|
||||
use std::io::prelude::*;
|
||||
use std::path::PathBuf;
|
||||
use std::process::{ExitStatus, Command, Child, Output, Stdio};
|
||||
@ -18,15 +17,22 @@ use std::process::{ExitStatus, Command, Child, Output, Stdio};
|
||||
fn add_target_env(cmd: &mut Command, lib_path: &str, aux_path: Option<&str>) {
|
||||
// Need to be sure to put both the lib_path and the aux path in the dylib
|
||||
// search path for the child.
|
||||
let mut path = DynamicLibrary::search_path();
|
||||
let var = if cfg!(windows) {
|
||||
"PATH"
|
||||
} else if cfg!(target_os = "macos") {
|
||||
"DYLD_LIBRARY_PATH"
|
||||
} else {
|
||||
"LD_LIBRARY_PATH"
|
||||
};
|
||||
let mut path = env::split_paths(&env::var_os(var).unwrap_or(OsString::new()))
|
||||
.collect::<Vec<_>>();
|
||||
if let Some(p) = aux_path {
|
||||
path.insert(0, PathBuf::from(p))
|
||||
}
|
||||
path.insert(0, PathBuf::from(lib_path));
|
||||
|
||||
// Add the new dylib search path var
|
||||
let var = DynamicLibrary::envvar();
|
||||
let newpath = DynamicLibrary::create_path(&path);
|
||||
let newpath = env::join_paths(&path).unwrap();
|
||||
cmd.env(var, newpath);
|
||||
}
|
||||
|
||||
|
@ -525,14 +525,14 @@ impl<I: ExactSizeIterator + ?Sized> ExactSizeIterator for Box<I> {}
|
||||
/// }
|
||||
/// ```
|
||||
#[rustc_paren_sugar]
|
||||
#[unstable(feature = "fnbox", reason = "Newly introduced", issue = "0")]
|
||||
#[unstable(feature = "fnbox", reason = "Newly introduced", issue = "28796")]
|
||||
pub trait FnBox<A> {
|
||||
type Output;
|
||||
|
||||
fn call_box(self: Box<Self>, args: A) -> Self::Output;
|
||||
}
|
||||
|
||||
#[unstable(feature = "fnbox", reason = "Newly introduced", issue = "0")]
|
||||
#[unstable(feature = "fnbox", reason = "Newly introduced", issue = "28796")]
|
||||
impl<A, F> FnBox<A> for F where F: FnOnce<A>
|
||||
{
|
||||
type Output = F::Output;
|
||||
@ -542,7 +542,7 @@ impl<A, F> FnBox<A> for F where F: FnOnce<A>
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "fnbox", reason = "Newly introduced", issue = "0")]
|
||||
#[unstable(feature = "fnbox", reason = "Newly introduced", issue = "28796")]
|
||||
impl<'a, A, R> FnOnce<A> for Box<FnBox<A, Output = R> + 'a> {
|
||||
type Output = R;
|
||||
|
||||
@ -551,7 +551,7 @@ impl<'a, A, R> FnOnce<A> for Box<FnBox<A, Output = R> + 'a> {
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "fnbox", reason = "Newly introduced", issue = "0")]
|
||||
#[unstable(feature = "fnbox", reason = "Newly introduced", issue = "28796")]
|
||||
impl<'a, A, R> FnOnce<A> for Box<FnBox<A, Output = R> + Send + 'a> {
|
||||
type Output = R;
|
||||
|
||||
|
@ -32,7 +32,6 @@
|
||||
#![feature(alloc)]
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(heap_api)]
|
||||
#![feature(raw)]
|
||||
#![feature(heap_api)]
|
||||
#![feature(staged_api)]
|
||||
#![feature(dropck_parametricity)]
|
||||
@ -48,326 +47,10 @@ use std::intrinsics;
|
||||
use std::marker::{PhantomData, Send};
|
||||
use std::mem;
|
||||
use std::ptr;
|
||||
use std::slice;
|
||||
|
||||
use alloc::heap;
|
||||
use alloc::raw_vec::RawVec;
|
||||
|
||||
struct Chunk {
|
||||
data: RawVec<u8>,
|
||||
/// Index of the first unused byte.
|
||||
fill: Cell<usize>,
|
||||
/// Indicates whether objects with destructors are stored in this chunk.
|
||||
is_copy: Cell<bool>,
|
||||
}
|
||||
|
||||
impl Chunk {
|
||||
fn new(size: usize, is_copy: bool) -> Chunk {
|
||||
Chunk {
|
||||
data: RawVec::with_capacity(size),
|
||||
fill: Cell::new(0),
|
||||
is_copy: Cell::new(is_copy),
|
||||
}
|
||||
}
|
||||
|
||||
fn capacity(&self) -> usize {
|
||||
self.data.cap()
|
||||
}
|
||||
|
||||
unsafe fn as_ptr(&self) -> *const u8 {
|
||||
self.data.ptr()
|
||||
}
|
||||
|
||||
// Walk down a chunk, running the destructors for any objects stored
|
||||
// in it.
|
||||
unsafe fn destroy(&self) {
|
||||
let mut idx = 0;
|
||||
let buf = self.as_ptr();
|
||||
let fill = self.fill.get();
|
||||
|
||||
while idx < fill {
|
||||
let tydesc_data = buf.offset(idx as isize) as *const usize;
|
||||
let (tydesc, is_done) = un_bitpack_tydesc_ptr(*tydesc_data);
|
||||
let (size, align) = ((*tydesc).size, (*tydesc).align);
|
||||
|
||||
let after_tydesc = idx + mem::size_of::<*const TyDesc>();
|
||||
|
||||
let start = round_up(after_tydesc, align);
|
||||
|
||||
if is_done {
|
||||
((*tydesc).drop_glue)(buf.offset(start as isize) as *const i8);
|
||||
}
|
||||
|
||||
// Find where the next tydesc lives
|
||||
idx = round_up(start + size, mem::align_of::<*const TyDesc>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A slower reflection-based arena that can allocate objects of any type.
|
||||
///
|
||||
/// This arena uses `RawVec<u8>` as a backing store to allocate objects from.
|
||||
/// For each allocated object, the arena stores a pointer to the type descriptor
|
||||
/// followed by the object (potentially with alignment padding after each
|
||||
/// element). When the arena is destroyed, it iterates through all of its
|
||||
/// chunks, and uses the tydesc information to trace through the objects,
|
||||
/// calling the destructors on them. One subtle point that needs to be
|
||||
/// addressed is how to handle panics while running the user provided
|
||||
/// initializer function. It is important to not run the destructor on
|
||||
/// uninitialized objects, but how to detect them is somewhat subtle. Since
|
||||
/// `alloc()` can be invoked recursively, it is not sufficient to simply exclude
|
||||
/// the most recent object. To solve this without requiring extra space, we
|
||||
/// use the low order bit of the tydesc pointer to encode whether the object
|
||||
/// it describes has been fully initialized.
|
||||
///
|
||||
/// As an optimization, objects with destructors are stored in different chunks
|
||||
/// than objects without destructors. This reduces overhead when initializing
|
||||
/// plain-old-data (`Copy` types) and means we don't need to waste time running
|
||||
/// their destructors.
|
||||
#[unstable(feature = "rustc_private",
|
||||
reason = "Private to rustc", issue = "0")]
|
||||
#[rustc_deprecated(since = "1.6.0-dev", reason =
|
||||
"The reflection-based arena is superseded by the any-arena crate")]
|
||||
pub struct Arena<'longer_than_self> {
|
||||
// The heads are separated out from the list as a unbenchmarked
|
||||
// microoptimization, to avoid needing to case on the list to access a head.
|
||||
head: RefCell<Chunk>,
|
||||
copy_head: RefCell<Chunk>,
|
||||
chunks: RefCell<Vec<Chunk>>,
|
||||
_marker: PhantomData<*mut &'longer_than_self ()>,
|
||||
}
|
||||
|
||||
impl<'a> Arena<'a> {
|
||||
/// Allocates a new Arena with 32 bytes preallocated.
|
||||
pub fn new() -> Arena<'a> {
|
||||
Arena::new_with_size(32)
|
||||
}
|
||||
|
||||
/// Allocates a new Arena with `initial_size` bytes preallocated.
|
||||
pub fn new_with_size(initial_size: usize) -> Arena<'a> {
|
||||
Arena {
|
||||
head: RefCell::new(Chunk::new(initial_size, false)),
|
||||
copy_head: RefCell::new(Chunk::new(initial_size, true)),
|
||||
chunks: RefCell::new(Vec::new()),
|
||||
_marker: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'longer_than_self> Drop for Arena<'longer_than_self> {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
self.head.borrow().destroy();
|
||||
for chunk in self.chunks.borrow().iter() {
|
||||
if !chunk.is_copy.get() {
|
||||
chunk.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn round_up(base: usize, align: usize) -> usize {
|
||||
(base.checked_add(align - 1)).unwrap() & !(align - 1)
|
||||
}
|
||||
|
||||
// We encode whether the object a tydesc describes has been
|
||||
// initialized in the arena in the low bit of the tydesc pointer. This
|
||||
// is necessary in order to properly do cleanup if a panic occurs
|
||||
// during an initializer.
|
||||
#[inline]
|
||||
fn bitpack_tydesc_ptr(p: *const TyDesc, is_done: bool) -> usize {
|
||||
p as usize | (is_done as usize)
|
||||
}
|
||||
#[inline]
|
||||
fn un_bitpack_tydesc_ptr(p: usize) -> (*const TyDesc, bool) {
|
||||
((p & !1) as *const TyDesc, p & 1 == 1)
|
||||
}
|
||||
|
||||
// HACK(eddyb) TyDesc replacement using a trait object vtable.
|
||||
// This could be replaced in the future with a custom DST layout,
|
||||
// or `&'static (drop_glue, size, align)` created by a `const fn`.
|
||||
// Requirements:
|
||||
// * rvalue promotion (issue #1056)
|
||||
// * mem::{size_of, align_of} must be const fns
|
||||
struct TyDesc {
|
||||
drop_glue: fn(*const i8),
|
||||
size: usize,
|
||||
align: usize,
|
||||
}
|
||||
|
||||
trait AllTypes {
|
||||
fn dummy(&self) {}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> AllTypes for T {}
|
||||
|
||||
unsafe fn get_tydesc<T>() -> *const TyDesc {
|
||||
use std::raw::TraitObject;
|
||||
|
||||
let ptr = &*(heap::EMPTY as *const T);
|
||||
|
||||
// Can use any trait that is implemented for all types.
|
||||
let obj = mem::transmute::<&AllTypes, TraitObject>(ptr);
|
||||
obj.vtable as *const TyDesc
|
||||
}
|
||||
|
||||
impl<'longer_than_self> Arena<'longer_than_self> {
|
||||
// Grows a given chunk and returns `false`, or replaces it with a bigger
|
||||
// chunk and returns `true`.
|
||||
// This method is shared by both parts of the arena.
|
||||
#[cold]
|
||||
fn alloc_grow(&self, head: &mut Chunk, used_cap: usize, n_bytes: usize) -> bool {
|
||||
if head.data.reserve_in_place(used_cap, n_bytes) {
|
||||
// In-place reallocation succeeded.
|
||||
false
|
||||
} else {
|
||||
// Allocate a new chunk.
|
||||
let new_min_chunk_size = cmp::max(n_bytes, head.capacity());
|
||||
let new_chunk = Chunk::new((new_min_chunk_size + 1).next_power_of_two(), false);
|
||||
let old_chunk = mem::replace(head, new_chunk);
|
||||
if old_chunk.fill.get() != 0 {
|
||||
self.chunks.borrow_mut().push(old_chunk);
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
// Functions for the copyable part of the arena.
|
||||
|
||||
#[inline]
|
||||
fn alloc_copy_inner(&self, n_bytes: usize, align: usize) -> *const u8 {
|
||||
let mut copy_head = self.copy_head.borrow_mut();
|
||||
let fill = copy_head.fill.get();
|
||||
let mut start = round_up(fill, align);
|
||||
let mut end = start + n_bytes;
|
||||
|
||||
if end > copy_head.capacity() {
|
||||
if self.alloc_grow(&mut *copy_head, fill, end - fill) {
|
||||
// Continuing with a newly allocated chunk
|
||||
start = 0;
|
||||
end = n_bytes;
|
||||
copy_head.is_copy.set(true);
|
||||
}
|
||||
}
|
||||
|
||||
copy_head.fill.set(end);
|
||||
|
||||
unsafe { copy_head.as_ptr().offset(start as isize) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn alloc_copy<T, F>(&self, op: F) -> &mut T
|
||||
where F: FnOnce() -> T
|
||||
{
|
||||
unsafe {
|
||||
let ptr = self.alloc_copy_inner(mem::size_of::<T>(), mem::align_of::<T>());
|
||||
let ptr = ptr as *mut T;
|
||||
ptr::write(&mut (*ptr), op());
|
||||
&mut *ptr
|
||||
}
|
||||
}
|
||||
|
||||
// Functions for the non-copyable part of the arena.
|
||||
|
||||
#[inline]
|
||||
fn alloc_noncopy_inner(&self, n_bytes: usize, align: usize) -> (*const u8, *const u8) {
|
||||
let mut head = self.head.borrow_mut();
|
||||
let fill = head.fill.get();
|
||||
|
||||
let mut tydesc_start = fill;
|
||||
let after_tydesc = fill + mem::size_of::<*const TyDesc>();
|
||||
let mut start = round_up(after_tydesc, align);
|
||||
let mut end = round_up(start + n_bytes, mem::align_of::<*const TyDesc>());
|
||||
|
||||
if end > head.capacity() {
|
||||
if self.alloc_grow(&mut *head, tydesc_start, end - tydesc_start) {
|
||||
// Continuing with a newly allocated chunk
|
||||
tydesc_start = 0;
|
||||
start = round_up(mem::size_of::<*const TyDesc>(), align);
|
||||
end = round_up(start + n_bytes, mem::align_of::<*const TyDesc>());
|
||||
}
|
||||
}
|
||||
|
||||
head.fill.set(end);
|
||||
|
||||
unsafe {
|
||||
let buf = head.as_ptr();
|
||||
(buf.offset(tydesc_start as isize),
|
||||
buf.offset(start as isize))
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn alloc_noncopy<T, F>(&self, op: F) -> &mut T
|
||||
where F: FnOnce() -> T
|
||||
{
|
||||
unsafe {
|
||||
let tydesc = get_tydesc::<T>();
|
||||
let (ty_ptr, ptr) = self.alloc_noncopy_inner(mem::size_of::<T>(), mem::align_of::<T>());
|
||||
let ty_ptr = ty_ptr as *mut usize;
|
||||
let ptr = ptr as *mut T;
|
||||
// Write in our tydesc along with a bit indicating that it
|
||||
// has *not* been initialized yet.
|
||||
*ty_ptr = bitpack_tydesc_ptr(tydesc, false);
|
||||
// Actually initialize it
|
||||
ptr::write(&mut (*ptr), op());
|
||||
// Now that we are done, update the tydesc to indicate that
|
||||
// the object is there.
|
||||
*ty_ptr = bitpack_tydesc_ptr(tydesc, true);
|
||||
|
||||
&mut *ptr
|
||||
}
|
||||
}
|
||||
|
||||
/// Allocates a new item in the arena, using `op` to initialize the value,
|
||||
/// and returns a reference to it.
|
||||
#[inline]
|
||||
pub fn alloc<T: 'longer_than_self, F>(&self, op: F) -> &mut T
|
||||
where F: FnOnce() -> T
|
||||
{
|
||||
unsafe {
|
||||
if intrinsics::needs_drop::<T>() {
|
||||
self.alloc_noncopy(op)
|
||||
} else {
|
||||
self.alloc_copy(op)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Allocates a slice of bytes of requested length. The bytes are not guaranteed to be zero
|
||||
/// if the arena has previously been cleared.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the requested length is too large and causes overflow.
|
||||
pub fn alloc_bytes(&self, len: usize) -> &mut [u8] {
|
||||
unsafe {
|
||||
// Check for overflow.
|
||||
self.copy_head.borrow().fill.get().checked_add(len).expect("length overflow");
|
||||
let ptr = self.alloc_copy_inner(len, 1);
|
||||
intrinsics::assume(!ptr.is_null());
|
||||
slice::from_raw_parts_mut(ptr as *mut _, len)
|
||||
}
|
||||
}
|
||||
|
||||
/// Clears the arena. Deallocates all but the longest chunk which may be reused.
|
||||
pub fn clear(&mut self) {
|
||||
unsafe {
|
||||
self.head.borrow().destroy();
|
||||
self.head.borrow().fill.set(0);
|
||||
self.copy_head.borrow().fill.set(0);
|
||||
for chunk in self.chunks.borrow().iter() {
|
||||
if !chunk.is_copy.get() {
|
||||
chunk.destroy();
|
||||
}
|
||||
}
|
||||
self.chunks.borrow_mut().clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A faster arena that can hold objects of only one type.
|
||||
pub struct TypedArena<T> {
|
||||
/// A pointer to the next object to be allocated.
|
||||
@ -566,9 +249,8 @@ unsafe impl<T: Send> Send for TypedArena<T> {}
|
||||
mod tests {
|
||||
extern crate test;
|
||||
use self::test::Bencher;
|
||||
use super::{Arena, TypedArena};
|
||||
use super::TypedArena;
|
||||
use std::cell::Cell;
|
||||
use std::rc::Rc;
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
@ -642,12 +324,6 @@ mod tests {
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
pub fn bench_copy_old_arena(b: &mut Bencher) {
|
||||
let arena = Arena::new();
|
||||
b.iter(|| arena.alloc(|| Point { x: 1, y: 2, z: 3 }))
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
struct Noncopy {
|
||||
string: String,
|
||||
@ -673,22 +349,6 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_arena_zero_sized() {
|
||||
let arena = Arena::new();
|
||||
let mut points = vec![];
|
||||
for _ in 0..1000 {
|
||||
for _ in 0..100 {
|
||||
arena.alloc(|| ());
|
||||
}
|
||||
let point = arena.alloc(|| Point { x: 1, y: 2, z: 3 });
|
||||
points.push(point);
|
||||
}
|
||||
for point in &points {
|
||||
assert_eq!(**point, Point { x: 1, y: 2, z: 3 });
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_typed_arena_clear() {
|
||||
let mut arena = TypedArena::new();
|
||||
@ -700,66 +360,6 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_arena_clear() {
|
||||
let mut arena = Arena::new();
|
||||
for _ in 0..10 {
|
||||
arena.clear();
|
||||
for _ in 0..10000 {
|
||||
arena.alloc(|| Point { x: 1, y: 2, z: 3 });
|
||||
arena.alloc(|| {
|
||||
Noncopy {
|
||||
string: "hello world".to_string(),
|
||||
array: vec![],
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_arena_alloc_bytes() {
|
||||
let arena = Arena::new();
|
||||
for i in 0..10000 {
|
||||
arena.alloc(|| Point { x: 1, y: 2, z: 3 });
|
||||
for byte in arena.alloc_bytes(i % 42).iter_mut() {
|
||||
*byte = i as u8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_arena_destructors() {
|
||||
let arena = Arena::new();
|
||||
for i in 0..10 {
|
||||
// Arena allocate something with drop glue to make sure it
|
||||
// doesn't leak.
|
||||
arena.alloc(|| Rc::new(i));
|
||||
// Allocate something with funny size and alignment, to keep
|
||||
// things interesting.
|
||||
arena.alloc(|| [0u8, 1u8, 2u8]);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_arena_destructors_fail() {
|
||||
let arena = Arena::new();
|
||||
// Put some stuff in the arena.
|
||||
for i in 0..10 {
|
||||
// Arena allocate something with drop glue to make sure it
|
||||
// doesn't leak.
|
||||
arena.alloc(|| Rc::new(i));
|
||||
// Allocate something with funny size and alignment, to keep
|
||||
// things interesting.
|
||||
arena.alloc(|| [0u8, 1, 2]);
|
||||
}
|
||||
// Now, panic while allocating
|
||||
arena.alloc::<Rc<i32>, _>(|| {
|
||||
panic!();
|
||||
});
|
||||
}
|
||||
|
||||
// Drop tests
|
||||
|
||||
struct DropCounter<'a> {
|
||||
@ -772,40 +372,6 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_arena_drop_count() {
|
||||
let counter = Cell::new(0);
|
||||
{
|
||||
let arena = Arena::new();
|
||||
for _ in 0..100 {
|
||||
// Allocate something with drop glue to make sure it doesn't leak.
|
||||
arena.alloc(|| DropCounter { count: &counter });
|
||||
// Allocate something with funny size and alignment, to keep
|
||||
// things interesting.
|
||||
arena.alloc(|| [0u8, 1u8, 2u8]);
|
||||
}
|
||||
// dropping
|
||||
};
|
||||
assert_eq!(counter.get(), 100);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_arena_drop_on_clear() {
|
||||
let counter = Cell::new(0);
|
||||
for i in 0..10 {
|
||||
let mut arena = Arena::new();
|
||||
for _ in 0..100 {
|
||||
// Allocate something with drop glue to make sure it doesn't leak.
|
||||
arena.alloc(|| DropCounter { count: &counter });
|
||||
// Allocate something with funny size and alignment, to keep
|
||||
// things interesting.
|
||||
arena.alloc(|| [0u8, 1u8, 2u8]);
|
||||
}
|
||||
arena.clear();
|
||||
assert_eq!(counter.get(), i * 100 + 100);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_typed_arena_drop_count() {
|
||||
let counter = Cell::new(0);
|
||||
@ -845,25 +411,6 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_arena_drop_small_count() {
|
||||
DROP_COUNTER.with(|c| c.set(0));
|
||||
{
|
||||
let arena = Arena::new();
|
||||
for _ in 0..10 {
|
||||
for _ in 0..10 {
|
||||
// Allocate something with drop glue to make sure it doesn't leak.
|
||||
arena.alloc(|| SmallDroppable);
|
||||
}
|
||||
// Allocate something with funny size and alignment, to keep
|
||||
// things interesting.
|
||||
arena.alloc(|| [0u8, 1u8, 2u8]);
|
||||
}
|
||||
// dropping
|
||||
};
|
||||
assert_eq!(DROP_COUNTER.with(|c| c.get()), 100);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_typed_arena_drop_small_count() {
|
||||
DROP_COUNTER.with(|c| c.set(0));
|
||||
@ -898,17 +445,4 @@ mod tests {
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
pub fn bench_noncopy_old_arena(b: &mut Bencher) {
|
||||
let arena = Arena::new();
|
||||
b.iter(|| {
|
||||
arena.alloc(|| {
|
||||
Noncopy {
|
||||
string: "hello world".to_string(),
|
||||
array: vec![1, 2, 3, 4, 5],
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -244,24 +244,6 @@ impl<'a, B: ?Sized> Hash for Cow<'a, B> where B: Hash + ToOwned {
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait for moving into a `Cow`.
|
||||
#[unstable(feature = "into_cow", reason = "may be replaced by `convert::Into`",
|
||||
issue = "27735")]
|
||||
#[rustc_deprecated(since = "1.7.0",
|
||||
reason = "conflicts with Into, may return with specialization")]
|
||||
pub trait IntoCow<'a, B: ?Sized> where B: ToOwned {
|
||||
/// Moves `self` into `Cow`
|
||||
fn into_cow(self) -> Cow<'a, B>;
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[allow(deprecated)]
|
||||
impl<'a, B: ?Sized> IntoCow<'a, B> for Cow<'a, B> where B: ToOwned {
|
||||
fn into_cow(self) -> Cow<'a, B> {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[allow(deprecated)]
|
||||
impl<'a, T: ?Sized + ToOwned> AsRef<T> for Cow<'a, T> {
|
||||
|
@ -81,13 +81,13 @@ pub trait CLike {
|
||||
fn from_usize(usize) -> Self;
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
fn bit<E: CLike>(e: &E) -> usize {
|
||||
use core::usize;
|
||||
use core::mem;
|
||||
let value = e.to_usize();
|
||||
assert!(value < usize::BITS,
|
||||
let bits = mem::size_of::<usize>() * 8;
|
||||
assert!(value < bits,
|
||||
"EnumSet only supports up to {} variants.",
|
||||
usize::BITS - 1);
|
||||
bits - 1);
|
||||
1 << value
|
||||
}
|
||||
|
||||
|
@ -491,10 +491,6 @@ pub use core::fmt::{LowerExp, UpperExp};
|
||||
pub use core::fmt::Error;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::fmt::{ArgumentV1, Arguments, write};
|
||||
#[unstable(feature = "fmt_radix", issue = "27728")]
|
||||
#[rustc_deprecated(since = "1.7.0", reason = "not used enough to stabilize")]
|
||||
#[allow(deprecated)]
|
||||
pub use core::fmt::{radix, Radix, RadixFmt};
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::fmt::{DebugList, DebugMap, DebugSet, DebugStruct, DebugTuple};
|
||||
|
||||
|
@ -38,18 +38,15 @@
|
||||
#![feature(decode_utf16)]
|
||||
#![feature(dropck_parametricity)]
|
||||
#![feature(fmt_internals)]
|
||||
#![feature(fmt_radix)]
|
||||
#![feature(heap_api)]
|
||||
#![feature(inclusive_range)]
|
||||
#![feature(iter_arith)]
|
||||
#![feature(lang_items)]
|
||||
#![feature(nonzero)]
|
||||
#![feature(num_bits_bytes)]
|
||||
#![feature(pattern)]
|
||||
#![feature(placement_in)]
|
||||
#![feature(placement_new_protocol)]
|
||||
#![feature(shared)]
|
||||
#![feature(slice_bytes)]
|
||||
#![feature(slice_patterns)]
|
||||
#![feature(staged_api)]
|
||||
#![feature(step_by)]
|
||||
|
@ -1232,7 +1232,7 @@ mod tests {
|
||||
m.append(&mut n);
|
||||
check_links(&m);
|
||||
let mut sum = v;
|
||||
sum.push_all(&u);
|
||||
sum.extend_from_slice(&u);
|
||||
assert_eq!(sum.len(), m.len());
|
||||
for elt in sum {
|
||||
assert_eq!(m.pop_front(), Some(elt))
|
||||
|
@ -104,9 +104,6 @@ pub use core::slice::{Iter, IterMut};
|
||||
pub use core::slice::{SplitMut, ChunksMut, Split};
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::slice::{SplitN, RSplitN, SplitNMut, RSplitNMut};
|
||||
#[unstable(feature = "slice_bytes", issue = "27740")]
|
||||
#[allow(deprecated)]
|
||||
pub use core::slice::bytes;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::slice::{from_raw_parts, from_raw_parts_mut};
|
||||
|
||||
|
@ -66,8 +66,7 @@ use core::str::pattern::Pattern;
|
||||
use rustc_unicode::char::{decode_utf16, REPLACEMENT_CHARACTER};
|
||||
use rustc_unicode::str as unicode_str;
|
||||
|
||||
#[allow(deprecated)]
|
||||
use borrow::{Cow, IntoCow};
|
||||
use borrow::Cow;
|
||||
use range::RangeArgument;
|
||||
use str::{self, FromStr, Utf8Error, Chars};
|
||||
use vec::Vec;
|
||||
@ -1838,26 +1837,6 @@ impl Into<Vec<u8>> for String {
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "into_cow", reason = "may be replaced by `convert::Into`",
|
||||
issue= "27735")]
|
||||
#[allow(deprecated)]
|
||||
impl IntoCow<'static, str> for String {
|
||||
#[inline]
|
||||
fn into_cow(self) -> Cow<'static, str> {
|
||||
Cow::Owned(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "into_cow", reason = "may be replaced by `convert::Into`",
|
||||
issue = "27735")]
|
||||
#[allow(deprecated)]
|
||||
impl<'a> IntoCow<'a, str> for &'a str {
|
||||
#[inline]
|
||||
fn into_cow(self) -> Cow<'a, str> {
|
||||
Cow::Borrowed(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl fmt::Write for String {
|
||||
#[inline]
|
||||
|
@ -63,6 +63,7 @@ use alloc::boxed::Box;
|
||||
use alloc::heap::EMPTY;
|
||||
use alloc::raw_vec::RawVec;
|
||||
use borrow::ToOwned;
|
||||
use borrow::Cow;
|
||||
use core::cmp::Ordering;
|
||||
use core::fmt;
|
||||
use core::hash::{self, Hash};
|
||||
@ -74,9 +75,6 @@ use core::ops;
|
||||
use core::ptr;
|
||||
use core::slice;
|
||||
|
||||
#[allow(deprecated)]
|
||||
use borrow::{Cow, IntoCow};
|
||||
|
||||
use super::range::RangeArgument;
|
||||
|
||||
/// A contiguous growable array type, written `Vec<T>` but pronounced 'vector.'
|
||||
@ -967,17 +965,6 @@ impl<T: Clone> Vec<T> {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(missing_docs)]
|
||||
#[inline]
|
||||
#[unstable(feature = "vec_push_all",
|
||||
reason = "likely to be replaced by a more optimized extend",
|
||||
issue = "27744")]
|
||||
#[rustc_deprecated(reason = "renamed to extend_from_slice",
|
||||
since = "1.6.0")]
|
||||
pub fn push_all(&mut self, other: &[T]) {
|
||||
self.extend_from_slice(other)
|
||||
}
|
||||
|
||||
/// Appends all elements in a slice to the `Vec`.
|
||||
///
|
||||
/// Iterates over the slice `other`, clones each element, and then appends
|
||||
@ -1598,22 +1585,6 @@ impl<'a, T> FromIterator<T> for Cow<'a, [T]> where T: Clone {
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[allow(deprecated)]
|
||||
impl<'a, T: 'a> IntoCow<'a, [T]> for Vec<T> where T: Clone {
|
||||
fn into_cow(self) -> Cow<'a, [T]> {
|
||||
Cow::Owned(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[allow(deprecated)]
|
||||
impl<'a, T> IntoCow<'a, [T]> for &'a [T] where T: Clone {
|
||||
fn into_cow(self) -> Cow<'a, [T]> {
|
||||
Cow::Borrowed(self)
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Iterators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -24,7 +24,6 @@
|
||||
#![feature(pattern)]
|
||||
#![feature(rand)]
|
||||
#![feature(set_recovery)]
|
||||
#![feature(slice_bytes)]
|
||||
#![feature(step_by)]
|
||||
#![feature(str_char)]
|
||||
#![feature(str_escape)]
|
||||
|
@ -865,18 +865,6 @@ fn test_vec_default() {
|
||||
t!(Vec<i32>);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[allow(deprecated)]
|
||||
fn test_bytes_set_memory() {
|
||||
use std::slice::bytes::MutableByteVector;
|
||||
|
||||
let mut values = [1,2,3,4,5];
|
||||
values[0..5].set_memory(0xAB);
|
||||
assert!(values == [0xAB, 0xAB, 0xAB, 0xAB, 0xAB]);
|
||||
values[2..4].set_memory(0xFF);
|
||||
assert!(values == [0xAB, 0xAB, 0xFF, 0xFF, 0xAB]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_overflow_does_not_cause_segfault() {
|
||||
|
@ -255,7 +255,7 @@ pub fn from_digit(num: u32, radix: u32) -> Option<char> {
|
||||
#[doc(hidden)]
|
||||
#[unstable(feature = "core_char_ext",
|
||||
reason = "the stable interface is `impl char` in later crate",
|
||||
issue = "27701")]
|
||||
issue = "32110")]
|
||||
pub trait CharExt {
|
||||
#[stable(feature = "core", since = "1.6.0")]
|
||||
fn is_digit(self, radix: u32) -> bool;
|
||||
|
@ -124,7 +124,8 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> {
|
||||
pub struct DebugTuple<'a, 'b: 'a> {
|
||||
fmt: &'a mut fmt::Formatter<'b>,
|
||||
result: fmt::Result,
|
||||
has_fields: bool,
|
||||
fields: usize,
|
||||
empty_name: bool,
|
||||
}
|
||||
|
||||
pub fn debug_tuple_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>, name: &str) -> DebugTuple<'a, 'b> {
|
||||
@ -132,7 +133,8 @@ pub fn debug_tuple_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>, name: &str) -> D
|
||||
DebugTuple {
|
||||
fmt: fmt,
|
||||
result: result,
|
||||
has_fields: false,
|
||||
fields: 0,
|
||||
empty_name: name.is_empty(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -141,7 +143,7 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> {
|
||||
#[stable(feature = "debug_builders", since = "1.2.0")]
|
||||
pub fn field(&mut self, value: &fmt::Debug) -> &mut DebugTuple<'a, 'b> {
|
||||
self.result = self.result.and_then(|_| {
|
||||
let (prefix, space) = if self.has_fields {
|
||||
let (prefix, space) = if self.fields > 0 {
|
||||
(",", " ")
|
||||
} else {
|
||||
("(", "")
|
||||
@ -155,20 +157,22 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> {
|
||||
}
|
||||
});
|
||||
|
||||
self.has_fields = true;
|
||||
self.fields += 1;
|
||||
self
|
||||
}
|
||||
|
||||
/// Finishes output and returns any error encountered.
|
||||
#[stable(feature = "debug_builders", since = "1.2.0")]
|
||||
pub fn finish(&mut self) -> fmt::Result {
|
||||
if self.has_fields {
|
||||
if self.fields > 0 {
|
||||
self.result = self.result.and_then(|_| {
|
||||
if self.is_pretty() {
|
||||
self.fmt.write_str("\n)")
|
||||
} else {
|
||||
self.fmt.write_str(")")
|
||||
try!(self.fmt.write_str("\n"));
|
||||
}
|
||||
if self.fields == 1 && self.empty_name {
|
||||
try!(self.fmt.write_str(","));
|
||||
}
|
||||
self.fmt.write_str(")")
|
||||
});
|
||||
}
|
||||
self.result
|
||||
@ -177,14 +181,6 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> {
|
||||
fn is_pretty(&self) -> bool {
|
||||
self.fmt.flags() & (1 << (FlagV1::Alternate as usize)) != 0
|
||||
}
|
||||
|
||||
/// Returns the wrapped `Formatter`.
|
||||
#[unstable(feature = "debug_builder_formatter", reason = "recently added",
|
||||
issue = "27782")]
|
||||
#[rustc_deprecated(since = "1.7.0", reason = "will be removed")]
|
||||
pub fn formatter(&mut self) -> &mut fmt::Formatter<'b> {
|
||||
&mut self.fmt
|
||||
}
|
||||
}
|
||||
|
||||
struct DebugInner<'a, 'b: 'a> {
|
||||
|
@ -36,18 +36,6 @@ pub enum Alignment {
|
||||
Unknown,
|
||||
}
|
||||
|
||||
#[unstable(feature = "fmt_radix", issue = "27728")]
|
||||
#[rustc_deprecated(since = "1.7.0", reason = "not used enough to stabilize")]
|
||||
#[allow(deprecated)]
|
||||
pub use self::num::radix;
|
||||
#[unstable(feature = "fmt_radix", issue = "27728")]
|
||||
#[rustc_deprecated(since = "1.7.0", reason = "not used enough to stabilize")]
|
||||
#[allow(deprecated)]
|
||||
pub use self::num::Radix;
|
||||
#[unstable(feature = "fmt_radix", issue = "27728")]
|
||||
#[rustc_deprecated(since = "1.7.0", reason = "not used enough to stabilize")]
|
||||
#[allow(deprecated)]
|
||||
pub use self::num::RadixFmt;
|
||||
#[stable(feature = "debug_builders", since = "1.2.0")]
|
||||
pub use self::builders::{DebugStruct, DebugTuple, DebugSet, DebugList, DebugMap};
|
||||
|
||||
@ -1561,16 +1549,10 @@ macro_rules! tuple {
|
||||
fn fmt(&self, f: &mut Formatter) -> Result {
|
||||
let mut builder = f.debug_tuple("");
|
||||
let ($(ref $name,)*) = *self;
|
||||
let mut n = 0;
|
||||
$(
|
||||
builder.field($name);
|
||||
n += 1;
|
||||
)*
|
||||
|
||||
if n == 1 {
|
||||
try!(write!(builder.formatter(), ","));
|
||||
}
|
||||
|
||||
builder.finish()
|
||||
}
|
||||
}
|
||||
|
@ -140,81 +140,6 @@ radix! { LowerHex, 16, "0x", x @ 0 ... 9 => b'0' + x,
|
||||
radix! { UpperHex, 16, "0x", x @ 0 ... 9 => b'0' + x,
|
||||
x @ 10 ... 15 => b'A' + (x - 10) }
|
||||
|
||||
/// A radix with in the range of `2..36`.
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
#[unstable(feature = "fmt_radix",
|
||||
reason = "may be renamed or move to a different module",
|
||||
issue = "27728")]
|
||||
#[rustc_deprecated(since = "1.7.0", reason = "not used enough to stabilize")]
|
||||
pub struct Radix {
|
||||
base: u8,
|
||||
}
|
||||
|
||||
impl Radix {
|
||||
fn new(base: u8) -> Radix {
|
||||
assert!(2 <= base && base <= 36,
|
||||
"the base must be in the range of 2..36: {}",
|
||||
base);
|
||||
Radix { base: base }
|
||||
}
|
||||
}
|
||||
|
||||
impl GenericRadix for Radix {
|
||||
fn base(&self) -> u8 {
|
||||
self.base
|
||||
}
|
||||
fn digit(&self, x: u8) -> u8 {
|
||||
match x {
|
||||
x @ 0 ... 9 => b'0' + x,
|
||||
x if x < self.base() => b'a' + (x - 10),
|
||||
x => panic!("number not in the range 0..{}: {}", self.base() - 1, x),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A helper type for formatting radixes.
|
||||
#[unstable(feature = "fmt_radix",
|
||||
reason = "may be renamed or move to a different module",
|
||||
issue = "27728")]
|
||||
#[rustc_deprecated(since = "1.7.0", reason = "not used enough to stabilize")]
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct RadixFmt<T, R>(T, R);
|
||||
|
||||
/// Constructs a radix formatter in the range of `2..36`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(fmt_radix)]
|
||||
///
|
||||
/// use std::fmt::radix;
|
||||
/// assert_eq!(format!("{}", radix(55, 36)), "1j".to_string());
|
||||
/// ```
|
||||
#[unstable(feature = "fmt_radix",
|
||||
reason = "may be renamed or move to a different module",
|
||||
issue = "27728")]
|
||||
#[rustc_deprecated(since = "1.7.0", reason = "not used enough to stabilize")]
|
||||
pub fn radix<T>(x: T, base: u8) -> RadixFmt<T, Radix> {
|
||||
RadixFmt(x, Radix::new(base))
|
||||
}
|
||||
|
||||
macro_rules! radix_fmt {
|
||||
($T:ty as $U:ty, $fmt:ident) => {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl fmt::Debug for RadixFmt<$T, Radix> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt::Display::fmt(self, f)
|
||||
}
|
||||
}
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl fmt::Display for RadixFmt<$T, Radix> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self { RadixFmt(ref x, radix) => radix.$fmt(*x as $U, f) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! int_base {
|
||||
($Trait:ident for $T:ident as $U:ident -> $Radix:ident) => {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
@ -243,14 +168,12 @@ macro_rules! integer {
|
||||
int_base! { Octal for $Int as $Uint -> Octal }
|
||||
int_base! { LowerHex for $Int as $Uint -> LowerHex }
|
||||
int_base! { UpperHex for $Int as $Uint -> UpperHex }
|
||||
radix_fmt! { $Int as $Int, fmt_int }
|
||||
debug! { $Int }
|
||||
|
||||
int_base! { Binary for $Uint as $Uint -> Binary }
|
||||
int_base! { Octal for $Uint as $Uint -> Octal }
|
||||
int_base! { LowerHex for $Uint as $Uint -> LowerHex }
|
||||
int_base! { UpperHex for $Uint as $Uint -> UpperHex }
|
||||
radix_fmt! { $Uint as $Uint, fmt_int }
|
||||
debug! { $Uint }
|
||||
}
|
||||
}
|
||||
|
@ -238,30 +238,6 @@ impl<H> Default for BuildHasherDefault<H> {
|
||||
}
|
||||
}
|
||||
|
||||
// The HashState trait is super deprecated, but it's here to have the blanket
|
||||
// impl that goes from HashState -> BuildHasher
|
||||
|
||||
/// Deprecated, renamed to `BuildHasher`
|
||||
#[unstable(feature = "hashmap_hasher", reason = "hasher stuff is unclear",
|
||||
issue = "27713")]
|
||||
#[rustc_deprecated(since = "1.7.0", reason = "support moved to std::hash and \
|
||||
renamed to BuildHasher")]
|
||||
pub trait HashState {
|
||||
/// Type of the hasher that will be created.
|
||||
type Hasher: Hasher;
|
||||
|
||||
/// Creates a new hasher based on the given state of this object.
|
||||
fn hasher(&self) -> Self::Hasher;
|
||||
}
|
||||
|
||||
#[unstable(feature = "hashmap_hasher", reason = "hasher stuff is unclear",
|
||||
issue = "27713")]
|
||||
#[allow(deprecated)]
|
||||
impl<T: HashState> BuildHasher for T {
|
||||
type Hasher = T::Hasher;
|
||||
fn build_hasher(&self) -> T::Hasher { self.hasher() }
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
mod impls {
|
||||
|
@ -1922,19 +1922,6 @@ pub trait Iterator {
|
||||
.map(|(_, x)| x)
|
||||
}
|
||||
|
||||
#[allow(missing_docs)]
|
||||
#[inline]
|
||||
#[unstable(feature = "iter_cmp",
|
||||
reason = "may want to produce an Ordering directly; see #15311",
|
||||
issue = "27724")]
|
||||
#[rustc_deprecated(reason = "renamed to max_by_key", since = "1.6.0")]
|
||||
fn max_by<B: Ord, F>(self, f: F) -> Option<Self::Item> where
|
||||
Self: Sized,
|
||||
F: FnMut(&Self::Item) -> B,
|
||||
{
|
||||
self.max_by_key(f)
|
||||
}
|
||||
|
||||
/// Returns the element that gives the maximum value from the
|
||||
/// specified function.
|
||||
///
|
||||
@ -1960,19 +1947,6 @@ pub trait Iterator {
|
||||
.map(|(_, x)| x)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[allow(missing_docs)]
|
||||
#[unstable(feature = "iter_cmp",
|
||||
reason = "may want to produce an Ordering directly; see #15311",
|
||||
issue = "27724")]
|
||||
#[rustc_deprecated(reason = "renamed to min_by_key", since = "1.6.0")]
|
||||
fn min_by<B: Ord, F>(self, f: F) -> Option<Self::Item> where
|
||||
Self: Sized,
|
||||
F: FnMut(&Self::Item) -> B,
|
||||
{
|
||||
self.min_by_key(f)
|
||||
}
|
||||
|
||||
/// Returns the element that gives the minimum value from the
|
||||
/// specified function.
|
||||
///
|
||||
@ -3679,7 +3653,7 @@ impl<I: Iterator> Peekable<I> {
|
||||
///
|
||||
/// assert_eq!(iter.is_empty(), true);
|
||||
/// ```
|
||||
#[unstable(feature = "peekable_is_empty", issue = "27701")]
|
||||
#[unstable(feature = "peekable_is_empty", issue = "32111")]
|
||||
#[inline]
|
||||
pub fn is_empty(&mut self) -> bool {
|
||||
self.peek().is_none()
|
||||
|
@ -141,7 +141,7 @@ pub mod consts {
|
||||
|
||||
#[unstable(feature = "core_float",
|
||||
reason = "stable interface is via `impl f{32,64}` in later crates",
|
||||
issue = "27702")]
|
||||
issue = "32110")]
|
||||
impl Float for f32 {
|
||||
#[inline]
|
||||
fn nan() -> f32 { NAN }
|
||||
|
@ -141,7 +141,7 @@ pub mod consts {
|
||||
|
||||
#[unstable(feature = "core_float",
|
||||
reason = "stable interface is via `impl f{32,64}` in later crates",
|
||||
issue = "27702")]
|
||||
issue = "32110")]
|
||||
impl Float for f64 {
|
||||
#[inline]
|
||||
fn nan() -> f64 { NAN }
|
||||
|
@ -12,25 +12,6 @@
|
||||
|
||||
macro_rules! int_module { ($T:ty, $bits:expr) => (
|
||||
|
||||
// FIXME(#11621): Should be deprecated once CTFE is implemented in favour of
|
||||
// calling the `mem::size_of` function.
|
||||
#[unstable(feature = "num_bits_bytes",
|
||||
reason = "may want to be an associated function",
|
||||
issue = "27753")]
|
||||
#[rustc_deprecated(since = "1.7.0",
|
||||
reason = "will be replaced via const fn or associated constants")]
|
||||
#[allow(missing_docs)]
|
||||
pub const BITS : usize = $bits;
|
||||
// FIXME(#11621): Should be deprecated once CTFE is implemented in favour of
|
||||
// calling the `mem::size_of` function.
|
||||
#[unstable(feature = "num_bits_bytes",
|
||||
reason = "may want to be an associated function",
|
||||
issue = "27753")]
|
||||
#[rustc_deprecated(since = "1.7.0",
|
||||
reason = "will be replaced via const fn or associated constants")]
|
||||
#[allow(missing_docs)]
|
||||
pub const BYTES : usize = ($bits / 8);
|
||||
|
||||
// FIXME(#11621): Should be deprecated once CTFE is implemented in favour of
|
||||
// calling the `Bounded::min_value` function.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
@ -41,7 +41,7 @@ use slice::SliceExt;
|
||||
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Debug, Default)]
|
||||
pub struct Wrapping<T>(#[stable(feature = "rust1", since = "1.0.0")] pub T);
|
||||
|
||||
pub mod wrapping;
|
||||
mod wrapping;
|
||||
|
||||
// All these modules are technically private and only exposed for libcoretest:
|
||||
pub mod flt2dec;
|
||||
@ -2209,7 +2209,7 @@ pub enum FpCategory {
|
||||
#[doc(hidden)]
|
||||
#[unstable(feature = "core_float",
|
||||
reason = "stable interface is via `impl f{32,64}` in later crates",
|
||||
issue = "27702")]
|
||||
issue = "32110")]
|
||||
pub trait Float: Sized {
|
||||
/// Returns the NaN value.
|
||||
#[unstable(feature = "float_extras", reason = "needs removal",
|
||||
|
@ -12,21 +12,6 @@
|
||||
|
||||
macro_rules! uint_module { ($T:ty, $bits:expr) => (
|
||||
|
||||
#[unstable(feature = "num_bits_bytes",
|
||||
reason = "may want to be an associated function",
|
||||
issue = "27753")]
|
||||
#[rustc_deprecated(since = "1.7.0",
|
||||
reason = "will be replaced via const fn or associated constants")]
|
||||
#[allow(missing_docs)]
|
||||
pub const BITS : usize = $bits;
|
||||
#[unstable(feature = "num_bits_bytes",
|
||||
reason = "may want to be an associated function",
|
||||
issue = "27753")]
|
||||
#[rustc_deprecated(since = "1.7.0",
|
||||
reason = "will be replaced via const fn or associated constants")]
|
||||
#[allow(missing_docs)]
|
||||
pub const BYTES : usize = ($bits / 8);
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[allow(missing_docs)]
|
||||
pub const MIN: $T = 0 as $T;
|
||||
|
@ -8,34 +8,10 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![allow(missing_docs)]
|
||||
#![unstable(feature = "old_wrapping", reason = "may be removed or relocated",
|
||||
issue = "27755")]
|
||||
|
||||
use intrinsics::{add_with_overflow, sub_with_overflow, mul_with_overflow};
|
||||
|
||||
use super::Wrapping;
|
||||
|
||||
use ops::*;
|
||||
|
||||
use ::{i8, i16, i32, i64, isize};
|
||||
|
||||
#[unstable(feature = "old_wrapping", reason = "may be removed or relocated",
|
||||
issue = "27755")]
|
||||
#[rustc_deprecated(since = "1.7.0", reason = "moved to inherent methods")]
|
||||
pub trait OverflowingOps {
|
||||
fn overflowing_add(self, rhs: Self) -> (Self, bool);
|
||||
fn overflowing_sub(self, rhs: Self) -> (Self, bool);
|
||||
fn overflowing_mul(self, rhs: Self) -> (Self, bool);
|
||||
|
||||
fn overflowing_div(self, rhs: Self) -> (Self, bool);
|
||||
fn overflowing_rem(self, rhs: Self) -> (Self, bool);
|
||||
fn overflowing_neg(self) -> (Self, bool);
|
||||
|
||||
fn overflowing_shl(self, rhs: u32) -> (Self, bool);
|
||||
fn overflowing_shr(self, rhs: u32) -> (Self, bool);
|
||||
}
|
||||
|
||||
macro_rules! sh_impl_signed {
|
||||
($t:ident, $f:ident) => (
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
@ -52,7 +28,7 @@ macro_rules! sh_impl_signed {
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "wrapping_impls", reason = "recently added", issue = "30524")]
|
||||
#[stable(feature = "wrapping_impls", since = "1.7.0")]
|
||||
impl ShlAssign<$f> for Wrapping<$t> {
|
||||
#[inline(always)]
|
||||
fn shl_assign(&mut self, other: $f) {
|
||||
@ -74,7 +50,7 @@ macro_rules! sh_impl_signed {
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "wrapping_impls", reason = "recently added", issue = "30524")]
|
||||
#[stable(feature = "wrapping_impls", since = "1.7.0")]
|
||||
impl ShrAssign<$f> for Wrapping<$t> {
|
||||
#[inline(always)]
|
||||
fn shr_assign(&mut self, other: $f) {
|
||||
@ -96,7 +72,7 @@ macro_rules! sh_impl_unsigned {
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "wrapping_impls", reason = "recently added", issue = "30524")]
|
||||
#[stable(feature = "wrapping_impls", since = "1.7.0")]
|
||||
impl ShlAssign<$f> for Wrapping<$t> {
|
||||
#[inline(always)]
|
||||
fn shl_assign(&mut self, other: $f) {
|
||||
@ -114,7 +90,7 @@ macro_rules! sh_impl_unsigned {
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "wrapping_impls", reason = "recently added", issue = "30524")]
|
||||
#[stable(feature = "wrapping_impls", since = "1.7.0")]
|
||||
impl ShrAssign<$f> for Wrapping<$t> {
|
||||
#[inline(always)]
|
||||
fn shr_assign(&mut self, other: $f) {
|
||||
@ -218,7 +194,7 @@ macro_rules! wrapping_impl {
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "wrapping_impls", reason = "recently added", issue = "30524")]
|
||||
#[stable(feature = "wrapping_impls", since = "1.7.0")]
|
||||
impl Rem for Wrapping<$t> {
|
||||
type Output = Wrapping<$t>;
|
||||
|
||||
@ -331,120 +307,3 @@ mod shift_max {
|
||||
pub const u64: u32 = i64;
|
||||
pub use self::platform::usize;
|
||||
}
|
||||
|
||||
macro_rules! signed_overflowing_impl {
|
||||
($($t:ident)*) => ($(
|
||||
#[allow(deprecated)]
|
||||
impl OverflowingOps for $t {
|
||||
#[inline(always)]
|
||||
fn overflowing_add(self, rhs: $t) -> ($t, bool) {
|
||||
unsafe {
|
||||
add_with_overflow(self, rhs)
|
||||
}
|
||||
}
|
||||
#[inline(always)]
|
||||
fn overflowing_sub(self, rhs: $t) -> ($t, bool) {
|
||||
unsafe {
|
||||
sub_with_overflow(self, rhs)
|
||||
}
|
||||
}
|
||||
#[inline(always)]
|
||||
fn overflowing_mul(self, rhs: $t) -> ($t, bool) {
|
||||
unsafe {
|
||||
mul_with_overflow(self, rhs)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn overflowing_div(self, rhs: $t) -> ($t, bool) {
|
||||
if self == $t::MIN && rhs == -1 {
|
||||
(self, true)
|
||||
} else {
|
||||
(self/rhs, false)
|
||||
}
|
||||
}
|
||||
#[inline(always)]
|
||||
fn overflowing_rem(self, rhs: $t) -> ($t, bool) {
|
||||
if self == $t::MIN && rhs == -1 {
|
||||
(0, true)
|
||||
} else {
|
||||
(self % rhs, false)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn overflowing_shl(self, rhs: u32) -> ($t, bool) {
|
||||
(self << (rhs & self::shift_max::$t),
|
||||
(rhs > self::shift_max::$t))
|
||||
}
|
||||
#[inline(always)]
|
||||
fn overflowing_shr(self, rhs: u32) -> ($t, bool) {
|
||||
(self >> (rhs & self::shift_max::$t),
|
||||
(rhs > self::shift_max::$t))
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn overflowing_neg(self) -> ($t, bool) {
|
||||
if self == $t::MIN {
|
||||
($t::MIN, true)
|
||||
} else {
|
||||
(-self, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
)*)
|
||||
}
|
||||
|
||||
macro_rules! unsigned_overflowing_impl {
|
||||
($($t:ident)*) => ($(
|
||||
#[allow(deprecated)]
|
||||
impl OverflowingOps for $t {
|
||||
#[inline(always)]
|
||||
fn overflowing_add(self, rhs: $t) -> ($t, bool) {
|
||||
unsafe {
|
||||
add_with_overflow(self, rhs)
|
||||
}
|
||||
}
|
||||
#[inline(always)]
|
||||
fn overflowing_sub(self, rhs: $t) -> ($t, bool) {
|
||||
unsafe {
|
||||
sub_with_overflow(self, rhs)
|
||||
}
|
||||
}
|
||||
#[inline(always)]
|
||||
fn overflowing_mul(self, rhs: $t) -> ($t, bool) {
|
||||
unsafe {
|
||||
mul_with_overflow(self, rhs)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn overflowing_div(self, rhs: $t) -> ($t, bool) {
|
||||
(self/rhs, false)
|
||||
}
|
||||
#[inline(always)]
|
||||
fn overflowing_rem(self, rhs: $t) -> ($t, bool) {
|
||||
(self % rhs, false)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn overflowing_shl(self, rhs: u32) -> ($t, bool) {
|
||||
(self << (rhs & self::shift_max::$t),
|
||||
(rhs > self::shift_max::$t))
|
||||
}
|
||||
#[inline(always)]
|
||||
fn overflowing_shr(self, rhs: u32) -> ($t, bool) {
|
||||
(self >> (rhs & self::shift_max::$t),
|
||||
(rhs > self::shift_max::$t))
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn overflowing_neg(self) -> ($t, bool) {
|
||||
((!self).wrapping_add(1), true)
|
||||
}
|
||||
}
|
||||
)*)
|
||||
}
|
||||
|
||||
signed_overflowing_impl! { i8 i16 i32 i64 isize }
|
||||
unsigned_overflowing_impl! { u8 u16 u32 u64 usize }
|
||||
|
@ -61,7 +61,7 @@ use raw::Slice as RawSlice;
|
||||
/// Extension methods for slices.
|
||||
#[unstable(feature = "core_slice_ext",
|
||||
reason = "stable interface provided by `impl [T]` in later crates",
|
||||
issue = "27701")]
|
||||
issue = "32110")]
|
||||
#[allow(missing_docs)] // documented elsewhere
|
||||
pub trait SliceExt {
|
||||
type Item;
|
||||
@ -182,7 +182,7 @@ macro_rules! slice_ref {
|
||||
|
||||
#[unstable(feature = "core_slice_ext",
|
||||
reason = "stable interface provided by `impl [T]` in later crates",
|
||||
issue = "27701")]
|
||||
issue = "32110")]
|
||||
impl<T> SliceExt for [T] {
|
||||
type Item = T;
|
||||
|
||||
@ -1552,52 +1552,6 @@ pub unsafe fn from_raw_parts_mut<'a, T>(p: *mut T, len: usize) -> &'a mut [T] {
|
||||
mem::transmute(RawSlice { data: p, len: len })
|
||||
}
|
||||
|
||||
//
|
||||
// Submodules
|
||||
//
|
||||
|
||||
/// Operations on `[u8]`.
|
||||
#[unstable(feature = "slice_bytes", reason = "needs review",
|
||||
issue = "27740")]
|
||||
#[rustc_deprecated(reason = "unidiomatic functions not pulling their weight",
|
||||
since = "1.6.0")]
|
||||
#[allow(deprecated)]
|
||||
pub mod bytes {
|
||||
use ptr;
|
||||
use slice::SliceExt;
|
||||
|
||||
/// A trait for operations on mutable `[u8]`s.
|
||||
pub trait MutableByteVector {
|
||||
/// Sets all bytes of the receiver to the given value.
|
||||
fn set_memory(&mut self, value: u8);
|
||||
}
|
||||
|
||||
impl MutableByteVector for [u8] {
|
||||
#[inline]
|
||||
fn set_memory(&mut self, value: u8) {
|
||||
unsafe { ptr::write_bytes(self.as_mut_ptr(), value, self.len()) };
|
||||
}
|
||||
}
|
||||
|
||||
/// Copies data from `src` to `dst`
|
||||
///
|
||||
/// Panics if the length of `dst` is less than the length of `src`.
|
||||
#[inline]
|
||||
pub fn copy_memory(src: &[u8], dst: &mut [u8]) {
|
||||
let len_src = src.len();
|
||||
assert!(dst.len() >= len_src);
|
||||
// `dst` is unaliasable, so we know statically it doesn't overlap
|
||||
// with `src`.
|
||||
unsafe {
|
||||
ptr::copy_nonoverlapping(src.as_ptr(),
|
||||
dst.as_mut_ptr(),
|
||||
len_src);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Boilerplate traits
|
||||
//
|
||||
|
@ -1561,7 +1561,7 @@ mod traits {
|
||||
#[doc(hidden)]
|
||||
#[unstable(feature = "core_str_ext",
|
||||
reason = "stable interface provided by `impl str` in later crates",
|
||||
issue = "27701")]
|
||||
issue = "32110")]
|
||||
pub trait StrExt {
|
||||
// NB there are no docs here are they're all located on the StrExt trait in
|
||||
// libcollections, not here.
|
||||
|
@ -150,107 +150,3 @@ fn test_format_int_twos_complement() {
|
||||
assert!(format!("{}", i32::MIN) == "-2147483648");
|
||||
assert!(format!("{}", i64::MIN) == "-9223372036854775808");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[allow(deprecated)]
|
||||
fn test_format_radix() {
|
||||
use core::fmt::radix;
|
||||
assert!(format!("{:04}", radix(3, 2)) == "0011");
|
||||
assert!(format!("{}", radix(55, 36)) == "1j");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
#[allow(deprecated)]
|
||||
fn test_radix_base_too_large() {
|
||||
use core::fmt::radix;
|
||||
let _ = radix(55, 37);
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
mod u32 {
|
||||
use test::Bencher;
|
||||
use core::fmt::radix;
|
||||
use std::__rand::{thread_rng, Rng};
|
||||
use std::io::{Write, sink};
|
||||
|
||||
#[bench]
|
||||
fn format_bin(b: &mut Bencher) {
|
||||
let mut rng = thread_rng();
|
||||
b.iter(|| { write!(&mut sink(), "{:b}", rng.gen::<u32>()) })
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn format_oct(b: &mut Bencher) {
|
||||
let mut rng = thread_rng();
|
||||
b.iter(|| { write!(&mut sink(), "{:o}", rng.gen::<u32>()) })
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn format_dec(b: &mut Bencher) {
|
||||
let mut rng = thread_rng();
|
||||
b.iter(|| { write!(&mut sink(), "{}", rng.gen::<u32>()) })
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn format_hex(b: &mut Bencher) {
|
||||
let mut rng = thread_rng();
|
||||
b.iter(|| { write!(&mut sink(), "{:x}", rng.gen::<u32>()) })
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn format_show(b: &mut Bencher) {
|
||||
let mut rng = thread_rng();
|
||||
b.iter(|| { write!(&mut sink(), "{:?}", rng.gen::<u32>()) })
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn format_base_36(b: &mut Bencher) {
|
||||
let mut rng = thread_rng();
|
||||
b.iter(|| { write!(&mut sink(), "{}", radix(rng.gen::<u32>(), 36)) })
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
mod i32 {
|
||||
use test::Bencher;
|
||||
use core::fmt::radix;
|
||||
use std::__rand::{thread_rng, Rng};
|
||||
use std::io::{Write, sink};
|
||||
|
||||
#[bench]
|
||||
fn format_bin(b: &mut Bencher) {
|
||||
let mut rng = thread_rng();
|
||||
b.iter(|| { write!(&mut sink(), "{:b}", rng.gen::<i32>()) })
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn format_oct(b: &mut Bencher) {
|
||||
let mut rng = thread_rng();
|
||||
b.iter(|| { write!(&mut sink(), "{:o}", rng.gen::<i32>()) })
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn format_dec(b: &mut Bencher) {
|
||||
let mut rng = thread_rng();
|
||||
b.iter(|| { write!(&mut sink(), "{}", rng.gen::<i32>()) })
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn format_hex(b: &mut Bencher) {
|
||||
let mut rng = thread_rng();
|
||||
b.iter(|| { write!(&mut sink(), "{:x}", rng.gen::<i32>()) })
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn format_show(b: &mut Bencher) {
|
||||
let mut rng = thread_rng();
|
||||
b.iter(|| { write!(&mut sink(), "{:?}", rng.gen::<i32>()) })
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn format_base_36(b: &mut Bencher) {
|
||||
let mut rng = thread_rng();
|
||||
b.iter(|| { write!(&mut sink(), "{}", radix(rng.gen::<i32>(), 36)) })
|
||||
}
|
||||
}
|
||||
|
@ -24,8 +24,6 @@
|
||||
#![feature(fixed_size_array)]
|
||||
#![feature(float_extras)]
|
||||
#![feature(flt2dec)]
|
||||
#![feature(fmt_radix)]
|
||||
#![feature(iter_arith)]
|
||||
#![feature(iter_arith)]
|
||||
#![feature(libc)]
|
||||
#![feature(nonzero)]
|
||||
|
@ -27,7 +27,7 @@
|
||||
#![feature(libc)]
|
||||
#![feature(staged_api)]
|
||||
#![feature(unique)]
|
||||
#![cfg_attr(test, feature(rustc_private, rand, vec_push_all))]
|
||||
#![cfg_attr(test, feature(rustc_private, rand))]
|
||||
|
||||
#[cfg(test)]
|
||||
#[macro_use]
|
||||
@ -173,7 +173,7 @@ mod tests {
|
||||
for _ in 0..20 {
|
||||
let mut input = vec![];
|
||||
for _ in 0..2000 {
|
||||
input.push_all(r.choose(&words).unwrap());
|
||||
input.extend_from_slice(r.choose(&words).unwrap());
|
||||
}
|
||||
debug!("de/inflate of {} bytes of random word-sequences",
|
||||
input.len());
|
||||
|
@ -30,7 +30,6 @@
|
||||
issue = "27703")]
|
||||
#![feature(core_float)]
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(num_bits_bytes)]
|
||||
#![feature(staged_api)]
|
||||
#![feature(step_by)]
|
||||
#![feature(custom_attribute)]
|
||||
|
@ -11,15 +11,14 @@
|
||||
//! The implementations of `Rand` for the built-in types.
|
||||
|
||||
use core::char;
|
||||
use core::isize;
|
||||
use core::usize;
|
||||
use core::mem;
|
||||
|
||||
use {Rand, Rng};
|
||||
|
||||
impl Rand for isize {
|
||||
#[inline]
|
||||
fn rand<R: Rng>(rng: &mut R) -> isize {
|
||||
if isize::BITS == 32 {
|
||||
if mem::size_of::<isize>() == 4 {
|
||||
rng.gen::<i32>() as isize
|
||||
} else {
|
||||
rng.gen::<i64>() as isize
|
||||
@ -58,7 +57,7 @@ impl Rand for i64 {
|
||||
impl Rand for usize {
|
||||
#[inline]
|
||||
fn rand<R: Rng>(rng: &mut R) -> usize {
|
||||
if usize::BITS == 32 {
|
||||
if mem::size_of::<usize>() == 4 {
|
||||
rng.gen::<u32>() as usize
|
||||
} else {
|
||||
rng.gen::<u64>() as usize
|
||||
|
@ -12,46 +12,22 @@
|
||||
//!
|
||||
//! A simple wrapper over the platform's dynamic library facilities
|
||||
|
||||
#![unstable(feature = "dynamic_lib",
|
||||
reason = "API has not been scrutinized and is highly likely to \
|
||||
either disappear or change",
|
||||
issue = "27810")]
|
||||
#![allow(missing_docs)]
|
||||
#![allow(deprecated)]
|
||||
use std::env;
|
||||
use std::ffi::{CString, OsString};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use prelude::v1::*;
|
||||
|
||||
use env;
|
||||
use ffi::{CString, OsString};
|
||||
use path::{Path, PathBuf};
|
||||
|
||||
#[unstable(feature = "dynamic_lib",
|
||||
reason = "API has not been scrutinized and is highly likely to \
|
||||
either disappear or change",
|
||||
issue = "27810")]
|
||||
#[rustc_deprecated(since = "1.5.0", reason = "replaced with 'dylib' on crates.io")]
|
||||
pub struct DynamicLibrary {
|
||||
handle: *mut u8
|
||||
}
|
||||
|
||||
impl Drop for DynamicLibrary {
|
||||
fn drop(&mut self) {
|
||||
match dl::check_for_errors_in(|| {
|
||||
unsafe {
|
||||
dl::close(self.handle)
|
||||
}
|
||||
}) {
|
||||
Ok(()) => {},
|
||||
Err(str) => panic!("{}", str)
|
||||
unsafe {
|
||||
dl::close(self.handle)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "dynamic_lib",
|
||||
reason = "API has not been scrutinized and is highly likely to \
|
||||
either disappear or change",
|
||||
issue = "27810")]
|
||||
#[rustc_deprecated(since = "1.5.0", reason = "replaced with 'dylib' on crates.io")]
|
||||
impl DynamicLibrary {
|
||||
/// Lazily open a dynamic library. When passed None it gives a
|
||||
/// handle to the calling process
|
||||
@ -116,9 +92,7 @@ impl DynamicLibrary {
|
||||
// T but that feature is still unimplemented
|
||||
|
||||
let raw_string = CString::new(symbol).unwrap();
|
||||
let maybe_symbol_value = dl::check_for_errors_in(|| {
|
||||
dl::symbol(self.handle, raw_string.as_ptr())
|
||||
});
|
||||
let maybe_symbol_value = dl::symbol(self.handle, raw_string.as_ptr());
|
||||
|
||||
// The value must not be constructed if there is an error so
|
||||
// the destructor does not run.
|
||||
@ -129,19 +103,18 @@ impl DynamicLibrary {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(test, not(target_os = "ios"), not(target_os = "nacl")))]
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use prelude::v1::*;
|
||||
use libc;
|
||||
use mem;
|
||||
use std::mem;
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(any(windows,
|
||||
target_os = "android", // FIXME #10379
|
||||
target_env = "musl"), ignore)]
|
||||
#[allow(deprecated)]
|
||||
fn test_loading_cosine() {
|
||||
if cfg!(windows) {
|
||||
return
|
||||
}
|
||||
|
||||
// The math library does not need to be loaded since it is already
|
||||
// statically linked in
|
||||
let libm = match DynamicLibrary::open(None) {
|
||||
@ -166,17 +139,12 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(target_os = "linux",
|
||||
target_os = "macos",
|
||||
target_os = "freebsd",
|
||||
target_os = "dragonfly",
|
||||
target_os = "bitrig",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "solaris"))]
|
||||
#[allow(deprecated)]
|
||||
fn test_errors_do_not_crash() {
|
||||
use path::Path;
|
||||
use std::path::Path;
|
||||
|
||||
if !cfg!(unix) {
|
||||
return
|
||||
}
|
||||
|
||||
// Open /dev/null as a library to get an error, and make sure
|
||||
// that only causes an error, and not a crash.
|
||||
@ -188,24 +156,13 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "linux",
|
||||
target_os = "android",
|
||||
target_os = "macos",
|
||||
target_os = "ios",
|
||||
target_os = "freebsd",
|
||||
target_os = "dragonfly",
|
||||
target_os = "bitrig",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "solaris",
|
||||
target_os = "emscripten"))]
|
||||
#[cfg(unix)]
|
||||
mod dl {
|
||||
use prelude::v1::*;
|
||||
|
||||
use ffi::{CStr, OsStr};
|
||||
use str;
|
||||
use libc;
|
||||
use ptr;
|
||||
use std::ffi::{CStr, OsStr, CString};
|
||||
use std::os::unix::prelude::*;
|
||||
use std::ptr;
|
||||
use std::str;
|
||||
|
||||
pub fn open(filename: Option<&OsStr>) -> Result<*mut u8, String> {
|
||||
check_for_errors_in(|| {
|
||||
@ -221,7 +178,7 @@ mod dl {
|
||||
const LAZY: libc::c_int = 1;
|
||||
|
||||
unsafe fn open_external(filename: &OsStr) -> *mut u8 {
|
||||
let s = filename.to_cstring().unwrap();
|
||||
let s = CString::new(filename.as_bytes()).unwrap();
|
||||
libc::dlopen(s.as_ptr(), LAZY) as *mut u8
|
||||
}
|
||||
|
||||
@ -232,7 +189,7 @@ mod dl {
|
||||
pub fn check_for_errors_in<T, F>(f: F) -> Result<T, String> where
|
||||
F: FnOnce() -> T,
|
||||
{
|
||||
use sync::StaticMutex;
|
||||
use std::sync::StaticMutex;
|
||||
static LOCK: StaticMutex = StaticMutex::new();
|
||||
unsafe {
|
||||
// dlerror isn't thread safe, so we need to lock around this entire
|
||||
@ -255,79 +212,74 @@ mod dl {
|
||||
}
|
||||
|
||||
pub unsafe fn symbol(handle: *mut u8,
|
||||
symbol: *const libc::c_char) -> *mut u8 {
|
||||
libc::dlsym(handle as *mut libc::c_void, symbol) as *mut u8
|
||||
symbol: *const libc::c_char)
|
||||
-> Result<*mut u8, String> {
|
||||
check_for_errors_in(|| {
|
||||
libc::dlsym(handle as *mut libc::c_void, symbol) as *mut u8
|
||||
})
|
||||
}
|
||||
pub unsafe fn close(handle: *mut u8) {
|
||||
libc::dlclose(handle as *mut libc::c_void); ()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
#[cfg(windows)]
|
||||
mod dl {
|
||||
use prelude::v1::*;
|
||||
use std::ffi::OsStr;
|
||||
use std::io;
|
||||
use std::os::windows::prelude::*;
|
||||
use std::ptr;
|
||||
|
||||
use ffi::OsStr;
|
||||
use libc;
|
||||
use os::windows::prelude::*;
|
||||
use ptr;
|
||||
use sys::c;
|
||||
use sys::os;
|
||||
use libc::{c_uint, c_void, c_char};
|
||||
|
||||
type DWORD = u32;
|
||||
type HMODULE = *mut u8;
|
||||
type BOOL = i32;
|
||||
type LPCWSTR = *const u16;
|
||||
type LPCSTR = *const i8;
|
||||
|
||||
extern "system" {
|
||||
fn SetThreadErrorMode(dwNewMode: DWORD,
|
||||
lpOldMode: *mut DWORD) -> c_uint;
|
||||
fn LoadLibraryW(name: LPCWSTR) -> HMODULE;
|
||||
fn GetModuleHandleExW(dwFlags: DWORD,
|
||||
name: LPCWSTR,
|
||||
handle: *mut HMODULE) -> BOOL;
|
||||
fn GetProcAddress(handle: HMODULE,
|
||||
name: LPCSTR) -> *mut c_void;
|
||||
fn FreeLibrary(handle: HMODULE) -> BOOL;
|
||||
}
|
||||
|
||||
pub fn open(filename: Option<&OsStr>) -> Result<*mut u8, String> {
|
||||
// disable "dll load failed" error dialog.
|
||||
let mut use_thread_mode = true;
|
||||
let prev_error_mode = unsafe {
|
||||
// SEM_FAILCRITICALERRORS 0x01
|
||||
let new_error_mode = 1;
|
||||
let mut prev_error_mode = 0;
|
||||
// Windows >= 7 supports thread error mode.
|
||||
let result = c::SetThreadErrorMode(new_error_mode,
|
||||
&mut prev_error_mode);
|
||||
let result = SetThreadErrorMode(new_error_mode,
|
||||
&mut prev_error_mode);
|
||||
if result == 0 {
|
||||
let err = os::errno();
|
||||
if err == c::ERROR_CALL_NOT_IMPLEMENTED as i32 {
|
||||
use_thread_mode = false;
|
||||
// SetThreadErrorMode not found. use fallback solution:
|
||||
// SetErrorMode() Note that SetErrorMode is process-wide so
|
||||
// this can cause race condition! However, since even
|
||||
// Windows APIs do not care of such problem (#20650), we
|
||||
// just assume SetErrorMode race is not a great deal.
|
||||
prev_error_mode = c::SetErrorMode(new_error_mode);
|
||||
}
|
||||
return Err(io::Error::last_os_error().to_string())
|
||||
}
|
||||
prev_error_mode
|
||||
};
|
||||
|
||||
unsafe {
|
||||
c::SetLastError(0);
|
||||
}
|
||||
|
||||
let result = match filename {
|
||||
Some(filename) => {
|
||||
let filename_str: Vec<_> =
|
||||
filename.encode_wide().chain(Some(0)).collect();
|
||||
let result = unsafe {
|
||||
c::LoadLibraryW(filename_str.as_ptr())
|
||||
LoadLibraryW(filename_str.as_ptr())
|
||||
};
|
||||
// beware: Vec/String may change errno during drop!
|
||||
// so we get error here.
|
||||
if result == ptr::null_mut() {
|
||||
let errno = os::errno();
|
||||
Err(os::error_string(errno))
|
||||
} else {
|
||||
Ok(result as *mut u8)
|
||||
}
|
||||
ptr_result(result)
|
||||
}
|
||||
None => {
|
||||
let mut handle = ptr::null_mut();
|
||||
let succeeded = unsafe {
|
||||
c::GetModuleHandleExW(0 as c::DWORD, ptr::null(),
|
||||
&mut handle)
|
||||
GetModuleHandleExW(0 as DWORD, ptr::null(), &mut handle)
|
||||
};
|
||||
if succeeded == c::FALSE {
|
||||
let errno = os::errno();
|
||||
Err(os::error_string(errno))
|
||||
if succeeded == 0 {
|
||||
Err(io::Error::last_os_error().to_string())
|
||||
} else {
|
||||
Ok(handle as *mut u8)
|
||||
}
|
||||
@ -335,64 +287,28 @@ mod dl {
|
||||
};
|
||||
|
||||
unsafe {
|
||||
if use_thread_mode {
|
||||
c::SetThreadErrorMode(prev_error_mode, ptr::null_mut());
|
||||
} else {
|
||||
c::SetErrorMode(prev_error_mode);
|
||||
}
|
||||
SetThreadErrorMode(prev_error_mode, ptr::null_mut());
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
pub fn check_for_errors_in<T, F>(f: F) -> Result<T, String> where
|
||||
F: FnOnce() -> T,
|
||||
{
|
||||
unsafe {
|
||||
c::SetLastError(0);
|
||||
pub unsafe fn symbol(handle: *mut u8,
|
||||
symbol: *const c_char)
|
||||
-> Result<*mut u8, String> {
|
||||
let ptr = GetProcAddress(handle as HMODULE, symbol) as *mut u8;
|
||||
ptr_result(ptr)
|
||||
}
|
||||
|
||||
let result = f();
|
||||
pub unsafe fn close(handle: *mut u8) {
|
||||
FreeLibrary(handle as HMODULE);
|
||||
}
|
||||
|
||||
let error = os::errno();
|
||||
if 0 == error {
|
||||
Ok(result)
|
||||
} else {
|
||||
Err(format!("Error code {}", error))
|
||||
}
|
||||
fn ptr_result<T>(ptr: *mut T) -> Result<*mut T, String> {
|
||||
if ptr.is_null() {
|
||||
Err(io::Error::last_os_error().to_string())
|
||||
} else {
|
||||
Ok(ptr)
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn symbol(handle: *mut u8, symbol: *const libc::c_char) -> *mut u8 {
|
||||
c::GetProcAddress(handle as c::HMODULE, symbol) as *mut u8
|
||||
}
|
||||
pub unsafe fn close(handle: *mut u8) {
|
||||
c::FreeLibrary(handle as c::HMODULE);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "nacl")]
|
||||
pub mod dl {
|
||||
use ffi::OsStr;
|
||||
use ptr;
|
||||
use result::Result;
|
||||
use result::Result::Err;
|
||||
use libc;
|
||||
use string::String;
|
||||
use ops::FnOnce;
|
||||
use option::Option;
|
||||
|
||||
pub fn open(_filename: Option<&OsStr>) -> Result<*mut u8, String> {
|
||||
Err(format!("NaCl + Newlib doesn't impl loading shared objects"))
|
||||
}
|
||||
|
||||
pub fn check_for_errors_in<T, F>(_f: F) -> Result<T, String>
|
||||
where F: FnOnce() -> T,
|
||||
{
|
||||
Err(format!("NaCl doesn't support shared objects"))
|
||||
}
|
||||
|
||||
pub unsafe fn symbol(_handle: *mut u8, _symbol: *const libc::c_char) -> *mut u8 {
|
||||
ptr::null_mut()
|
||||
}
|
||||
pub unsafe fn close(_handle: *mut u8) { }
|
||||
}
|
@ -31,12 +31,14 @@
|
||||
#![cfg_attr(not(stage0), deny(warnings))]
|
||||
|
||||
#![feature(box_syntax)]
|
||||
#![feature(const_fn)]
|
||||
#![feature(copy_from_slice)]
|
||||
#![feature(libc)]
|
||||
#![feature(rand)]
|
||||
#![feature(rustc_private)]
|
||||
#![feature(staged_api)]
|
||||
#![feature(step_by)]
|
||||
#![cfg_attr(unix, feature(static_mutex))]
|
||||
#![cfg_attr(test, feature(test, rand))]
|
||||
|
||||
extern crate syntax;
|
||||
@ -53,3 +55,4 @@ pub mod sha2;
|
||||
pub mod svh;
|
||||
pub mod target;
|
||||
pub mod slice;
|
||||
pub mod dynamic_lib;
|
||||
|
@ -11,6 +11,7 @@ crate-type = ["dylib"]
|
||||
[dependencies]
|
||||
log = { path = "../liblog" }
|
||||
rustc = { path = "../librustc" }
|
||||
rustc_back = { path = "../librustc_back" }
|
||||
rustc_bitflags = { path = "../librustc_bitflags" }
|
||||
rustc_front = { path = "../librustc_front" }
|
||||
rustc_metadata = { path = "../librustc_metadata" }
|
||||
|
@ -59,7 +59,6 @@
|
||||
html_root_url = "https://doc.rust-lang.org/nightly/")]
|
||||
#![cfg_attr(not(stage0), deny(warnings))]
|
||||
|
||||
#![feature(dynamic_lib)]
|
||||
#![feature(staged_api)]
|
||||
#![feature(rustc_diagnostic_macros)]
|
||||
#![feature(rustc_private)]
|
||||
@ -69,6 +68,7 @@
|
||||
#[macro_use] #[no_link] extern crate rustc_bitflags;
|
||||
|
||||
extern crate rustc;
|
||||
extern crate rustc_back;
|
||||
extern crate rustc_front;
|
||||
extern crate rustc_metadata;
|
||||
extern crate rustc_mir;
|
||||
|
@ -103,12 +103,11 @@ impl<'a> PluginLoader<'a> {
|
||||
}
|
||||
|
||||
// Dynamically link a registrar function into the compiler process.
|
||||
#[allow(deprecated)]
|
||||
fn dylink_registrar(&mut self,
|
||||
span: Span,
|
||||
path: PathBuf,
|
||||
symbol: String) -> PluginRegistrarFun {
|
||||
use std::dynamic_lib::DynamicLibrary;
|
||||
use rustc_back::dynamic_lib::DynamicLibrary;
|
||||
|
||||
// Make sure the path contains a / or the linker will search for it.
|
||||
let path = env::current_dir().unwrap().join(&path);
|
||||
|
@ -20,7 +20,6 @@
|
||||
|
||||
#![feature(box_patterns)]
|
||||
#![feature(box_syntax)]
|
||||
#![feature(dynamic_lib)]
|
||||
#![feature(libc)]
|
||||
#![feature(recover)]
|
||||
#![feature(rustc_private)]
|
||||
|
@ -12,12 +12,13 @@
|
||||
|
||||
use clean;
|
||||
|
||||
use std::dynamic_lib as dl;
|
||||
use serialize::json;
|
||||
use std::mem;
|
||||
use std::string::String;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use rustc_back::dynamic_lib as dl;
|
||||
|
||||
pub type PluginJson = Option<(String, json::Json)>;
|
||||
pub type PluginResult = (clean::Crate, PluginJson);
|
||||
pub type PluginCallback = fn (clean::Crate) -> PluginResult;
|
||||
|
@ -8,11 +8,8 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![allow(deprecated)]
|
||||
|
||||
use std::cell::{RefCell, Cell};
|
||||
use std::collections::HashMap;
|
||||
use std::dynamic_lib::DynamicLibrary;
|
||||
use std::env;
|
||||
use std::ffi::OsString;
|
||||
use std::io::prelude::*;
|
||||
@ -32,6 +29,7 @@ use rustc::session::{self, config};
|
||||
use rustc::session::config::{get_unstable_features_setting, OutputType};
|
||||
use rustc::session::search_paths::{SearchPaths, PathKind};
|
||||
use rustc_front::lowering::{lower_crate, LoweringContext};
|
||||
use rustc_back::dynamic_lib::DynamicLibrary;
|
||||
use rustc_back::tempdir::TempDir;
|
||||
use rustc_driver::{driver, Compilation};
|
||||
use rustc_metadata::cstore::CStore;
|
||||
|
@ -592,15 +592,6 @@ impl<K, V, S> HashMap<K, V, S>
|
||||
}
|
||||
}
|
||||
|
||||
/// Deprecated, renamed to `with_hasher`
|
||||
#[inline]
|
||||
#[unstable(feature = "hashmap_hasher", reason = "hasher stuff is unclear",
|
||||
issue = "27713")]
|
||||
#[rustc_deprecated(since = "1.7.0", reason = "renamed to with_hasher")]
|
||||
pub fn with_hash_state(hash_state: S) -> HashMap<K, V, S> {
|
||||
HashMap::with_hasher(hash_state)
|
||||
}
|
||||
|
||||
/// Creates an empty HashMap with space for at least `capacity`
|
||||
/// elements, using `hasher` to hash the keys.
|
||||
///
|
||||
@ -634,17 +625,6 @@ impl<K, V, S> HashMap<K, V, S>
|
||||
}
|
||||
}
|
||||
|
||||
/// Deprecated, renamed to `with_capacity_and_hasher`
|
||||
#[inline]
|
||||
#[unstable(feature = "hashmap_hasher", reason = "hasher stuff is unclear",
|
||||
issue = "27713")]
|
||||
#[rustc_deprecated(since = "1.7.0",
|
||||
reason = "renamed to with_capacity_and_hasher")]
|
||||
pub fn with_capacity_and_hash_state(capacity: usize, hash_state: S)
|
||||
-> HashMap<K, V, S> {
|
||||
HashMap::with_capacity_and_hasher(capacity, hash_state)
|
||||
}
|
||||
|
||||
/// Returns a reference to the map's hasher.
|
||||
#[unstable(feature = "hashmap_public_hasher", reason = "don't want to make insta-stable",
|
||||
issue = "31262")]
|
||||
|
@ -14,7 +14,6 @@ mod bench;
|
||||
mod table;
|
||||
pub mod map;
|
||||
pub mod set;
|
||||
pub mod state;
|
||||
|
||||
trait Recover<Q: ?Sized> {
|
||||
type Key;
|
||||
|
@ -200,26 +200,6 @@ impl<T, S> HashSet<T, S>
|
||||
self.map.hasher()
|
||||
}
|
||||
|
||||
/// Deprecated, renamed to `with_hasher`
|
||||
#[inline]
|
||||
#[unstable(feature = "hashmap_hasher", reason = "hasher stuff is unclear",
|
||||
issue = "27713")]
|
||||
#[rustc_deprecated(since = "1.7.0", reason = "renamed to with_hasher")]
|
||||
pub fn with_hash_state(hash_state: S) -> HashSet<T, S> {
|
||||
HashSet::with_hasher(hash_state)
|
||||
}
|
||||
|
||||
/// Deprecated, renamed to `with_capacity_and_hasher`
|
||||
#[inline]
|
||||
#[unstable(feature = "hashmap_hasher", reason = "hasher stuff is unclear",
|
||||
issue = "27713")]
|
||||
#[rustc_deprecated(since = "1.7.0",
|
||||
reason = "renamed to with_capacity_and_hasher")]
|
||||
pub fn with_capacity_and_hash_state(capacity: usize, hash_state: S)
|
||||
-> HashSet<T, S> {
|
||||
HashSet::with_capacity_and_hasher(capacity, hash_state)
|
||||
}
|
||||
|
||||
/// Returns the number of elements the set can hold without reallocating.
|
||||
///
|
||||
/// # Examples
|
||||
|
@ -1,40 +0,0 @@
|
||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![unstable(feature = "hashmap_hasher", reason = "hasher stuff is unclear",
|
||||
issue = "27713")]
|
||||
#![rustc_deprecated(since = "1.7.0", reason = "support moved to std::hash")]
|
||||
#![allow(deprecated)]
|
||||
|
||||
use clone::Clone;
|
||||
use default::Default;
|
||||
use hash;
|
||||
use marker;
|
||||
|
||||
pub use hash::HashState;
|
||||
|
||||
/// A structure which is a factory for instances of `Hasher` which implement the
|
||||
/// default trait.
|
||||
///
|
||||
/// This struct is 0-sized and does not need construction.
|
||||
pub struct DefaultState<H>(marker::PhantomData<H>);
|
||||
|
||||
impl<H: Default + hash::Hasher> HashState for DefaultState<H> {
|
||||
type Hasher = H;
|
||||
fn hasher(&self) -> H { Default::default() }
|
||||
}
|
||||
|
||||
impl<H> Clone for DefaultState<H> {
|
||||
fn clone(&self) -> DefaultState<H> { DefaultState(marker::PhantomData) }
|
||||
}
|
||||
|
||||
impl<H> Default for DefaultState<H> {
|
||||
fn default() -> DefaultState<H> { DefaultState(marker::PhantomData) }
|
||||
}
|
@ -442,13 +442,3 @@ pub mod hash_set {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use super::hash::set::*;
|
||||
}
|
||||
|
||||
/// Experimental support for providing custom hash algorithms to a HashMap and
|
||||
/// HashSet.
|
||||
#[unstable(feature = "hashmap_hasher", reason = "module was recently added",
|
||||
issue = "27713")]
|
||||
#[rustc_deprecated(since = "1.7.0", reason = "support moved to std::hash")]
|
||||
#[allow(deprecated)]
|
||||
pub mod hash_state {
|
||||
pub use super::hash::state::*;
|
||||
}
|
||||
|
@ -9,7 +9,6 @@
|
||||
// except according to those terms.
|
||||
|
||||
use borrow::{Borrow, Cow, ToOwned};
|
||||
use ffi::CString;
|
||||
use fmt::{self, Debug};
|
||||
use mem;
|
||||
use string::String;
|
||||
@ -56,22 +55,6 @@ impl OsString {
|
||||
OsString { inner: Buf::from_string(String::new()) }
|
||||
}
|
||||
|
||||
/// Constructs an `OsString` from a byte sequence.
|
||||
///
|
||||
/// # Platform behavior
|
||||
///
|
||||
/// On Unix systems, any byte sequence can be successfully
|
||||
/// converted into an `OsString`.
|
||||
///
|
||||
/// On Windows system, only UTF-8 byte sequences will successfully
|
||||
/// convert; non UTF-8 data will produce `None`.
|
||||
#[unstable(feature = "convert", reason = "recently added", issue = "27704")]
|
||||
#[rustc_deprecated(reason = "RFC was closed, hides subtle Windows semantics",
|
||||
since = "1.6.0")]
|
||||
pub fn from_bytes<B>(bytes: B) -> Option<OsString> where B: Into<Vec<u8>> {
|
||||
Self::_from_bytes(bytes.into())
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
fn _from_bytes(vec: Vec<u8>) -> Option<OsString> {
|
||||
use os::unix::ffi::OsStringExt;
|
||||
@ -294,41 +277,6 @@ impl OsStr {
|
||||
OsString { inner: self.inner.to_owned() }
|
||||
}
|
||||
|
||||
/// Yields this `OsStr` as a byte slice.
|
||||
///
|
||||
/// # Platform behavior
|
||||
///
|
||||
/// On Unix systems, this is a no-op.
|
||||
///
|
||||
/// On Windows systems, this returns `None` unless the `OsStr` is
|
||||
/// valid Unicode, in which case it produces UTF-8-encoded
|
||||
/// data. This may entail checking validity.
|
||||
#[unstable(feature = "convert", reason = "recently added", issue = "27704")]
|
||||
#[rustc_deprecated(reason = "RFC was closed, hides subtle Windows semantics",
|
||||
since = "1.6.0")]
|
||||
pub fn to_bytes(&self) -> Option<&[u8]> {
|
||||
if cfg!(windows) {
|
||||
self.to_str().map(|s| s.as_bytes())
|
||||
} else {
|
||||
Some(self.bytes())
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a `CString` containing this `OsStr` data.
|
||||
///
|
||||
/// Fails if the `OsStr` contains interior nulls.
|
||||
///
|
||||
/// This is a convenience for creating a `CString` from
|
||||
/// `self.to_bytes()`, and inherits the platform behavior of the
|
||||
/// `to_bytes` method.
|
||||
#[unstable(feature = "convert", reason = "recently added", issue = "27704")]
|
||||
#[rustc_deprecated(reason = "RFC was closed, hides subtle Windows semantics",
|
||||
since = "1.6.0")]
|
||||
#[allow(deprecated)]
|
||||
pub fn to_cstring(&self) -> Option<CString> {
|
||||
self.to_bytes().and_then(|b| CString::new(b).ok())
|
||||
}
|
||||
|
||||
/// Checks whether the `OsStr` is empty.
|
||||
#[unstable(feature = "osstring_simple_functions",
|
||||
reason = "recently added", issue = "29453")]
|
||||
|
102
src/libstd/fs.rs
102
src/libstd/fs.rs
@ -85,19 +85,6 @@ pub struct ReadDir(fs_imp::ReadDir);
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct DirEntry(fs_imp::DirEntry);
|
||||
|
||||
/// An iterator that recursively walks over the contents of a directory.
|
||||
#[unstable(feature = "fs_walk",
|
||||
reason = "the precise semantics and defaults for a recursive walk \
|
||||
may change and this may end up accounting for files such \
|
||||
as symlinks differently",
|
||||
issue = "27707")]
|
||||
#[rustc_deprecated(reason = "superceded by the walkdir crate",
|
||||
since = "1.6.0")]
|
||||
pub struct WalkDir {
|
||||
cur: Option<ReadDir>,
|
||||
stack: Vec<io::Result<ReadDir>>,
|
||||
}
|
||||
|
||||
/// Options and flags which can be used to configure how a file is opened.
|
||||
///
|
||||
/// This builder exposes the ability to configure how a `File` is opened and
|
||||
@ -1345,7 +1332,7 @@ pub fn remove_dir_all<P: AsRef<Path>>(path: P) -> io::Result<()> {
|
||||
/// use std::fs::{self, DirEntry};
|
||||
/// use std::path::Path;
|
||||
///
|
||||
/// // one possible implementation of fs::walk_dir only visiting files
|
||||
/// // one possible implementation of walking a directory only visiting files
|
||||
/// fn visit_dirs(dir: &Path, cb: &Fn(&DirEntry)) -> io::Result<()> {
|
||||
/// if try!(fs::metadata(dir)).is_dir() {
|
||||
/// for entry in try!(fs::read_dir(dir)) {
|
||||
@ -1365,64 +1352,6 @@ pub fn read_dir<P: AsRef<Path>>(path: P) -> io::Result<ReadDir> {
|
||||
fs_imp::readdir(path.as_ref()).map(ReadDir)
|
||||
}
|
||||
|
||||
/// Returns an iterator that will recursively walk the directory structure
|
||||
/// rooted at `path`.
|
||||
///
|
||||
/// The path given will not be iterated over, and this will perform iteration in
|
||||
/// some top-down order. The contents of unreadable subdirectories are ignored.
|
||||
///
|
||||
/// The iterator will yield instances of `io::Result<DirEntry>`. New errors may
|
||||
/// be encountered after an iterator is initially constructed.
|
||||
#[unstable(feature = "fs_walk",
|
||||
reason = "the precise semantics and defaults for a recursive walk \
|
||||
may change and this may end up accounting for files such \
|
||||
as symlinks differently",
|
||||
issue = "27707")]
|
||||
#[rustc_deprecated(reason = "superceded by the walkdir crate",
|
||||
since = "1.6.0")]
|
||||
#[allow(deprecated)]
|
||||
pub fn walk_dir<P: AsRef<Path>>(path: P) -> io::Result<WalkDir> {
|
||||
_walk_dir(path.as_ref())
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
fn _walk_dir(path: &Path) -> io::Result<WalkDir> {
|
||||
let start = try!(read_dir(path));
|
||||
Ok(WalkDir { cur: Some(start), stack: Vec::new() })
|
||||
}
|
||||
|
||||
#[unstable(feature = "fs_walk", issue = "27707")]
|
||||
#[rustc_deprecated(reason = "superceded by the walkdir crate",
|
||||
since = "1.6.0")]
|
||||
#[allow(deprecated)]
|
||||
impl Iterator for WalkDir {
|
||||
type Item = io::Result<DirEntry>;
|
||||
|
||||
fn next(&mut self) -> Option<io::Result<DirEntry>> {
|
||||
loop {
|
||||
if let Some(ref mut cur) = self.cur {
|
||||
match cur.next() {
|
||||
Some(Err(e)) => return Some(Err(e)),
|
||||
Some(Ok(next)) => {
|
||||
let path = next.path();
|
||||
if path.is_dir() {
|
||||
self.stack.push(read_dir(&*path));
|
||||
}
|
||||
return Some(Ok(next))
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
self.cur = None;
|
||||
match self.stack.pop() {
|
||||
Some(Err(e)) => return Some(Err(e)),
|
||||
Some(Ok(next)) => self.cur = Some(next),
|
||||
None => return None,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Changes the permissions found on a file or a directory.
|
||||
///
|
||||
/// # Platform-specific behavior
|
||||
@ -1865,35 +1794,6 @@ mod tests {
|
||||
check!(fs::remove_dir(dir));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[allow(deprecated)]
|
||||
fn file_test_walk_dir() {
|
||||
let tmpdir = tmpdir();
|
||||
let dir = &tmpdir.join("walk_dir");
|
||||
check!(fs::create_dir(dir));
|
||||
|
||||
let dir1 = &dir.join("01/02/03");
|
||||
check!(fs::create_dir_all(dir1));
|
||||
check!(File::create(&dir1.join("04")));
|
||||
|
||||
let dir2 = &dir.join("11/12/13");
|
||||
check!(fs::create_dir_all(dir2));
|
||||
check!(File::create(&dir2.join("14")));
|
||||
|
||||
let files = check!(fs::walk_dir(dir));
|
||||
let mut cur = [0; 2];
|
||||
for f in files {
|
||||
let f = f.unwrap().path();
|
||||
let stem = f.file_stem().unwrap().to_str().unwrap();
|
||||
let root = stem.as_bytes()[0] - b'0';
|
||||
let name = stem.as_bytes()[1] - b'0';
|
||||
assert!(cur[root as usize] < name);
|
||||
cur[root as usize] = name;
|
||||
}
|
||||
|
||||
check!(fs::remove_dir_all(dir));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mkdir_path_already_exists_error() {
|
||||
let tmpdir = tmpdir();
|
||||
|
@ -150,12 +150,6 @@ pub enum ErrorKind {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
Other,
|
||||
|
||||
#[allow(missing_docs)]
|
||||
#[unstable(feature = "read_exact_old", reason = "recently added",
|
||||
issue = "0")]
|
||||
#[rustc_deprecated(since = "1.6.0", reason = "renamed to UnexpectedEof")]
|
||||
UnexpectedEOF,
|
||||
|
||||
/// An error returned when an operation could not be completed because an
|
||||
/// "end of file" was reached prematurely.
|
||||
///
|
||||
@ -311,7 +305,6 @@ impl fmt::Display for Error {
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl error::Error for Error {
|
||||
#[allow(deprecated)] // remove with UnexpectedEOF
|
||||
fn description(&self) -> &str {
|
||||
match self.repr {
|
||||
Repr::Os(..) => match self.kind() {
|
||||
@ -332,7 +325,6 @@ impl error::Error for Error {
|
||||
ErrorKind::WriteZero => "write zero",
|
||||
ErrorKind::Interrupted => "operation interrupted",
|
||||
ErrorKind::Other => "other os error",
|
||||
ErrorKind::UnexpectedEOF => "unexpected end of file",
|
||||
ErrorKind::UnexpectedEof => "unexpected end of file",
|
||||
ErrorKind::__Nonexhaustive => unreachable!()
|
||||
},
|
||||
|
@ -811,49 +811,6 @@ pub trait Read {
|
||||
fn take(self, limit: u64) -> Take<Self> where Self: Sized {
|
||||
Take { inner: self, limit: limit }
|
||||
}
|
||||
|
||||
/// Creates a reader adaptor which will write all read data into the given
|
||||
/// output stream.
|
||||
///
|
||||
/// Whenever the returned `Read` instance is read it will write the read
|
||||
/// data to `out`. The current semantics of this implementation imply that
|
||||
/// a `write` error will not report how much data was initially read.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// [`File`][file]s implement `Read`:
|
||||
///
|
||||
/// [file]: ../fs/struct.File.html
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(io)]
|
||||
/// use std::io;
|
||||
/// use std::io::prelude::*;
|
||||
/// use std::fs::File;
|
||||
///
|
||||
/// # fn foo() -> io::Result<()> {
|
||||
/// let mut f = try!(File::open("foo.txt"));
|
||||
/// let mut buffer1 = Vec::with_capacity(10);
|
||||
/// let mut buffer2 = Vec::with_capacity(10);
|
||||
///
|
||||
/// // write the output to buffer1 as we read
|
||||
/// let mut handle = f.tee(&mut buffer1);
|
||||
///
|
||||
/// try!(handle.read(&mut buffer2));
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[unstable(feature = "io", reason = "the semantics of a partial read/write \
|
||||
of where errors happen is currently \
|
||||
unclear and may change",
|
||||
issue = "27802")]
|
||||
#[rustc_deprecated(reason = "error handling semantics unclear and \
|
||||
don't seem to have an ergonomic resolution",
|
||||
since = "1.6.0")]
|
||||
#[allow(deprecated)]
|
||||
fn tee<W: Write>(self, out: W) -> Tee<Self, W> where Self: Sized {
|
||||
Tee { reader: self, writer: out }
|
||||
}
|
||||
}
|
||||
|
||||
/// A trait for objects which are byte-oriented sinks.
|
||||
@ -1089,47 +1046,6 @@ pub trait Write {
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn by_ref(&mut self) -> &mut Self where Self: Sized { self }
|
||||
|
||||
/// Creates a new writer which will write all data to both this writer and
|
||||
/// another writer.
|
||||
///
|
||||
/// All data written to the returned writer will both be written to `self`
|
||||
/// as well as `other`. Note that the error semantics of the current
|
||||
/// implementation do not precisely track where errors happen. For example
|
||||
/// an error on the second call to `write` will not report that the first
|
||||
/// call to `write` succeeded.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(io)]
|
||||
/// use std::io::prelude::*;
|
||||
/// use std::fs::File;
|
||||
///
|
||||
/// # fn foo() -> std::io::Result<()> {
|
||||
/// let mut buffer1 = try!(File::create("foo.txt"));
|
||||
/// let mut buffer2 = Vec::new();
|
||||
///
|
||||
/// // write the output to buffer1 as we read
|
||||
/// let mut handle = buffer1.broadcast(&mut buffer2);
|
||||
///
|
||||
/// try!(handle.write(b"some bytes"));
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[unstable(feature = "io", reason = "the semantics of a partial read/write \
|
||||
of where errors happen is currently \
|
||||
unclear and may change",
|
||||
issue = "27802")]
|
||||
#[rustc_deprecated(reason = "error handling semantics unclear and \
|
||||
don't seem to have an ergonomic resolution",
|
||||
since = "1.6.0")]
|
||||
#[allow(deprecated)]
|
||||
fn broadcast<W: Write>(self, other: W) -> Broadcast<Self, W>
|
||||
where Self: Sized
|
||||
{
|
||||
Broadcast { first: self, second: other }
|
||||
}
|
||||
}
|
||||
|
||||
/// The `Seek` trait provides a cursor which can be moved within a stream of
|
||||
@ -1500,41 +1416,6 @@ pub trait BufRead: Read {
|
||||
}
|
||||
}
|
||||
|
||||
/// A `Write` adaptor which will write data to multiple locations.
|
||||
///
|
||||
/// This struct is generally created by calling [`broadcast()`][broadcast] on a
|
||||
/// writer. Please see the documentation of `broadcast()` for more details.
|
||||
///
|
||||
/// [broadcast]: trait.Write.html#method.broadcast
|
||||
#[unstable(feature = "io", reason = "awaiting stability of Write::broadcast",
|
||||
issue = "27802")]
|
||||
#[rustc_deprecated(reason = "error handling semantics unclear and \
|
||||
don't seem to have an ergonomic resolution",
|
||||
since = "1.6.0")]
|
||||
pub struct Broadcast<T, U> {
|
||||
first: T,
|
||||
second: U,
|
||||
}
|
||||
|
||||
#[unstable(feature = "io", reason = "awaiting stability of Write::broadcast",
|
||||
issue = "27802")]
|
||||
#[rustc_deprecated(reason = "error handling semantics unclear and \
|
||||
don't seem to have an ergonomic resolution",
|
||||
since = "1.6.0")]
|
||||
#[allow(deprecated)]
|
||||
impl<T: Write, U: Write> Write for Broadcast<T, U> {
|
||||
fn write(&mut self, data: &[u8]) -> Result<usize> {
|
||||
let n = try!(self.first.write(data));
|
||||
// FIXME: what if the write fails? (we wrote something)
|
||||
try!(self.second.write_all(&data[..n]));
|
||||
Ok(n)
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> Result<()> {
|
||||
self.first.flush().and(self.second.flush())
|
||||
}
|
||||
}
|
||||
|
||||
/// Adaptor to chain together two readers.
|
||||
///
|
||||
/// This struct is generally created by calling [`chain()`][chain] on a reader.
|
||||
@ -1616,37 +1497,6 @@ impl<T: BufRead> BufRead for Take<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// An adaptor which will emit all read data to a specified writer as well.
|
||||
///
|
||||
/// This struct is generally created by calling [`tee()`][tee] on a reader.
|
||||
/// Please see the documentation of `tee()` for more details.
|
||||
///
|
||||
/// [tee]: trait.Read.html#method.tee
|
||||
#[unstable(feature = "io", reason = "awaiting stability of Read::tee",
|
||||
issue = "27802")]
|
||||
#[rustc_deprecated(reason = "error handling semantics unclear and \
|
||||
don't seem to have an ergonomic resolution",
|
||||
since = "1.6.0")]
|
||||
pub struct Tee<R, W> {
|
||||
reader: R,
|
||||
writer: W,
|
||||
}
|
||||
|
||||
#[unstable(feature = "io", reason = "awaiting stability of Read::tee",
|
||||
issue = "27802")]
|
||||
#[rustc_deprecated(reason = "error handling semantics unclear and \
|
||||
don't seem to have an ergonomic resolution",
|
||||
since = "1.6.0")]
|
||||
#[allow(deprecated)]
|
||||
impl<R: Read, W: Write> Read for Tee<R, W> {
|
||||
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
|
||||
let n = try!(self.reader.read(buf));
|
||||
// FIXME: what if the write fails? (we read something)
|
||||
try!(self.writer.write_all(&buf[..n]));
|
||||
Ok(n)
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator over `u8` values of a reader.
|
||||
///
|
||||
/// This struct is generally created by calling [`bytes()`][bytes] on a reader.
|
||||
|
@ -197,31 +197,4 @@ mod tests {
|
||||
assert_eq!(repeat(4).take(100).bytes().next().unwrap().unwrap(), 4);
|
||||
assert_eq!(repeat(1).take(10).chain(repeat(2).take(10)).bytes().count(), 20);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[allow(deprecated)]
|
||||
fn tee() {
|
||||
let mut buf = [0; 10];
|
||||
{
|
||||
let mut ptr: &mut [u8] = &mut buf;
|
||||
assert_eq!(repeat(4).tee(&mut ptr).take(5).read(&mut [0; 10]).unwrap(), 5);
|
||||
}
|
||||
assert_eq!(buf, [4, 4, 4, 4, 4, 0, 0, 0, 0, 0]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[allow(deprecated)]
|
||||
fn broadcast() {
|
||||
let mut buf1 = [0; 10];
|
||||
let mut buf2 = [0; 10];
|
||||
{
|
||||
let mut ptr1: &mut [u8] = &mut buf1;
|
||||
let mut ptr2: &mut [u8] = &mut buf2;
|
||||
|
||||
assert_eq!((&mut ptr1).broadcast(&mut ptr2)
|
||||
.write(&[1, 2, 3]).unwrap(), 3);
|
||||
}
|
||||
assert_eq!(buf1, buf2);
|
||||
assert_eq!(buf1, [1, 2, 3, 0, 0, 0, 0, 0, 0, 0]);
|
||||
}
|
||||
}
|
||||
|
@ -418,7 +418,6 @@ pub mod num;
|
||||
pub mod thread;
|
||||
|
||||
pub mod collections;
|
||||
pub mod dynamic_lib;
|
||||
pub mod env;
|
||||
pub mod ffi;
|
||||
pub mod fs;
|
||||
|
@ -128,33 +128,3 @@ impl Iterator for LookupHost {
|
||||
pub fn lookup_host(host: &str) -> io::Result<LookupHost> {
|
||||
net_imp::lookup_host(host).map(LookupHost)
|
||||
}
|
||||
|
||||
/// Resolve the given address to a hostname.
|
||||
///
|
||||
/// This function may perform a DNS query to resolve `addr` and may also inspect
|
||||
/// system configuration to resolve the specified address. If the address
|
||||
/// cannot be resolved, it is returned in string format.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// #![feature(lookup_addr)]
|
||||
/// #![feature(ip_addr)]
|
||||
///
|
||||
/// use std::net::{self, Ipv4Addr, IpAddr};
|
||||
///
|
||||
/// let ip_addr = "8.8.8.8";
|
||||
/// let addr: Ipv4Addr = ip_addr.parse().unwrap();
|
||||
/// let hostname = net::lookup_addr(&IpAddr::V4(addr)).unwrap();
|
||||
///
|
||||
/// println!("{} --> {}", ip_addr, hostname);
|
||||
/// // Output: 8.8.8.8 --> google-public-dns-a.google.com
|
||||
/// ```
|
||||
#[unstable(feature = "lookup_addr", reason = "recent addition",
|
||||
issue = "27705")]
|
||||
#[rustc_deprecated(reason = "ipaddr type is being deprecated",
|
||||
since = "1.6.0")]
|
||||
#[allow(deprecated)]
|
||||
pub fn lookup_addr(addr: &IpAddr) -> io::Result<String> {
|
||||
net_imp::lookup_addr(addr)
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ pub use core::num::{Zero, One};
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::num::{FpCategory, ParseIntError, ParseFloatError};
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::num::{wrapping, Wrapping};
|
||||
pub use core::num::Wrapping;
|
||||
|
||||
#[cfg(test)] use cmp::PartialEq;
|
||||
#[cfg(test)] use fmt;
|
||||
|
@ -100,8 +100,7 @@
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
use ascii::*;
|
||||
#[allow(deprecated)]
|
||||
use borrow::{Borrow, IntoCow, ToOwned, Cow};
|
||||
use borrow::{Borrow, ToOwned, Cow};
|
||||
use cmp;
|
||||
use error::Error;
|
||||
use fmt;
|
||||
@ -781,14 +780,6 @@ impl<'a> Components<'a> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Examine the next component without consuming it.
|
||||
#[unstable(feature = "path_components_peek", issue = "27727")]
|
||||
#[rustc_deprecated(reason = "use peekable() instead",
|
||||
since = "1.6.0")]
|
||||
pub fn peek(&self) -> Option<Component<'a>> {
|
||||
self.clone().next()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
@ -1218,22 +1209,6 @@ impl Borrow<Path> for PathBuf {
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[allow(deprecated)]
|
||||
impl IntoCow<'static, Path> for PathBuf {
|
||||
fn into_cow(self) -> Cow<'static, Path> {
|
||||
Cow::Owned(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[allow(deprecated)]
|
||||
impl<'a> IntoCow<'a, Path> for &'a Path {
|
||||
fn into_cow(self) -> Cow<'a, Path> {
|
||||
Cow::Borrowed(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "cow_from_path", since = "1.6.0")]
|
||||
impl<'a> From<&'a Path> for Cow<'a, Path> {
|
||||
#[inline]
|
||||
@ -1474,17 +1449,7 @@ impl Path {
|
||||
!self.is_absolute()
|
||||
}
|
||||
|
||||
/// Returns the *prefix* of a path, if any.
|
||||
///
|
||||
/// Prefixes are relevant only for Windows paths, and consist of volumes
|
||||
/// like `C:`, UNC prefixes like `\\server`, and others described in more
|
||||
/// detail in `std::os::windows::PathExt`.
|
||||
#[unstable(feature = "path_prefix",
|
||||
reason = "uncertain whether to expose this convenience",
|
||||
issue = "27722")]
|
||||
#[rustc_deprecated(since = "1.7.0",
|
||||
reason = "inspect components().next() instead")]
|
||||
pub fn prefix(&self) -> Option<Prefix> {
|
||||
fn prefix(&self) -> Option<Prefix> {
|
||||
self.components().prefix
|
||||
}
|
||||
|
||||
@ -1566,17 +1531,6 @@ impl Path {
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns a path that, when joined onto `base`, yields `self`.
|
||||
///
|
||||
/// If `base` is not a prefix of `self` (i.e. `starts_with`
|
||||
/// returns false), then `relative_from` returns `None`.
|
||||
#[unstable(feature = "path_relative_from", reason = "see #23284",
|
||||
issue = "23284")]
|
||||
#[rustc_deprecated(since = "1.7.0", reason = "renamed to strip_prefix")]
|
||||
pub fn relative_from<'a, P: ?Sized + AsRef<Path>>(&'a self, base: &'a P) -> Option<&Path> {
|
||||
self._strip_prefix(base.as_ref()).ok()
|
||||
}
|
||||
|
||||
/// Returns a path that, when joined onto `base`, yields `self`.
|
||||
///
|
||||
/// # Errors
|
||||
@ -2236,27 +2190,6 @@ mod tests {
|
||||
);
|
||||
);
|
||||
|
||||
#[test]
|
||||
#[allow(deprecated)]
|
||||
fn into_cow() {
|
||||
use borrow::{Cow, IntoCow};
|
||||
|
||||
let static_path = Path::new("/home/foo");
|
||||
let static_cow_path: Cow<'static, Path> = static_path.into_cow();
|
||||
let pathbuf = PathBuf::from("/home/foo");
|
||||
|
||||
{
|
||||
let path: &Path = &pathbuf;
|
||||
let borrowed_cow_path: Cow<Path> = path.into_cow();
|
||||
|
||||
assert_eq!(static_cow_path, borrowed_cow_path);
|
||||
}
|
||||
|
||||
let owned_cow_path: Cow<'static, Path> = pathbuf.into_cow();
|
||||
|
||||
assert_eq!(static_cow_path, owned_cow_path);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn into() {
|
||||
use borrow::Cow;
|
||||
|
@ -167,13 +167,12 @@ impl Condvar {
|
||||
/// returns, regardless of whether the timeout elapsed or not.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_deprecated(since = "1.6.0", reason = "replaced by `std::sync::Condvar::wait_timeout`")]
|
||||
#[allow(deprecated)]
|
||||
pub fn wait_timeout_ms<'a, T>(&self, guard: MutexGuard<'a, T>, ms: u32)
|
||||
-> LockResult<(MutexGuard<'a, T>, bool)> {
|
||||
unsafe {
|
||||
let me: &'static Condvar = &*(self as *const _);
|
||||
me.inner.wait_timeout_ms(guard, ms)
|
||||
}
|
||||
let res = self.wait_timeout(guard, Duration::from_millis(ms as u64));
|
||||
poison::map_result(res, |(a, b)| {
|
||||
(a, !b.timed_out())
|
||||
})
|
||||
}
|
||||
|
||||
/// Waits on this condition variable for a notification, timing out after a
|
||||
@ -200,30 +199,6 @@ impl Condvar {
|
||||
}
|
||||
}
|
||||
|
||||
/// Waits on this condition variable for a notification, timing out after a
|
||||
/// specified duration.
|
||||
///
|
||||
/// The semantics of this function are equivalent to `wait_timeout` except
|
||||
/// that the implementation will repeatedly wait while the duration has not
|
||||
/// passed and the provided function returns `false`.
|
||||
#[unstable(feature = "wait_timeout_with",
|
||||
reason = "unsure if this API is broadly needed or what form it should take",
|
||||
issue = "27748")]
|
||||
#[rustc_deprecated(since = "1.8.0",
|
||||
reason = "wonky signature and questionable \
|
||||
implementation didn't justify existence")]
|
||||
pub fn wait_timeout_with<'a, T, F>(&self,
|
||||
guard: MutexGuard<'a, T>,
|
||||
dur: Duration,
|
||||
f: F)
|
||||
-> LockResult<(MutexGuard<'a, T>, WaitTimeoutResult)>
|
||||
where F: FnMut(LockResult<&mut T>) -> bool {
|
||||
unsafe {
|
||||
let me: &'static Condvar = &*(self as *const _);
|
||||
me.inner.wait_timeout_with(guard, dur, f)
|
||||
}
|
||||
}
|
||||
|
||||
/// Wakes up one blocked thread on this condvar.
|
||||
///
|
||||
/// If there is a blocked thread on this condition variable, then it will
|
||||
@ -286,26 +261,6 @@ impl StaticCondvar {
|
||||
}
|
||||
}
|
||||
|
||||
/// Waits on this condition variable for a notification, timing out after a
|
||||
/// specified duration.
|
||||
///
|
||||
/// See `Condvar::wait_timeout`.
|
||||
#[unstable(feature = "static_condvar",
|
||||
reason = "may be merged with Condvar in the future",
|
||||
issue = "27717")]
|
||||
#[rustc_deprecated(since = "1.6.0",
|
||||
reason = "replaced by `std::sync::StaticCondvar::wait_timeout`")]
|
||||
pub fn wait_timeout_ms<'a, T>(&'static self, guard: MutexGuard<'a, T>, ms: u32)
|
||||
-> LockResult<(MutexGuard<'a, T>, bool)> {
|
||||
match self.wait_timeout(guard, Duration::from_millis(ms as u64)) {
|
||||
Ok((guard, timed_out)) => Ok((guard, !timed_out.timed_out())),
|
||||
Err(poison) => {
|
||||
let (guard, timed_out) = poison.into_inner();
|
||||
Err(PoisonError::new((guard, !timed_out.timed_out())))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Waits on this condition variable for a notification, timing out after a
|
||||
/// specified duration.
|
||||
///
|
||||
|
@ -38,9 +38,6 @@ pub use sys_common::poison::{PoisonError, TryLockError, TryLockResult, LockResul
|
||||
pub use self::rwlock::{RwLockReadGuard, RwLockWriteGuard};
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use self::rwlock::{RwLock, StaticRwLock, RW_LOCK_INIT};
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[allow(deprecated)]
|
||||
pub use self::semaphore::{Semaphore, SemaphoreGuard};
|
||||
|
||||
pub mod mpsc;
|
||||
|
||||
@ -49,4 +46,3 @@ mod condvar;
|
||||
mod mutex;
|
||||
mod once;
|
||||
mod rwlock;
|
||||
mod semaphore;
|
||||
|
@ -1,226 +0,0 @@
|
||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![unstable(feature = "semaphore",
|
||||
reason = "the interaction between semaphores and the acquisition/release \
|
||||
of resources is currently unclear",
|
||||
issue = "27798")]
|
||||
#![allow(deprecated)]
|
||||
|
||||
use ops::Drop;
|
||||
use sync::{Mutex, Condvar};
|
||||
|
||||
/// A counting, blocking, semaphore.
|
||||
///
|
||||
/// Semaphores are a form of atomic counter where access is only granted if the
|
||||
/// counter is a positive value. Each acquisition will block the calling thread
|
||||
/// until the counter is positive, and each release will increment the counter
|
||||
/// and unblock any threads if necessary.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(semaphore)]
|
||||
///
|
||||
/// use std::sync::Semaphore;
|
||||
///
|
||||
/// // Create a semaphore that represents 5 resources
|
||||
/// let sem = Semaphore::new(5);
|
||||
///
|
||||
/// // Acquire one of the resources
|
||||
/// sem.acquire();
|
||||
///
|
||||
/// // Acquire one of the resources for a limited period of time
|
||||
/// {
|
||||
/// let _guard = sem.access();
|
||||
/// // ...
|
||||
/// } // resources is released here
|
||||
///
|
||||
/// // Release our initially acquired resource
|
||||
/// sem.release();
|
||||
/// ```
|
||||
#[rustc_deprecated(since = "1.7.0",
|
||||
reason = "easily confused with system semaphores and not \
|
||||
used enough to pull its weight")]
|
||||
#[unstable(feature = "semaphore",
|
||||
reason = "the interaction between semaphores and the acquisition/release \
|
||||
of resources is currently unclear",
|
||||
issue = "27798")]
|
||||
pub struct Semaphore {
|
||||
lock: Mutex<isize>,
|
||||
cvar: Condvar,
|
||||
}
|
||||
|
||||
/// An RAII guard which will release a resource acquired from a semaphore when
|
||||
/// dropped.
|
||||
#[rustc_deprecated(since = "1.7.0",
|
||||
reason = "easily confused with system semaphores and not \
|
||||
used enough to pull its weight")]
|
||||
#[unstable(feature = "semaphore",
|
||||
reason = "the interaction between semaphores and the acquisition/release \
|
||||
of resources is currently unclear",
|
||||
issue = "27798")]
|
||||
pub struct SemaphoreGuard<'a> {
|
||||
sem: &'a Semaphore,
|
||||
}
|
||||
|
||||
#[rustc_deprecated(since = "1.7.0",
|
||||
reason = "easily confused with system semaphores and not \
|
||||
used enough to pull its weight")]
|
||||
#[unstable(feature = "semaphore",
|
||||
reason = "the interaction between semaphores and the acquisition/release \
|
||||
of resources is currently unclear",
|
||||
issue = "27798")]
|
||||
impl Semaphore {
|
||||
/// Creates a new semaphore with the initial count specified.
|
||||
///
|
||||
/// The count specified can be thought of as a number of resources, and a
|
||||
/// call to `acquire` or `access` will block until at least one resource is
|
||||
/// available. It is valid to initialize a semaphore with a negative count.
|
||||
pub fn new(count: isize) -> Semaphore {
|
||||
Semaphore {
|
||||
lock: Mutex::new(count),
|
||||
cvar: Condvar::new(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Acquires a resource of this semaphore, blocking the current thread until
|
||||
/// it can do so.
|
||||
///
|
||||
/// This method will block until the internal count of the semaphore is at
|
||||
/// least 1.
|
||||
pub fn acquire(&self) {
|
||||
let mut count = self.lock.lock().unwrap();
|
||||
while *count <= 0 {
|
||||
count = self.cvar.wait(count).unwrap();
|
||||
}
|
||||
*count -= 1;
|
||||
}
|
||||
|
||||
/// Release a resource from this semaphore.
|
||||
///
|
||||
/// This will increment the number of resources in this semaphore by 1 and
|
||||
/// will notify any pending waiters in `acquire` or `access` if necessary.
|
||||
pub fn release(&self) {
|
||||
*self.lock.lock().unwrap() += 1;
|
||||
self.cvar.notify_one();
|
||||
}
|
||||
|
||||
/// Acquires a resource of this semaphore, returning an RAII guard to
|
||||
/// release the semaphore when dropped.
|
||||
///
|
||||
/// This function is semantically equivalent to an `acquire` followed by a
|
||||
/// `release` when the guard returned is dropped.
|
||||
pub fn access(&self) -> SemaphoreGuard {
|
||||
self.acquire();
|
||||
SemaphoreGuard { sem: self }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<'a> Drop for SemaphoreGuard<'a> {
|
||||
fn drop(&mut self) {
|
||||
self.sem.release();
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use prelude::v1::*;
|
||||
|
||||
use sync::Arc;
|
||||
use super::Semaphore;
|
||||
use sync::mpsc::channel;
|
||||
use thread;
|
||||
|
||||
#[test]
|
||||
fn test_sem_acquire_release() {
|
||||
let s = Semaphore::new(1);
|
||||
s.acquire();
|
||||
s.release();
|
||||
s.acquire();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sem_basic() {
|
||||
let s = Semaphore::new(1);
|
||||
let _g = s.access();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sem_as_mutex() {
|
||||
let s = Arc::new(Semaphore::new(1));
|
||||
let s2 = s.clone();
|
||||
let _t = thread::spawn(move|| {
|
||||
let _g = s2.access();
|
||||
});
|
||||
let _g = s.access();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sem_as_cvar() {
|
||||
/* Child waits and parent signals */
|
||||
let (tx, rx) = channel();
|
||||
let s = Arc::new(Semaphore::new(0));
|
||||
let s2 = s.clone();
|
||||
let _t = thread::spawn(move|| {
|
||||
s2.acquire();
|
||||
tx.send(()).unwrap();
|
||||
});
|
||||
s.release();
|
||||
let _ = rx.recv();
|
||||
|
||||
/* Parent waits and child signals */
|
||||
let (tx, rx) = channel();
|
||||
let s = Arc::new(Semaphore::new(0));
|
||||
let s2 = s.clone();
|
||||
let _t = thread::spawn(move|| {
|
||||
s2.release();
|
||||
let _ = rx.recv();
|
||||
});
|
||||
s.acquire();
|
||||
tx.send(()).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sem_multi_resource() {
|
||||
// Parent and child both get in the critical section at the same
|
||||
// time, and shake hands.
|
||||
let s = Arc::new(Semaphore::new(2));
|
||||
let s2 = s.clone();
|
||||
let (tx1, rx1) = channel();
|
||||
let (tx2, rx2) = channel();
|
||||
let _t = thread::spawn(move|| {
|
||||
let _g = s2.access();
|
||||
let _ = rx2.recv();
|
||||
tx1.send(()).unwrap();
|
||||
});
|
||||
let _g = s.access();
|
||||
tx2.send(()).unwrap();
|
||||
rx1.recv().unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sem_runtime_friendly_blocking() {
|
||||
let s = Arc::new(Semaphore::new(1));
|
||||
let s2 = s.clone();
|
||||
let (tx, rx) = channel();
|
||||
{
|
||||
let _g = s.access();
|
||||
thread::spawn(move|| {
|
||||
tx.send(()).unwrap();
|
||||
drop(s2.access());
|
||||
tx.send(()).unwrap();
|
||||
});
|
||||
rx.recv().unwrap(); // wait for child to come alive
|
||||
}
|
||||
rx.recv().unwrap(); // wait for child to be done
|
||||
}
|
||||
}
|
@ -11,15 +11,13 @@
|
||||
use prelude::v1::*;
|
||||
|
||||
use cmp;
|
||||
use ffi::{CStr, CString};
|
||||
use ffi::CString;
|
||||
use fmt;
|
||||
use io::{self, Error, ErrorKind};
|
||||
use libc::{c_int, c_char, c_void};
|
||||
use libc::{c_int, c_void};
|
||||
use mem;
|
||||
#[allow(deprecated)]
|
||||
use net::{SocketAddr, Shutdown, IpAddr, Ipv4Addr, Ipv6Addr};
|
||||
use net::{SocketAddr, Shutdown, Ipv4Addr, Ipv6Addr};
|
||||
use ptr;
|
||||
use str::from_utf8;
|
||||
use sys::net::{cvt, cvt_r, cvt_gai, Socket, init, wrlen_t};
|
||||
use sys::net::netc as c;
|
||||
use sys_common::{AsInner, FromInner, IntoInner};
|
||||
@ -154,34 +152,6 @@ pub fn lookup_host(host: &str) -> io::Result<LookupHost> {
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// lookup_addr
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[allow(deprecated)]
|
||||
pub fn lookup_addr(addr: &IpAddr) -> io::Result<String> {
|
||||
init();
|
||||
|
||||
let saddr = SocketAddr::new(*addr, 0);
|
||||
let (inner, len) = saddr.into_inner();
|
||||
let mut hostbuf = [0 as c_char; c::NI_MAXHOST as usize];
|
||||
|
||||
let data = unsafe {
|
||||
try!(cvt_gai(c::getnameinfo(inner, len,
|
||||
hostbuf.as_mut_ptr(),
|
||||
c::NI_MAXHOST,
|
||||
ptr::null_mut(), 0, 0)));
|
||||
|
||||
CStr::from_ptr(hostbuf.as_ptr())
|
||||
};
|
||||
|
||||
match from_utf8(data.to_bytes()) {
|
||||
Ok(name) => Ok(name.to_owned()),
|
||||
Err(_) => Err(io::Error::new(io::ErrorKind::Other,
|
||||
"failed to lookup address information"))
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// TCP streams
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -8,9 +8,6 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![unstable(feature = "reentrant_mutex", reason = "new API",
|
||||
issue = "27738")]
|
||||
|
||||
use prelude::v1::*;
|
||||
|
||||
use fmt;
|
||||
|
@ -15,90 +15,11 @@
|
||||
use fs::{self, Permissions, OpenOptions};
|
||||
use io;
|
||||
use libc;
|
||||
#[allow(deprecated)]
|
||||
use os::unix::raw;
|
||||
use path::Path;
|
||||
use sys;
|
||||
use sys_common::{FromInner, AsInner, AsInnerMut};
|
||||
use sys::platform::fs::MetadataExt as UnixMetadataExt;
|
||||
|
||||
#[unstable(feature = "fs_mode", reason = "recently added API", issue = "27712")]
|
||||
#[rustc_deprecated(since = "1.7.0", reason = "moved to the libc crate instead")]
|
||||
#[allow(deprecated)]
|
||||
pub const USER_READ: raw::mode_t = 0o400;
|
||||
#[unstable(feature = "fs_mode", reason = "recently added API", issue = "27712")]
|
||||
#[rustc_deprecated(since = "1.7.0", reason = "moved to the libc crate instead")]
|
||||
#[allow(deprecated)]
|
||||
pub const USER_WRITE: raw::mode_t = 0o200;
|
||||
#[unstable(feature = "fs_mode", reason = "recently added API", issue = "27712")]
|
||||
#[rustc_deprecated(since = "1.7.0", reason = "moved to the libc crate instead")]
|
||||
#[allow(deprecated)]
|
||||
pub const USER_EXECUTE: raw::mode_t = 0o100;
|
||||
#[unstable(feature = "fs_mode", reason = "recently added API", issue = "27712")]
|
||||
#[rustc_deprecated(since = "1.7.0", reason = "moved to the libc crate instead")]
|
||||
#[allow(deprecated)]
|
||||
pub const USER_RWX: raw::mode_t = 0o700;
|
||||
#[unstable(feature = "fs_mode", reason = "recently added API", issue = "27712")]
|
||||
#[rustc_deprecated(since = "1.7.0", reason = "moved to the libc crate instead")]
|
||||
#[allow(deprecated)]
|
||||
pub const GROUP_READ: raw::mode_t = 0o040;
|
||||
#[unstable(feature = "fs_mode", reason = "recently added API", issue = "27712")]
|
||||
#[rustc_deprecated(since = "1.7.0", reason = "moved to the libc crate instead")]
|
||||
#[allow(deprecated)]
|
||||
pub const GROUP_WRITE: raw::mode_t = 0o020;
|
||||
#[unstable(feature = "fs_mode", reason = "recently added API", issue = "27712")]
|
||||
#[rustc_deprecated(since = "1.7.0", reason = "moved to the libc crate instead")]
|
||||
#[allow(deprecated)]
|
||||
pub const GROUP_EXECUTE: raw::mode_t = 0o010;
|
||||
#[unstable(feature = "fs_mode", reason = "recently added API", issue = "27712")]
|
||||
#[rustc_deprecated(since = "1.7.0", reason = "moved to the libc crate instead")]
|
||||
#[allow(deprecated)]
|
||||
pub const GROUP_RWX: raw::mode_t = 0o070;
|
||||
#[unstable(feature = "fs_mode", reason = "recently added API", issue = "27712")]
|
||||
#[rustc_deprecated(since = "1.7.0", reason = "moved to the libc crate instead")]
|
||||
#[allow(deprecated)]
|
||||
pub const OTHER_READ: raw::mode_t = 0o004;
|
||||
#[unstable(feature = "fs_mode", reason = "recently added API", issue = "27712")]
|
||||
#[rustc_deprecated(since = "1.7.0", reason = "moved to the libc crate instead")]
|
||||
#[allow(deprecated)]
|
||||
pub const OTHER_WRITE: raw::mode_t = 0o002;
|
||||
#[unstable(feature = "fs_mode", reason = "recently added API", issue = "27712")]
|
||||
#[rustc_deprecated(since = "1.7.0", reason = "moved to the libc crate instead")]
|
||||
#[allow(deprecated)]
|
||||
pub const OTHER_EXECUTE: raw::mode_t = 0o001;
|
||||
#[unstable(feature = "fs_mode", reason = "recently added API", issue = "27712")]
|
||||
#[rustc_deprecated(since = "1.7.0", reason = "moved to the libc crate instead")]
|
||||
#[allow(deprecated)]
|
||||
pub const OTHER_RWX: raw::mode_t = 0o007;
|
||||
#[unstable(feature = "fs_mode", reason = "recently added API", issue = "27712")]
|
||||
#[rustc_deprecated(since = "1.7.0", reason = "moved to the libc crate instead")]
|
||||
#[allow(deprecated)]
|
||||
pub const ALL_READ: raw::mode_t = 0o444;
|
||||
#[unstable(feature = "fs_mode", reason = "recently added API", issue = "27712")]
|
||||
#[rustc_deprecated(since = "1.7.0", reason = "moved to the libc crate instead")]
|
||||
#[allow(deprecated)]
|
||||
pub const ALL_WRITE: raw::mode_t = 0o222;
|
||||
#[unstable(feature = "fs_mode", reason = "recently added API", issue = "27712")]
|
||||
#[rustc_deprecated(since = "1.7.0", reason = "moved to the libc crate instead")]
|
||||
#[allow(deprecated)]
|
||||
pub const ALL_EXECUTE: raw::mode_t = 0o111;
|
||||
#[unstable(feature = "fs_mode", reason = "recently added API", issue = "27712")]
|
||||
#[rustc_deprecated(since = "1.7.0", reason = "moved to the libc crate instead")]
|
||||
#[allow(deprecated)]
|
||||
pub const ALL_RWX: raw::mode_t = 0o777;
|
||||
#[unstable(feature = "fs_mode", reason = "recently added API", issue = "27712")]
|
||||
#[rustc_deprecated(since = "1.7.0", reason = "moved to the libc crate instead")]
|
||||
#[allow(deprecated)]
|
||||
pub const SETUID: raw::mode_t = 0o4000;
|
||||
#[unstable(feature = "fs_mode", reason = "recently added API", issue = "27712")]
|
||||
#[rustc_deprecated(since = "1.7.0", reason = "moved to the libc crate instead")]
|
||||
#[allow(deprecated)]
|
||||
pub const SETGID: raw::mode_t = 0o2000;
|
||||
#[unstable(feature = "fs_mode", reason = "recently added API", issue = "27712")]
|
||||
#[rustc_deprecated(since = "1.7.0", reason = "moved to the libc crate instead")]
|
||||
#[allow(deprecated)]
|
||||
pub const STICKY_BIT: raw::mode_t = 0o1000;
|
||||
|
||||
/// Unix-specific extensions to `Permissions`
|
||||
#[stable(feature = "fs_ext", since = "1.1.0")]
|
||||
pub trait PermissionsExt {
|
||||
|
@ -26,22 +26,22 @@
|
||||
|
||||
use io::prelude::*;
|
||||
|
||||
use dynamic_lib::DynamicLibrary;
|
||||
use io;
|
||||
use libc::c_void;
|
||||
use mem;
|
||||
use path::Path;
|
||||
use ptr;
|
||||
use sync::StaticMutex;
|
||||
use sys::c;
|
||||
use sys::dynamic_lib::DynamicLibrary;
|
||||
|
||||
macro_rules! sym{ ($lib:expr, $e:expr, $t:ident) => (unsafe {
|
||||
let lib = $lib;
|
||||
match lib.symbol($e) {
|
||||
Ok(f) => $crate::mem::transmute::<*mut u8, $t>(f),
|
||||
Err(..) => return Ok(())
|
||||
}
|
||||
}) }
|
||||
macro_rules! sym {
|
||||
($lib:expr, $e:expr, $t:ident) => (
|
||||
match $lib.symbol($e) {
|
||||
Ok(f) => $crate::mem::transmute::<usize, $t>(f),
|
||||
Err(..) => return Ok(())
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(target_env = "msvc")]
|
||||
#[path = "printing/msvc.rs"]
|
||||
@ -52,16 +52,16 @@ mod printing;
|
||||
mod printing;
|
||||
|
||||
type SymInitializeFn =
|
||||
extern "system" fn(c::HANDLE, *mut c_void,
|
||||
c::BOOL) -> c::BOOL;
|
||||
unsafe extern "system" fn(c::HANDLE, *mut c_void,
|
||||
c::BOOL) -> c::BOOL;
|
||||
type SymCleanupFn =
|
||||
extern "system" fn(c::HANDLE) -> c::BOOL;
|
||||
unsafe extern "system" fn(c::HANDLE) -> c::BOOL;
|
||||
|
||||
type StackWalk64Fn =
|
||||
extern "system" fn(c::DWORD, c::HANDLE, c::HANDLE,
|
||||
*mut c::STACKFRAME64, *mut c::CONTEXT,
|
||||
*mut c_void, *mut c_void,
|
||||
*mut c_void, *mut c_void) -> c::BOOL;
|
||||
unsafe extern "system" fn(c::DWORD, c::HANDLE, c::HANDLE,
|
||||
*mut c::STACKFRAME64, *mut c::CONTEXT,
|
||||
*mut c_void, *mut c_void,
|
||||
*mut c_void, *mut c_void) -> c::BOOL;
|
||||
|
||||
#[cfg(target_arch = "x86")]
|
||||
pub fn init_frame(frame: &mut c::STACKFRAME64,
|
||||
@ -93,7 +93,9 @@ struct Cleanup {
|
||||
}
|
||||
|
||||
impl Drop for Cleanup {
|
||||
fn drop(&mut self) { (self.SymCleanup)(self.handle); }
|
||||
fn drop(&mut self) {
|
||||
unsafe { (self.SymCleanup)(self.handle); }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write(w: &mut Write) -> io::Result<()> {
|
||||
@ -102,52 +104,50 @@ pub fn write(w: &mut Write) -> io::Result<()> {
|
||||
static LOCK: StaticMutex = StaticMutex::new();
|
||||
let _g = LOCK.lock();
|
||||
|
||||
// Open up dbghelp.dll, we don't link to it explicitly because it can't
|
||||
// always be found. Additionally, it's nice having fewer dependencies.
|
||||
let path = Path::new("dbghelp.dll");
|
||||
let dbghelp = match DynamicLibrary::open(Some(&path)) {
|
||||
let dbghelp = match DynamicLibrary::open("dbghelp.dll") {
|
||||
Ok(lib) => lib,
|
||||
Err(..) => return Ok(()),
|
||||
};
|
||||
unsafe {
|
||||
// Fetch the symbols necessary from dbghelp.dll
|
||||
let SymInitialize = sym!(dbghelp, "SymInitialize", SymInitializeFn);
|
||||
let SymCleanup = sym!(dbghelp, "SymCleanup", SymCleanupFn);
|
||||
let StackWalk64 = sym!(dbghelp, "StackWalk64", StackWalk64Fn);
|
||||
|
||||
// Fetch the symbols necessary from dbghelp.dll
|
||||
let SymInitialize = sym!(&dbghelp, "SymInitialize", SymInitializeFn);
|
||||
let SymCleanup = sym!(&dbghelp, "SymCleanup", SymCleanupFn);
|
||||
let StackWalk64 = sym!(&dbghelp, "StackWalk64", StackWalk64Fn);
|
||||
// Allocate necessary structures for doing the stack walk
|
||||
let process = c::GetCurrentProcess();
|
||||
let thread = c::GetCurrentThread();
|
||||
let mut context: c::CONTEXT = mem::zeroed();
|
||||
c::RtlCaptureContext(&mut context);
|
||||
let mut frame: c::STACKFRAME64 = mem::zeroed();
|
||||
let image = init_frame(&mut frame, &context);
|
||||
|
||||
// Allocate necessary structures for doing the stack walk
|
||||
let process = unsafe { c::GetCurrentProcess() };
|
||||
let thread = unsafe { c::GetCurrentThread() };
|
||||
let mut context: c::CONTEXT = unsafe { mem::zeroed() };
|
||||
unsafe { c::RtlCaptureContext(&mut context); }
|
||||
let mut frame: c::STACKFRAME64 = unsafe { mem::zeroed() };
|
||||
let image = init_frame(&mut frame, &context);
|
||||
// Initialize this process's symbols
|
||||
let ret = SymInitialize(process, ptr::null_mut(), c::TRUE);
|
||||
if ret != c::TRUE { return Ok(()) }
|
||||
let _c = Cleanup { handle: process, SymCleanup: SymCleanup };
|
||||
|
||||
// Initialize this process's symbols
|
||||
let ret = SymInitialize(process, ptr::null_mut(), c::TRUE);
|
||||
if ret != c::TRUE { return Ok(()) }
|
||||
let _c = Cleanup { handle: process, SymCleanup: SymCleanup };
|
||||
// And now that we're done with all the setup, do the stack walking!
|
||||
// Start from -1 to avoid printing this stack frame, which will
|
||||
// always be exactly the same.
|
||||
let mut i = -1;
|
||||
try!(write!(w, "stack backtrace:\n"));
|
||||
while StackWalk64(image, process, thread, &mut frame, &mut context,
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut()) == c::TRUE {
|
||||
let addr = frame.AddrPC.Offset;
|
||||
if addr == frame.AddrReturn.Offset || addr == 0 ||
|
||||
frame.AddrReturn.Offset == 0 { break }
|
||||
|
||||
// And now that we're done with all the setup, do the stack walking!
|
||||
// Start from -1 to avoid printing this stack frame, which will
|
||||
// always be exactly the same.
|
||||
let mut i = -1;
|
||||
try!(write!(w, "stack backtrace:\n"));
|
||||
while StackWalk64(image, process, thread, &mut frame, &mut context,
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut()) == c::TRUE {
|
||||
let addr = frame.AddrPC.Offset;
|
||||
if addr == frame.AddrReturn.Offset || addr == 0 ||
|
||||
frame.AddrReturn.Offset == 0 { break }
|
||||
i += 1;
|
||||
|
||||
i += 1;
|
||||
|
||||
if i >= 0 {
|
||||
try!(printing::print(w, i, addr-1, &dbghelp, process));
|
||||
if i >= 0 {
|
||||
try!(printing::print(w, i, addr - 1, process, &dbghelp));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -154,8 +154,6 @@ pub const WSAESHUTDOWN: c_int = 10058;
|
||||
pub const WSAETIMEDOUT: c_int = 10060;
|
||||
pub const WSAECONNREFUSED: c_int = 10061;
|
||||
|
||||
pub const NI_MAXHOST: DWORD = 1025;
|
||||
|
||||
pub const MAX_PROTOCOL_CHAIN: DWORD = 7;
|
||||
|
||||
pub const TOKEN_READ: DWORD = 0x20008;
|
||||
@ -1099,18 +1097,11 @@ extern "system" {
|
||||
hints: *const ADDRINFOA,
|
||||
res: *mut *mut ADDRINFOA) -> c_int;
|
||||
pub fn freeaddrinfo(res: *mut ADDRINFOA);
|
||||
pub fn getnameinfo(sa: *const SOCKADDR, salen: c_int,
|
||||
host: *mut c_char, hostlen: DWORD,
|
||||
serv: *mut c_char, servlen: DWORD,
|
||||
flags: c_int) -> c_int;
|
||||
|
||||
pub fn LoadLibraryW(name: LPCWSTR) -> HMODULE;
|
||||
pub fn GetModuleHandleExW(dwFlags: DWORD, name: LPCWSTR,
|
||||
handle: *mut HMODULE) -> BOOL;
|
||||
pub fn FreeLibrary(handle: HMODULE) -> BOOL;
|
||||
pub fn GetProcAddress(handle: HMODULE,
|
||||
name: LPCSTR) -> *mut c_void;
|
||||
pub fn FreeLibrary(handle: HMODULE) -> BOOL;
|
||||
pub fn SetErrorMode(uMode: c_uint) -> c_uint;
|
||||
pub fn GetModuleHandleW(lpModuleName: LPCWSTR) -> HMODULE;
|
||||
pub fn CryptAcquireContextA(phProv: *mut HCRYPTPROV,
|
||||
pszContainer: LPCSTR,
|
||||
@ -1177,10 +1168,6 @@ compat_fn! {
|
||||
_dwFlags: DWORD) -> DWORD {
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); 0
|
||||
}
|
||||
pub fn SetThreadErrorMode(_dwNewMode: DWORD,
|
||||
_lpOldMode: *mut DWORD) -> c_uint {
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); 0
|
||||
}
|
||||
pub fn SetThreadStackGuarantee(_size: *mut c_ulong) -> BOOL {
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); 0
|
||||
}
|
||||
|
55
src/libstd/sys/windows/dynamic_lib.rs
Normal file
55
src/libstd/sys/windows/dynamic_lib.rs
Normal file
@ -0,0 +1,55 @@
|
||||
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use prelude::v1::*;
|
||||
use os::windows::prelude::*;
|
||||
|
||||
use ffi::{CString, OsStr};
|
||||
use io;
|
||||
use sys::c;
|
||||
|
||||
pub struct DynamicLibrary {
|
||||
handle: c::HMODULE,
|
||||
}
|
||||
|
||||
impl DynamicLibrary {
|
||||
pub fn open(filename: &str) -> io::Result<DynamicLibrary> {
|
||||
let filename = OsStr::new(filename)
|
||||
.encode_wide()
|
||||
.chain(Some(0))
|
||||
.collect::<Vec<_>>();
|
||||
let result = unsafe {
|
||||
c::LoadLibraryW(filename.as_ptr())
|
||||
};
|
||||
if result.is_null() {
|
||||
Err(io::Error::last_os_error())
|
||||
} else {
|
||||
Ok(DynamicLibrary { handle: result })
|
||||
}
|
||||
}
|
||||
|
||||
pub fn symbol(&self, symbol: &str) -> io::Result<usize> {
|
||||
let symbol = try!(CString::new(symbol));
|
||||
unsafe {
|
||||
match c::GetProcAddress(self.handle, symbol.as_ptr()) as usize {
|
||||
0 => Err(io::Error::last_os_error()),
|
||||
n => Ok(n),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for DynamicLibrary {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
c::FreeLibrary(self.handle);
|
||||
}
|
||||
}
|
||||
}
|
@ -24,6 +24,7 @@ use time::Duration;
|
||||
pub mod backtrace;
|
||||
pub mod c;
|
||||
pub mod condvar;
|
||||
pub mod dynamic_lib;
|
||||
pub mod ext;
|
||||
pub mod fs;
|
||||
pub mod handle;
|
||||
|
@ -8,18 +8,19 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![allow(deprecated)]
|
||||
|
||||
use dynamic_lib::DynamicLibrary;
|
||||
use io::prelude::*;
|
||||
use io;
|
||||
use sys::c;
|
||||
use libc::c_void;
|
||||
|
||||
use sys::c;
|
||||
use sys::dynamic_lib::DynamicLibrary;
|
||||
use sys_common::gnu::libbacktrace;
|
||||
|
||||
pub fn print(w: &mut Write, i: isize, addr: u64, _: &DynamicLibrary, _: c::HANDLE)
|
||||
-> io::Result<()> {
|
||||
pub fn print(w: &mut Write,
|
||||
i: isize,
|
||||
addr: u64,
|
||||
_process: c::HANDLE,
|
||||
_dbghelp: &DynamicLibrary)
|
||||
-> io::Result<()> {
|
||||
let addr = addr as usize as *mut c_void;
|
||||
libbacktrace::print(w, i, addr, addr)
|
||||
}
|
||||
|
@ -8,60 +8,66 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![allow(deprecated)]
|
||||
|
||||
use dynamic_lib::DynamicLibrary;
|
||||
use ffi::CStr;
|
||||
use io::prelude::*;
|
||||
use io;
|
||||
use libc::{c_ulong, c_int, c_char, c_void};
|
||||
use mem;
|
||||
use sys::c;
|
||||
use sys::dynamic_lib::DynamicLibrary;
|
||||
use sys_common::backtrace::{output, output_fileline};
|
||||
|
||||
type SymFromAddrFn =
|
||||
extern "system" fn(c::HANDLE, u64, *mut u64,
|
||||
*mut c::SYMBOL_INFO) -> c::BOOL;
|
||||
unsafe extern "system" fn(c::HANDLE, u64, *mut u64,
|
||||
*mut c::SYMBOL_INFO) -> c::BOOL;
|
||||
type SymGetLineFromAddr64Fn =
|
||||
extern "system" fn(c::HANDLE, u64, *mut u32,
|
||||
*mut c::IMAGEHLP_LINE64) -> c::BOOL;
|
||||
unsafe extern "system" fn(c::HANDLE, u64, *mut u32,
|
||||
*mut c::IMAGEHLP_LINE64) -> c::BOOL;
|
||||
|
||||
pub fn print(w: &mut Write, i: isize, addr: u64, dbghelp: &DynamicLibrary,
|
||||
process: c::HANDLE) -> io::Result<()> {
|
||||
let SymFromAddr = sym!(dbghelp, "SymFromAddr", SymFromAddrFn);
|
||||
let SymGetLineFromAddr64 = sym!(dbghelp, "SymGetLineFromAddr64", SymGetLineFromAddr64Fn);
|
||||
pub fn print(w: &mut Write,
|
||||
i: isize,
|
||||
addr: u64,
|
||||
process: c::HANDLE,
|
||||
dbghelp: &DynamicLibrary)
|
||||
-> io::Result<()> {
|
||||
unsafe {
|
||||
let SymFromAddr = sym!(dbghelp, "SymFromAddr", SymFromAddrFn);
|
||||
let SymGetLineFromAddr64 = sym!(dbghelp,
|
||||
"SymGetLineFromAddr64",
|
||||
SymGetLineFromAddr64Fn);
|
||||
|
||||
let mut info: c::SYMBOL_INFO = unsafe { mem::zeroed() };
|
||||
info.MaxNameLen = c::MAX_SYM_NAME as c_ulong;
|
||||
// the struct size in C. the value is different to
|
||||
// `size_of::<SYMBOL_INFO>() - MAX_SYM_NAME + 1` (== 81)
|
||||
// due to struct alignment.
|
||||
info.SizeOfStruct = 88;
|
||||
let mut info: c::SYMBOL_INFO = mem::zeroed();
|
||||
info.MaxNameLen = c::MAX_SYM_NAME as c_ulong;
|
||||
// the struct size in C. the value is different to
|
||||
// `size_of::<SYMBOL_INFO>() - MAX_SYM_NAME + 1` (== 81)
|
||||
// due to struct alignment.
|
||||
info.SizeOfStruct = 88;
|
||||
|
||||
let mut displacement = 0u64;
|
||||
let ret = SymFromAddr(process, addr, &mut displacement, &mut info);
|
||||
let mut displacement = 0u64;
|
||||
let ret = SymFromAddr(process, addr, &mut displacement, &mut info);
|
||||
|
||||
let name = if ret == c::TRUE {
|
||||
let ptr = info.Name.as_ptr() as *const c_char;
|
||||
Some(unsafe { CStr::from_ptr(ptr).to_bytes() })
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let name = if ret == c::TRUE {
|
||||
let ptr = info.Name.as_ptr() as *const c_char;
|
||||
Some(CStr::from_ptr(ptr).to_bytes())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
try!(output(w, i, addr as usize as *mut c_void, name));
|
||||
try!(output(w, i, addr as usize as *mut c_void, name));
|
||||
|
||||
// Now find out the filename and line number
|
||||
let mut line: c::IMAGEHLP_LINE64 = unsafe { mem::zeroed() };
|
||||
line.SizeOfStruct = ::mem::size_of::<c::IMAGEHLP_LINE64>() as u32;
|
||||
// Now find out the filename and line number
|
||||
let mut line: c::IMAGEHLP_LINE64 = mem::zeroed();
|
||||
line.SizeOfStruct = ::mem::size_of::<c::IMAGEHLP_LINE64>() as u32;
|
||||
|
||||
let mut displacement = 0u32;
|
||||
let ret = SymGetLineFromAddr64(process, addr, &mut displacement, &mut line);
|
||||
if ret == c::TRUE {
|
||||
output_fileline(w,
|
||||
unsafe { CStr::from_ptr(line.Filename).to_bytes() },
|
||||
line.LineNumber as c_int,
|
||||
false)
|
||||
} else {
|
||||
Ok(())
|
||||
let mut displacement = 0u32;
|
||||
let ret = SymGetLineFromAddr64(process, addr, &mut displacement, &mut line);
|
||||
if ret == c::TRUE {
|
||||
output_fileline(w,
|
||||
CStr::from_ptr(line.Filename).to_bytes(),
|
||||
line.LineNumber as c_int,
|
||||
false)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -339,40 +339,6 @@ pub fn panicking() -> bool {
|
||||
unwind::panicking()
|
||||
}
|
||||
|
||||
/// Invokes a closure, capturing the cause of panic if one occurs.
|
||||
///
|
||||
/// This function will return `Ok` with the closure's result if the closure
|
||||
/// does not panic, and will return `Err(cause)` if the closure panics. The
|
||||
/// `cause` returned is the object with which panic was originally invoked.
|
||||
///
|
||||
/// It is currently undefined behavior to unwind from Rust code into foreign
|
||||
/// code, so this function is particularly useful when Rust is called from
|
||||
/// another language (normally C). This can run arbitrary Rust code, capturing a
|
||||
/// panic and allowing a graceful handling of the error.
|
||||
///
|
||||
/// It is **not** recommended to use this function for a general try/catch
|
||||
/// mechanism. The `Result` type is more appropriate to use for functions that
|
||||
/// can fail on a regular basis.
|
||||
///
|
||||
/// The closure provided is required to adhere to the `'static` bound to ensure
|
||||
/// that it cannot reference data in the parent stack frame, mitigating problems
|
||||
/// with exception safety. Furthermore, a `Send` bound is also required,
|
||||
/// providing the same safety guarantees as `thread::spawn` (ensuring the
|
||||
/// closure is properly isolated from the parent).
|
||||
#[unstable(feature = "catch_panic", reason = "recent API addition",
|
||||
issue = "27719")]
|
||||
#[rustc_deprecated(since = "1.6.0", reason = "renamed to std::panic::recover")]
|
||||
pub fn catch_panic<F, R>(f: F) -> Result<R>
|
||||
where F: FnOnce() -> R + Send + 'static
|
||||
{
|
||||
let mut result = None;
|
||||
unsafe {
|
||||
let result = &mut result;
|
||||
try!(unwind::try(move || *result = Some(f())))
|
||||
}
|
||||
Ok(result.unwrap())
|
||||
}
|
||||
|
||||
/// Puts the current thread to sleep for the specified amount of time.
|
||||
///
|
||||
/// The thread may sleep longer than the duration specified due to scheduling
|
||||
|
@ -9,7 +9,6 @@
|
||||
// except according to those terms.
|
||||
|
||||
use ops::{Add, Sub, Mul, Div};
|
||||
use time::Instant;
|
||||
|
||||
const NANOS_PER_SEC: u32 = 1_000_000_000;
|
||||
const NANOS_PER_MILLI: u32 = 1_000_000;
|
||||
@ -59,21 +58,6 @@ impl Duration {
|
||||
Duration { secs: secs, nanos: nanos }
|
||||
}
|
||||
|
||||
/// Runs a closure, returning the duration of time it took to run the
|
||||
/// closure.
|
||||
#[unstable(feature = "duration_span",
|
||||
reason = "unsure if this is the right API or whether it should \
|
||||
wait for a more general \"moment in time\" \
|
||||
abstraction",
|
||||
issue = "27799")]
|
||||
#[rustc_deprecated(reason = "use std::time::Instant instead",
|
||||
since = "1.6.0")]
|
||||
pub fn span<F>(f: F) -> Duration where F: FnOnce() {
|
||||
let start = Instant::now();
|
||||
f();
|
||||
start.elapsed()
|
||||
}
|
||||
|
||||
/// Creates a new `Duration` from the specified number of seconds.
|
||||
#[stable(feature = "duration", since = "1.3.0")]
|
||||
pub fn from_secs(secs: u64) -> Duration {
|
||||
|
@ -8,13 +8,15 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(dynamic_lib)]
|
||||
#![feature(rustc_private)]
|
||||
|
||||
// We're testing linkage visibility; the compiler warns us, but we want to
|
||||
// do the runtime check that these functions aren't exported.
|
||||
#![allow(private_no_mangle_fns)]
|
||||
|
||||
use std::dynamic_lib::DynamicLibrary;
|
||||
extern crate rustc_back;
|
||||
|
||||
use rustc_back::dynamic_lib::DynamicLibrary;
|
||||
|
||||
#[no_mangle]
|
||||
pub fn foo() { bar(); }
|
||||
|
@ -8,7 +8,17 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use std::borrow::IntoCow;
|
||||
use std::borrow::Cow;
|
||||
|
||||
pub trait IntoCow<'a, B: ?Sized> where B: ToOwned {
|
||||
fn into_cow(self) -> Cow<'a, B>;
|
||||
}
|
||||
|
||||
impl<'a> IntoCow<'a, str> for String {
|
||||
fn into_cow(self) -> Cow<'a, str> {
|
||||
Cow::Owned(self)
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
<String as IntoCow>::into_cow("foo".to_string());
|
||||
|
@ -8,9 +8,11 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(dynamic_lib)]
|
||||
#![feature(rustc_private)]
|
||||
|
||||
use std::dynamic_lib::DynamicLibrary;
|
||||
extern crate rustc_back;
|
||||
|
||||
use rustc_back::dynamic_lib::DynamicLibrary;
|
||||
use std::path::Path;
|
||||
|
||||
pub fn main() {
|
||||
|
@ -1,16 +1,18 @@
|
||||
-include ../tools.mk
|
||||
|
||||
OUT := $(TMPDIR)/out
|
||||
|
||||
ifndef IS_WINDOWS
|
||||
all: time
|
||||
|
||||
time: libc
|
||||
mkdir -p out/time out/time/deps
|
||||
ln -sf out/libc/liblibc.rlib out/time/deps/
|
||||
$(RUSTC) in/time/lib.rs -Ldependency=out/time/deps/
|
||||
mkdir -p $(OUT)/time $(OUT)/time/deps
|
||||
ln -sf $(OUT)/libc/liblibc.rlib $(OUT)/time/deps/
|
||||
$(RUSTC) in/time/lib.rs -Ldependency=$(OUT)/time/deps/
|
||||
|
||||
libc:
|
||||
mkdir -p out/libc
|
||||
$(RUSTC) in/libc/lib.rs --crate-name=libc -o out/libc/liblibc.rlib
|
||||
mkdir -p $(OUT)/libc
|
||||
$(RUSTC) in/libc/lib.rs --crate-name=libc -o $(OUT)/libc/liblibc.rlib
|
||||
else
|
||||
all:
|
||||
endif
|
||||
|
@ -1,8 +1,10 @@
|
||||
-include ../tools.mk
|
||||
|
||||
LOG := $(TMPDIR)/foo.log
|
||||
|
||||
all:
|
||||
cp foo.rs $(TMPDIR)
|
||||
cd $(TMPDIR)
|
||||
-$(RUSTC) -Z unstable-options --error-format=json foo.rs 2>foo.log
|
||||
grep -q '{"message":"unresolved name `y`","code":{"code":"E0425","explanation":"\\nAn unresolved name was used. Example of erroneous codes.*"},"level":"error","spans":\[{"file_name":"foo.rs","byte_start":496,"byte_end":497,"line_start":12,"line_end":12,"column_start":18,"column_end":19}\],"children":\[\]}' foo.log
|
||||
grep -q '{"message":".*","code":{"code":"E0277","explanation":"\\nYou tried.*"},"level":"error","spans":\[{.*}\],"children":\[{"message":"the .*","code":null,"level":"help","spans":\[{"file_name":"foo.rs","byte_start":504,"byte_end":516,"line_start":14,"line_end":14,"column_start":0,"column_end":0}\],"children":\[\]},{"message":" <u8 as core::ops::Add>","code":null,"level":"help",' foo.log
|
||||
-$(RUSTC) -Z unstable-options --error-format=json foo.rs 2>$(LOG)
|
||||
grep -q '{"message":"unresolved name `y`","code":{"code":"E0425","explanation":"\\nAn unresolved name was used. Example of erroneous codes.*"},"level":"error","spans":\[{"file_name":"foo.rs","byte_start":496,"byte_end":497,"line_start":12,"line_end":12,"column_start":18,"column_end":19}\],"children":\[\]}' $(LOG)
|
||||
grep -q '{"message":".*","code":{"code":"E0277","explanation":"\\nYou tried.*"},"level":"error","spans":\[{.*}\],"children":\[{"message":"the .*","code":null,"level":"help","spans":\[{"file_name":"foo.rs","byte_start":504,"byte_end":516,"line_start":14,"line_end":14,"column_start":0,"column_end":0}\],"children":\[\]},{"message":" <u8 as core::ops::Add>","code":null,"level":"help",' $(LOG)
|
||||
|
@ -1,22 +0,0 @@
|
||||
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(rustc_private)]
|
||||
|
||||
extern crate arena;
|
||||
use arena::Arena;
|
||||
|
||||
pub fn main() {
|
||||
let mut arena = Arena::new();
|
||||
let p = &mut arena;
|
||||
let x = p.alloc(|| 4_usize);
|
||||
println!("{}", *x);
|
||||
assert_eq!(*x, 4_usize);
|
||||
}
|
@ -15,7 +15,6 @@
|
||||
// ignore-emscripten
|
||||
// no-prefer-dynamic
|
||||
|
||||
#![feature(convert)]
|
||||
#![feature(libc)]
|
||||
|
||||
extern crate libc;
|
||||
@ -23,7 +22,8 @@ extern crate libc;
|
||||
use libc::c_char;
|
||||
use libc::execve;
|
||||
use std::env;
|
||||
use std::ffi::OsStr;
|
||||
use std::ffi::CString;
|
||||
use std::os::unix::prelude::*;
|
||||
use std::ptr;
|
||||
|
||||
fn main() {
|
||||
@ -34,8 +34,11 @@ fn main() {
|
||||
return;
|
||||
}
|
||||
|
||||
let current_exe = env::current_exe().unwrap().into_os_string().to_cstring().unwrap();
|
||||
let new_env_var = OsStr::new("FOOBAR").to_cstring().unwrap();
|
||||
let current_exe = CString::new(env::current_exe()
|
||||
.unwrap()
|
||||
.as_os_str()
|
||||
.as_bytes()).unwrap();
|
||||
let new_env_var = CString::new("FOOBAR").unwrap();
|
||||
let filename: *const c_char = current_exe.as_ptr();
|
||||
let argv: &[*const c_char] = &[filename, filename, ptr::null()];
|
||||
let envp: &[*const c_char] = &[new_env_var.as_ptr(), ptr::null()];
|
||||
|
@ -10,15 +10,14 @@
|
||||
|
||||
// pretty-expanded FIXME #23616
|
||||
|
||||
#![feature(num_bits_bytes)]
|
||||
|
||||
use std::u8;
|
||||
mod u8 {
|
||||
pub const BITS: usize = 8;
|
||||
}
|
||||
|
||||
const NUM: usize = u8::BITS;
|
||||
|
||||
struct MyStruct { nums: [usize; 8] }
|
||||
|
||||
|
||||
fn main() {
|
||||
let _s = MyStruct { nums: [0; NUM] };
|
||||
}
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
// pretty-expanded FIXME #23616
|
||||
|
||||
#![feature(fs, net, fs_walk)]
|
||||
#![feature(fs, net)]
|
||||
|
||||
use std::{fs, net};
|
||||
|
||||
@ -22,7 +22,6 @@ fn main() {
|
||||
assert_both::<fs::Metadata>();
|
||||
assert_both::<fs::ReadDir>();
|
||||
assert_both::<fs::DirEntry>();
|
||||
assert_send::<fs::WalkDir>();
|
||||
assert_both::<fs::OpenOptions>();
|
||||
assert_both::<fs::Permissions>();
|
||||
|
||||
|
@ -8,8 +8,6 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(iter_min_max, cmp_partial, iter_cmp)]
|
||||
|
||||
use std::fmt::Debug;
|
||||
use std::cmp::{self, PartialOrd, Ordering};
|
||||
|
||||
@ -43,13 +41,13 @@ fn main() {
|
||||
|
||||
// `min` should return the left when the values are equal
|
||||
assert_eq!(data.iter().min(), Some(&a));
|
||||
assert_eq!(data.iter().min_by(|a| a.n), Some(&a));
|
||||
assert_eq!(data.iter().min_by_key(|a| a.n), Some(&a));
|
||||
assert_eq!(cmp::min(a, b), a);
|
||||
assert_eq!(cmp::min(b, a), b);
|
||||
|
||||
// `max` should return the right when the values are equal
|
||||
assert_eq!(data.iter().max(), Some(&f));
|
||||
assert_eq!(data.iter().max_by(|a| a.n), Some(&f));
|
||||
assert_eq!(data.iter().max_by_key(|a| a.n), Some(&f));
|
||||
assert_eq!(cmp::max(e, f), f);
|
||||
assert_eq!(cmp::max(f, e), e);
|
||||
|
||||
|
@ -12,7 +12,7 @@
|
||||
//
|
||||
// Test std::num::Wrapping<T> for {uN, iN, usize, isize}
|
||||
|
||||
#![feature(num_bits_bytes, test)]
|
||||
#![feature(test)]
|
||||
|
||||
extern crate test;
|
||||
|
||||
@ -22,9 +22,40 @@ use std::ops::{
|
||||
AddAssign, SubAssign, MulAssign, DivAssign, RemAssign, BitXorAssign, BitOrAssign, BitAndAssign,
|
||||
Shl, Shr, ShlAssign, ShrAssign
|
||||
};
|
||||
use std::{i8, i16, i32, i64, isize, u8, u16, u32, u64, usize};
|
||||
use test::black_box;
|
||||
|
||||
macro_rules! int_modules {
|
||||
($(($name:ident, $size:expr),)*) => ($(
|
||||
mod $name {
|
||||
pub const BITS: usize = $size;
|
||||
pub use std::$name::*;
|
||||
}
|
||||
)*)
|
||||
}
|
||||
|
||||
int_modules! {
|
||||
(i8, 8),
|
||||
(i16, 16),
|
||||
(i32, 32),
|
||||
(i64, 64),
|
||||
(u8, 8),
|
||||
(u16, 16),
|
||||
(u32, 32),
|
||||
(u64, 64),
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
int_modules! {
|
||||
(isize, 32),
|
||||
(usize, 32),
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
int_modules! {
|
||||
(isize, 64),
|
||||
(usize, 64),
|
||||
}
|
||||
|
||||
fn main() {
|
||||
test_ops();
|
||||
test_op_assigns();
|
||||
|
@ -8,57 +8,55 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
|
||||
#![feature(collections, into_cow)]
|
||||
|
||||
extern crate collections;
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::borrow::{Cow, IntoCow};
|
||||
use std::borrow::Cow;
|
||||
|
||||
use std::borrow::Cow::Borrowed as B;
|
||||
use std::borrow::Cow::Owned as O;
|
||||
|
||||
type SendStr = Cow<'static, str>;
|
||||
|
||||
pub fn main() {
|
||||
fn main() {
|
||||
let mut map: HashMap<SendStr, usize> = HashMap::new();
|
||||
assert!(map.insert("foo".into_cow(), 42).is_none());
|
||||
assert!(map.insert("foo".to_string().into_cow(), 42).is_some());
|
||||
assert!(map.insert("foo".into_cow(), 42).is_some());
|
||||
assert!(map.insert("foo".to_string().into_cow(), 42).is_some());
|
||||
assert!(map.insert(B("foo"), 42).is_none());
|
||||
assert!(map.insert(O("foo".to_string()), 42).is_some());
|
||||
assert!(map.insert(B("foo"), 42).is_some());
|
||||
assert!(map.insert(O("foo".to_string()), 42).is_some());
|
||||
|
||||
assert!(map.insert("foo".into_cow(), 43).is_some());
|
||||
assert!(map.insert("foo".to_string().into_cow(), 44).is_some());
|
||||
assert!(map.insert("foo".into_cow(), 45).is_some());
|
||||
assert!(map.insert("foo".to_string().into_cow(), 46).is_some());
|
||||
assert!(map.insert(B("foo"), 43).is_some());
|
||||
assert!(map.insert(O("foo".to_string()), 44).is_some());
|
||||
assert!(map.insert(B("foo"), 45).is_some());
|
||||
assert!(map.insert(O("foo".to_string()), 46).is_some());
|
||||
|
||||
let v = 46;
|
||||
|
||||
assert_eq!(map.get(&"foo".to_string().into_cow()), Some(&v));
|
||||
assert_eq!(map.get(&"foo".into_cow()), Some(&v));
|
||||
assert_eq!(map.get(&O("foo".to_string())), Some(&v));
|
||||
assert_eq!(map.get(&B("foo")), Some(&v));
|
||||
|
||||
let (a, b, c, d) = (50, 51, 52, 53);
|
||||
|
||||
assert!(map.insert("abc".into_cow(), a).is_none());
|
||||
assert!(map.insert("bcd".to_string().into_cow(), b).is_none());
|
||||
assert!(map.insert("cde".into_cow(), c).is_none());
|
||||
assert!(map.insert("def".to_string().into_cow(), d).is_none());
|
||||
assert!(map.insert(B("abc"), a).is_none());
|
||||
assert!(map.insert(O("bcd".to_string()), b).is_none());
|
||||
assert!(map.insert(B("cde"), c).is_none());
|
||||
assert!(map.insert(O("def".to_string()), d).is_none());
|
||||
|
||||
assert!(map.insert("abc".into_cow(), a).is_some());
|
||||
assert!(map.insert("bcd".to_string().into_cow(), b).is_some());
|
||||
assert!(map.insert("cde".into_cow(), c).is_some());
|
||||
assert!(map.insert("def".to_string().into_cow(), d).is_some());
|
||||
assert!(map.insert(B("abc"), a).is_some());
|
||||
assert!(map.insert(O("bcd".to_string()), b).is_some());
|
||||
assert!(map.insert(B("cde"), c).is_some());
|
||||
assert!(map.insert(O("def".to_string()), d).is_some());
|
||||
|
||||
assert!(map.insert("abc".to_string().into_cow(), a).is_some());
|
||||
assert!(map.insert("bcd".into_cow(), b).is_some());
|
||||
assert!(map.insert("cde".to_string().into_cow(), c).is_some());
|
||||
assert!(map.insert("def".into_cow(), d).is_some());
|
||||
assert!(map.insert(O("abc".to_string()), a).is_some());
|
||||
assert!(map.insert(B("bcd"), b).is_some());
|
||||
assert!(map.insert(O("cde".to_string()), c).is_some());
|
||||
assert!(map.insert(B("def"), d).is_some());
|
||||
|
||||
assert_eq!(map.get("abc"), Some(&a));
|
||||
assert_eq!(map.get("bcd"), Some(&b));
|
||||
assert_eq!(map.get("cde"), Some(&c));
|
||||
assert_eq!(map.get("def"), Some(&d));
|
||||
|
||||
assert_eq!(map.get(&"abc".into_cow()), Some(&a));
|
||||
assert_eq!(map.get(&"bcd".into_cow()), Some(&b));
|
||||
assert_eq!(map.get(&"cde".into_cow()), Some(&c));
|
||||
assert_eq!(map.get(&"def".into_cow()), Some(&d));
|
||||
assert_eq!(map.get(&B("abc")), Some(&a));
|
||||
assert_eq!(map.get(&B("bcd")), Some(&b));
|
||||
assert_eq!(map.get(&B("cde")), Some(&c));
|
||||
assert_eq!(map.get(&B("def")), Some(&d));
|
||||
}
|
||||
|
@ -8,61 +8,58 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
use std::borrow::Cow;
|
||||
|
||||
#![feature(collections, into_cow)]
|
||||
|
||||
extern crate collections;
|
||||
|
||||
use self::collections::BTreeMap;
|
||||
use std::borrow::{Cow, IntoCow};
|
||||
use std::borrow::Cow::{Owned as O, Borrowed as B};
|
||||
|
||||
type SendStr = Cow<'static, str>;
|
||||
|
||||
pub fn main() {
|
||||
fn main() {
|
||||
let mut map: BTreeMap<SendStr, usize> = BTreeMap::new();
|
||||
assert!(map.insert("foo".into_cow(), 42).is_none());
|
||||
assert!(map.insert("foo".to_string().into_cow(), 42).is_some());
|
||||
assert!(map.insert("foo".into_cow(), 42).is_some());
|
||||
assert!(map.insert("foo".to_string().into_cow(), 42).is_some());
|
||||
assert!(map.insert(B("foo"), 42).is_none());
|
||||
assert!(map.insert(O("foo".to_string()), 42).is_some());
|
||||
assert!(map.insert(B("foo"), 42).is_some());
|
||||
assert!(map.insert(O("foo".to_string()), 42).is_some());
|
||||
|
||||
assert!(map.insert("foo".into_cow(), 43).is_some());
|
||||
assert!(map.insert("foo".to_string().into_cow(), 44).is_some());
|
||||
assert!(map.insert("foo".into_cow(), 45).is_some());
|
||||
assert!(map.insert("foo".to_string().into_cow(), 46).is_some());
|
||||
assert!(map.insert(B("foo"), 43).is_some());
|
||||
assert!(map.insert(O("foo".to_string()), 44).is_some());
|
||||
assert!(map.insert(B("foo"), 45).is_some());
|
||||
assert!(map.insert(O("foo".to_string()), 46).is_some());
|
||||
|
||||
let v = 46;
|
||||
|
||||
assert_eq!(map.get(&"foo".to_string().into_cow()), Some(&v));
|
||||
assert_eq!(map.get(&"foo".into_cow()), Some(&v));
|
||||
assert_eq!(map.get(&O("foo".to_string())), Some(&v));
|
||||
assert_eq!(map.get(&B("foo")), Some(&v));
|
||||
|
||||
let (a, b, c, d) = (50, 51, 52, 53);
|
||||
|
||||
assert!(map.insert("abc".into_cow(), a).is_none());
|
||||
assert!(map.insert("bcd".to_string().into_cow(), b).is_none());
|
||||
assert!(map.insert("cde".into_cow(), c).is_none());
|
||||
assert!(map.insert("def".to_string().into_cow(), d).is_none());
|
||||
assert!(map.insert(B("abc"), a).is_none());
|
||||
assert!(map.insert(O("bcd".to_string()), b).is_none());
|
||||
assert!(map.insert(B("cde"), c).is_none());
|
||||
assert!(map.insert(O("def".to_string()), d).is_none());
|
||||
|
||||
assert!(map.insert("abc".into_cow(), a).is_some());
|
||||
assert!(map.insert("bcd".to_string().into_cow(), b).is_some());
|
||||
assert!(map.insert("cde".into_cow(), c).is_some());
|
||||
assert!(map.insert("def".to_string().into_cow(), d).is_some());
|
||||
assert!(map.insert(B("abc"), a).is_some());
|
||||
assert!(map.insert(O("bcd".to_string()), b).is_some());
|
||||
assert!(map.insert(B("cde"), c).is_some());
|
||||
assert!(map.insert(O("def".to_string()), d).is_some());
|
||||
|
||||
assert!(map.insert("abc".to_string().into_cow(), a).is_some());
|
||||
assert!(map.insert("bcd".into_cow(), b).is_some());
|
||||
assert!(map.insert("cde".to_string().into_cow(), c).is_some());
|
||||
assert!(map.insert("def".into_cow(), d).is_some());
|
||||
assert!(map.insert(O("abc".to_string()), a).is_some());
|
||||
assert!(map.insert(B("bcd"), b).is_some());
|
||||
assert!(map.insert(O("cde".to_string()), c).is_some());
|
||||
assert!(map.insert(B("def"), d).is_some());
|
||||
|
||||
assert_eq!(map.get(&"abc".into_cow()), Some(&a));
|
||||
assert_eq!(map.get(&"bcd".into_cow()), Some(&b));
|
||||
assert_eq!(map.get(&"cde".into_cow()), Some(&c));
|
||||
assert_eq!(map.get(&"def".into_cow()), Some(&d));
|
||||
assert_eq!(map.get(&B("abc")), Some(&a));
|
||||
assert_eq!(map.get(&B("bcd")), Some(&b));
|
||||
assert_eq!(map.get(&B("cde")), Some(&c));
|
||||
assert_eq!(map.get(&B("def")), Some(&d));
|
||||
|
||||
assert_eq!(map.get(&"abc".to_string().into_cow()), Some(&a));
|
||||
assert_eq!(map.get(&"bcd".to_string().into_cow()), Some(&b));
|
||||
assert_eq!(map.get(&"cde".to_string().into_cow()), Some(&c));
|
||||
assert_eq!(map.get(&"def".to_string().into_cow()), Some(&d));
|
||||
assert_eq!(map.get(&O("abc".to_string())), Some(&a));
|
||||
assert_eq!(map.get(&O("bcd".to_string())), Some(&b));
|
||||
assert_eq!(map.get(&O("cde".to_string())), Some(&c));
|
||||
assert_eq!(map.get(&O("def".to_string())), Some(&d));
|
||||
|
||||
assert!(map.remove(&"foo".into_cow()).is_some());
|
||||
assert!(map.remove(&B("foo")).is_some());
|
||||
assert_eq!(map.into_iter().map(|(k, v)| format!("{}{}", k, v))
|
||||
.collect::<Vec<String>>()
|
||||
.concat(),
|
||||
|
@ -24,7 +24,6 @@ fn main() {
|
||||
assert_both::<sync::Mutex<()>>();
|
||||
assert_both::<sync::Condvar>();
|
||||
assert_both::<sync::RwLock<()>>();
|
||||
assert_both::<sync::Semaphore>();
|
||||
assert_both::<sync::Barrier>();
|
||||
assert_both::<sync::Arc<()>>();
|
||||
assert_both::<sync::Weak<()>>();
|
||||
|
@ -8,9 +8,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(into_cow)]
|
||||
|
||||
use std::borrow::{Cow, IntoCow};
|
||||
use std::borrow::{Cow, ToOwned};
|
||||
use std::default::Default;
|
||||
use std::iter::FromIterator;
|
||||
use std::ops::Add;
|
||||
@ -25,6 +23,16 @@ pub trait Rand: Default + Sized {
|
||||
}
|
||||
impl Rand for i32 { }
|
||||
|
||||
pub trait IntoCow<'a, B: ?Sized> where B: ToOwned {
|
||||
fn into_cow(self) -> Cow<'a, B>;
|
||||
}
|
||||
|
||||
impl<'a> IntoCow<'a, str> for String {
|
||||
fn into_cow(self) -> Cow<'a, str> {
|
||||
Cow::Owned(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
struct Newt<T>(T);
|
||||
|
||||
|
@ -8,15 +8,13 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(vec_push_all)]
|
||||
|
||||
use std::vec;
|
||||
|
||||
pub fn main() {
|
||||
let a: Vec<isize> = vec!(1, 2, 3, 4, 5);
|
||||
let b: Vec<isize> = vec!(6, 7, 8, 9, 0);
|
||||
let mut v: Vec<isize> = a;
|
||||
v.push_all(&b);
|
||||
v.extend_from_slice(&b);
|
||||
println!("{}", v[9]);
|
||||
assert_eq!(v[0], 1);
|
||||
assert_eq!(v[7], 8);
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
// ignore-emscripten no threads support
|
||||
|
||||
#![feature(rand, num_bits_bytes)]
|
||||
#![feature(rand)]
|
||||
#![feature(const_fn)]
|
||||
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
@ -47,7 +47,6 @@ impl Drop for DropCounter {
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
assert!(MAX_LEN <= std::usize::BITS);
|
||||
// len can't go above 64.
|
||||
for len in 2..MAX_LEN {
|
||||
for _ in 0..REPEATS {
|
||||
|
Loading…
x
Reference in New Issue
Block a user