Browse Source

Merge pull request #73 from FenrirWolf/update-2018-08-18

Update for nightly-2018-08-18
pull/10/head
FenrirWolf 6 years ago committed by GitHub
parent
commit
15cb3c1e91
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 7
      .travis.yml
  2. 121
      ctr-std/src/alloc.rs
  3. 290
      ctr-std/src/ascii.rs
  4. 11
      ctr-std/src/build.rs
  5. 38
      ctr-std/src/collections/hash/map.rs
  6. 24
      ctr-std/src/collections/hash/set.rs
  7. 7
      ctr-std/src/collections/hash/table.rs
  8. 10
      ctr-std/src/collections/mod.rs
  9. 25
      ctr-std/src/env.rs
  10. 93
      ctr-std/src/error.rs
  11. 11
      ctr-std/src/f32.rs
  12. 11
      ctr-std/src/f64.rs
  13. 43
      ctr-std/src/ffi/c_str.rs
  14. 48
      ctr-std/src/ffi/os_str.rs
  15. 6
      ctr-std/src/fs.rs
  16. 116
      ctr-std/src/future.rs
  17. 85
      ctr-std/src/io/buffered.rs
  18. 57
      ctr-std/src/io/cursor.rs
  19. 25
      ctr-std/src/io/error.rs
  20. 30
      ctr-std/src/io/lazy.rs
  21. 171
      ctr-std/src/io/mod.rs
  22. 40
      ctr-std/src/io/stdio.rs
  23. 2
      ctr-std/src/io/util.rs
  24. 58
      ctr-std/src/keyword_docs.rs
  25. 76
      ctr-std/src/lib.rs
  26. 80
      ctr-std/src/macros.rs
  27. 218
      ctr-std/src/net/ip.rs
  28. 7
      ctr-std/src/net/parser.rs
  29. 4
      ctr-std/src/net/tcp.rs
  30. 2
      ctr-std/src/net/udp.rs
  31. 389
      ctr-std/src/os/hermit/fs.rs
  32. 16
      ctr-std/src/os/hermit/mod.rs
  33. 27
      ctr-std/src/os/hermit/raw.rs
  34. 1
      ctr-std/src/os/mod.rs
  35. 6
      ctr-std/src/os/raw/mod.rs
  36. 30
      ctr-std/src/panic.rs
  37. 132
      ctr-std/src/panicking.rs
  38. 31
      ctr-std/src/path.rs
  39. 58
      ctr-std/src/prelude/v1.rs
  40. 37
      ctr-std/src/process.rs
  41. 2
      ctr-std/src/rt.rs
  42. 2
      ctr-std/src/sync/mod.rs
  43. 40
      ctr-std/src/sync/mpsc/mod.rs
  44. 2
      ctr-std/src/sync/mpsc/select.rs
  45. 4
      ctr-std/src/sync/mutex.rs
  46. 40
      ctr-std/src/sync/once.rs
  47. 18
      ctr-std/src/sys/cloudabi/abi/cloudabi.rs
  48. 18
      ctr-std/src/sys/cloudabi/backtrace.rs
  49. 2
      ctr-std/src/sys/cloudabi/thread.rs
  50. 13
      ctr-std/src/sys/horizon/net.rs
  51. 3
      ctr-std/src/sys/mod.rs
  52. 16
      ctr-std/src/sys/redox/args.rs
  53. 18
      ctr-std/src/sys/redox/backtrace/tracing.rs
  54. 1
      ctr-std/src/sys/redox/ext/mod.rs
  55. 769
      ctr-std/src/sys/redox/ext/net.rs
  56. 5
      ctr-std/src/sys/redox/fd.rs
  57. 4
      ctr-std/src/sys/redox/net/mod.rs
  58. 2
      ctr-std/src/sys/redox/net/netc.rs
  59. 2
      ctr-std/src/sys/redox/net/udp.rs
  60. 3
      ctr-std/src/sys/redox/os.rs
  61. 15
      ctr-std/src/sys/redox/process.rs
  62. 2
      ctr-std/src/sys/redox/thread.rs
  63. 19
      ctr-std/src/sys/unix/args.rs
  64. 18
      ctr-std/src/sys/unix/backtrace/tracing/gcc_s.rs
  65. 13
      ctr-std/src/sys/unix/condvar.rs
  66. 11
      ctr-std/src/sys/unix/env.rs
  67. 127
      ctr-std/src/sys/unix/ext/fs.rs
  68. 1
      ctr-std/src/sys/unix/ext/mod.rs
  69. 6
      ctr-std/src/sys/unix/ext/net.rs
  70. 7
      ctr-std/src/sys/unix/fast_thread_local.rs
  71. 56
      ctr-std/src/sys/unix/fs.rs
  72. 1
      ctr-std/src/sys/unix/mod.rs
  73. 9
      ctr-std/src/sys/unix/mutex.rs
  74. 39
      ctr-std/src/sys/unix/os.rs
  75. 6
      ctr-std/src/sys/unix/process/process_common.rs
  76. 29
      ctr-std/src/sys/unix/rand.rs
  77. 5
      ctr-std/src/sys/unix/thread.rs
  78. 4
      ctr-std/src/sys/unix/time.rs
  79. 2
      ctr-std/src/sys/wasm/os.rs
  80. 2
      ctr-std/src/sys/wasm/thread.rs
  81. 297
      ctr-std/src/sys/windows/backtrace/mod.rs
  82. 14
      ctr-std/src/sys/windows/backtrace/printing/mod.rs
  83. 196
      ctr-std/src/sys/windows/backtrace/printing/msvc.rs
  84. 82
      ctr-std/src/sys/windows/c.rs
  85. 3
      ctr-std/src/sys/windows/ext/ffi.rs
  86. 1
      ctr-std/src/sys/windows/ext/mod.rs
  87. 10
      ctr-std/src/sys/windows/mod.rs
  88. 8
      ctr-std/src/sys/windows/process.rs
  89. 5
      ctr-std/src/sys/windows/thread.rs
  90. 36
      ctr-std/src/sys_common/at_exit_imp.rs
  91. 21
      ctr-std/src/sys_common/backtrace.rs
  92. 32
      ctr-std/src/sys_common/mutex.rs
  93. 2
      ctr-std/src/sys_common/poison.rs
  94. 4
      ctr-std/src/sys_common/remutex.rs
  95. 2
      ctr-std/src/sys_common/thread.rs
  96. 5
      ctr-std/src/sys_common/thread_local.rs
  97. 14
      ctr-std/src/sys_common/wtf8.rs
  98. 3
      ctr-std/src/tests/env.rs
  99. 2
      ctr-std/src/thread/local.rs
  100. 37
      ctr-std/src/thread/mod.rs
  101. Some files were not shown because too many files have changed in this diff Show More

7
.travis.yml

@ -1,12 +1,7 @@ @@ -1,12 +1,7 @@
language: rust
rust:
- nightly-2018-06-09
- nightly
matrix:
allow_failures:
- rust: nightly
- nightly-2018-08-18
install:
- set -eo pipefail

121
ctr-std/src/alloc.rs

@ -8,61 +8,129 @@ @@ -8,61 +8,129 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! dox
//! Memory allocation APIs
//!
//! In a given program, the standard library has one “global” memory allocator
//! that is used for example by `Box<T>` and `Vec<T>`.
//!
//! Currently the default global allocator is unspecified.
//! The compiler may link to a version of [jemalloc] on some platforms,
//! but this is not guaranteed.
//! Libraries, however, like `cdylib`s and `staticlib`s are guaranteed
//! to use the [`System`] by default.
//!
//! [jemalloc]: https://github.com/jemalloc/jemalloc
//! [`System`]: struct.System.html
//!
//! # The `#[global_allocator]` attribute
//!
//! This attribute allows configuring the choice of global allocator.
//! You can use this to implement a completely custom global allocator
//! to route all default allocation requests to a custom object.
//!
//! ```rust
//! use std::alloc::{GlobalAlloc, System, Layout};
//!
//! struct MyAllocator;
//!
//! unsafe impl GlobalAlloc for MyAllocator {
//! unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
//! System.alloc(layout)
//! }
//!
//! unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
//! System.dealloc(ptr, layout)
//! }
//! }
//!
//! #[global_allocator]
//! static GLOBAL: MyAllocator = MyAllocator;
//!
//! fn main() {
//! // This `Vec` will allocate memory through `GLOBAL` above
//! let mut v = Vec::new();
//! v.push(1);
//! }
//! ```
//!
//! The attribute is used on a `static` item whose type implements the
//! [`GlobalAlloc`] trait. This type can be provided by an external library:
//!
//! [`GlobalAlloc`]: ../../core/alloc/trait.GlobalAlloc.html
//!
//! ```rust,ignore (demonstrates crates.io usage)
//! extern crate jemallocator;
//!
//! use jemallocator::Jemalloc;
//!
//! #[global_allocator]
//! static GLOBAL: Jemalloc = Jemalloc;
//!
//! fn main() {}
//! ```
//!
//! The `#[global_allocator]` can only be used once in a crate
//! or its recursive dependencies.
#![unstable(issue = "32838", feature = "allocator_api")]
#[doc(inline)] #[allow(deprecated)] pub use alloc_crate::alloc::Heap;
#[doc(inline)] pub use alloc_crate::alloc::{Global, Layout, oom};
#[doc(inline)] pub use alloc_system::System;
#[doc(inline)] pub use core::alloc::*;
#![stable(feature = "alloc_module", since = "1.28.0")]
use core::sync::atomic::{AtomicPtr, Ordering};
use core::{mem, ptr};
use sys_common::util::dumb_print;
#[stable(feature = "alloc_module", since = "1.28.0")]
#[doc(inline)]
pub use alloc_crate::alloc::*;
#[stable(feature = "alloc_system_type", since = "1.28.0")]
#[doc(inline)]
pub use alloc_system::System;
static HOOK: AtomicPtr<()> = AtomicPtr::new(ptr::null_mut());
/// Registers a custom OOM hook, replacing any that was previously registered.
/// Registers a custom allocation error hook, replacing any that was previously registered.
///
/// The OOM hook is invoked when an infallible memory allocation fails, before
/// The allocation error hook is invoked when an infallible memory allocation fails, before
/// the runtime aborts. The default hook prints a message to standard error,
/// but this behavior can be customized with the [`set_oom_hook`] and
/// [`take_oom_hook`] functions.
/// but this behavior can be customized with the [`set_alloc_error_hook`] and
/// [`take_alloc_error_hook`] functions.
///
/// The hook is provided with a `Layout` struct which contains information
/// about the allocation that failed.
///
/// The OOM hook is a global resource.
pub fn set_oom_hook(hook: fn(Layout)) {
/// The allocation error hook is a global resource.
#[unstable(feature = "alloc_error_hook", issue = "51245")]
pub fn set_alloc_error_hook(hook: fn(Layout)) {
HOOK.store(hook as *mut (), Ordering::SeqCst);
}
/// Unregisters the current OOM hook, returning it.
/// Unregisters the current allocation error hook, returning it.
///
/// *See also the function [`set_oom_hook`].*
/// *See also the function [`set_alloc_error_hook`].*
///
/// If no custom hook is registered, the default hook will be returned.
pub fn take_oom_hook() -> fn(Layout) {
#[unstable(feature = "alloc_error_hook", issue = "51245")]
pub fn take_alloc_error_hook() -> fn(Layout) {
let hook = HOOK.swap(ptr::null_mut(), Ordering::SeqCst);
if hook.is_null() {
default_oom_hook
default_alloc_error_hook
} else {
unsafe { mem::transmute(hook) }
}
}
fn default_oom_hook(layout: Layout) {
fn default_alloc_error_hook(layout: Layout) {
dumb_print(format_args!("memory allocation of {} bytes failed", layout.size()));
}
#[cfg(not(test))]
#[doc(hidden)]
#[lang = "oom"]
pub extern fn rust_oom(layout: Layout) -> ! {
#[alloc_error_handler]
#[unstable(feature = "alloc_internals", issue = "0")]
pub fn rust_oom(layout: Layout) -> ! {
let hook = HOOK.load(Ordering::SeqCst);
let hook: fn(Layout) = if hook.is_null() {
default_oom_hook
default_alloc_error_hook
} else {
unsafe { mem::transmute(hook) }
};
@ -73,8 +141,9 @@ pub extern fn rust_oom(layout: Layout) -> ! { @@ -73,8 +141,9 @@ pub extern fn rust_oom(layout: Layout) -> ! {
#[cfg(not(test))]
#[doc(hidden)]
#[allow(unused_attributes)]
#[unstable(feature = "alloc_internals", issue = "0")]
pub mod __default_lib_allocator {
use super::{System, Layout, GlobalAlloc, Opaque};
use super::{System, Layout, GlobalAlloc};
// for symbol names src/librustc/middle/allocator.rs
// for signatures src/librustc_allocator/lib.rs
@ -85,7 +154,7 @@ pub mod __default_lib_allocator { @@ -85,7 +154,7 @@ pub mod __default_lib_allocator {
#[rustc_std_internal_symbol]
pub unsafe extern fn __rdl_alloc(size: usize, align: usize) -> *mut u8 {
let layout = Layout::from_size_align_unchecked(size, align);
System.alloc(layout) as *mut u8
System.alloc(layout)
}
#[no_mangle]
@ -93,7 +162,7 @@ pub mod __default_lib_allocator { @@ -93,7 +162,7 @@ pub mod __default_lib_allocator {
pub unsafe extern fn __rdl_dealloc(ptr: *mut u8,
size: usize,
align: usize) {
System.dealloc(ptr as *mut Opaque, Layout::from_size_align_unchecked(size, align))
System.dealloc(ptr, Layout::from_size_align_unchecked(size, align))
}
#[no_mangle]
@ -103,13 +172,13 @@ pub mod __default_lib_allocator { @@ -103,13 +172,13 @@ pub mod __default_lib_allocator {
align: usize,
new_size: usize) -> *mut u8 {
let old_layout = Layout::from_size_align_unchecked(old_size, align);
System.realloc(ptr as *mut Opaque, old_layout, new_size) as *mut u8
System.realloc(ptr, old_layout, new_size)
}
#[no_mangle]
#[rustc_std_internal_symbol]
pub unsafe extern fn __rdl_alloc_zeroed(size: usize, align: usize) -> *mut u8 {
let layout = Layout::from_size_align_unchecked(size, align);
System.alloc_zeroed(layout) as *mut u8
System.alloc_zeroed(layout)
}
}

290
ctr-std/src/ascii.rs

@ -154,160 +154,6 @@ pub trait AsciiExt { @@ -154,160 +154,6 @@ pub trait AsciiExt {
/// [`to_ascii_lowercase`]: #tymethod.to_ascii_lowercase
#[stable(feature = "ascii", since = "1.9.0")]
fn make_ascii_lowercase(&mut self);
/// Checks if the value is an ASCII alphabetic character:
/// U+0041 'A' ... U+005A 'Z' or U+0061 'a' ... U+007A 'z'.
/// For strings, true if all characters in the string are
/// ASCII alphabetic.
///
/// # Note
///
/// This method will be deprecated in favor of the identically-named
/// inherent methods on `u8`, `char`, `[u8]` and `str`.
#[unstable(feature = "ascii_ctype", issue = "39658")]
#[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
fn is_ascii_alphabetic(&self) -> bool { unimplemented!(); }
/// Checks if the value is an ASCII uppercase character:
/// U+0041 'A' ... U+005A 'Z'.
/// For strings, true if all characters in the string are
/// ASCII uppercase.
///
/// # Note
///
/// This method will be deprecated in favor of the identically-named
/// inherent methods on `u8`, `char`, `[u8]` and `str`.
#[unstable(feature = "ascii_ctype", issue = "39658")]
#[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
fn is_ascii_uppercase(&self) -> bool { unimplemented!(); }
/// Checks if the value is an ASCII lowercase character:
/// U+0061 'a' ... U+007A 'z'.
/// For strings, true if all characters in the string are
/// ASCII lowercase.
///
/// # Note
///
/// This method will be deprecated in favor of the identically-named
/// inherent methods on `u8`, `char`, `[u8]` and `str`.
#[unstable(feature = "ascii_ctype", issue = "39658")]
#[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
fn is_ascii_lowercase(&self) -> bool { unimplemented!(); }
/// Checks if the value is an ASCII alphanumeric character:
/// U+0041 'A' ... U+005A 'Z', U+0061 'a' ... U+007A 'z', or
/// U+0030 '0' ... U+0039 '9'.
/// For strings, true if all characters in the string are
/// ASCII alphanumeric.
///
/// # Note
///
/// This method will be deprecated in favor of the identically-named
/// inherent methods on `u8`, `char`, `[u8]` and `str`.
#[unstable(feature = "ascii_ctype", issue = "39658")]
#[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
fn is_ascii_alphanumeric(&self) -> bool { unimplemented!(); }
/// Checks if the value is an ASCII decimal digit:
/// U+0030 '0' ... U+0039 '9'.
/// For strings, true if all characters in the string are
/// ASCII digits.
///
/// # Note
///
/// This method will be deprecated in favor of the identically-named
/// inherent methods on `u8`, `char`, `[u8]` and `str`.
#[unstable(feature = "ascii_ctype", issue = "39658")]
#[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
fn is_ascii_digit(&self) -> bool { unimplemented!(); }
/// Checks if the value is an ASCII hexadecimal digit:
/// U+0030 '0' ... U+0039 '9', U+0041 'A' ... U+0046 'F', or
/// U+0061 'a' ... U+0066 'f'.
/// For strings, true if all characters in the string are
/// ASCII hex digits.
///
/// # Note
///
/// This method will be deprecated in favor of the identically-named
/// inherent methods on `u8`, `char`, `[u8]` and `str`.
#[unstable(feature = "ascii_ctype", issue = "39658")]
#[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
fn is_ascii_hexdigit(&self) -> bool { unimplemented!(); }
/// Checks if the value is an ASCII punctuation character:
///
/// U+0021 ... U+002F `! " # $ % & ' ( ) * + , - . /`
/// U+003A ... U+0040 `: ; < = > ? @`
/// U+005B ... U+0060 ``[ \\ ] ^ _ ` ``
/// U+007B ... U+007E `{ | } ~`
///
/// For strings, true if all characters in the string are
/// ASCII punctuation.
///
/// # Note
///
/// This method will be deprecated in favor of the identically-named
/// inherent methods on `u8`, `char`, `[u8]` and `str`.
#[unstable(feature = "ascii_ctype", issue = "39658")]
#[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
fn is_ascii_punctuation(&self) -> bool { unimplemented!(); }
/// Checks if the value is an ASCII graphic character:
/// U+0021 '!' ... U+007E '~'.
/// For strings, true if all characters in the string are
/// ASCII graphic characters.
///
/// # Note
///
/// This method will be deprecated in favor of the identically-named
/// inherent methods on `u8`, `char`, `[u8]` and `str`.
#[unstable(feature = "ascii_ctype", issue = "39658")]
#[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
fn is_ascii_graphic(&self) -> bool { unimplemented!(); }
/// Checks if the value is an ASCII whitespace character:
/// U+0020 SPACE, U+0009 HORIZONTAL TAB, U+000A LINE FEED,
/// U+000C FORM FEED, or U+000D CARRIAGE RETURN.
/// For strings, true if all characters in the string are
/// ASCII whitespace.
///
/// Rust uses the WhatWG Infra Standard's [definition of ASCII
/// whitespace][infra-aw]. There are several other definitions in
/// wide use. For instance, [the POSIX locale][pct] includes
/// U+000B VERTICAL TAB as well as all the above characters,
/// but—from the very same specification—[the default rule for
/// "field splitting" in the Bourne shell][bfs] considers *only*
/// SPACE, HORIZONTAL TAB, and LINE FEED as whitespace.
///
/// If you are writing a program that will process an existing
/// file format, check what that format's definition of whitespace is
/// before using this function.
///
/// [infra-aw]: https://infra.spec.whatwg.org/#ascii-whitespace
/// [pct]: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap07.html#tag_07_03_01
/// [bfs]: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_05
///
/// # Note
///
/// This method will be deprecated in favor of the identically-named
/// inherent methods on `u8`, `char`, `[u8]` and `str`.
#[unstable(feature = "ascii_ctype", issue = "39658")]
#[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
fn is_ascii_whitespace(&self) -> bool { unimplemented!(); }
/// Checks if the value is an ASCII control character:
/// U+0000 NUL ... U+001F UNIT SEPARATOR, or U+007F DELETE.
/// Note that most ASCII whitespace characters are control
/// characters, but SPACE is not.
///
/// # Note
///
/// This method will be deprecated in favor of the identically-named
/// inherent methods on `u8`, `char`, `[u8]` and `str`.
#[unstable(feature = "ascii_ctype", issue = "39658")]
#[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
fn is_ascii_control(&self) -> bool { unimplemented!(); }
}
macro_rules! delegating_ascii_methods {
@ -332,47 +178,12 @@ macro_rules! delegating_ascii_methods { @@ -332,47 +178,12 @@ macro_rules! delegating_ascii_methods {
}
}
macro_rules! delegating_ascii_ctype_methods {
() => {
#[inline]
fn is_ascii_alphabetic(&self) -> bool { self.is_ascii_alphabetic() }
#[inline]
fn is_ascii_uppercase(&self) -> bool { self.is_ascii_uppercase() }
#[inline]
fn is_ascii_lowercase(&self) -> bool { self.is_ascii_lowercase() }
#[inline]
fn is_ascii_alphanumeric(&self) -> bool { self.is_ascii_alphanumeric() }
#[inline]
fn is_ascii_digit(&self) -> bool { self.is_ascii_digit() }
#[inline]
fn is_ascii_hexdigit(&self) -> bool { self.is_ascii_hexdigit() }
#[inline]
fn is_ascii_punctuation(&self) -> bool { self.is_ascii_punctuation() }
#[inline]
fn is_ascii_graphic(&self) -> bool { self.is_ascii_graphic() }
#[inline]
fn is_ascii_whitespace(&self) -> bool { self.is_ascii_whitespace() }
#[inline]
fn is_ascii_control(&self) -> bool { self.is_ascii_control() }
}
}
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(deprecated)]
impl AsciiExt for u8 {
type Owned = u8;
delegating_ascii_methods!();
delegating_ascii_ctype_methods!();
}
#[stable(feature = "rust1", since = "1.0.0")]
@ -381,7 +192,6 @@ impl AsciiExt for char { @@ -381,7 +192,6 @@ impl AsciiExt for char {
type Owned = char;
delegating_ascii_methods!();
delegating_ascii_ctype_methods!();
}
#[stable(feature = "rust1", since = "1.0.0")]
@ -390,56 +200,6 @@ impl AsciiExt for [u8] { @@ -390,56 +200,6 @@ impl AsciiExt for [u8] {
type Owned = Vec<u8>;
delegating_ascii_methods!();
#[inline]
fn is_ascii_alphabetic(&self) -> bool {
self.iter().all(|b| b.is_ascii_alphabetic())
}
#[inline]
fn is_ascii_uppercase(&self) -> bool {
self.iter().all(|b| b.is_ascii_uppercase())
}
#[inline]
fn is_ascii_lowercase(&self) -> bool {
self.iter().all(|b| b.is_ascii_lowercase())
}
#[inline]
fn is_ascii_alphanumeric(&self) -> bool {
self.iter().all(|b| b.is_ascii_alphanumeric())
}
#[inline]
fn is_ascii_digit(&self) -> bool {
self.iter().all(|b| b.is_ascii_digit())
}
#[inline]
fn is_ascii_hexdigit(&self) -> bool {
self.iter().all(|b| b.is_ascii_hexdigit())
}
#[inline]
fn is_ascii_punctuation(&self) -> bool {
self.iter().all(|b| b.is_ascii_punctuation())
}
#[inline]
fn is_ascii_graphic(&self) -> bool {
self.iter().all(|b| b.is_ascii_graphic())
}
#[inline]
fn is_ascii_whitespace(&self) -> bool {
self.iter().all(|b| b.is_ascii_whitespace())
}
#[inline]
fn is_ascii_control(&self) -> bool {
self.iter().all(|b| b.is_ascii_control())
}
}
#[stable(feature = "rust1", since = "1.0.0")]
@ -448,54 +208,4 @@ impl AsciiExt for str { @@ -448,54 +208,4 @@ impl AsciiExt for str {
type Owned = String;
delegating_ascii_methods!();
#[inline]
fn is_ascii_alphabetic(&self) -> bool {
self.bytes().all(|b| b.is_ascii_alphabetic())
}
#[inline]
fn is_ascii_uppercase(&self) -> bool {
self.bytes().all(|b| b.is_ascii_uppercase())
}
#[inline]
fn is_ascii_lowercase(&self) -> bool {
self.bytes().all(|b| b.is_ascii_lowercase())
}
#[inline]
fn is_ascii_alphanumeric(&self) -> bool {
self.bytes().all(|b| b.is_ascii_alphanumeric())
}
#[inline]
fn is_ascii_digit(&self) -> bool {
self.bytes().all(|b| b.is_ascii_digit())
}
#[inline]
fn is_ascii_hexdigit(&self) -> bool {
self.bytes().all(|b| b.is_ascii_hexdigit())
}
#[inline]
fn is_ascii_punctuation(&self) -> bool {
self.bytes().all(|b| b.is_ascii_punctuation())
}
#[inline]
fn is_ascii_graphic(&self) -> bool {
self.bytes().all(|b| b.is_ascii_graphic())
}
#[inline]
fn is_ascii_whitespace(&self) -> bool {
self.bytes().all(|b| b.is_ascii_whitespace())
}
#[inline]
fn is_ascii_control(&self) -> bool {
self.bytes().all(|b| b.is_ascii_control())
}
}

11
ctr-std/src/build.rs

@ -22,7 +22,6 @@ fn main() { @@ -22,7 +22,6 @@ fn main() {
if cfg!(feature = "backtrace") &&
!target.contains("cloudabi") &&
!target.contains("emscripten") &&
!target.contains("fuchsia") &&
!target.contains("msvc") &&
!target.contains("wasm32")
{
@ -68,10 +67,6 @@ fn main() { @@ -68,10 +67,6 @@ fn main() {
println!("cargo:rustc-link-lib=userenv");
println!("cargo:rustc-link-lib=shell32");
} else if target.contains("fuchsia") {
// use system-provided libbacktrace
if cfg!(feature = "backtrace") {
println!("cargo:rustc-link-lib=backtrace");
}
println!("cargo:rustc-link-lib=zircon");
println!("cargo:rustc-link-lib=fdio");
} else if target.contains("cloudabi") {
@ -109,7 +104,8 @@ fn build_libbacktrace(target: &str) -> Result<(), ()> { @@ -109,7 +104,8 @@ fn build_libbacktrace(target: &str) -> Result<(), ()> {
} else {
build.file("../libbacktrace/elf.c");
if target.contains("64") {
let pointer_width = env::var("CARGO_CFG_TARGET_POINTER_WIDTH").unwrap();
if pointer_width == "64" {
build.define("BACKTRACE_ELF_SIZE", "64");
} else {
build.define("BACKTRACE_ELF_SIZE", "32");
@ -126,7 +122,8 @@ fn build_libbacktrace(target: &str) -> Result<(), ()> { @@ -126,7 +122,8 @@ fn build_libbacktrace(target: &str) -> Result<(), ()> {
if !target.contains("apple-ios") &&
!target.contains("solaris") &&
!target.contains("redox") &&
!target.contains("android") {
!target.contains("android") &&
!target.contains("haiku") {
build.define("HAVE_DL_ITERATE_PHDR", "1");
}
build.define("_GNU_SOURCE", "1");

38
ctr-std/src/collections/hash/map.rs

@ -11,7 +11,7 @@ @@ -11,7 +11,7 @@
use self::Entry::*;
use self::VacantEntryState::*;
use alloc::CollectionAllocErr;
use collections::CollectionAllocErr;
use cell::Cell;
use borrow::Borrow;
use cmp::max;
@ -276,17 +276,31 @@ const DISPLACEMENT_THRESHOLD: usize = 128; @@ -276,17 +276,31 @@ const DISPLACEMENT_THRESHOLD: usize = 128;
/// ```
/// use std::collections::HashMap;
///
/// // type inference lets us omit an explicit type signature (which
/// // would be `HashMap<&str, &str>` in this example).
/// // Type inference lets us omit an explicit type signature (which
/// // would be `HashMap<String, String>` in this example).
/// let mut book_reviews = HashMap::new();
///
/// // review some books.
/// book_reviews.insert("Adventures of Huckleberry Finn", "My favorite book.");
/// book_reviews.insert("Grimms' Fairy Tales", "Masterpiece.");
/// book_reviews.insert("Pride and Prejudice", "Very enjoyable.");
/// book_reviews.insert("The Adventures of Sherlock Holmes", "Eye lyked it alot.");
/// // Review some books.
/// book_reviews.insert(
/// "Adventures of Huckleberry Finn".to_string(),
/// "My favorite book.".to_string(),
/// );
/// book_reviews.insert(
/// "Grimms' Fairy Tales".to_string(),
/// "Masterpiece.".to_string(),
/// );
/// book_reviews.insert(
/// "Pride and Prejudice".to_string(),
/// "Very enjoyable.".to_string(),
/// );
/// book_reviews.insert(
/// "The Adventures of Sherlock Holmes".to_string(),
/// "Eye lyked it alot.".to_string(),
/// );
///
/// // check for a specific one.
/// // Check for a specific one.
/// // When collections store owned values (String), they can still be
/// // queried using references (&str).
/// if !book_reviews.contains_key("Les Misérables") {
/// println!("We've got {} reviews, but Les Misérables ain't one.",
/// book_reviews.len());
@ -295,16 +309,16 @@ const DISPLACEMENT_THRESHOLD: usize = 128; @@ -295,16 +309,16 @@ const DISPLACEMENT_THRESHOLD: usize = 128;
/// // oops, this review has a lot of spelling mistakes, let's delete it.
/// book_reviews.remove("The Adventures of Sherlock Holmes");
///
/// // look up the values associated with some keys.
/// // Look up the values associated with some keys.
/// let to_find = ["Pride and Prejudice", "Alice's Adventure in Wonderland"];
/// for book in &to_find {
/// for &book in &to_find {
/// match book_reviews.get(book) {
/// Some(review) => println!("{}: {}", book, review),
/// None => println!("{} is unreviewed.", book)
/// }
/// }
///
/// // iterate over everything.
/// // Iterate over everything.
/// for (book, review) in &book_reviews {
/// println!("{}: \"{}\"", book, review);
/// }

24
ctr-std/src/collections/hash/set.rs

@ -49,14 +49,14 @@ use super::map::{self, HashMap, Keys, RandomState}; @@ -49,14 +49,14 @@ use super::map::{self, HashMap, Keys, RandomState};
/// ```
/// use std::collections::HashSet;
/// // Type inference lets us omit an explicit type signature (which
/// // would be `HashSet<&str>` in this example).
/// // would be `HashSet<String>` in this example).
/// let mut books = HashSet::new();
///
/// // Add some books.
/// books.insert("A Dance With Dragons");
/// books.insert("To Kill a Mockingbird");
/// books.insert("The Odyssey");
/// books.insert("The Great Gatsby");
/// books.insert("A Dance With Dragons".to_string());
/// books.insert("To Kill a Mockingbird".to_string());
/// books.insert("The Odyssey".to_string());
/// books.insert("The Great Gatsby".to_string());
///
/// // Check for a specific one.
/// if !books.contains("The Winds of Winter") {
@ -80,17 +80,17 @@ use super::map::{self, HashMap, Keys, RandomState}; @@ -80,17 +80,17 @@ use super::map::{self, HashMap, Keys, RandomState};
/// ```
/// use std::collections::HashSet;
/// #[derive(Hash, Eq, PartialEq, Debug)]
/// struct Viking<'a> {
/// name: &'a str,
/// struct Viking {
/// name: String,
/// power: usize,
/// }
///
/// let mut vikings = HashSet::new();
///
/// vikings.insert(Viking { name: "Einar", power: 9 });
/// vikings.insert(Viking { name: "Einar", power: 9 });
/// vikings.insert(Viking { name: "Olaf", power: 4 });
/// vikings.insert(Viking { name: "Harald", power: 8 });
/// vikings.insert(Viking { name: "Einar".to_string(), power: 9 });
/// vikings.insert(Viking { name: "Einar".to_string(), power: 9 });
/// vikings.insert(Viking { name: "Olaf".to_string(), power: 4 });
/// vikings.insert(Viking { name: "Harald".to_string(), power: 8 });
///
/// // Use derived implementation to print the vikings.
/// for x in &vikings {
@ -104,7 +104,7 @@ use super::map::{self, HashMap, Keys, RandomState}; @@ -104,7 +104,7 @@ use super::map::{self, HashMap, Keys, RandomState};
/// use std::collections::HashSet;
///
/// fn main() {
/// let viking_names: HashSet<&str> =
/// let viking_names: HashSet<&'static str> =
/// [ "Einar", "Olaf", "Harald" ].iter().cloned().collect();
/// // use the values stored in the set
/// }

7
ctr-std/src/collections/hash/table.rs

@ -8,7 +8,8 @@ @@ -8,7 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use alloc::{Global, Alloc, Layout, LayoutErr, CollectionAllocErr, oom};
use alloc::{Global, Alloc, Layout, LayoutErr, handle_alloc_error};
use collections::CollectionAllocErr;
use hash::{BuildHasher, Hash, Hasher};
use marker;
use mem::{size_of, needs_drop};
@ -699,7 +700,7 @@ impl<K, V> RawTable<K, V> { @@ -699,7 +700,7 @@ impl<K, V> RawTable<K, V> {
// point into it.
let (layout, _) = calculate_layout::<K, V>(capacity)?;
let buffer = Global.alloc(layout).map_err(|e| match fallibility {
Infallible => oom(layout),
Infallible => handle_alloc_error(layout),
Fallible => e,
})?;
@ -1124,7 +1125,7 @@ unsafe impl<#[may_dangle] K, #[may_dangle] V> Drop for RawTable<K, V> { @@ -1124,7 +1125,7 @@ unsafe impl<#[may_dangle] K, #[may_dangle] V> Drop for RawTable<K, V> {
let (layout, _) = calculate_layout::<K, V>(self.capacity())
.unwrap_or_else(|_| unsafe { hint::unreachable_unchecked() });
unsafe {
Global.dealloc(NonNull::new_unchecked(self.hashes.ptr()).as_opaque(), layout);
Global.dealloc(NonNull::new_unchecked(self.hashes.ptr()).cast(), layout);
// Remember how everything was allocated out of one buffer
// during initialization? We only need one call to free here.
}

10
ctr-std/src/collections/mod.rs

@ -424,13 +424,13 @@ @@ -424,13 +424,13 @@
#[doc(hidden)]
pub use ops::Bound;
#[stable(feature = "rust1", since = "1.0.0")]
pub use alloc_crate::{BinaryHeap, BTreeMap, BTreeSet};
pub use alloc_crate::collections::{BinaryHeap, BTreeMap, BTreeSet};
#[stable(feature = "rust1", since = "1.0.0")]
pub use alloc_crate::{LinkedList, VecDeque};
pub use alloc_crate::collections::{LinkedList, VecDeque};
#[stable(feature = "rust1", since = "1.0.0")]
pub use alloc_crate::{binary_heap, btree_map, btree_set};
pub use alloc_crate::collections::{binary_heap, btree_map, btree_set};
#[stable(feature = "rust1", since = "1.0.0")]
pub use alloc_crate::{linked_list, vec_deque};
pub use alloc_crate::collections::{linked_list, vec_deque};
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::hash_map::HashMap;
@ -438,7 +438,7 @@ pub use self::hash_map::HashMap; @@ -438,7 +438,7 @@ pub use self::hash_map::HashMap;
pub use self::hash_set::HashSet;
#[unstable(feature = "try_reserve", reason = "new API", issue="48043")]
pub use heap::CollectionAllocErr;
pub use alloc_crate::collections::CollectionAllocErr;
mod hash;

25
ctr-std/src/env.rs

@ -512,18 +512,20 @@ impl Error for JoinPathsError { @@ -512,18 +512,20 @@ impl Error for JoinPathsError {
///
/// # Unix
///
/// Returns the value of the 'HOME' environment variable if it is set
/// and not equal to the empty string. Otherwise, it tries to determine the
/// home directory by invoking the `getpwuid_r` function on the UID of the
/// current user.
/// - Returns the value of the 'HOME' environment variable if it is set
/// (including to an empty string).
/// - Otherwise, it tries to determine the home directory by invoking the `getpwuid_r` function
/// using the UID of the current user. An empty home directory field returned from the
/// `getpwuid_r` function is considered to be a valid value.
/// - Returns `None` if the current user has no entry in the /etc/passwd file.
///
/// # Windows
///
/// Returns the value of the 'HOME' environment variable if it is
/// set and not equal to the empty string. Otherwise, returns the value of the
/// 'USERPROFILE' environment variable if it is set and not equal to the empty
/// string. If both do not exist, [`GetUserProfileDirectory`][msdn] is used to
/// return the appropriate path.
/// - Returns the value of the 'HOME' environment variable if it is set
/// (including to an empty string).
/// - Otherwise, returns the value of the 'USERPROFILE' environment variable if it is set
/// (including to an empty string).
/// - If both do not exist, [`GetUserProfileDirectory`][msdn] is used to return the path.
///
/// [msdn]: https://msdn.microsoft.com/en-us/library/windows/desktop/bb762280(v=vs.85).aspx
///
@ -533,10 +535,13 @@ impl Error for JoinPathsError { @@ -533,10 +535,13 @@ impl Error for JoinPathsError {
/// use std::env;
///
/// match env::home_dir() {
/// Some(path) => println!("{}", path.display()),
/// Some(path) => println!("Your home directory, probably: {}", path.display()),
/// None => println!("Impossible to get your home dir!"),
/// }
/// ```
#[rustc_deprecated(since = "1.29.0",
reason = "This function's behavior is unexpected and probably not what you want. \
Consider using the home_dir function from https://crates.io/crates/dirs instead.")]
#[stable(feature = "env", since = "1.0.0")]
pub fn home_dir() -> Option<PathBuf> {
os_imp::home_dir()

93
ctr-std/src/error.rs

@ -23,13 +23,13 @@ @@ -23,13 +23,13 @@
// coherence challenge (e.g., specialization, neg impls, etc) we can
// reconsider what crate these items belong in.
use alloc::{AllocErr, LayoutErr, CannotReallocInPlace};
use any::TypeId;
use borrow::Cow;
use cell;
use char;
use core::array;
use fmt::{self, Debug, Display};
use heap::{AllocErr, LayoutErr, CannotReallocInPlace};
use mem::transmute;
use num;
use str;
@ -49,6 +49,7 @@ use string; @@ -49,6 +49,7 @@ use string;
///
/// [`Result<T, E>`]: ../result/enum.Result.html
/// [`Display`]: ../fmt/trait.Display.html
/// [`Debug`]: ../fmt/trait.Debug.html
/// [`cause`]: trait.Error.html#method.cause
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Error: Debug + Display {
@ -137,7 +138,7 @@ pub trait Error: Debug + Display { @@ -137,7 +138,7 @@ pub trait Error: Debug + Display {
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn cause(&self) -> Option<&Error> { None }
fn cause(&self) -> Option<&dyn Error> { None }
/// Get the `TypeId` of `self`
#[doc(hidden)]
@ -150,22 +151,22 @@ pub trait Error: Debug + Display { @@ -150,22 +151,22 @@ pub trait Error: Debug + Display {
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, E: Error + 'a> From<E> for Box<Error + 'a> {
fn from(err: E) -> Box<Error + 'a> {
impl<'a, E: Error + 'a> From<E> for Box<dyn Error + 'a> {
fn from(err: E) -> Box<dyn Error + 'a> {
Box::new(err)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, E: Error + Send + Sync + 'a> From<E> for Box<Error + Send + Sync + 'a> {
fn from(err: E) -> Box<Error + Send + Sync + 'a> {
impl<'a, E: Error + Send + Sync + 'a> From<E> for Box<dyn Error + Send + Sync + 'a> {
fn from(err: E) -> Box<dyn Error + Send + Sync + 'a> {
Box::new(err)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl From<String> for Box<Error + Send + Sync> {
fn from(err: String) -> Box<Error + Send + Sync> {
impl From<String> for Box<dyn Error + Send + Sync> {
fn from(err: String) -> Box<dyn Error + Send + Sync> {
#[derive(Debug)]
struct StringError(String);
@ -184,38 +185,38 @@ impl From<String> for Box<Error + Send + Sync> { @@ -184,38 +185,38 @@ impl From<String> for Box<Error + Send + Sync> {
}
#[stable(feature = "string_box_error", since = "1.6.0")]
impl From<String> for Box<Error> {
fn from(str_err: String) -> Box<Error> {
let err1: Box<Error + Send + Sync> = From::from(str_err);
let err2: Box<Error> = err1;
impl From<String> for Box<dyn Error> {
fn from(str_err: String) -> Box<dyn Error> {
let err1: Box<dyn Error + Send + Sync> = From::from(str_err);
let err2: Box<dyn Error> = err1;
err2
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, 'b> From<&'b str> for Box<Error + Send + Sync + 'a> {
fn from(err: &'b str) -> Box<Error + Send + Sync + 'a> {
impl<'a, 'b> From<&'b str> for Box<dyn Error + Send + Sync + 'a> {
fn from(err: &'b str) -> Box<dyn Error + Send + Sync + 'a> {
From::from(String::from(err))
}
}
#[stable(feature = "string_box_error", since = "1.6.0")]
impl<'a> From<&'a str> for Box<Error> {
fn from(err: &'a str) -> Box<Error> {
impl<'a> From<&'a str> for Box<dyn Error> {
fn from(err: &'a str) -> Box<dyn Error> {
From::from(String::from(err))
}
}
#[stable(feature = "cow_box_error", since = "1.22.0")]
impl<'a, 'b> From<Cow<'b, str>> for Box<Error + Send + Sync + 'a> {
fn from(err: Cow<'b, str>) -> Box<Error + Send + Sync + 'a> {
impl<'a, 'b> From<Cow<'b, str>> for Box<dyn Error + Send + Sync + 'a> {
fn from(err: Cow<'b, str>) -> Box<dyn Error + Send + Sync + 'a> {
From::from(String::from(err))
}
}
#[stable(feature = "cow_box_error", since = "1.22.0")]
impl<'a> From<Cow<'a, str>> for Box<Error> {
fn from(err: Cow<'a, str>) -> Box<Error> {
impl<'a> From<Cow<'a, str>> for Box<dyn Error> {
fn from(err: Cow<'a, str>) -> Box<dyn Error> {
From::from(String::from(err))
}
}
@ -326,7 +327,7 @@ impl<T: Error> Error for Box<T> { @@ -326,7 +327,7 @@ impl<T: Error> Error for Box<T> {
Error::description(&**self)
}
fn cause(&self) -> Option<&Error> {
fn cause(&self) -> Option<&dyn Error> {
Error::cause(&**self)
}
}
@ -367,7 +368,7 @@ impl Error for char::ParseCharError { @@ -367,7 +368,7 @@ impl Error for char::ParseCharError {
}
// copied from any.rs
impl Error + 'static {
impl dyn Error + 'static {
/// Returns true if the boxed type is the same as `T`
#[stable(feature = "error_downcast", since = "1.3.0")]
#[inline]
@ -389,7 +390,7 @@ impl Error + 'static { @@ -389,7 +390,7 @@ impl Error + 'static {
pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> {
if self.is::<T>() {
unsafe {
Some(&*(self as *const Error as *const T))
Some(&*(self as *const dyn Error as *const T))
}
} else {
None
@ -403,7 +404,7 @@ impl Error + 'static { @@ -403,7 +404,7 @@ impl Error + 'static {
pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> {
if self.is::<T>() {
unsafe {
Some(&mut *(self as *mut Error as *mut T))
Some(&mut *(self as *mut dyn Error as *mut T))
}
} else {
None
@ -411,60 +412,60 @@ impl Error + 'static { @@ -411,60 +412,60 @@ impl Error + 'static {
}
}
impl Error + 'static + Send {
impl dyn Error + 'static + Send {
/// Forwards to the method defined on the type `Any`.
#[stable(feature = "error_downcast", since = "1.3.0")]
#[inline]
pub fn is<T: Error + 'static>(&self) -> bool {
<Error + 'static>::is::<T>(self)
<dyn Error + 'static>::is::<T>(self)
}
/// Forwards to the method defined on the type `Any`.
#[stable(feature = "error_downcast", since = "1.3.0")]
#[inline]
pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> {
<Error + 'static>::downcast_ref::<T>(self)
<dyn Error + 'static>::downcast_ref::<T>(self)
}
/// Forwards to the method defined on the type `Any`.
#[stable(feature = "error_downcast", since = "1.3.0")]
#[inline]
pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> {
<Error + 'static>::downcast_mut::<T>(self)
<dyn Error + 'static>::downcast_mut::<T>(self)
}
}
impl Error + 'static + Send + Sync {
impl dyn Error + 'static + Send + Sync {
/// Forwards to the method defined on the type `Any`.
#[stable(feature = "error_downcast", since = "1.3.0")]
#[inline]
pub fn is<T: Error + 'static>(&self) -> bool {
<Error + 'static>::is::<T>(self)
<dyn Error + 'static>::is::<T>(self)
}
/// Forwards to the method defined on the type `Any`.
#[stable(feature = "error_downcast", since = "1.3.0")]
#[inline]
pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> {
<Error + 'static>::downcast_ref::<T>(self)
<dyn Error + 'static>::downcast_ref::<T>(self)
}
/// Forwards to the method defined on the type `Any`.
#[stable(feature = "error_downcast", since = "1.3.0")]
#[inline]
pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> {
<Error + 'static>::downcast_mut::<T>(self)
<dyn Error + 'static>::downcast_mut::<T>(self)
}
}
impl Error {
impl dyn Error {
#[inline]
#[stable(feature = "error_downcast", since = "1.3.0")]
/// Attempt to downcast the box to a concrete type.
pub fn downcast<T: Error + 'static>(self: Box<Self>) -> Result<Box<T>, Box<Error>> {
pub fn downcast<T: Error + 'static>(self: Box<Self>) -> Result<Box<T>, Box<dyn Error>> {
if self.is::<T>() {
unsafe {
let raw: *mut Error = Box::into_raw(self);
let raw: *mut dyn Error = Box::into_raw(self);
Ok(Box::from_raw(raw as *mut T))
}
} else {
@ -473,30 +474,30 @@ impl Error { @@ -473,30 +474,30 @@ impl Error {
}
}
impl Error + Send {
impl dyn Error + Send {
#[inline]
#[stable(feature = "error_downcast", since = "1.3.0")]
/// Attempt to downcast the box to a concrete type.
pub fn downcast<T: Error + 'static>(self: Box<Self>)
-> Result<Box<T>, Box<Error + Send>> {
let err: Box<Error> = self;
<Error>::downcast(err).map_err(|s| unsafe {
-> Result<Box<T>, Box<dyn Error + Send>> {
let err: Box<dyn Error> = self;
<dyn Error>::downcast(err).map_err(|s| unsafe {
// reapply the Send marker
transmute::<Box<Error>, Box<Error + Send>>(s)
transmute::<Box<dyn Error>, Box<dyn Error + Send>>(s)
})
}
}
impl Error + Send + Sync {
impl dyn Error + Send + Sync {
#[inline]
#[stable(feature = "error_downcast", since = "1.3.0")]
/// Attempt to downcast the box to a concrete type.
pub fn downcast<T: Error + 'static>(self: Box<Self>)
-> Result<Box<T>, Box<Self>> {
let err: Box<Error> = self;
<Error>::downcast(err).map_err(|s| unsafe {
let err: Box<dyn Error> = self;
<dyn Error>::downcast(err).map_err(|s| unsafe {
// reapply the Send+Sync marker
transmute::<Box<Error>, Box<Error + Send + Sync>>(s)
transmute::<Box<dyn Error>, Box<dyn Error + Send + Sync>>(s)
})
}
}
@ -532,13 +533,13 @@ mod tests { @@ -532,13 +533,13 @@ mod tests {
#[test]
fn downcasting() {
let mut a = A;
let a = &mut a as &mut (Error + 'static);
let a = &mut a as &mut (dyn Error + 'static);
assert_eq!(a.downcast_ref::<A>(), Some(&A));
assert_eq!(a.downcast_ref::<B>(), None);
assert_eq!(a.downcast_mut::<A>(), Some(&mut A));
assert_eq!(a.downcast_mut::<B>(), None);
let a: Box<Error> = Box::new(A);
let a: Box<dyn Error> = Box::new(A);
match a.downcast::<B>() {
Ok(..) => panic!("expected error"),
Err(e) => assert_eq!(*e.downcast::<A>().unwrap(), A),

11
ctr-std/src/f32.rs

@ -254,7 +254,14 @@ impl f32 { @@ -254,7 +254,14 @@ impl f32 {
/// Calculates the Euclidean modulo (self mod rhs), which is never negative.
///
/// In particular, the result `n` satisfies `0 <= n < rhs.abs()`.
/// In particular, the return value `r` satisfies `0.0 <= r < rhs.abs()` in
/// most cases. However, due to a floating point round-off error it can
/// result in `r == rhs.abs()`, violating the mathematical definition, if
/// `self` is much smaller than `rhs.abs()` in magnitude and `self < 0.0`.
/// This result is not an element of the function's codomain, but it is the
/// closest floating point number in the real numbers and thus fulfills the
/// property `self == self.div_euc(rhs) * rhs + self.mod_euc(rhs)`
/// approximatively.
///
/// # Examples
///
@ -266,6 +273,8 @@ impl f32 { @@ -266,6 +273,8 @@ impl f32 {
/// assert_eq!((-a).mod_euc(b), 1.0);
/// assert_eq!(a.mod_euc(-b), 3.0);
/// assert_eq!((-a).mod_euc(-b), 1.0);
/// // limitation due to round-off error
/// assert!((-std::f32::EPSILON).mod_euc(3.0) != 0.0);
/// ```
#[inline]
#[unstable(feature = "euclidean_division", issue = "49048")]

11
ctr-std/src/f64.rs

@ -230,7 +230,14 @@ impl f64 { @@ -230,7 +230,14 @@ impl f64 {
/// Calculates the Euclidean modulo (self mod rhs), which is never negative.
///
/// In particular, the result `n` satisfies `0 <= n < rhs.abs()`.
/// In particular, the return value `r` satisfies `0.0 <= r < rhs.abs()` in
/// most cases. However, due to a floating point round-off error it can
/// result in `r == rhs.abs()`, violating the mathematical definition, if
/// `self` is much smaller than `rhs.abs()` in magnitude and `self < 0.0`.
/// This result is not an element of the function's codomain, but it is the
/// closest floating point number in the real numbers and thus fulfills the
/// property `self == self.div_euc(rhs) * rhs + self.mod_euc(rhs)`
/// approximatively.
///
/// # Examples
///
@ -242,6 +249,8 @@ impl f64 { @@ -242,6 +249,8 @@ impl f64 {
/// assert_eq!((-a).mod_euc(b), 1.0);
/// assert_eq!(a.mod_euc(-b), 3.0);
/// assert_eq!((-a).mod_euc(-b), 1.0);
/// // limitation due to round-off error
/// assert!((-std::f64::EPSILON).mod_euc(3.0) != 0.0);
/// ```
#[inline]
#[unstable(feature = "euclidean_division", issue = "49048")]

43
ctr-std/src/ffi/c_str.rs

@ -692,6 +692,12 @@ impl fmt::Debug for CString { @@ -692,6 +692,12 @@ impl fmt::Debug for CString {
#[stable(feature = "cstring_into", since = "1.7.0")]
impl From<CString> for Vec<u8> {
/// Converts a [`CString`] into a [`Vec`]`<u8>`.
///
/// The conversion consumes the [`CString`], and removes the terminating NUL byte.
///
/// [`Vec`]: ../vec/struct.Vec.html
/// [`CString`]: ../ffi/struct.CString.html
#[inline]
fn from(s: CString) -> Vec<u8> {
s.into_bytes()
@ -750,14 +756,30 @@ impl<'a> From<&'a CStr> for Box<CStr> { @@ -750,14 +756,30 @@ impl<'a> From<&'a CStr> for Box<CStr> {
#[stable(feature = "c_string_from_box", since = "1.18.0")]
impl From<Box<CStr>> for CString {
/// Converts a [`Box`]`<CStr>` into a [`CString`] without copying or allocating.
///
/// [`Box`]: ../boxed/struct.Box.html
/// [`CString`]: ../ffi/struct.CString.html
#[inline]
fn from(s: Box<CStr>) -> CString {
s.into_c_string()
}
}
#[stable(feature = "more_box_slice_clone", since = "1.29.0")]
impl Clone for Box<CStr> {
#[inline]
fn clone(&self) -> Self {
(**self).into()
}
}
#[stable(feature = "box_from_c_string", since = "1.20.0")]
impl From<CString> for Box<CStr> {
/// Converts a [`CString`] into a [`Box`]`<CStr>` without copying or allocating.
///
/// [`CString`]: ../ffi/struct.CString.html
/// [`Box`]: ../boxed/struct.Box.html
#[inline]
fn from(s: CString) -> Box<CStr> {
s.into_boxed_c_str()
@ -790,6 +812,10 @@ impl<'a> From<&'a CString> for Cow<'a, CStr> { @@ -790,6 +812,10 @@ impl<'a> From<&'a CString> for Cow<'a, CStr> {
#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl From<CString> for Arc<CStr> {
/// Converts a [`CString`] into a [`Arc`]`<CStr>` without copying or allocating.
///
/// [`CString`]: ../ffi/struct.CString.html
/// [`Arc`]: ../sync/struct.Arc.html
#[inline]
fn from(s: CString) -> Arc<CStr> {
let arc: Arc<[u8]> = Arc::from(s.into_inner());
@ -808,6 +834,10 @@ impl<'a> From<&'a CStr> for Arc<CStr> { @@ -808,6 +834,10 @@ impl<'a> From<&'a CStr> for Arc<CStr> {
#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl From<CString> for Rc<CStr> {
/// Converts a [`CString`] into a [`Rc`]`<CStr>` without copying or allocating.
///
/// [`CString`]: ../ffi/struct.CString.html
/// [`Rc`]: ../rc/struct.Rc.html
#[inline]
fn from(s: CString) -> Rc<CStr> {
let rc: Rc<[u8]> = Rc::from(s.into_inner());
@ -881,6 +911,10 @@ impl fmt::Display for NulError { @@ -881,6 +911,10 @@ impl fmt::Display for NulError {
#[stable(feature = "rust1", since = "1.0.0")]
impl From<NulError> for io::Error {
/// Converts a [`NulError`] into a [`io::Error`].
///
/// [`NulError`]: ../ffi/struct.NulError.html
/// [`io::Error`]: ../io/struct.Error.html
fn from(_: NulError) -> io::Error {
io::Error::new(io::ErrorKind::InvalidInput,
"data provided contains a nul byte")
@ -933,7 +967,7 @@ impl Error for IntoStringError { @@ -933,7 +967,7 @@ impl Error for IntoStringError {
"C string contained non-utf8 bytes"
}
fn cause(&self) -> Option<&Error> {
fn cause(&self) -> Option<&dyn Error> {
Some(&self.error)
}
}
@ -1234,9 +1268,9 @@ impl CStr { @@ -1234,9 +1268,9 @@ impl CStr {
/// If the contents of the `CStr` are valid UTF-8 data, this
/// function will return a [`Cow`]`::`[`Borrowed`]`(`[`&str`]`)`
/// with the the corresponding [`&str`] slice. Otherwise, it will
/// replace any invalid UTF-8 sequences with `U+FFFD REPLACEMENT
/// CHARACTER` and return a [`Cow`]`::`[`Owned`]`(`[`String`]`)`
/// with the result.
/// replace any invalid UTF-8 sequences with
/// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD] and return a
/// [`Cow`]`::`[`Owned`]`(`[`String`]`)` with the result.
///
/// > **Note**: This method is currently implemented to check for validity
/// > after a constant-time cast, but it is planned to alter its definition
@ -1248,6 +1282,7 @@ impl CStr { @@ -1248,6 +1282,7 @@ impl CStr {
/// [`Owned`]: ../borrow/enum.Cow.html#variant.Owned
/// [`str`]: ../primitive.str.html
/// [`String`]: ../string/struct.String.html
/// [U+FFFD]: ../char/constant.REPLACEMENT_CHARACTER.html
///
/// # Examples
///

48
ctr-std/src/ffi/os_str.rs

@ -348,6 +348,12 @@ impl OsString { @@ -348,6 +348,12 @@ impl OsString {
#[stable(feature = "rust1", since = "1.0.0")]
impl From<String> for OsString {
/// Converts a [`String`] into a [`OsString`].
///
/// The conversion copies the data, and includes an allocation on the heap.
///
/// [`String`]: ../string/struct.String.html
/// [`OsString`]: struct.OsString.html
fn from(s: String) -> OsString {
OsString { inner: Buf::from_string(s) }
}
@ -417,6 +423,20 @@ impl PartialEq<OsString> for str { @@ -417,6 +423,20 @@ impl PartialEq<OsString> for str {
}
}
#[stable(feature = "os_str_str_ref_eq", since = "1.28.0")]
impl<'a> PartialEq<&'a str> for OsString {
fn eq(&self, other: &&'a str) -> bool {
**self == **other
}
}
#[stable(feature = "os_str_str_ref_eq", since = "1.28.0")]
impl<'a> PartialEq<OsString> for &'a str {
fn eq(&self, other: &OsString) -> bool {
**other == **self
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl Eq for OsString {}
@ -500,10 +520,12 @@ impl OsStr { @@ -500,10 +520,12 @@ impl OsStr {
/// Converts an `OsStr` to a [`Cow`]`<`[`str`]`>`.
///
/// Any non-Unicode sequences are replaced with U+FFFD REPLACEMENT CHARACTER.
/// Any non-Unicode sequences are replaced with
/// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD].
///
/// [`Cow`]: ../../std/borrow/enum.Cow.html
/// [`str`]: ../../std/primitive.str.html
/// [U+FFFD]: ../../std/char/constant.REPLACEMENT_CHARACTER.html
///
/// # Examples
///
@ -616,6 +638,10 @@ impl<'a> From<&'a OsStr> for Box<OsStr> { @@ -616,6 +638,10 @@ impl<'a> From<&'a OsStr> for Box<OsStr> {
#[stable(feature = "os_string_from_box", since = "1.18.0")]
impl From<Box<OsStr>> for OsString {
/// Converts a `Box<OsStr>` into a `OsString` without copying or allocating.
///
/// [`Box`]: ../boxed/struct.Box.html
/// [`OsString`]: ../ffi/struct.OsString.html
fn from(boxed: Box<OsStr>) -> OsString {
boxed.into_os_string()
}
@ -623,13 +649,29 @@ impl From<Box<OsStr>> for OsString { @@ -623,13 +649,29 @@ impl From<Box<OsStr>> for OsString {
#[stable(feature = "box_from_os_string", since = "1.20.0")]
impl From<OsString> for Box<OsStr> {
/// Converts a [`OsString`] into a [`Box`]`<OsStr>` without copying or allocating.
///
/// [`Box`]: ../boxed/struct.Box.html
/// [`OsString`]: ../ffi/struct.OsString.html
fn from(s: OsString) -> Box<OsStr> {
s.into_boxed_os_str()
}
}
#[stable(feature = "more_box_slice_clone", since = "1.29.0")]
impl Clone for Box<OsStr> {
#[inline]
fn clone(&self) -> Self {
self.to_os_string().into_boxed_os_str()
}
}
#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl From<OsString> for Arc<OsStr> {
/// Converts a [`OsString`] into a [`Arc`]`<OsStr>` without copying or allocating.
///
/// [`Arc`]: ../sync/struct.Arc.html
/// [`OsString`]: ../ffi/struct.OsString.html
#[inline]
fn from(s: OsString) -> Arc<OsStr> {
let arc = s.inner.into_arc();
@ -648,6 +690,10 @@ impl<'a> From<&'a OsStr> for Arc<OsStr> { @@ -648,6 +690,10 @@ impl<'a> From<&'a OsStr> for Arc<OsStr> {
#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl From<OsString> for Rc<OsStr> {
/// Converts a [`OsString`] into a [`Rc`]`<OsStr>` without copying or allocating.
///
/// [`Rc`]: ../rc/struct.Rc.html
/// [`OsString`]: ../ffi/struct.OsString.html
#[inline]
fn from(s: OsString) -> Rc<OsStr> {
let rc = s.inner.into_rc();

6
ctr-std/src/fs.rs

@ -356,9 +356,9 @@ impl File { @@ -356,9 +356,9 @@ impl File {
/// use std::fs::File;
///
/// fn main() -> std::io::Result<()> {
/// let mut f = File::open("foo.txt")?;
/// # Ok(())
/// # }
/// let mut f = File::open("foo.txt")?;
/// Ok(())
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn open<P: AsRef<Path>>(path: P) -> io::Result<File> {

116
ctr-std/src/future.rs

@ -0,0 +1,116 @@ @@ -0,0 +1,116 @@
// Copyright 2018 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.
//! Asynchronous values.
use core::cell::Cell;
use core::marker::Unpin;
use core::mem::PinMut;
use core::option::Option;
use core::ptr::NonNull;
use core::task::{self, Poll};
use core::ops::{Drop, Generator, GeneratorState};
#[doc(inline)]
pub use core::future::*;
/// Wrap a future in a generator.
///
/// This function returns a `GenFuture` underneath, but hides it in `impl Trait` to give
/// better error messages (`impl Future` rather than `GenFuture<[closure.....]>`).
#[unstable(feature = "gen_future", issue = "50547")]
pub fn from_generator<T: Generator<Yield = ()>>(x: T) -> impl Future<Output = T::Return> {
GenFuture(x)
}
/// A wrapper around generators used to implement `Future` for `async`/`await` code.
#[unstable(feature = "gen_future", issue = "50547")]
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
struct GenFuture<T: Generator<Yield = ()>>(T);
// We rely on the fact that async/await futures are immovable in order to create
// self-referential borrows in the underlying generator.
impl<T: Generator<Yield = ()>> !Unpin for GenFuture<T> {}
#[unstable(feature = "gen_future", issue = "50547")]
impl<T: Generator<Yield = ()>> Future for GenFuture<T> {
type Output = T::Return;
fn poll(self: PinMut<Self>, cx: &mut task::Context) -> Poll<Self::Output> {
set_task_cx(cx, || match unsafe { PinMut::get_mut_unchecked(self).0.resume() } {
GeneratorState::Yielded(()) => Poll::Pending,
GeneratorState::Complete(x) => Poll::Ready(x),
})
}
}
thread_local! {
static TLS_CX: Cell<Option<NonNull<task::Context<'static>>>> = Cell::new(None);
}
struct SetOnDrop(Option<NonNull<task::Context<'static>>>);
impl Drop for SetOnDrop {
fn drop(&mut self) {
TLS_CX.with(|tls_cx| {
tls_cx.set(self.0.take());
});
}
}
#[unstable(feature = "gen_future", issue = "50547")]
/// Sets the thread-local task context used by async/await futures.
pub fn set_task_cx<F, R>(cx: &mut task::Context, f: F) -> R
where
F: FnOnce() -> R
{
let old_cx = TLS_CX.with(|tls_cx| {
tls_cx.replace(NonNull::new(
cx
as *mut task::Context
as *mut ()
as *mut task::Context<'static>
))
});
let _reset_cx = SetOnDrop(old_cx);
f()
}
#[unstable(feature = "gen_future", issue = "50547")]
/// Retrieves the thread-local task context used by async/await futures.
///
/// This function acquires exclusive access to the task context.
///
/// Panics if no task has been set or if the task context has already been
/// retrived by a surrounding call to get_task_cx.
pub fn get_task_cx<F, R>(f: F) -> R
where
F: FnOnce(&mut task::Context) -> R
{
let cx_ptr = TLS_CX.with(|tls_cx| {
// Clear the entry so that nested `with_get_cx` calls
// will fail or set their own value.
tls_cx.replace(None)
});
let _reset_cx = SetOnDrop(cx_ptr);
let mut cx_ptr = cx_ptr.expect(
"TLS task::Context not set. This is a rustc bug. \
Please file an issue on https://github.com/rust-lang/rust.");
unsafe { f(cx_ptr.as_mut()) }
}
#[unstable(feature = "gen_future", issue = "50547")]
/// Polls a future in the current thread-local task context.
pub fn poll_in_task_cx<F>(f: PinMut<F>) -> Poll<F::Output>
where
F: Future
{
get_task_cx(|cx| f.poll(cx))
}

85
ctr-std/src/io/buffered.rs

@ -61,7 +61,8 @@ pub struct BufReader<R> { @@ -61,7 +61,8 @@ pub struct BufReader<R> {
}
impl<R: Read> BufReader<R> {
/// Creates a new `BufReader` with a default buffer capacity.
/// Creates a new `BufReader` with a default buffer capacity. The default is currently 8 KB,
/// but may change in the future.
///
/// # Examples
///
@ -153,33 +154,6 @@ impl<R: Read> BufReader<R> { @@ -153,33 +154,6 @@ impl<R: Read> BufReader<R> {
#[stable(feature = "rust1", since = "1.0.0")]
pub fn get_mut(&mut self) -> &mut R { &mut self.inner }
/// Returns `true` if there are no bytes in the internal buffer.
///
/// # Examples
//
/// ```no_run
/// # #![feature(bufreader_is_empty)]
/// use std::io::BufReader;
/// use std::io::BufRead;
/// use std::fs::File;
///
/// fn main() -> std::io::Result<()> {
/// let f1 = File::open("log.txt")?;
/// let mut reader = BufReader::new(f1);
/// assert!(reader.is_empty());
///
/// if reader.fill_buf()?.len() > 0 {
/// assert!(!reader.is_empty());
/// }
/// Ok(())
/// }
/// ```
#[unstable(feature = "bufreader_is_empty", issue = "45323", reason = "recently added")]
#[rustc_deprecated(since = "1.26.0", reason = "use .buffer().is_empty() instead")]
pub fn is_empty(&self) -> bool {
self.buffer().is_empty()
}
/// Returns a reference to the internally buffered data.
///
/// Unlike `fill_buf`, this will not attempt to fill the buffer if it is empty.
@ -454,7 +428,8 @@ pub struct BufWriter<W: Write> { @@ -454,7 +428,8 @@ pub struct BufWriter<W: Write> {
pub struct IntoInnerError<W>(W, Error);
impl<W: Write> BufWriter<W> {
/// Creates a new `BufWriter` with a default buffer capacity.
/// Creates a new `BufWriter` with a default buffer capacity. The default is currently 8 KB,
/// but may change in the future.
///
/// # Examples
///
@ -738,7 +713,7 @@ impl<W> fmt::Display for IntoInnerError<W> { @@ -738,7 +713,7 @@ impl<W> fmt::Display for IntoInnerError<W> {
/// reducing the number of actual writes to the file.
///
/// ```no_run
/// use std::fs::File;
/// use std::fs::{self, File};
/// use std::io::prelude::*;
/// use std::io::LineWriter;
///
@ -752,17 +727,30 @@ impl<W> fmt::Display for IntoInnerError<W> { @@ -752,17 +727,30 @@ impl<W> fmt::Display for IntoInnerError<W> {
/// let file = File::create("poem.txt")?;
/// let mut file = LineWriter::new(file);
///
/// for &byte in road_not_taken.iter() {
/// file.write(&[byte]).unwrap();
/// }
/// file.write_all(b"I shall be telling this with a sigh")?;
///
/// // let's check we did the right thing.
/// let mut file = File::open("poem.txt")?;
/// let mut contents = String::new();
/// // No bytes are written until a newline is encountered (or
/// // the internal buffer is filled).
/// assert_eq!(fs::read_to_string("poem.txt")?, "");
/// file.write_all(b"\n")?;
/// assert_eq!(
/// fs::read_to_string("poem.txt")?,
/// "I shall be telling this with a sigh\n",
/// );
///
/// file.read_to_string(&mut contents)?;
/// // Write the rest of the poem.
/// file.write_all(b"Somewhere ages and ages hence:
/// Two roads diverged in a wood, and I -
/// I took the one less traveled by,
/// And that has made all the difference.")?;
///
/// assert_eq!(contents.as_bytes(), &road_not_taken[..]);
/// // The last line of the poem doesn't end in a newline, so
/// // we have to flush or drop the `LineWriter` to finish
/// // writing.
/// file.flush()?;
///
/// // Confirm the whole poem was written.
/// assert_eq!(fs::read("poem.txt")?, &road_not_taken[..]);
/// Ok(())
/// }
/// ```
@ -862,7 +850,7 @@ impl<W: Write> LineWriter<W> { @@ -862,7 +850,7 @@ impl<W: Write> LineWriter<W> {
///
/// The internal buffer is written out before returning the writer.
///
// # Errors
/// # Errors
///
/// An `Err` will be returned if an error occurs while flushing the buffer.
///
@ -1250,25 +1238,6 @@ mod tests { @@ -1250,25 +1238,6 @@ mod tests {
assert_eq!(reader.read(&mut buf).unwrap(), 0);
}
#[test]
#[allow(deprecated)]
fn read_char_buffered() {
let buf = [195, 159];
let reader = BufReader::with_capacity(1, &buf[..]);
assert_eq!(reader.chars().next().unwrap().unwrap(), 'ß');
}
#[test]
#[allow(deprecated)]
fn test_chars() {
let buf = [195, 159, b'a'];
let reader = BufReader::with_capacity(1, &buf[..]);
let mut it = reader.chars();
assert_eq!(it.next().unwrap().unwrap(), 'ß');
assert_eq!(it.next().unwrap().unwrap(), 'a');
assert!(it.next().is_none());
}
#[test]
#[should_panic]
fn dont_panic_in_drop_on_panicked_flush() {

57
ctr-std/src/io/cursor.rs

@ -10,15 +10,17 @@ @@ -10,15 +10,17 @@
use io::prelude::*;
use core::convert::TryInto;
use cmp;
use io::{self, Initializer, SeekFrom, Error, ErrorKind};
/// A `Cursor` wraps another type and provides it with a
/// A `Cursor` wraps an in-memory buffer and provides it with a
/// [`Seek`] implementation.
///
/// `Cursor`s are typically used with in-memory buffers to allow them to
/// implement [`Read`] and/or [`Write`], allowing these buffers to be used
/// anywhere you might use a reader or writer that does actual I/O.
/// `Cursor`s are used with in-memory buffers, anything implementing
/// `AsRef<[u8]>`, to allow them to implement [`Read`] and/or [`Write`],
/// allowing these buffers to be used anywhere you might use a reader or writer
/// that does actual I/O.
///
/// The standard library implements some I/O traits on various types which
/// are commonly used as a buffer, like `Cursor<`[`Vec`]`<u8>>` and
@ -86,11 +88,11 @@ pub struct Cursor<T> { @@ -86,11 +88,11 @@ pub struct Cursor<T> {
}
impl<T> Cursor<T> {
/// Creates a new cursor wrapping the provided underlying I/O object.
/// Creates a new cursor wrapping the provided underlying in-memory buffer.
///
/// Cursor initial position is `0` even if underlying object (e.
/// g. `Vec`) is not empty. So writing to cursor starts with
/// overwriting `Vec` content, not with appending to it.
/// Cursor initial position is `0` even if underlying buffer (e.g. `Vec`)
/// is not empty. So writing to cursor starts with overwriting `Vec`
/// content, not with appending to it.
///
/// # Examples
///
@ -259,26 +261,9 @@ fn slice_write(pos_mut: &mut u64, slice: &mut [u8], buf: &[u8]) -> io::Result<us @@ -259,26 +261,9 @@ fn slice_write(pos_mut: &mut u64, slice: &mut [u8], buf: &[u8]) -> io::Result<us
Ok(amt)
}
/// Compensate removal of some impls per
/// https://github.com/rust-lang/rust/pull/49305#issuecomment-376293243
#[cfg(any(target_pointer_width = "16",
target_pointer_width = "32"))]
fn try_into(n: u64) -> Result<usize, ()> {
if n <= (<usize>::max_value() as u64) {
Ok(n as usize)
} else {
Err(())
}
}
#[cfg(any(target_pointer_width = "64"))]
fn try_into(n: u64) -> Result<usize, ()> {
Ok(n as usize)
}
// Resizing write implementation
fn vec_write(pos_mut: &mut u64, vec: &mut Vec<u8>, buf: &[u8]) -> io::Result<usize> {
let pos: usize = try_into(*pos_mut).map_err(|_| {
let pos: usize = (*pos_mut).try_into().map_err(|_| {
Error::new(ErrorKind::InvalidInput,
"cursor position exceeds maximum possible vector length")
})?;
@ -565,26 +550,6 @@ mod tests { @@ -565,26 +550,6 @@ mod tests {
assert_eq!(reader.read(&mut buf).unwrap(), 0);
}
#[test]
#[allow(deprecated)]
fn test_read_char() {
let b = &b"Vi\xE1\xBB\x87t"[..];
let mut c = Cursor::new(b).chars();
assert_eq!(c.next().unwrap().unwrap(), 'V');
assert_eq!(c.next().unwrap().unwrap(), 'i');
assert_eq!(c.next().unwrap().unwrap(), 'ệ');
assert_eq!(c.next().unwrap().unwrap(), 't');
assert!(c.next().is_none());
}
#[test]
#[allow(deprecated)]
fn test_read_bad_char() {
let b = &b"\x80"[..];
let mut c = Cursor::new(b).chars();
assert!(c.next().unwrap().is_err());
}
#[test]
fn seek_past_end() {
let buf = [0xff];

25
ctr-std/src/io/error.rs

@ -83,7 +83,7 @@ enum Repr { @@ -83,7 +83,7 @@ enum Repr {
#[derive(Debug)]
struct Custom {
kind: ErrorKind,
error: Box<error::Error+Send+Sync>,
error: Box<dyn error::Error+Send+Sync>,
}
/// A list specifying general categories of I/O error.
@ -97,6 +97,7 @@ struct Custom { @@ -97,6 +97,7 @@ struct Custom {
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(deprecated)]
#[non_exhaustive]
pub enum ErrorKind {
/// An entity was not found, often a file.
#[stable(feature = "rust1", since = "1.0.0")]
@ -180,15 +181,6 @@ pub enum ErrorKind { @@ -180,15 +181,6 @@ pub enum ErrorKind {
/// read.
#[stable(feature = "read_exact", since = "1.6.0")]
UnexpectedEof,
/// A marker variant that tells the compiler that users of this enum cannot
/// match it exhaustively.
#[unstable(feature = "io_error_internals",
reason = "better expressed through extensible enums that this \
enum cannot be exhaustively matched against",
issue = "0")]
#[doc(hidden)]
__Nonexhaustive,
}
impl ErrorKind {
@ -212,7 +204,6 @@ impl ErrorKind { @@ -212,7 +204,6 @@ impl ErrorKind {
ErrorKind::Interrupted => "operation interrupted",
ErrorKind::Other => "other os error",
ErrorKind::UnexpectedEof => "unexpected end of file",
ErrorKind::__Nonexhaustive => unreachable!()
}
}
}
@ -250,12 +241,12 @@ impl Error { @@ -250,12 +241,12 @@ impl Error {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn new<E>(kind: ErrorKind, error: E) -> Error
where E: Into<Box<error::Error+Send+Sync>>
where E: Into<Box<dyn error::Error+Send+Sync>>
{
Self::_new(kind, error.into())
}
fn _new(kind: ErrorKind, error: Box<error::Error+Send+Sync>) -> Error {
fn _new(kind: ErrorKind, error: Box<dyn error::Error+Send+Sync>) -> Error {
Error {
repr: Repr::Custom(Box::new(Custom {
kind,
@ -373,7 +364,7 @@ impl Error { @@ -373,7 +364,7 @@ impl Error {
/// }
/// ```
#[stable(feature = "io_error_inner", since = "1.3.0")]
pub fn get_ref(&self) -> Option<&(error::Error+Send+Sync+'static)> {
pub fn get_ref(&self) -> Option<&(dyn error::Error+Send+Sync+'static)> {
match self.repr {
Repr::Os(..) => None,
Repr::Simple(..) => None,
@ -444,7 +435,7 @@ impl Error { @@ -444,7 +435,7 @@ impl Error {
/// }
/// ```
#[stable(feature = "io_error_inner", since = "1.3.0")]
pub fn get_mut(&mut self) -> Option<&mut (error::Error+Send+Sync+'static)> {
pub fn get_mut(&mut self) -> Option<&mut (dyn error::Error+Send+Sync+'static)> {
match self.repr {
Repr::Os(..) => None,
Repr::Simple(..) => None,
@ -478,7 +469,7 @@ impl Error { @@ -478,7 +469,7 @@ impl Error {
/// }
/// ```
#[stable(feature = "io_error_inner", since = "1.3.0")]
pub fn into_inner(self) -> Option<Box<error::Error+Send+Sync>> {
pub fn into_inner(self) -> Option<Box<dyn error::Error+Send+Sync>> {
match self.repr {
Repr::Os(..) => None,
Repr::Simple(..) => None,
@ -551,7 +542,7 @@ impl error::Error for Error { @@ -551,7 +542,7 @@ impl error::Error for Error {
}
}
fn cause(&self) -> Option<&error::Error> {
fn cause(&self) -> Option<&dyn error::Error> {
match self.repr {
Repr::Os(..) => None,
Repr::Simple(..) => None,

30
ctr-std/src/io/lazy.rs

@ -15,15 +15,21 @@ use sys_common; @@ -15,15 +15,21 @@ use sys_common;
use sys_common::mutex::Mutex;
pub struct Lazy<T> {
// We never call `lock.init()`, so it is UB to attempt to acquire this mutex reentrantly!
lock: Mutex,
ptr: Cell<*mut Arc<T>>,
init: fn() -> Arc<T>,
}
#[inline]
const fn done<T>() -> *mut Arc<T> { 1_usize as *mut _ }
unsafe impl<T> Sync for Lazy<T> {}
impl<T: Send + Sync + 'static> Lazy<T> {
pub const fn new(init: fn() -> Arc<T>) -> Lazy<T> {
/// Safety: `init` must not call `get` on the variable that is being
/// initialized.
pub const unsafe fn new(init: fn() -> Arc<T>) -> Lazy<T> {
Lazy {
lock: Mutex::new(),
ptr: Cell::new(ptr::null_mut()),
@ -33,32 +39,34 @@ impl<T: Send + Sync + 'static> Lazy<T> { @@ -33,32 +39,34 @@ impl<T: Send + Sync + 'static> Lazy<T> {
pub fn get(&'static self) -> Option<Arc<T>> {
unsafe {
self.lock.lock();
let _guard = self.lock.lock();
let ptr = self.ptr.get();
let ret = if ptr.is_null() {
if ptr.is_null() {
Some(self.init())
} else if ptr as usize == 1 {
} else if ptr == done() {
None
} else {
Some((*ptr).clone())
};
self.lock.unlock();
return ret
}
}
}
// Must only be called with `lock` held
unsafe fn init(&'static self) -> Arc<T> {
// If we successfully register an at exit handler, then we cache the
// `Arc` allocation in our own internal box (it will get deallocated by
// the at exit handler). Otherwise we just return the freshly allocated
// `Arc`.
let registered = sys_common::at_exit(move || {
self.lock.lock();
let ptr = self.ptr.get();
self.ptr.set(1 as *mut _);
self.lock.unlock();
let ptr = {
let _guard = self.lock.lock();
self.ptr.replace(done())
};
drop(Box::from_raw(ptr))
});
// This could reentrantly call `init` again, which is a problem
// because our `lock` allows reentrancy!
// That's why `new` is unsafe and requires the caller to ensure no reentrancy happens.
let ret = (self.init)();
if registered.is_ok() {
self.ptr.set(Box::into_raw(Box::new(ret.clone())));

171
ctr-std/src/io/mod.rs

@ -147,7 +147,7 @@ @@ -147,7 +147,7 @@
//! ```
//!
//! Note that you cannot use the [`?` operator] in functions that do not return
//! a [`Result<T, E>`][`Result`] (e.g. `main`). Instead, you can call [`.unwrap()`]
//! a [`Result<T, E>`][`Result`]. Instead, you can call [`.unwrap()`]
//! or `match` on the return value to catch any possible errors:
//!
//! ```no_run
@ -270,10 +270,7 @@ @@ -270,10 +270,7 @@
#![stable(feature = "rust1", since = "1.0.0")]
use cmp;
use core::str as core_str;
use error as std_error;
use fmt;
use result;
use str;
use memchr;
use ptr;
@ -357,19 +354,26 @@ fn append_to_string<F>(buf: &mut String, f: F) -> Result<usize> @@ -357,19 +354,26 @@ fn append_to_string<F>(buf: &mut String, f: F) -> Result<usize>
// avoid paying to allocate and zero a huge chunk of memory if the reader only
// has 4 bytes while still making large reads if the reader does have a ton
// of data to return. Simply tacking on an extra DEFAULT_BUF_SIZE space every
// time is 4,500 times (!) slower than this if the reader has a very small
// amount of data to return.
// time is 4,500 times (!) slower than a default reservation size of 32 if the
// reader has a very small amount of data to return.
//
// Because we're extending the buffer with uninitialized data for trusted
// readers, we need to make sure to truncate that if any of this panics.
fn read_to_end<R: Read + ?Sized>(r: &mut R, buf: &mut Vec<u8>) -> Result<usize> {
read_to_end_with_reservation(r, buf, 32)
}
fn read_to_end_with_reservation<R: Read + ?Sized>(r: &mut R,
buf: &mut Vec<u8>,
reservation_size: usize) -> Result<usize>
{
let start_len = buf.len();
let mut g = Guard { len: buf.len(), buf: buf };
let ret;
loop {
if g.len == g.buf.len() {
unsafe {
g.buf.reserve(32);
g.buf.reserve(reservation_size);
let capacity = g.buf.capacity();
g.buf.set_len(capacity);
r.initializer().initialize(&mut g.buf[g.len..]);
@ -800,53 +804,6 @@ pub trait Read { @@ -800,53 +804,6 @@ pub trait Read {
Bytes { inner: self }
}
/// Transforms this `Read` instance to an [`Iterator`] over [`char`]s.
///
/// This adaptor will attempt to interpret this reader as a UTF-8 encoded
/// sequence of characters. The returned iterator will return [`None`] once
/// EOF is reached for this reader. Otherwise each element yielded will be a
/// [`Result`]`<`[`char`]`, E>` where `E` may contain information about what I/O error
/// occurred or where decoding failed.
///
/// Currently this adaptor will discard intermediate data read, and should
/// be avoided if this is not desired.
///
/// # Examples
///
/// [`File`]s implement `Read`:
///
/// [`File`]: ../fs/struct.File.html
/// [`Iterator`]: ../../std/iter/trait.Iterator.html
/// [`Result`]: ../../std/result/enum.Result.html
/// [`char`]: ../../std/primitive.char.html
/// [`None`]: ../../std/option/enum.Option.html#variant.None
///
/// ```no_run
/// #![feature(io)]
/// use std::io;
/// use std::io::prelude::*;
/// use std::fs::File;
///
/// fn main() -> io::Result<()> {
/// let mut f = File::open("foo.txt")?;
///
/// for c in f.chars() {
/// println!("{}", c.unwrap());
/// }
/// 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(since = "1.27.0", reason = "Use str::from_utf8 instead:
https://doc.rust-lang.org/nightly/std/str/struct.Utf8Error.html#examples")]
#[allow(deprecated)]
fn chars(self) -> Chars<Self> where Self: Sized {
Chars { inner: self }
}
/// Creates an adaptor which will chain this stream with another.
///
/// The returned `Read` instance will first read all bytes from this object
@ -1949,6 +1906,12 @@ impl<T: Read> Read for Take<T> { @@ -1949,6 +1906,12 @@ impl<T: Read> Read for Take<T> {
unsafe fn initializer(&self) -> Initializer {
self.inner.initializer()
}
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize> {
let reservation_size = cmp::min(self.limit, 32) as usize;
read_to_end_with_reservation(self, buf, reservation_size)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
@ -1972,7 +1935,7 @@ impl<T: BufRead> BufRead for Take<T> { @@ -1972,7 +1935,7 @@ impl<T: BufRead> BufRead for Take<T> {
}
}
fn read_one_byte(reader: &mut Read) -> Option<Result<u8>> {
fn read_one_byte(reader: &mut dyn Read) -> Option<Result<u8>> {
let mut buf = [0];
loop {
return match reader.read(&mut buf) {
@ -2005,104 +1968,6 @@ impl<R: Read> Iterator for Bytes<R> { @@ -2005,104 +1968,6 @@ impl<R: Read> Iterator for Bytes<R> {
}
}
/// An iterator over the `char`s of a reader.
///
/// This struct is generally created by calling [`chars`][chars] on a reader.
/// Please see the documentation of `chars()` for more details.
///
/// [chars]: trait.Read.html#method.chars
#[unstable(feature = "io", reason = "awaiting stability of Read::chars",
issue = "27802")]
#[rustc_deprecated(since = "1.27.0", reason = "Use str::from_utf8 instead:
https://doc.rust-lang.org/nightly/std/str/struct.Utf8Error.html#examples")]
#[derive(Debug)]
#[allow(deprecated)]
pub struct Chars<R> {
inner: R,
}
/// An enumeration of possible errors that can be generated from the `Chars`
/// adapter.
#[unstable(feature = "io", reason = "awaiting stability of Read::chars",
issue = "27802")]
#[rustc_deprecated(since = "1.27.0", reason = "Use str::from_utf8 instead:
https://doc.rust-lang.org/nightly/std/str/struct.Utf8Error.html#examples")]
#[derive(Debug)]
#[allow(deprecated)]
pub enum CharsError {
/// Variant representing that the underlying stream was read successfully
/// but it did not contain valid utf8 data.
NotUtf8,
/// Variant representing that an I/O error occurred.
Other(Error),
}
#[unstable(feature = "io", reason = "awaiting stability of Read::chars",
issue = "27802")]
#[allow(deprecated)]
impl<R: Read> Iterator for Chars<R> {
type Item = result::Result<char, CharsError>;
fn next(&mut self) -> Option<result::Result<char, CharsError>> {
let first_byte = match read_one_byte(&mut self.inner)? {
Ok(b) => b,
Err(e) => return Some(Err(CharsError::Other(e))),
};
let width = core_str::utf8_char_width(first_byte);
if width == 1 { return Some(Ok(first_byte as char)) }
if width == 0 { return Some(Err(CharsError::NotUtf8)) }
let mut buf = [first_byte, 0, 0, 0];
{
let mut start = 1;
while start < width {
match self.inner.read(&mut buf[start..width]) {
Ok(0) => return Some(Err(CharsError::NotUtf8)),
Ok(n) => start += n,
Err(ref e) if e.kind() == ErrorKind::Interrupted => continue,
Err(e) => return Some(Err(CharsError::Other(e))),
}
}
}
Some(match str::from_utf8(&buf[..width]).ok() {
Some(s) => Ok(s.chars().next().unwrap()),
None => Err(CharsError::NotUtf8),
})
}
}
#[unstable(feature = "io", reason = "awaiting stability of Read::chars",
issue = "27802")]
#[allow(deprecated)]
impl std_error::Error for CharsError {
fn description(&self) -> &str {
match *self {
CharsError::NotUtf8 => "invalid utf8 encoding",
CharsError::Other(ref e) => std_error::Error::description(e),
}
}
fn cause(&self) -> Option<&std_error::Error> {
match *self {
CharsError::NotUtf8 => None,
CharsError::Other(ref e) => e.cause(),
}
}
}
#[unstable(feature = "io", reason = "awaiting stability of Read::chars",
issue = "27802")]
#[allow(deprecated)]
impl fmt::Display for CharsError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
CharsError::NotUtf8 => {
"byte stream did not contain valid utf8".fmt(f)
}
CharsError::Other(ref e) => e.fmt(f),
}
}
}
/// An iterator over the contents of an instance of `BufRead` split on a
/// particular byte.
///

40
ctr-std/src/io/stdio.rs

@ -21,7 +21,7 @@ use thread::LocalKey; @@ -21,7 +21,7 @@ use thread::LocalKey;
/// Stdout used by print! and println! macros
thread_local! {
static LOCAL_STDOUT: RefCell<Option<Box<Write + Send>>> = {
static LOCAL_STDOUT: RefCell<Option<Box<dyn Write + Send>>> = {
RefCell::new(None)
}
}
@ -197,12 +197,13 @@ pub struct StdinLock<'a> { @@ -197,12 +197,13 @@ pub struct StdinLock<'a> {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn stdin() -> Stdin {
static INSTANCE: Lazy<Mutex<BufReader<Maybe<StdinRaw>>>> = Lazy::new(stdin_init);
static INSTANCE: Lazy<Mutex<BufReader<Maybe<StdinRaw>>>> = unsafe { Lazy::new(stdin_init) };
return Stdin {
inner: INSTANCE.get().expect("cannot access stdin during shutdown"),
};
fn stdin_init() -> Arc<Mutex<BufReader<Maybe<StdinRaw>>>> {
// This must not reentrantly access `INSTANCE`
let stdin = match stdin_raw() {
Ok(stdin) => Maybe::Real(stdin),
_ => Maybe::Fake
@ -396,12 +397,13 @@ pub struct StdoutLock<'a> { @@ -396,12 +397,13 @@ pub struct StdoutLock<'a> {
#[stable(feature = "rust1", since = "1.0.0")]
pub fn stdout() -> Stdout {
static INSTANCE: Lazy<ReentrantMutex<RefCell<LineWriter<Maybe<StdoutRaw>>>>>
= Lazy::new(stdout_init);
= unsafe { Lazy::new(stdout_init) };
return Stdout {
inner: INSTANCE.get().expect("cannot access stdout during shutdown"),
};
fn stdout_init() -> Arc<ReentrantMutex<RefCell<LineWriter<Maybe<StdoutRaw>>>>> {
// This must not reentrantly access `INSTANCE`
let stdout = match stdout_raw() {
Ok(stdout) => Maybe::Real(stdout),
_ => Maybe::Fake,
@ -531,12 +533,14 @@ pub struct StderrLock<'a> { @@ -531,12 +533,14 @@ pub struct StderrLock<'a> {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn stderr() -> Stderr {
static INSTANCE: Lazy<ReentrantMutex<RefCell<Maybe<StderrRaw>>>> = Lazy::new(stderr_init);
static INSTANCE: Lazy<ReentrantMutex<RefCell<Maybe<StderrRaw>>>> =
unsafe { Lazy::new(stderr_init) };
return Stderr {
inner: INSTANCE.get().expect("cannot access stderr during shutdown"),
};
fn stderr_init() -> Arc<ReentrantMutex<RefCell<Maybe<StderrRaw>>>> {
// This must not reentrantly access `INSTANCE`
let stderr = match stderr_raw() {
Ok(stderr) => Maybe::Real(stderr),
_ => Maybe::Fake,
@ -624,7 +628,7 @@ impl<'a> fmt::Debug for StderrLock<'a> { @@ -624,7 +628,7 @@ impl<'a> fmt::Debug for StderrLock<'a> {
with a more general mechanism",
issue = "0")]
#[doc(hidden)]
pub fn set_panic(sink: Option<Box<Write + Send>>) -> Option<Box<Write + Send>> {
pub fn set_panic(sink: Option<Box<dyn Write + Send>>) -> Option<Box<dyn Write + Send>> {
use panicking::LOCAL_STDERR;
use mem;
LOCAL_STDERR.with(move |slot| {
@ -648,7 +652,7 @@ pub fn set_panic(sink: Option<Box<Write + Send>>) -> Option<Box<Write + Send>> { @@ -648,7 +652,7 @@ pub fn set_panic(sink: Option<Box<Write + Send>>) -> Option<Box<Write + Send>> {
with a more general mechanism",
issue = "0")]
#[doc(hidden)]
pub fn set_print(sink: Option<Box<Write + Send>>) -> Option<Box<Write + Send>> {
pub fn set_print(sink: Option<Box<dyn Write + Send>>) -> Option<Box<dyn Write + Send>> {
use mem;
LOCAL_STDOUT.with(move |slot| {
mem::replace(&mut *slot.borrow_mut(), sink)
@ -670,7 +674,7 @@ pub fn set_print(sink: Option<Box<Write + Send>>) -> Option<Box<Write + Send>> { @@ -670,7 +674,7 @@ pub fn set_print(sink: Option<Box<Write + Send>>) -> Option<Box<Write + Send>> {
/// However, if the actual I/O causes an error, this function does panic.
fn print_to<T>(
args: fmt::Arguments,
local_s: &'static LocalKey<RefCell<Option<Box<Write+Send>>>>,
local_s: &'static LocalKey<RefCell<Option<Box<dyn Write+Send>>>>,
global_s: fn() -> T,
label: &str,
)
@ -712,9 +716,31 @@ pub fn _eprint(args: fmt::Arguments) { @@ -712,9 +716,31 @@ pub fn _eprint(args: fmt::Arguments) {
#[cfg(test)]
mod tests {
use panic::{UnwindSafe, RefUnwindSafe};
use thread;
use super::*;
#[test]
fn stdout_unwind_safe() {
assert_unwind_safe::<Stdout>();
}
#[test]
fn stdoutlock_unwind_safe() {
assert_unwind_safe::<StdoutLock>();
assert_unwind_safe::<StdoutLock<'static>>();
}
#[test]
fn stderr_unwind_safe() {
assert_unwind_safe::<Stderr>();
}
#[test]
fn stderrlock_unwind_safe() {
assert_unwind_safe::<StderrLock>();
assert_unwind_safe::<StderrLock<'static>>();
}
fn assert_unwind_safe<T: UnwindSafe + RefUnwindSafe>() {}
#[test]
#[cfg_attr(target_os = "emscripten", ignore)]
fn panic_doesnt_poison() {

2
ctr-std/src/io/util.rs

@ -223,7 +223,7 @@ mod tests { @@ -223,7 +223,7 @@ mod tests {
assert_eq!(copy(&mut r, &mut w).unwrap(), 4);
let mut r = repeat(0).take(1 << 17);
assert_eq!(copy(&mut r as &mut Read, &mut w as &mut Write).unwrap(), 1 << 17);
assert_eq!(copy(&mut r as &mut dyn Read, &mut w as &mut dyn Write).unwrap(), 1 << 17);
}
#[test]

58
ctr-std/src/keyword_docs.rs

@ -0,0 +1,58 @@ @@ -0,0 +1,58 @@
// Copyright 2018 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.
#[doc(keyword = "fn")]
//
/// The `fn` keyword.
///
/// The `fn` keyword is used to declare a function.
///
/// Example:
///
/// ```rust
/// fn some_function() {
/// // code goes in here
/// }
/// ```
///
/// For more information about functions, take a look at the [Rust Book][book].
///
/// [book]: https://doc.rust-lang.org/book/second-edition/ch03-03-how-functions-work.html
mod fn_keyword { }
#[doc(keyword = "let")]
//
/// The `let` keyword.
///
/// The `let` keyword is used to declare a variable.
///
/// Example:
///
/// ```rust
/// # #![allow(unused_assignments)]
/// let x = 3; // We create a variable named `x` with the value `3`.
/// ```
///
/// By default, all variables are **not** mutable. If you want a mutable variable,
/// you'll have to use the `mut` keyword.
///
/// Example:
///
/// ```rust
/// # #![allow(unused_assignments)]
/// let mut x = 3; // We create a mutable variable named `x` with the value `3`.
///
/// x += 4; // `x` is now equal to `7`.
/// ```
///
/// For more information about the `let` keyword, take a look at the [Rust Book][book].
///
/// [book]: https://doc.rust-lang.org/book/second-edition/ch03-01-variables-and-mutability.html
mod let_keyword { }

76
ctr-std/src/lib.rs

@ -232,15 +232,16 @@ @@ -232,15 +232,16 @@
// std is implemented with unstable features, many of which are internal
// compiler details that will never be stable
#![cfg_attr(test, feature(test, update_panic_count))]
#![feature(alloc)]
#![feature(alloc_error_handler)]
#![feature(allocator_api)]
#![feature(alloc_system)]
#![feature(allocator_internals)]
#![feature(allow_internal_unsafe)]
#![feature(allow_internal_unstable)]
#![feature(align_offset)]
#![feature(arbitrary_self_types)]
#![feature(array_error_internals)]
#![feature(ascii_ctype)]
#![feature(asm)]
#![feature(attr_literals)]
#![feature(box_syntax)]
@ -248,25 +249,22 @@ @@ -248,25 +249,22 @@
#![feature(cfg_target_thread_local)]
#![feature(cfg_target_vendor)]
#![feature(char_error_internals)]
#![feature(char_internals)]
#![feature(collections_range)]
#![feature(compiler_builtins_lib)]
#![feature(const_fn)]
#![feature(const_int_ops)]
#![feature(const_ip)]
#![feature(core_intrinsics)]
#![feature(dropck_eyepatch)]
#![feature(exact_size_is_empty)]
#![feature(external_doc)]
#![feature(fs_read_write)]
#![feature(fixed_size_array)]
#![feature(float_from_str_radix)]
#![feature(fn_traits)]
#![feature(fnbox)]
#![feature(futures_api)]
#![feature(generator_trait)]
#![feature(hashmap_internals)]
#![feature(heap_api)]
#![feature(int_error_internals)]
#![feature(integer_atomics)]
#![feature(into_cow)]
#![feature(lang_items)]
#![feature(libc)]
#![feature(link_args)]
@ -274,35 +272,28 @@ @@ -274,35 +272,28 @@
#![feature(macro_vis_matcher)]
#![feature(needs_panic_runtime)]
#![feature(never_type)]
#![cfg_attr(not(stage0), feature(nll))]
#![feature(exhaustive_patterns)]
#![feature(num_bits_bytes)]
#![feature(old_wrapping)]
#![feature(on_unimplemented)]
#![feature(oom)]
#![feature(optin_builtin_traits)]
#![feature(panic_internals)]
#![feature(panic_unwind)]
#![feature(peek)]
#![feature(pin)]
#![feature(placement_new_protocol)]
#![feature(prelude_import)]
#![feature(ptr_internals)]
#![feature(rand)]
#![feature(raw)]
#![feature(rustc_attrs)]
#![feature(rustc_const_unstable)]
#![feature(std_internals)]
#![feature(stdsimd)]
#![feature(shrink_to)]
#![feature(slice_bytes)]
#![feature(slice_concat_ext)]
#![feature(slice_internals)]
#![feature(slice_patterns)]
#![feature(staged_api)]
#![feature(stmt_expr_attributes)]
#![feature(str_char)]
#![feature(str_internals)]
#![feature(str_utf16)]
#![feature(test, rustc_private)]
#![feature(rustc_private)]
#![feature(thread_local)]
#![feature(toowned_clone_into)]
#![feature(try_from)]
@ -310,18 +301,16 @@ @@ -310,18 +301,16 @@
#![feature(unboxed_closures)]
#![feature(untagged_unions)]
#![feature(unwind_attributes)]
#![feature(use_extern_macros)]
#![feature(vec_push_all)]
#![cfg_attr(stage0, feature(use_extern_macros))]
#![feature(doc_cfg)]
#![feature(doc_masked)]
#![feature(doc_spotlight)]
#![cfg_attr(test, feature(update_panic_count))]
#![cfg_attr(windows, feature(used))]
#![feature(doc_alias)]
#![feature(doc_keyword)]
#![feature(float_internals)]
#![feature(panic_info_message)]
#![cfg_attr(not(stage0), feature(panic_implementation))]
#![feature(panic_implementation)]
#![feature(non_exhaustive)]
#![default_lib_allocator]
@ -331,9 +320,6 @@ @@ -331,9 +320,6 @@
// `force_alloc_system` is *only* intended as a workaround for local rebuilds
// with a rustc without jemalloc.
// FIXME(#44236) shouldn't need MSVC logic
#![cfg_attr(all(not(target_env = "msvc"),
any(all(stage0, not(test)), feature = "force_alloc_system")),
feature(global_allocator))]
#[cfg(all(not(target_env = "msvc"),
any(all(stage0, not(test)), feature = "force_alloc_system")))]
#[global_allocator]
@ -465,20 +451,6 @@ pub use core::u128; @@ -465,20 +451,6 @@ pub use core::u128;
#[stable(feature = "core_hint", since = "1.27.0")]
pub use core::hint;
#[unstable(feature = "futures_api",
reason = "futures in libcore are unstable",
issue = "50547")]
pub mod task {
//! Types and Traits for working with asynchronous tasks.
pub use core::task::*;
pub use alloc_crate::task::*;
}
#[unstable(feature = "futures_api",
reason = "futures in libcore are unstable",
issue = "50547")]
pub use core::future;
pub mod f32;
pub mod f64;
@ -500,13 +472,22 @@ pub mod process; @@ -500,13 +472,22 @@ pub mod process;
pub mod sync;
pub mod time;
#[unstable(feature = "allocator_api", issue = "32838")]
#[rustc_deprecated(since = "1.27.0", reason = "module renamed to `alloc`")]
/// Use the `alloc` module instead.
pub mod heap {
pub use alloc::*;
#[unstable(feature = "futures_api",
reason = "futures in libcore are unstable",
issue = "50547")]
pub mod task {
//! Types and Traits for working with asynchronous tasks.
#[doc(inline)]
pub use core::task::*;
#[doc(inline)]
pub use alloc_crate::task::*;
}
#[unstable(feature = "futures_api",
reason = "futures in libcore are unstable",
issue = "50547")]
pub mod future;
// Platform-abstraction modules
#[macro_use]
mod sys_common;
@ -526,3 +507,8 @@ pub mod rt; @@ -526,3 +507,8 @@ pub mod rt;
// the rustdoc documentation for primitive types. Using `include!`
// because rustdoc only looks for these modules at the crate level.
include!("primitive_docs.rs");
// Include a number of private modules that exist solely to provide
// the rustdoc documentation for the existing keywords. Using `include!`
// because rustdoc only looks for these modules at the crate level.
include!("keyword_docs.rs");

80
ctr-std/src/macros.rs

@ -38,10 +38,13 @@ @@ -38,10 +38,13 @@
/// The multi-argument form of this macro panics with a string and has the
/// [`format!`] syntax for building a string.
///
/// See also the macro [`compile_error!`], for raising errors during compilation.
///
/// [runwrap]: ../std/result/enum.Result.html#method.unwrap
/// [`Option`]: ../std/option/enum.Option.html#method.unwrap
/// [`Result`]: ../std/result/enum.Result.html
/// [`format!`]: ../std/macro.format.html
/// [`compile_error!`]: ../std/macro.compile_error.html
/// [book]: ../book/second-edition/ch09-01-unrecoverable-errors-with-panic.html
///
/// # Current implementation
@ -150,10 +153,12 @@ macro_rules! print { @@ -150,10 +153,12 @@ macro_rules! print {
/// ```
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
#[allow_internal_unstable]
macro_rules! println {
() => (print!("\n"));
($fmt:expr) => (print!(concat!($fmt, "\n")));
($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*));
($($arg:tt)*) => ({
$crate::io::_print(format_args_nl!($($arg)*));
})
}
/// Macro for printing to the standard error.
@ -207,10 +212,34 @@ macro_rules! eprint { @@ -207,10 +212,34 @@ macro_rules! eprint {
/// ```
#[macro_export]
#[stable(feature = "eprint", since = "1.19.0")]
#[allow_internal_unstable]
macro_rules! eprintln {
() => (eprint!("\n"));
($fmt:expr) => (eprint!(concat!($fmt, "\n")));
($fmt:expr, $($arg:tt)*) => (eprint!(concat!($fmt, "\n"), $($arg)*));
($($arg:tt)*) => ({
$crate::io::_eprint(format_args_nl!($($arg)*));
})
}
#[macro_export]
#[unstable(feature = "await_macro", issue = "50547")]
#[allow_internal_unstable]
#[allow_internal_unsafe]
macro_rules! await {
($e:expr) => { {
let mut pinned = $e;
loop {
if let $crate::task::Poll::Ready(x) =
$crate::future::poll_in_task_cx(unsafe {
$crate::mem::PinMut::new_unchecked(&mut pinned)
})
{
break x;
}
// FIXME(cramertj) prior to stabilizing await, we have to ensure that this
// can't be used to create a generator on stable via `|| await!()`.
yield
}
} }
}
/// A macro to select an event from a number of receivers.
@ -281,18 +310,21 @@ macro_rules! assert_approx_eq { @@ -281,18 +310,21 @@ macro_rules! assert_approx_eq {
/// macro, but are documented here. Their implementations can be found hardcoded
/// into libsyntax itself.
#[cfg(dox)]
pub mod builtin {
mod builtin {
/// Unconditionally causes compilation to fail with the given error message when encountered.
///
/// This macro should be used when a crate uses a conditional compilation strategy to provide
/// better error messages for erroneous conditions.
/// better error messages for erroneous conditions. It's the compiler-level form of [`panic!`],
/// which emits an error at *runtime*, rather than during compilation.
///
/// # Examples
///
/// Two such examples are macros and `#[cfg]` environments.
///
/// Emit better compiler error if a macro is passed invalid values.
/// Emit better compiler error if a macro is passed invalid values. Without the final branch,
/// the compiler would still emit an error, but the error's message would not mention the two
/// valid values.
///
/// ```compile_fail
/// macro_rules! give_me_foo_or_bar {
@ -313,8 +345,10 @@ pub mod builtin { @@ -313,8 +345,10 @@ pub mod builtin {
/// #[cfg(not(any(feature = "foo", feature = "bar")))]
/// compile_error!("Either feature \"foo\" or \"bar\" must be enabled for this crate.")
/// ```
///
/// [`panic!`]: ../std/macro.panic.html
#[stable(feature = "compile_error_macro", since = "1.20.0")]
#[macro_export]
#[rustc_doc_only_macro]
macro_rules! compile_error {
($msg:expr) => ({ /* compiler built-in */ });
($msg:expr,) => ({ /* compiler built-in */ });
@ -366,7 +400,7 @@ pub mod builtin { @@ -366,7 +400,7 @@ pub mod builtin {
/// assert_eq!(s, format!("hello {}", "world"));
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[macro_export]
#[rustc_doc_only_macro]
macro_rules! format_args {
($fmt:expr) => ({ /* compiler built-in */ });
($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ });
@ -404,7 +438,7 @@ pub mod builtin { @@ -404,7 +438,7 @@ pub mod builtin {
/// error: what's that?!
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[macro_export]
#[rustc_doc_only_macro]
macro_rules! env {
($name:expr) => ({ /* compiler built-in */ });
($name:expr,) => ({ /* compiler built-in */ });
@ -430,7 +464,7 @@ pub mod builtin { @@ -430,7 +464,7 @@ pub mod builtin {
/// println!("the secret key might be: {:?}", key);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[macro_export]
#[rustc_doc_only_macro]
macro_rules! option_env {
($name:expr) => ({ /* compiler built-in */ });
($name:expr,) => ({ /* compiler built-in */ });
@ -461,7 +495,7 @@ pub mod builtin { @@ -461,7 +495,7 @@ pub mod builtin {
/// # }
/// ```
#[unstable(feature = "concat_idents_macro", issue = "29599")]
#[macro_export]
#[rustc_doc_only_macro]
macro_rules! concat_idents {
($($e:ident),+) => ({ /* compiler built-in */ });
($($e:ident,)+) => ({ /* compiler built-in */ });
@ -483,7 +517,7 @@ pub mod builtin { @@ -483,7 +517,7 @@ pub mod builtin {
/// assert_eq!(s, "test10btrue");
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[macro_export]
#[rustc_doc_only_macro]
macro_rules! concat {
($($e:expr),*) => ({ /* compiler built-in */ });
($($e:expr,)*) => ({ /* compiler built-in */ });
@ -511,7 +545,7 @@ pub mod builtin { @@ -511,7 +545,7 @@ pub mod builtin {
/// println!("defined on line: {}", current_line);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[macro_export]
#[rustc_doc_only_macro]
macro_rules! line { () => ({ /* compiler built-in */ }) }
/// A macro which expands to the column number on which it was invoked.
@ -536,7 +570,7 @@ pub mod builtin { @@ -536,7 +570,7 @@ pub mod builtin {
/// println!("defined on column: {}", current_col);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[macro_export]
#[rustc_doc_only_macro]
macro_rules! column { () => ({ /* compiler built-in */ }) }
/// A macro which expands to the file name from which it was invoked.
@ -560,7 +594,7 @@ pub mod builtin { @@ -560,7 +594,7 @@ pub mod builtin {
/// println!("defined in file: {}", this_file);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[macro_export]
#[rustc_doc_only_macro]
macro_rules! file { () => ({ /* compiler built-in */ }) }
/// A macro which stringifies its arguments.
@ -579,7 +613,7 @@ pub mod builtin { @@ -579,7 +613,7 @@ pub mod builtin {
/// assert_eq!(one_plus_one, "1 + 1");
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[macro_export]
#[rustc_doc_only_macro]
macro_rules! stringify { ($($t:tt)*) => ({ /* compiler built-in */ }) }
/// Includes a utf8-encoded file as a string.
@ -613,7 +647,7 @@ pub mod builtin { @@ -613,7 +647,7 @@ pub mod builtin {
///
/// Compiling 'main.rs' and running the resulting binary will print "adiós".
#[stable(feature = "rust1", since = "1.0.0")]
#[macro_export]
#[rustc_doc_only_macro]
macro_rules! include_str {
($file:expr) => ({ /* compiler built-in */ });
($file:expr,) => ({ /* compiler built-in */ });
@ -650,7 +684,7 @@ pub mod builtin { @@ -650,7 +684,7 @@ pub mod builtin {
///
/// Compiling 'main.rs' and running the resulting binary will print "adiós".
#[stable(feature = "rust1", since = "1.0.0")]
#[macro_export]
#[rustc_doc_only_macro]
macro_rules! include_bytes {
($file:expr) => ({ /* compiler built-in */ });
($file:expr,) => ({ /* compiler built-in */ });
@ -674,7 +708,7 @@ pub mod builtin { @@ -674,7 +708,7 @@ pub mod builtin {
/// test::foo();
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[macro_export]
#[rustc_doc_only_macro]
macro_rules! module_path { () => ({ /* compiler built-in */ }) }
/// Boolean evaluation of configuration flags, at compile-time.
@ -696,7 +730,7 @@ pub mod builtin { @@ -696,7 +730,7 @@ pub mod builtin {
/// };
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[macro_export]
#[rustc_doc_only_macro]
macro_rules! cfg { ($($cfg:tt)*) => ({ /* compiler built-in */ }) }
/// Parse a file as an expression or an item according to the context.
@ -739,7 +773,7 @@ pub mod builtin { @@ -739,7 +773,7 @@ pub mod builtin {
/// Compiling 'main.rs' and running the resulting binary will print
/// "🙈🙊🙉🙈🙊🙉".
#[stable(feature = "rust1", since = "1.0.0")]
#[macro_export]
#[rustc_doc_only_macro]
macro_rules! include {
($file:expr) => ({ /* compiler built-in */ });
($file:expr,) => ({ /* compiler built-in */ });
@ -792,7 +826,7 @@ pub mod builtin { @@ -792,7 +826,7 @@ pub mod builtin {
/// assert!(a + b == 30, "a = {}, b = {}", a, b);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[macro_export]
#[rustc_doc_only_macro]
macro_rules! assert {
($cond:expr) => ({ /* compiler built-in */ });
($cond:expr,) => ({ /* compiler built-in */ });

218
ctr-std/src/net/ip.rs

@ -16,8 +16,6 @@ @@ -16,8 +16,6 @@
use cmp::Ordering;
use fmt;
use hash;
use mem;
use net::{hton, ntoh};
use sys::net::netc as c;
use sys_common::{AsInner, FromInner};
@ -162,9 +160,9 @@ impl IpAddr { @@ -162,9 +160,9 @@ impl IpAddr {
/// ```
#[stable(feature = "ip_shared", since = "1.12.0")]
pub fn is_unspecified(&self) -> bool {
match *self {
IpAddr::V4(ref a) => a.is_unspecified(),
IpAddr::V6(ref a) => a.is_unspecified(),
match self {
IpAddr::V4(ip) => ip.is_unspecified(),
IpAddr::V6(ip) => ip.is_unspecified(),
}
}
@ -187,9 +185,9 @@ impl IpAddr { @@ -187,9 +185,9 @@ impl IpAddr {
/// ```
#[stable(feature = "ip_shared", since = "1.12.0")]
pub fn is_loopback(&self) -> bool {
match *self {
IpAddr::V4(ref a) => a.is_loopback(),
IpAddr::V6(ref a) => a.is_loopback(),
match self {
IpAddr::V4(ip) => ip.is_loopback(),
IpAddr::V6(ip) => ip.is_loopback(),
}
}
@ -216,9 +214,9 @@ impl IpAddr { @@ -216,9 +214,9 @@ impl IpAddr {
/// }
/// ```
pub fn is_global(&self) -> bool {
match *self {
IpAddr::V4(ref a) => a.is_global(),
IpAddr::V6(ref a) => a.is_global(),
match self {
IpAddr::V4(ip) => ip.is_global(),
IpAddr::V6(ip) => ip.is_global(),
}
}
@ -241,9 +239,9 @@ impl IpAddr { @@ -241,9 +239,9 @@ impl IpAddr {
/// ```
#[stable(feature = "ip_shared", since = "1.12.0")]
pub fn is_multicast(&self) -> bool {
match *self {
IpAddr::V4(ref a) => a.is_multicast(),
IpAddr::V6(ref a) => a.is_multicast(),
match self {
IpAddr::V4(ip) => ip.is_multicast(),
IpAddr::V6(ip) => ip.is_multicast(),
}
}
@ -270,9 +268,9 @@ impl IpAddr { @@ -270,9 +268,9 @@ impl IpAddr {
/// }
/// ```
pub fn is_documentation(&self) -> bool {
match *self {
IpAddr::V4(ref a) => a.is_documentation(),
IpAddr::V6(ref a) => a.is_documentation(),
match self {
IpAddr::V4(ip) => ip.is_documentation(),
IpAddr::V6(ip) => ip.is_documentation(),
}
}
@ -295,7 +293,7 @@ impl IpAddr { @@ -295,7 +293,7 @@ impl IpAddr {
/// ```
#[stable(feature = "ipaddr_checker", since = "1.16.0")]
pub fn is_ipv4(&self) -> bool {
match *self {
match self {
IpAddr::V4(_) => true,
IpAddr::V6(_) => false,
}
@ -320,7 +318,7 @@ impl IpAddr { @@ -320,7 +318,7 @@ impl IpAddr {
/// ```
#[stable(feature = "ipaddr_checker", since = "1.16.0")]
pub fn is_ipv6(&self) -> bool {
match *self {
match self {
IpAddr::V4(_) => false,
IpAddr::V6(_) => true,
}
@ -340,18 +338,21 @@ impl Ipv4Addr { @@ -340,18 +338,21 @@ impl Ipv4Addr {
/// let addr = Ipv4Addr::new(127, 0, 0, 1);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr {
#[rustc_const_unstable(feature = "const_ip")]
pub const fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr {
Ipv4Addr {
inner: c::in_addr {
s_addr: hton(((a as u32) << 24) |
((b as u32) << 16) |
((c as u32) << 8) |
(d as u32)),
s_addr: u32::to_be(
((a as u32) << 24) |
((b as u32) << 16) |
((c as u32) << 8) |
(d as u32)
),
}
}
}
/// Creates a new IPv4 address with the address pointing to localhost: 127.0.0.1.
/// An IPv4 address with the address pointing to localhost: 127.0.0.1.
///
/// # Examples
///
@ -359,17 +360,15 @@ impl Ipv4Addr { @@ -359,17 +360,15 @@ impl Ipv4Addr {
/// #![feature(ip_constructors)]
/// use std::net::Ipv4Addr;
///
/// let addr = Ipv4Addr::localhost();
/// let addr = Ipv4Addr::LOCALHOST;
/// assert_eq!(addr, Ipv4Addr::new(127, 0, 0, 1));
/// ```
#[unstable(feature = "ip_constructors",
reason = "requires greater scrutiny before stabilization",
issue = "44582")]
pub fn localhost() -> Ipv4Addr {
Ipv4Addr::new(127, 0, 0, 1)
}
pub const LOCALHOST: Self = Ipv4Addr::new(127, 0, 0, 1);
/// Creates a new IPv4 address representing an unspecified address: 0.0.0.0
/// An IPv4 address representing an unspecified address: 0.0.0.0
///
/// # Examples
///
@ -377,15 +376,29 @@ impl Ipv4Addr { @@ -377,15 +376,29 @@ impl Ipv4Addr {
/// #![feature(ip_constructors)]
/// use std::net::Ipv4Addr;
///
/// let addr = Ipv4Addr::unspecified();
/// let addr = Ipv4Addr::UNSPECIFIED;
/// assert_eq!(addr, Ipv4Addr::new(0, 0, 0, 0));
/// ```
#[unstable(feature = "ip_constructors",
reason = "requires greater scrutiny before stabilization",
issue = "44582")]
pub fn unspecified() -> Ipv4Addr {
Ipv4Addr::new(0, 0, 0, 0)
}
pub const UNSPECIFIED: Self = Ipv4Addr::new(0, 0, 0, 0);
/// An IPv4 address representing the broadcast address: 255.255.255.255
///
/// # Examples
///
/// ```
/// #![feature(ip_constructors)]
/// use std::net::Ipv4Addr;
///
/// let addr = Ipv4Addr::BROADCAST;
/// assert_eq!(addr, Ipv4Addr::new(255, 255, 255, 255));
/// ```
#[unstable(feature = "ip_constructors",
reason = "requires greater scrutiny before stabilization",
issue = "44582")]
pub const BROADCAST: Self = Ipv4Addr::new(255, 255, 255, 255);
/// Returns the four eight-bit integers that make up this address.
///
@ -399,7 +412,7 @@ impl Ipv4Addr { @@ -399,7 +412,7 @@ impl Ipv4Addr {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn octets(&self) -> [u8; 4] {
let bits = ntoh(self.inner.s_addr);
let bits = u32::from_be(self.inner.s_addr);
[(bits >> 24) as u8, (bits >> 16) as u8, (bits >> 8) as u8, bits as u8]
}
@ -470,11 +483,11 @@ impl Ipv4Addr { @@ -470,11 +483,11 @@ impl Ipv4Addr {
/// ```
#[stable(since = "1.7.0", feature = "ip_17")]
pub fn is_private(&self) -> bool {
match (self.octets()[0], self.octets()[1]) {
(10, _) => true,
(172, b) if b >= 16 && b <= 31 => true,
(192, 168) => true,
_ => false
match self.octets() {
[10, ..] => true,
[172, b, ..] if b >= 16 && b <= 31 => true,
[192, 168, ..] => true,
_ => false,
}
}
@ -496,7 +509,10 @@ impl Ipv4Addr { @@ -496,7 +509,10 @@ impl Ipv4Addr {
/// ```
#[stable(since = "1.7.0", feature = "ip_17")]
pub fn is_link_local(&self) -> bool {
self.octets()[0] == 169 && self.octets()[1] == 254
match self.octets() {
[169, 254, ..] => true,
_ => false,
}
}
/// Returns [`true`] if the address appears to be globally routable.
@ -573,8 +589,7 @@ impl Ipv4Addr { @@ -573,8 +589,7 @@ impl Ipv4Addr {
/// ```
#[stable(since = "1.7.0", feature = "ip_17")]
pub fn is_broadcast(&self) -> bool {
self.octets()[0] == 255 && self.octets()[1] == 255 &&
self.octets()[2] == 255 && self.octets()[3] == 255
self == &Self::BROADCAST
}
/// Returns [`true`] if this address is in a range designated for documentation.
@ -600,11 +615,11 @@ impl Ipv4Addr { @@ -600,11 +615,11 @@ impl Ipv4Addr {
/// ```
#[stable(since = "1.7.0", feature = "ip_17")]
pub fn is_documentation(&self) -> bool {
match(self.octets()[0], self.octets()[1], self.octets()[2], self.octets()[3]) {
(192, 0, 2, _) => true,
(198, 51, 100, _) => true,
(203, 0, 113, _) => true,
_ => false
match self.octets() {
[192, 0, 2, _] => true,
[198, 51, 100, _] => true,
[203, 0, 113, _] => true,
_ => false,
}
}
@ -654,9 +669,9 @@ impl Ipv4Addr { @@ -654,9 +669,9 @@ impl Ipv4Addr {
#[stable(feature = "ip_addr", since = "1.7.0")]
impl fmt::Display for IpAddr {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
match *self {
IpAddr::V4(ref a) => a.fmt(fmt),
IpAddr::V6(ref a) => a.fmt(fmt),
match self {
IpAddr::V4(ip) => ip.fmt(fmt),
IpAddr::V6(ip) => ip.fmt(fmt),
}
}
}
@ -705,8 +720,8 @@ impl PartialEq for Ipv4Addr { @@ -705,8 +720,8 @@ impl PartialEq for Ipv4Addr {
#[stable(feature = "ip_cmp", since = "1.16.0")]
impl PartialEq<Ipv4Addr> for IpAddr {
fn eq(&self, other: &Ipv4Addr) -> bool {
match *self {
IpAddr::V4(ref v4) => v4 == other,
match self {
IpAddr::V4(v4) => v4 == other,
IpAddr::V6(_) => false,
}
}
@ -715,8 +730,8 @@ impl PartialEq<Ipv4Addr> for IpAddr { @@ -715,8 +730,8 @@ impl PartialEq<Ipv4Addr> for IpAddr {
#[stable(feature = "ip_cmp", since = "1.16.0")]
impl PartialEq<IpAddr> for Ipv4Addr {
fn eq(&self, other: &IpAddr) -> bool {
match *other {
IpAddr::V4(ref v4) => self == v4,
match other {
IpAddr::V4(v4) => self == v4,
IpAddr::V6(_) => false,
}
}
@ -743,8 +758,8 @@ impl PartialOrd for Ipv4Addr { @@ -743,8 +758,8 @@ impl PartialOrd for Ipv4Addr {
#[stable(feature = "ip_cmp", since = "1.16.0")]
impl PartialOrd<Ipv4Addr> for IpAddr {
fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> {
match *self {
IpAddr::V4(ref v4) => v4.partial_cmp(other),
match self {
IpAddr::V4(v4) => v4.partial_cmp(other),
IpAddr::V6(_) => Some(Ordering::Greater),
}
}
@ -753,8 +768,8 @@ impl PartialOrd<Ipv4Addr> for IpAddr { @@ -753,8 +768,8 @@ impl PartialOrd<Ipv4Addr> for IpAddr {
#[stable(feature = "ip_cmp", since = "1.16.0")]
impl PartialOrd<IpAddr> for Ipv4Addr {
fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> {
match *other {
IpAddr::V4(ref v4) => self.partial_cmp(v4),
match other {
IpAddr::V4(v4) => self.partial_cmp(v4),
IpAddr::V6(_) => Some(Ordering::Less),
}
}
@ -763,7 +778,7 @@ impl PartialOrd<IpAddr> for Ipv4Addr { @@ -763,7 +778,7 @@ impl PartialOrd<IpAddr> for Ipv4Addr {
#[stable(feature = "rust1", since = "1.0.0")]
impl Ord for Ipv4Addr {
fn cmp(&self, other: &Ipv4Addr) -> Ordering {
ntoh(self.inner.s_addr).cmp(&ntoh(other.inner.s_addr))
u32::from_be(self.inner.s_addr).cmp(&u32::from_be(other.inner.s_addr))
}
}
@ -856,21 +871,27 @@ impl Ipv6Addr { @@ -856,21 +871,27 @@ impl Ipv6Addr {
/// let addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16,
h: u16) -> Ipv6Addr {
let mut addr: c::in6_addr = unsafe { mem::zeroed() };
addr.s6_addr = [(a >> 8) as u8, a as u8,
(b >> 8) as u8, b as u8,
(c >> 8) as u8, c as u8,
(d >> 8) as u8, d as u8,
(e >> 8) as u8, e as u8,
(f >> 8) as u8, f as u8,
(g >> 8) as u8, g as u8,
(h >> 8) as u8, h as u8];
Ipv6Addr { inner: addr }
#[rustc_const_unstable(feature = "const_ip")]
pub const fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16,
g: u16, h: u16) -> Ipv6Addr {
Ipv6Addr {
inner: c::in6_addr {
s6_addr: [
(a >> 8) as u8, a as u8,
(b >> 8) as u8, b as u8,
(c >> 8) as u8, c as u8,
(d >> 8) as u8, d as u8,
(e >> 8) as u8, e as u8,
(f >> 8) as u8, f as u8,
(g >> 8) as u8, g as u8,
(h >> 8) as u8, h as u8
],
}
}
}
/// Creates a new IPv6 address representing localhost: `::1`.
/// An IPv6 address representing localhost: `::1`.
///
/// # Examples
///
@ -878,17 +899,15 @@ impl Ipv6Addr { @@ -878,17 +899,15 @@ impl Ipv6Addr {
/// #![feature(ip_constructors)]
/// use std::net::Ipv6Addr;
///
/// let addr = Ipv6Addr::localhost();
/// let addr = Ipv6Addr::LOCALHOST;
/// assert_eq!(addr, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
/// ```
#[unstable(feature = "ip_constructors",
reason = "requires greater scrutiny before stabilization",
issue = "44582")]
pub fn localhost() -> Ipv6Addr {
Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)
}
pub const LOCALHOST: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
/// Creates a new IPv6 address representing the unspecified address: `::`
/// An IPv6 address representing the unspecified address: `::`
///
/// # Examples
///
@ -896,15 +915,13 @@ impl Ipv6Addr { @@ -896,15 +915,13 @@ impl Ipv6Addr {
/// #![feature(ip_constructors)]
/// use std::net::Ipv6Addr;
///
/// let addr = Ipv6Addr::unspecified();
/// let addr = Ipv6Addr::UNSPECIFIED;
/// assert_eq!(addr, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0));
/// ```
#[unstable(feature = "ip_constructors",
reason = "requires greater scrutiny before stabilization",
issue = "44582")]
pub fn unspecified() -> Ipv6Addr {
Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)
}
pub const UNSPECIFIED: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0);
/// Returns the eight 16-bit segments that make up this address.
///
@ -1321,9 +1338,9 @@ impl PartialEq for Ipv6Addr { @@ -1321,9 +1338,9 @@ impl PartialEq for Ipv6Addr {
#[stable(feature = "ip_cmp", since = "1.16.0")]
impl PartialEq<IpAddr> for Ipv6Addr {
fn eq(&self, other: &IpAddr) -> bool {
match *other {
match other {
IpAddr::V4(_) => false,
IpAddr::V6(ref v6) => self == v6,
IpAddr::V6(v6) => self == v6,
}
}
}
@ -1331,9 +1348,9 @@ impl PartialEq<IpAddr> for Ipv6Addr { @@ -1331,9 +1348,9 @@ impl PartialEq<IpAddr> for Ipv6Addr {
#[stable(feature = "ip_cmp", since = "1.16.0")]
impl PartialEq<Ipv6Addr> for IpAddr {
fn eq(&self, other: &Ipv6Addr) -> bool {
match *self {
match self {
IpAddr::V4(_) => false,
IpAddr::V6(ref v6) => v6 == other,
IpAddr::V6(v6) => v6 == other,
}
}
}
@ -1358,9 +1375,9 @@ impl PartialOrd for Ipv6Addr { @@ -1358,9 +1375,9 @@ impl PartialOrd for Ipv6Addr {
#[stable(feature = "ip_cmp", since = "1.16.0")]
impl PartialOrd<Ipv6Addr> for IpAddr {
fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> {
match *self {
match self {
IpAddr::V4(_) => Some(Ordering::Less),
IpAddr::V6(ref v6) => v6.partial_cmp(other),
IpAddr::V6(v6) => v6.partial_cmp(other),
}
}
}
@ -1368,9 +1385,9 @@ impl PartialOrd<Ipv6Addr> for IpAddr { @@ -1368,9 +1385,9 @@ impl PartialOrd<Ipv6Addr> for IpAddr {
#[stable(feature = "ip_cmp", since = "1.16.0")]
impl PartialOrd<IpAddr> for Ipv6Addr {
fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> {
match *other {
match other {
IpAddr::V4(_) => Some(Ordering::Greater),
IpAddr::V6(ref v6) => self.partial_cmp(v6),
IpAddr::V6(v6) => self.partial_cmp(v6),
}
}
}
@ -1414,8 +1431,7 @@ impl From<u128> for Ipv6Addr { @@ -1414,8 +1431,7 @@ impl From<u128> for Ipv6Addr {
#[stable(feature = "ipv6_from_octets", since = "1.9.0")]
impl From<[u8; 16]> for Ipv6Addr {
fn from(octets: [u8; 16]) -> Ipv6Addr {
let mut inner: c::in6_addr = unsafe { mem::zeroed() };
inner.s6_addr = octets;
let inner = c::in6_addr { s6_addr: octets };
Ipv6Addr::from_inner(inner)
}
}
@ -1846,18 +1862,20 @@ mod tests { @@ -1846,18 +1862,20 @@ mod tests {
#[test]
fn ipv4_from_constructors() {
assert_eq!(Ipv4Addr::localhost(), Ipv4Addr::new(127, 0, 0, 1));
assert!(Ipv4Addr::localhost().is_loopback());
assert_eq!(Ipv4Addr::unspecified(), Ipv4Addr::new(0, 0, 0, 0));
assert!(Ipv4Addr::unspecified().is_unspecified());
assert_eq!(Ipv4Addr::LOCALHOST, Ipv4Addr::new(127, 0, 0, 1));
assert!(Ipv4Addr::LOCALHOST.is_loopback());
assert_eq!(Ipv4Addr::UNSPECIFIED, Ipv4Addr::new(0, 0, 0, 0));
assert!(Ipv4Addr::UNSPECIFIED.is_unspecified());
assert_eq!(Ipv4Addr::BROADCAST, Ipv4Addr::new(255, 255, 255, 255));
assert!(Ipv4Addr::BROADCAST.is_broadcast());
}
#[test]
fn ipv6_from_contructors() {
assert_eq!(Ipv6Addr::localhost(), Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
assert!(Ipv6Addr::localhost().is_loopback());
assert_eq!(Ipv6Addr::unspecified(), Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0));
assert!(Ipv6Addr::unspecified().is_unspecified());
assert_eq!(Ipv6Addr::LOCALHOST, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
assert!(Ipv6Addr::LOCALHOST.is_loopback());
assert_eq!(Ipv6Addr::UNSPECIFIED, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0));
assert!(Ipv6Addr::UNSPECIFIED.is_unspecified());
}
#[test]

7
ctr-std/src/net/parser.rs

@ -53,15 +53,12 @@ impl<'a> Parser<'a> { @@ -53,15 +53,12 @@ impl<'a> Parser<'a> {
F: FnOnce(&mut Parser) -> Option<T>,
{
self.read_atomically(move |p| {
match cb(p) {
Some(x) => if p.is_eof() {Some(x)} else {None},
None => None,
}
cb(p).filter(|_| p.is_eof())
})
}
// Return result of first successful parser
fn read_or<T>(&mut self, parsers: &mut [Box<FnMut(&mut Parser) -> Option<T> + 'static>])
fn read_or<T>(&mut self, parsers: &mut [Box<dyn FnMut(&mut Parser) -> Option<T> + 'static>])
-> Option<T> {
for pf in parsers {
if let Some(r) = self.read_atomically(|p: &mut Parser| pf(p)) {

4
ctr-std/src/net/tcp.rs

@ -81,7 +81,7 @@ pub struct TcpStream(net_imp::TcpStream); @@ -81,7 +81,7 @@ pub struct TcpStream(net_imp::TcpStream);
/// }
///
/// fn main() -> io::Result<()> {
/// let listener = TcpListener::bind("127.0.0.1:80").unwrap();
/// let listener = TcpListener::bind("127.0.0.1:80")?;
///
/// // accept connections and process them serially
/// for stream in listener.incoming() {
@ -927,7 +927,7 @@ mod tests { @@ -927,7 +927,7 @@ mod tests {
use time::{Instant, Duration};
use thread;
fn each_ip(f: &mut FnMut(SocketAddr)) {
fn each_ip(f: &mut dyn FnMut(SocketAddr)) {
f(next_test_ip4());
f(next_test_ip6());
}

2
ctr-std/src/net/udp.rs

@ -826,7 +826,7 @@ mod tests { @@ -826,7 +826,7 @@ mod tests {
use time::{Instant, Duration};
use thread;
fn each_ip(f: &mut FnMut(SocketAddr, SocketAddr)) {
fn each_ip(f: &mut dyn FnMut(SocketAddr, SocketAddr)) {
f(next_test_ip4(), next_test_ip4());
f(next_test_ip6(), next_test_ip6());
}

389
ctr-std/src/os/hermit/fs.rs

@ -0,0 +1,389 @@ @@ -0,0 +1,389 @@
// Copyright 2018 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.
#![stable(feature = "metadata_ext", since = "1.1.0")]
use libc;
use fs::Metadata;
use sys_common::AsInner;
#[allow(deprecated)]
use os::hermit::raw;
/// OS-specific extensions to [`fs::Metadata`].
///
/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
#[stable(feature = "metadata_ext", since = "1.1.0")]
pub trait MetadataExt {
/// Gain a reference to the underlying `stat` structure which contains
/// the raw information returned by the OS.
///
/// The contents of the returned [`stat`] are **not** consistent across
/// Unix platforms. The `os::unix::fs::MetadataExt` trait contains the
/// cross-Unix abstractions contained within the raw stat.
///
/// [`stat`]: ../../../../std/os/linux/raw/struct.stat.html
///
/// # Examples
///
/// ```no_run
/// use std::fs;
/// use std::io;
/// use std::os::linux::fs::MetadataExt;
///
/// fn main() -> io::Result<()> {
/// let meta = fs::metadata("some_file")?;
/// let stat = meta.as_raw_stat();
/// Ok(())
/// }
/// ```
#[stable(feature = "metadata_ext", since = "1.1.0")]
#[rustc_deprecated(since = "1.8.0",
reason = "deprecated in favor of the accessor \
methods of this trait")]
#[allow(deprecated)]
fn as_raw_stat(&self) -> &raw::stat;
/// Returns the device ID on which this file resides.
///
/// # Examples
///
/// ```no_run
/// use std::fs;
/// use std::io;
/// use std::os::linux::fs::MetadataExt;
///
/// fn main() -> io::Result<()> {
/// let meta = fs::metadata("some_file")?;
/// println!("{}", meta.st_dev());
/// Ok(())
/// }
/// ```
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_dev(&self) -> u64;
/// Returns the inode number.
///
/// # Examples
///
/// ```no_run
/// use std::fs;
/// use std::io;
/// use std::os::linux::fs::MetadataExt;
///
/// fn main() -> io::Result<()> {
/// let meta = fs::metadata("some_file")?;
/// println!("{}", meta.st_ino());
/// Ok(())
/// }
/// ```
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_ino(&self) -> u64;
/// Returns the file type and mode.
///
/// # Examples
///
/// ```no_run
/// use std::fs;
/// use std::io;
/// use std::os::linux::fs::MetadataExt;
///
/// fn main() -> io::Result<()> {
/// let meta = fs::metadata("some_file")?;
/// println!("{}", meta.st_mode());
/// Ok(())
/// }
/// ```
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_mode(&self) -> u32;
/// Returns the number of hard links to file.
///
/// # Examples
///
/// ```no_run
/// use std::fs;
/// use std::io;
/// use std::os::linux::fs::MetadataExt;
///
/// fn main() -> io::Result<()> {
/// let meta = fs::metadata("some_file")?;
/// println!("{}", meta.st_nlink());
/// Ok(())
/// }
/// ```
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_nlink(&self) -> u64;
/// Returns the user ID of the file owner.
///
/// # Examples
///
/// ```no_run
/// use std::fs;
/// use std::io;
/// use std::os::linux::fs::MetadataExt;
///
/// fn main() -> io::Result<()> {
/// let meta = fs::metadata("some_file")?;
/// println!("{}", meta.st_uid());
/// Ok(())
/// }
/// ```
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_uid(&self) -> u32;
/// Returns the group ID of the file owner.
///
/// # Examples
///
/// ```no_run
/// use std::fs;
/// use std::io;
/// use std::os::linux::fs::MetadataExt;
///
/// fn main() -> io::Result<()> {
/// let meta = fs::metadata("some_file")?;
/// println!("{}", meta.st_gid());
/// Ok(())
/// }
/// ```
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_gid(&self) -> u32;
/// Returns the device ID that this file represents. Only relevant for special file.
///
/// # Examples
///
/// ```no_run
/// use std::fs;
/// use std::io;
/// use std::os::linux::fs::MetadataExt;
///
/// fn main() -> io::Result<()> {
/// let meta = fs::metadata("some_file")?;
/// println!("{}", meta.st_rdev());
/// Ok(())
/// }
/// ```
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_rdev(&self) -> u64;
/// Returns the size of the file (if it is a regular file or a symbolic link) in bytes.
///
/// The size of a symbolic link is the length of the pathname it contains,
/// without a terminating null byte.
///
/// # Examples
///
/// ```no_run
/// use std::fs;
/// use std::io;
/// use std::os::linux::fs::MetadataExt;
///
/// fn main() -> io::Result<()> {
/// let meta = fs::metadata("some_file")?;
/// println!("{}", meta.st_size());
/// Ok(())
/// }
/// ```
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_size(&self) -> u64;
/// Returns the last access time.
///
/// # Examples
///
/// ```no_run
/// use std::fs;
/// use std::io;
/// use std::os::linux::fs::MetadataExt;
///
/// fn main() -> io::Result<()> {
/// let meta = fs::metadata("some_file")?;
/// println!("{}", meta.st_atime());
/// Ok(())
/// }
/// ```
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_atime(&self) -> i64;
/// Returns the last access time, nano seconds part.
///
/// # Examples
///
/// ```no_run
/// use std::fs;
/// use std::io;
/// use std::os::linux::fs::MetadataExt;
///
/// fn main() -> io::Result<()> {
/// let meta = fs::metadata("some_file")?;
/// println!("{}", meta.st_atime_nsec());
/// Ok(())
/// }
/// ```
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_atime_nsec(&self) -> i64;
/// Returns the last modification time.
///
/// # Examples
///
/// ```no_run
/// use std::fs;
/// use std::io;
/// use std::os::linux::fs::MetadataExt;
///
/// fn main() -> io::Result<()> {
/// let meta = fs::metadata("some_file")?;
/// println!("{}", meta.st_mtime());
/// Ok(())
/// }
/// ```
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_mtime(&self) -> i64;
/// Returns the last modification time, nano seconds part.
///
/// # Examples
///
/// ```no_run
/// use std::fs;
/// use std::io;
/// use std::os::linux::fs::MetadataExt;
///
/// fn main() -> io::Result<()> {
/// let meta = fs::metadata("some_file")?;
/// println!("{}", meta.st_mtime_nsec());
/// Ok(())
/// }
/// ```
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_mtime_nsec(&self) -> i64;
/// Returns the last status change time.
///
/// # Examples
///
/// ```no_run
/// use std::fs;
/// use std::io;
/// use std::os::linux::fs::MetadataExt;
///
/// fn main() -> io::Result<()> {
/// let meta = fs::metadata("some_file")?;
/// println!("{}", meta.st_ctime());
/// Ok(())
/// }
/// ```
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_ctime(&self) -> i64;
/// Returns the last status change time, nano seconds part.
///
/// # Examples
///
/// ```no_run
/// use std::fs;
/// use std::io;
/// use std::os::linux::fs::MetadataExt;
///
/// fn main() -> io::Result<()> {
/// let meta = fs::metadata("some_file")?;
/// println!("{}", meta.st_ctime_nsec());
/// Ok(())
/// }
/// ```
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_ctime_nsec(&self) -> i64;
/// Returns the "preferred" blocksize for efficient filesystem I/O.
///
/// # Examples
///
/// ```no_run
/// use std::fs;
/// use std::io;
/// use std::os::linux::fs::MetadataExt;
///
/// fn main() -> io::Result<()> {
/// let meta = fs::metadata("some_file")?;
/// println!("{}", meta.st_blksize());
/// Ok(())
/// }
/// ```
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_blksize(&self) -> u64;
/// Returns the number of blocks allocated to the file, 512-byte units.
///
/// # Examples
///
/// ```no_run
/// use std::fs;
/// use std::io;
/// use std::os::linux::fs::MetadataExt;
///
/// fn main() -> io::Result<()> {
/// let meta = fs::metadata("some_file")?;
/// println!("{}", meta.st_blocks());
/// Ok(())
/// }
/// ```
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_blocks(&self) -> u64;
}
#[stable(feature = "metadata_ext", since = "1.1.0")]
impl MetadataExt for Metadata {
#[allow(deprecated)]
fn as_raw_stat(&self) -> &raw::stat {
unsafe {
&*(self.as_inner().as_inner() as *const libc::stat64
as *const raw::stat)
}
}
fn st_dev(&self) -> u64 {
self.as_inner().as_inner().st_dev as u64
}
fn st_ino(&self) -> u64 {
self.as_inner().as_inner().st_ino as u64
}
fn st_mode(&self) -> u32 {
self.as_inner().as_inner().st_mode as u32
}
fn st_nlink(&self) -> u64 {
self.as_inner().as_inner().st_nlink as u64
}
fn st_uid(&self) -> u32 {
self.as_inner().as_inner().st_uid as u32
}
fn st_gid(&self) -> u32 {
self.as_inner().as_inner().st_gid as u32
}
fn st_rdev(&self) -> u64 {
self.as_inner().as_inner().st_rdev as u64
}
fn st_size(&self) -> u64 {
self.as_inner().as_inner().st_size as u64
}
fn st_atime(&self) -> i64 {
self.as_inner().as_inner().st_atime as i64
}
fn st_atime_nsec(&self) -> i64 {
self.as_inner().as_inner().st_atime_nsec as i64
}
fn st_mtime(&self) -> i64 {
self.as_inner().as_inner().st_mtime as i64
}
fn st_mtime_nsec(&self) -> i64 {
self.as_inner().as_inner().st_mtime_nsec as i64
}
fn st_ctime(&self) -> i64 {
self.as_inner().as_inner().st_ctime as i64
}
fn st_ctime_nsec(&self) -> i64 {
self.as_inner().as_inner().st_ctime_nsec as i64
}
fn st_blksize(&self) -> u64 {
self.as_inner().as_inner().st_blksize as u64
}
fn st_blocks(&self) -> u64 {
self.as_inner().as_inner().st_blocks as u64
}
}

16
ctr-std/src/os/hermit/mod.rs

@ -0,0 +1,16 @@ @@ -0,0 +1,16 @@
// Copyright 2018 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.
//! HermitCore-specific definitions
#![stable(feature = "raw_ext", since = "1.1.0")]
pub mod raw;
pub mod fs;

27
ctr-std/src/os/hermit/raw.rs

@ -0,0 +1,27 @@ @@ -0,0 +1,27 @@
// Copyright 2018 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.
//! HermitCore-specific raw type definitions
#![stable(feature = "raw_ext", since = "1.1.0")]
#![rustc_deprecated(since = "1.8.0",
reason = "these type aliases are no longer supported by \
the standard library, the `libc` crate on \
crates.io should be used instead for the correct \
definitions")]
#![allow(deprecated)]
#![allow(missing_debug_implementations)]
#[stable(feature = "pthread_t", since = "1.8.0")]
pub use libc::pthread_t;
#[doc(inline)]
#[stable(feature = "raw_ext", since = "1.1.0")]
pub use libc::{dev_t, mode_t, off_t, ino_t, nlink_t, blksize_t, blkcnt_t, stat, time_t};

1
ctr-std/src/os/mod.rs

@ -47,6 +47,7 @@ cfg_if! { @@ -47,6 +47,7 @@ cfg_if! {
#[cfg(target_os = "solaris")] pub mod solaris;
#[cfg(target_os = "emscripten")] pub mod emscripten;
#[cfg(target_os = "fuchsia")] pub mod fuchsia;
#[cfg(target_os = "hermit")] pub mod hermit;
#[cfg(target_os = "horizon")] pub mod horizon;
#[cfg(any(target_os = "redox", unix))]

6
ctr-std/src/os/raw/mod.rs

@ -29,6 +29,9 @@ use fmt; @@ -29,6 +29,9 @@ use fmt;
all(target_os = "android", any(target_arch = "aarch64",
target_arch = "arm")),
all(target_os = "l4re", target_arch = "x86_64"),
all(target_os = "netbsd", any(target_arch = "aarch64",
target_arch = "arm",
target_arch = "powerpc")),
all(target_os = "openbsd", target_arch = "aarch64"),
all(target_os = "fuchsia", target_arch = "aarch64")))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = u8;
@ -41,6 +44,9 @@ use fmt; @@ -41,6 +44,9 @@ use fmt;
all(target_os = "android", any(target_arch = "aarch64",
target_arch = "arm")),
all(target_os = "l4re", target_arch = "x86_64"),
all(target_os = "netbsd", any(target_arch = "aarch64",
target_arch = "arm",
target_arch = "powerpc")),
all(target_os = "openbsd", target_arch = "aarch64"),
all(target_os = "fuchsia", target_arch = "aarch64"))))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = i8;

30
ctr-std/src/panic.rs

@ -15,11 +15,14 @@ @@ -15,11 +15,14 @@
use any::Any;
use cell::UnsafeCell;
use fmt;
use future::Future;
use mem::PinMut;
use ops::{Deref, DerefMut};
use panicking;
use ptr::{Unique, NonNull};
use rc::Rc;
use sync::{Arc, Mutex, RwLock, atomic};
use task::{self, Poll};
use thread::Result;
#[stable(feature = "panic_hooks", since = "1.10.0")]
@ -107,8 +110,10 @@ pub use core::panic::{PanicInfo, Location}; @@ -107,8 +110,10 @@ pub use core::panic::{PanicInfo, Location};
///
/// [`AssertUnwindSafe`]: ./struct.AssertUnwindSafe.html
#[stable(feature = "catch_unwind", since = "1.9.0")]
#[rustc_on_unimplemented = "the type {Self} may not be safely transferred \
across an unwind boundary"]
#[rustc_on_unimplemented(
message="the type `{Self}` may not be safely transferred across an unwind boundary",
label="`{Self}` may not be safely transferred across an unwind boundary",
)]
pub auto trait UnwindSafe {}
/// A marker trait representing types where a shared reference is considered
@ -123,9 +128,12 @@ pub auto trait UnwindSafe {} @@ -123,9 +128,12 @@ pub auto trait UnwindSafe {}
/// [`UnsafeCell`]: ../cell/struct.UnsafeCell.html
/// [`UnwindSafe`]: ./trait.UnwindSafe.html
#[stable(feature = "catch_unwind", since = "1.9.0")]
#[rustc_on_unimplemented = "the type {Self} may contain interior mutability \
and a reference may not be safely transferrable \
across a catch_unwind boundary"]
#[rustc_on_unimplemented(
message="the type `{Self}` may contain interior mutability and a reference may not be safely \
transferrable across a catch_unwind boundary",
label="`{Self}` may contain interior mutability and a reference may not be safely \
transferrable across a catch_unwind boundary",
)]
pub auto trait RefUnwindSafe {}
/// A simple wrapper around a type to assert that it is unwind safe.
@ -315,6 +323,16 @@ impl<T: fmt::Debug> fmt::Debug for AssertUnwindSafe<T> { @@ -315,6 +323,16 @@ impl<T: fmt::Debug> fmt::Debug for AssertUnwindSafe<T> {
}
}
#[unstable(feature = "futures_api", issue = "50547")]
impl<'a, F: Future> Future for AssertUnwindSafe<F> {
type Output = F::Output;
fn poll(self: PinMut<Self>, cx: &mut task::Context) -> Poll<Self::Output> {
let pinned_field = unsafe { PinMut::map_unchecked(self, |x| &mut x.0) };
pinned_field.poll(cx)
}
}
/// Invokes a closure, capturing the cause of an unwinding panic if one occurs.
///
/// This function will return `Ok` with the closure's result if the closure
@ -403,6 +421,6 @@ pub fn catch_unwind<F: FnOnce() -> R + UnwindSafe, R>(f: F) -> Result<R> { @@ -403,6 +421,6 @@ pub fn catch_unwind<F: FnOnce() -> R + UnwindSafe, R>(f: F) -> Result<R> {
/// }
/// ```
#[stable(feature = "resume_unwind", since = "1.9.0")]
pub fn resume_unwind(payload: Box<Any + Send>) -> ! {
pub fn resume_unwind(payload: Box<dyn Any + Send>) -> ! {
panicking::update_count_then_panic(payload)
}

132
ctr-std/src/panicking.rs

@ -36,7 +36,7 @@ use sys_common::util; @@ -36,7 +36,7 @@ use sys_common::util;
use thread;
thread_local! {
pub static LOCAL_STDERR: RefCell<Option<Box<Write + Send>>> = {
pub static LOCAL_STDERR: RefCell<Option<Box<dyn Write + Send>>> = {
RefCell::new(None)
}
}
@ -64,7 +64,7 @@ extern { @@ -64,7 +64,7 @@ extern {
#[derive(Copy, Clone)]
enum Hook {
Default,
Custom(*mut (Fn(&PanicInfo) + 'static + Sync + Send)),
Custom(*mut (dyn Fn(&PanicInfo) + 'static + Sync + Send)),
}
static HOOK_LOCK: RWLock = RWLock::new();
@ -104,7 +104,7 @@ static mut HOOK: Hook = Hook::Default; @@ -104,7 +104,7 @@ static mut HOOK: Hook = Hook::Default;
/// panic!("Normal panic");
/// ```
#[stable(feature = "panic_hooks", since = "1.10.0")]
pub fn set_hook(hook: Box<Fn(&PanicInfo) + 'static + Sync + Send>) {
pub fn set_hook(hook: Box<dyn Fn(&PanicInfo) + 'static + Sync + Send>) {
if thread::panicking() {
panic!("cannot modify the panic hook from a panicking thread");
}
@ -149,7 +149,7 @@ pub fn set_hook(hook: Box<Fn(&PanicInfo) + 'static + Sync + Send>) { @@ -149,7 +149,7 @@ pub fn set_hook(hook: Box<Fn(&PanicInfo) + 'static + Sync + Send>) {
/// panic!("Normal panic");
/// ```
#[stable(feature = "panic_hooks", since = "1.10.0")]
pub fn take_hook() -> Box<Fn(&PanicInfo) + 'static + Sync + Send> {
pub fn take_hook() -> Box<dyn Fn(&PanicInfo) + 'static + Sync + Send> {
if thread::panicking() {
panic!("cannot modify the panic hook from a panicking thread");
}
@ -222,7 +222,7 @@ fn default_hook(info: &PanicInfo) { @@ -222,7 +222,7 @@ fn default_hook(info: &PanicInfo) {
consoleDebugInit(debugDevice_SVC);
}
let write = |err: &mut ::io::Write| {
let write = |err: &mut dyn (::io::Write)| {
let _ = writeln!(err, "thread '{}' panicked at '{}', {}",
name, msg, location);
@ -273,7 +273,7 @@ pub fn update_panic_count(amt: isize) -> usize { @@ -273,7 +273,7 @@ pub fn update_panic_count(amt: isize) -> usize {
pub use realstd::rt::update_panic_count;
/// Invoke a closure, capturing the cause of an unwinding panic if one occurs.
pub unsafe fn try<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<Any + Send>> {
pub unsafe fn try<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>> {
#[allow(unions_with_drop_fields)]
union Data<F, R> {
f: F,
@ -344,18 +344,6 @@ pub fn panicking() -> bool { @@ -344,18 +344,6 @@ pub fn panicking() -> bool {
/// Entry point of panic from the libcore crate.
#[cfg(not(test))]
#[cfg(stage0)]
#[lang = "panic_fmt"]
pub extern fn rust_begin_panic(msg: fmt::Arguments,
file: &'static str,
line: u32,
col: u32) -> ! {
begin_panic_fmt(&msg, &(file, line, col))
}
/// Entry point of panic from the libcore crate.
#[cfg(not(test))]
#[cfg(not(stage0))]
#[panic_implementation]
#[unwind(allowed)]
pub fn rust_begin_panic(info: &PanicInfo) -> ! {
@ -368,78 +356,54 @@ pub fn rust_begin_panic(info: &PanicInfo) -> ! { @@ -368,78 +356,54 @@ pub fn rust_begin_panic(info: &PanicInfo) -> ! {
/// site as much as possible (so that `panic!()` has as low an impact
/// on (e.g.) the inlining of other functions as possible), by moving
/// the actual formatting into this shared place.
#[cfg(stage0)]
#[unstable(feature = "libstd_sys_internals",
reason = "used by the panic! macro",
issue = "0")]
#[inline(never)] #[cold]
pub fn begin_panic_fmt(msg: &fmt::Arguments,
file_line_col: &(&'static str, u32, u32)) -> ! {
// We do two allocations here, unfortunately. But (a) they're
// required with the current scheme, and (b) we don't handle
// panic + OOM properly anyway (see comment in begin_panic
// below).
rust_panic_with_hook(&mut PanicPayload::new(msg), Some(msg), file_line_col);
}
// NOTE(stage0) move into `continue_panic_fmt` on next stage0 update
struct PanicPayload<'a> {
inner: &'a fmt::Arguments<'a>,
string: Option<String>,
let (file, line, col) = *file_line_col;
let info = PanicInfo::internal_constructor(
Some(msg),
Location::internal_constructor(file, line, col),
);
continue_panic_fmt(&info)
}
impl<'a> PanicPayload<'a> {
fn new(inner: &'a fmt::Arguments<'a>) -> PanicPayload<'a> {
PanicPayload { inner, string: None }
fn continue_panic_fmt(info: &PanicInfo) -> ! {
struct PanicPayload<'a> {
inner: &'a fmt::Arguments<'a>,
string: Option<String>,
}
fn fill(&mut self) -> &mut String {
use fmt::Write;
impl<'a> PanicPayload<'a> {
fn new(inner: &'a fmt::Arguments<'a>) -> PanicPayload<'a> {
PanicPayload { inner, string: None }
}
let inner = self.inner;
self.string.get_or_insert_with(|| {
let mut s = String::new();
drop(s.write_fmt(*inner));
s
})
}
}
fn fill(&mut self) -> &mut String {
use fmt::Write;
unsafe impl<'a> BoxMeUp for PanicPayload<'a> {
fn box_me_up(&mut self) -> *mut (Any + Send) {
let contents = mem::replace(self.fill(), String::new());
Box::into_raw(Box::new(contents))
let inner = self.inner;
self.string.get_or_insert_with(|| {
let mut s = String::new();
drop(s.write_fmt(*inner));
s
})
}
}
fn get(&mut self) -> &(Any + Send) {
self.fill()
}
}
unsafe impl<'a> BoxMeUp for PanicPayload<'a> {
fn box_me_up(&mut self) -> *mut (dyn Any + Send) {
let contents = mem::replace(self.fill(), String::new());
Box::into_raw(Box::new(contents))
}
/// The entry point for panicking with a formatted message.
///
/// This is designed to reduce the amount of code required at the call
/// site as much as possible (so that `panic!()` has as low an impact
/// on (e.g.) the inlining of other functions as possible), by moving
/// the actual formatting into this shared place.
#[cfg(not(stage0))]
#[unstable(feature = "libstd_sys_internals",
reason = "used by the panic! macro",
issue = "0")]
#[inline(never)] #[cold]
pub fn begin_panic_fmt(msg: &fmt::Arguments,
file_line_col: &(&'static str, u32, u32)) -> ! {
let (file, line, col) = *file_line_col;
let info = PanicInfo::internal_constructor(
Some(msg),
Location::internal_constructor(file, line, col),
);
continue_panic_fmt(&info)
}
fn get(&mut self) -> &(dyn Any + Send) {
self.fill()
}
}
#[cfg(not(stage0))]
fn continue_panic_fmt(info: &PanicInfo) -> ! {
// We do two allocations here, unfortunately. But (a) they're
// required with the current scheme, and (b) we don't handle
// panic + OOM properly anyway (see comment in begin_panic
@ -480,15 +444,15 @@ pub fn begin_panic<M: Any + Send>(msg: M, file_line_col: &(&'static str, u32, u3 @@ -480,15 +444,15 @@ pub fn begin_panic<M: Any + Send>(msg: M, file_line_col: &(&'static str, u32, u3
}
unsafe impl<A: Send + 'static> BoxMeUp for PanicPayload<A> {
fn box_me_up(&mut self) -> *mut (Any + Send) {
fn box_me_up(&mut self) -> *mut (dyn Any + Send) {
let data = match self.inner.take() {
Some(a) => Box::new(a) as Box<Any + Send>,
Some(a) => Box::new(a) as Box<dyn Any + Send>,
None => Box::new(()),
};
Box::into_raw(data)
}
fn get(&mut self) -> &(Any + Send) {
fn get(&mut self) -> &(dyn Any + Send) {
match self.inner {
Some(ref a) => a,
None => &(),
@ -502,7 +466,7 @@ pub fn begin_panic<M: Any + Send>(msg: M, file_line_col: &(&'static str, u32, u3 @@ -502,7 +466,7 @@ pub fn begin_panic<M: Any + Send>(msg: M, file_line_col: &(&'static str, u32, u3
/// Executes the primary logic for a panic, including checking for recursive
/// panics, panic hooks, and finally dispatching to the panic runtime to either
/// abort or unwind.
fn rust_panic_with_hook(payload: &mut BoxMeUp,
fn rust_panic_with_hook(payload: &mut dyn BoxMeUp,
message: Option<&fmt::Arguments>,
file_line_col: &(&str, u32, u32)) -> ! {
let (file, line, col) = *file_line_col;
@ -557,17 +521,17 @@ fn rust_panic_with_hook(payload: &mut BoxMeUp, @@ -557,17 +521,17 @@ fn rust_panic_with_hook(payload: &mut BoxMeUp,
}
/// Shim around rust_panic. Called by resume_unwind.
pub fn update_count_then_panic(msg: Box<Any + Send>) -> ! {
pub fn update_count_then_panic(msg: Box<dyn Any + Send>) -> ! {
update_panic_count(1);
struct RewrapBox(Box<Any + Send>);
struct RewrapBox(Box<dyn Any + Send>);
unsafe impl BoxMeUp for RewrapBox {
fn box_me_up(&mut self) -> *mut (Any + Send) {
fn box_me_up(&mut self) -> *mut (dyn Any + Send) {
Box::into_raw(mem::replace(&mut self.0, Box::new(())))
}
fn get(&mut self) -> &(Any + Send) {
fn get(&mut self) -> &(dyn Any + Send) {
&*self.0
}
}
@ -578,9 +542,9 @@ pub fn update_count_then_panic(msg: Box<Any + Send>) -> ! { @@ -578,9 +542,9 @@ pub fn update_count_then_panic(msg: Box<Any + Send>) -> ! {
/// A private no-mangle function on which to slap yer breakpoints.
#[no_mangle]
#[allow(private_no_mangle_fns)] // yes we get it, but we like breakpoints
pub fn rust_panic(mut msg: &mut BoxMeUp) -> ! {
pub fn rust_panic(mut msg: &mut dyn BoxMeUp) -> ! {
let code = unsafe {
let obj = &mut msg as *mut &mut BoxMeUp;
let obj = &mut msg as *mut &mut dyn BoxMeUp;
__rust_start_panic(obj as usize)
};
rtabort!("failed to initiate panic, error {}", code)

31
ctr-std/src/path.rs

@ -1045,8 +1045,6 @@ impl<'a> cmp::Ord for Components<'a> { @@ -1045,8 +1045,6 @@ impl<'a> cmp::Ord for Components<'a> {
/// # Examples
///
/// ```
/// #![feature(path_ancestors)]
///
/// use std::path::Path;
///
/// let path = Path::new("/foo/bar");
@ -1059,26 +1057,23 @@ impl<'a> cmp::Ord for Components<'a> { @@ -1059,26 +1057,23 @@ impl<'a> cmp::Ord for Components<'a> {
/// [`ancestors`]: struct.Path.html#method.ancestors
/// [`Path`]: struct.Path.html
#[derive(Copy, Clone, Debug)]
#[unstable(feature = "path_ancestors", issue = "48581")]
#[stable(feature = "path_ancestors", since = "1.28.0")]
pub struct Ancestors<'a> {
next: Option<&'a Path>,
}
#[unstable(feature = "path_ancestors", issue = "48581")]
#[stable(feature = "path_ancestors", since = "1.28.0")]
impl<'a> Iterator for Ancestors<'a> {
type Item = &'a Path;
fn next(&mut self) -> Option<Self::Item> {
let next = self.next;
self.next = match next {
Some(path) => path.parent(),
None => None,
};
self.next = next.and_then(Path::parent);
next
}
}
#[unstable(feature = "path_ancestors", issue = "48581")]
#[stable(feature = "path_ancestors", since = "1.28.0")]
impl<'a> FusedIterator for Ancestors<'a> {}
////////////////////////////////////////////////////////////////////////////////
@ -1415,6 +1410,14 @@ impl From<PathBuf> for Box<Path> { @@ -1415,6 +1410,14 @@ impl From<PathBuf> for Box<Path> {
}
}
#[stable(feature = "more_box_slice_clone", since = "1.29.0")]
impl Clone for Box<Path> {
#[inline]
fn clone(&self) -> Self {
self.to_path_buf().into_boxed_path()
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized + AsRef<OsStr>> From<&'a T> for PathBuf {
fn from(s: &'a T) -> PathBuf {
@ -1737,9 +1740,11 @@ impl Path { @@ -1737,9 +1740,11 @@ impl Path {
/// Converts a `Path` to a [`Cow<str>`].
///
/// Any non-Unicode sequences are replaced with U+FFFD REPLACEMENT CHARACTER.
/// Any non-Unicode sequences are replaced with
/// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD].
///
/// [`Cow<str>`]: ../borrow/enum.Cow.html
/// [U+FFFD]: ../char/constant.REPLACEMENT_CHARACTER.html
///
/// # Examples
///
@ -1833,7 +1838,7 @@ impl Path { @@ -1833,7 +1838,7 @@ impl Path {
/// * On Unix, a path has a root if it begins with `/`.
///
/// * On Windows, a path has a root if it:
/// * has no prefix and begins with a separator, e.g. `\\windows`
/// * has no prefix and begins with a separator, e.g. `\windows`
/// * has a prefix followed by a separator, e.g. `c:\windows` but not `c:windows`
/// * has any non-disk prefix, e.g. `\\server\share`
///
@ -1893,8 +1898,6 @@ impl Path { @@ -1893,8 +1898,6 @@ impl Path {
/// # Examples
///
/// ```
/// #![feature(path_ancestors)]
///
/// use std::path::Path;
///
/// let mut ancestors = Path::new("/foo/bar").ancestors();
@ -1906,7 +1909,7 @@ impl Path { @@ -1906,7 +1909,7 @@ impl Path {
///
/// [`None`]: ../../std/option/enum.Option.html#variant.None
/// [`parent`]: struct.Path.html#method.parent
#[unstable(feature = "path_ancestors", issue = "48581")]
#[stable(feature = "path_ancestors", since = "1.28.0")]
pub fn ancestors(&self) -> Ancestors {
Ancestors {
next: Some(&self),

58
ctr-std/src/prelude/v1.rs

@ -12,42 +12,68 @@ @@ -12,42 +12,68 @@
//!
//! See the [module-level documentation](../index.html) for more.
#![stable(feature = "rust1", since = "1.0.0")]
// Re-exported core operators
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)] pub use marker::{Copy, Send, Sized, Sync};
#[doc(no_inline)]
pub use marker::{Copy, Send, Sized, Sync};
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)] pub use ops::{Drop, Fn, FnMut, FnOnce};
#[doc(no_inline)]
pub use ops::{Drop, Fn, FnMut, FnOnce};
// Re-exported functions
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)] pub use mem::drop;
#[doc(no_inline)]
pub use mem::drop;
// Re-exported types and traits
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)] pub use boxed::Box;
#[doc(no_inline)]
pub use clone::Clone;
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)] pub use borrow::ToOwned;
#[doc(no_inline)]
pub use cmp::{PartialEq, PartialOrd, Eq, Ord};
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)] pub use clone::Clone;
#[doc(no_inline)]
pub use convert::{AsRef, AsMut, Into, From};
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)] pub use cmp::{PartialEq, PartialOrd, Eq, Ord};
#[doc(no_inline)]
pub use default::Default;
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)] pub use convert::{AsRef, AsMut, Into, From};
#[doc(no_inline)]
pub use iter::{Iterator, Extend, IntoIterator};
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)] pub use default::Default;
#[doc(no_inline)]
pub use iter::{DoubleEndedIterator, ExactSizeIterator};
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)] pub use iter::{Iterator, Extend, IntoIterator};
#[doc(no_inline)]
pub use option::Option::{self, Some, None};
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)] pub use iter::{DoubleEndedIterator, ExactSizeIterator};
#[doc(no_inline)]
pub use result::Result::{self, Ok, Err};
// The file so far is equivalent to src/libcore/prelude/v1.rs,
// and below to src/liballoc/prelude.rs.
// Those files are duplicated rather than using glob imports
// because we want docs to show these re-exports as pointing to within `std`.
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)] pub use option::Option::{self, Some, None};
#[doc(no_inline)]
pub use boxed::Box;
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)] pub use result::Result::{self, Ok, Err};
#[doc(no_inline)]
pub use borrow::ToOwned;
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)] pub use slice::SliceConcatExt;
#[doc(no_inline)]
pub use slice::SliceConcatExt;
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)] pub use string::{String, ToString};
#[doc(no_inline)]
pub use string::{String, ToString};
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)] pub use vec::Vec;
#[doc(no_inline)]
pub use vec::Vec;

37
ctr-std/src/process.rs

@ -381,6 +381,39 @@ impl fmt::Debug for ChildStderr { @@ -381,6 +381,39 @@ impl fmt::Debug for ChildStderr {
///
/// let hello = output.stdout;
/// ```
///
/// `Command` can be reused to spawn multiple processes. The builder methods
/// change the command without needing to immediately spawn the process.
///
/// ```no_run
/// use std::process::Command;
///
/// let mut echo_hello = Command::new("sh");
/// echo_hello.arg("-c")
/// .arg("echo hello");
/// let hello_1 = echo_hello.output().expect("failed to execute process");
/// let hello_2 = echo_hello.output().expect("failed to execute process");
/// ```
///
/// Similarly, you can call builder methods after spawning a process and then
/// spawn a new process with the modified settings.
///
/// ```no_run
/// use std::process::Command;
///
/// let mut list_dir = Command::new("ls");
///
/// // Execute `ls` in the current directory of the program.
/// list_dir.status().expect("process failed to execute");
///
/// println!("");
///
/// // Change `ls` to execute in the root directory.
/// list_dir.current_dir("/");
///
/// // And then execute `ls` again but in the root directory.
/// list_dir.status().expect("process failed to execute");
/// ```
#[stable(feature = "process", since = "1.0.0")]
pub struct Command {
inner: imp::Command,
@ -813,13 +846,13 @@ impl fmt::Debug for Output { @@ -813,13 +846,13 @@ impl fmt::Debug for Output {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
let stdout_utf8 = str::from_utf8(&self.stdout);
let stdout_debug: &fmt::Debug = match stdout_utf8 {
let stdout_debug: &dyn fmt::Debug = match stdout_utf8 {
Ok(ref str) => str,
Err(_) => &self.stdout
};
let stderr_utf8 = str::from_utf8(&self.stderr);
let stderr_debug: &fmt::Debug = match stderr_utf8 {
let stderr_debug: &dyn fmt::Debug = match stderr_utf8 {
Ok(ref str) => str,
Err(_) => &self.stderr
};

2
ctr-std/src/rt.rs

@ -29,7 +29,7 @@ pub use panicking::{begin_panic, begin_panic_fmt, update_panic_count}; @@ -29,7 +29,7 @@ pub use panicking::{begin_panic, begin_panic_fmt, update_panic_count};
// To reduce the generated code of the new `lang_start`, this function is doing
// the real work.
#[cfg(not(test))]
fn lang_start_internal(main: &(Fn() -> i32 + Sync + ::panic::RefUnwindSafe),
fn lang_start_internal(main: &(dyn Fn() -> i32 + Sync + ::panic::RefUnwindSafe),
argc: isize, argv: *const *const u8) -> isize {
use panic;
use sys;

2
ctr-std/src/sync/mod.rs

@ -18,7 +18,7 @@ @@ -18,7 +18,7 @@
#![stable(feature = "rust1", since = "1.0.0")]
#[stable(feature = "rust1", since = "1.0.0")]
pub use alloc_crate::arc::{Arc, Weak};
pub use alloc_crate::sync::{Arc, Weak};
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::sync::atomic;

40
ctr-std/src/sync/mpsc/mod.rs

@ -689,7 +689,7 @@ impl<T> UnsafeFlavor<T> for Receiver<T> { @@ -689,7 +689,7 @@ impl<T> UnsafeFlavor<T> for Receiver<T> {
/// only one [`Receiver`] is supported.
///
/// If the [`Receiver`] is disconnected while trying to [`send`] with the
/// [`Sender`], the [`send`] method will return a [`SendError`]. Similarly, If the
/// [`Sender`], the [`send`] method will return a [`SendError`]. Similarly, if the
/// [`Sender`] is disconnected while trying to [`recv`], the [`recv`] method will
/// return a [`RecvError`].
///
@ -1247,6 +1247,34 @@ impl<T> Receiver<T> { @@ -1247,6 +1247,34 @@ impl<T> Receiver<T> {
/// [`SyncSender`]: struct.SyncSender.html
/// [`Err`]: ../../../std/result/enum.Result.html#variant.Err
///
/// # Known Issues
///
/// There is currently a known issue (see [`#39364`]) that causes `recv_timeout`
/// to panic unexpectedly with the following example:
///
/// ```no_run
/// use std::sync::mpsc::channel;
/// use std::thread;
/// use std::time::Duration;
///
/// let (tx, rx) = channel::<String>();
///
/// thread::spawn(move || {
/// let d = Duration::from_millis(10);
/// loop {
/// println!("recv");
/// let _r = rx.recv_timeout(d);
/// }
/// });
///
/// thread::sleep(Duration::from_millis(100));
/// let _c1 = tx.clone();
///
/// thread::sleep(Duration::from_secs(1));
/// ```
///
/// [`#39364`]: https://github.com/rust-lang/rust/issues/39364
///
/// # Examples
///
/// Successfully receiving value before encountering timeout:
@ -1638,7 +1666,7 @@ impl<T: Send> error::Error for SendError<T> { @@ -1638,7 +1666,7 @@ impl<T: Send> error::Error for SendError<T> {
"sending on a closed channel"
}
fn cause(&self) -> Option<&error::Error> {
fn cause(&self) -> Option<&dyn error::Error> {
None
}
}
@ -1681,7 +1709,7 @@ impl<T: Send> error::Error for TrySendError<T> { @@ -1681,7 +1709,7 @@ impl<T: Send> error::Error for TrySendError<T> {
}
}
fn cause(&self) -> Option<&error::Error> {
fn cause(&self) -> Option<&dyn error::Error> {
None
}
}
@ -1709,7 +1737,7 @@ impl error::Error for RecvError { @@ -1709,7 +1737,7 @@ impl error::Error for RecvError {
"receiving on a closed channel"
}
fn cause(&self) -> Option<&error::Error> {
fn cause(&self) -> Option<&dyn error::Error> {
None
}
}
@ -1742,7 +1770,7 @@ impl error::Error for TryRecvError { @@ -1742,7 +1770,7 @@ impl error::Error for TryRecvError {
}
}
fn cause(&self) -> Option<&error::Error> {
fn cause(&self) -> Option<&dyn error::Error> {
None
}
}
@ -1783,7 +1811,7 @@ impl error::Error for RecvTimeoutError { @@ -1783,7 +1811,7 @@ impl error::Error for RecvTimeoutError {
}
}
fn cause(&self) -> Option<&error::Error> {
fn cause(&self) -> Option<&dyn error::Error> {
None
}
}

2
ctr-std/src/sync/mpsc/select.rs

@ -93,7 +93,7 @@ pub struct Handle<'rx, T:Send+'rx> { @@ -93,7 +93,7 @@ pub struct Handle<'rx, T:Send+'rx> {
next: *mut Handle<'static, ()>,
prev: *mut Handle<'static, ()>,
added: bool,
packet: &'rx (Packet+'rx),
packet: &'rx (dyn Packet+'rx),
// due to our fun transmutes, we be sure to place this at the end. (nothing
// previous relies on T)

4
ctr-std/src/sync/mutex.rs

@ -227,7 +227,7 @@ impl<T: ?Sized> Mutex<T> { @@ -227,7 +227,7 @@ impl<T: ?Sized> Mutex<T> {
#[stable(feature = "rust1", since = "1.0.0")]
pub fn lock(&self) -> LockResult<MutexGuard<T>> {
unsafe {
self.inner.lock();
self.inner.raw_lock();
MutexGuard::new(self)
}
}
@ -454,7 +454,7 @@ impl<'a, T: ?Sized> Drop for MutexGuard<'a, T> { @@ -454,7 +454,7 @@ impl<'a, T: ?Sized> Drop for MutexGuard<'a, T> {
fn drop(&mut self) {
unsafe {
self.__lock.poison.done(&self.__poison);
self.__lock.inner.unlock();
self.__lock.inner.raw_unlock();
}
}
}

40
ctr-std/src/sync/once.rs

@ -31,12 +31,10 @@ @@ -31,12 +31,10 @@
// initialization closure panics, the Once enters a "poisoned" state which means
// that all future calls will immediately panic as well.
//
// So to implement this, one might first reach for a `StaticMutex`, but those
// unfortunately need to be deallocated (e.g. call `destroy()`) to free memory
// on all OSes (some of the BSDs allocate memory for mutexes). It also gets a
// lot harder with poisoning to figure out when the mutex needs to be
// deallocated because it's not after the closure finishes, but after the first
// successful closure finishes.
// So to implement this, one might first reach for a `Mutex`, but those cannot
// be put into a `static`. It also gets a lot harder with poisoning to figure
// out when the mutex needs to be deallocated because it's not after the closure
// finishes, but after the first successful closure finishes.
//
// All in all, this is instead implemented with atomics and lock-free
// operations! Whee! Each `Once` has one word of atomic state, and this state is
@ -149,9 +147,9 @@ struct Waiter { @@ -149,9 +147,9 @@ struct Waiter {
// Helper struct used to clean up after a closure call with a `Drop`
// implementation to also run on panic.
struct Finish {
struct Finish<'a> {
panicked: bool,
me: &'static Once,
me: &'a Once,
}
impl Once {
@ -178,6 +176,10 @@ impl Once { @@ -178,6 +176,10 @@ impl Once {
/// happens-before relation between the closure and code executing after the
/// return).
///
/// If the given closure recusively invokes `call_once` on the same `Once`
/// instance the exact behavior is not specified, allowed outcomes are
/// a panic or a deadlock.
///
/// # Examples
///
/// ```
@ -218,9 +220,13 @@ impl Once { @@ -218,9 +220,13 @@ impl Once {
///
/// [poison]: struct.Mutex.html#poisoning
#[stable(feature = "rust1", since = "1.0.0")]
pub fn call_once<F>(&'static self, f: F) where F: FnOnce() {
pub fn call_once<F>(&self, f: F) where F: FnOnce() {
// Fast path, just see if we've completed initialization.
if self.state.load(Ordering::SeqCst) == COMPLETE {
// An `Acquire` load is enough because that makes all the initialization
// operations visible to us. The cold path uses SeqCst consistently
// because the performance difference really does not matter there,
// and SeqCst minimizes the chances of something going wrong.
if self.state.load(Ordering::Acquire) == COMPLETE {
return
}
@ -275,9 +281,13 @@ impl Once { @@ -275,9 +281,13 @@ impl Once {
/// INIT.call_once(|| {});
/// ```
#[unstable(feature = "once_poison", issue = "33577")]
pub fn call_once_force<F>(&'static self, f: F) where F: FnOnce(&OnceState) {
pub fn call_once_force<F>(&self, f: F) where F: FnOnce(&OnceState) {
// same as above, just with a different parameter to `call_inner`.
if self.state.load(Ordering::SeqCst) == COMPLETE {
// An `Acquire` load is enough because that makes all the initialization
// operations visible to us. The cold path uses SeqCst consistently
// because the performance difference really does not matter there,
// and SeqCst minimizes the chances of something going wrong.
if self.state.load(Ordering::Acquire) == COMPLETE {
return
}
@ -299,9 +309,9 @@ impl Once { @@ -299,9 +309,9 @@ impl Once {
// currently no way to take an `FnOnce` and call it via virtual dispatch
// without some allocation overhead.
#[cold]
fn call_inner(&'static self,
fn call_inner(&self,
ignore_poisoning: bool,
init: &mut FnMut(bool)) {
init: &mut dyn FnMut(bool)) {
let mut state = self.state.load(Ordering::SeqCst);
'outer: loop {
@ -390,7 +400,7 @@ impl fmt::Debug for Once { @@ -390,7 +400,7 @@ impl fmt::Debug for Once {
}
}
impl Drop for Finish {
impl<'a> Drop for Finish<'a> {
fn drop(&mut self) {
// Swap out our state with however we finished. We should only ever see
// an old state which was RUNNING.

18
ctr-std/src/sys/cloudabi/abi/cloudabi.rs

@ -121,6 +121,7 @@ include!("bitflags.rs"); @@ -121,6 +121,7 @@ include!("bitflags.rs");
/// File or memory access pattern advisory information.
#[repr(u8)]
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
#[non_exhaustive]
pub enum advice {
/// The application expects that it will not access the
/// specified data in the near future.
@ -140,12 +141,12 @@ pub enum advice { @@ -140,12 +141,12 @@ pub enum advice {
/// The application expects to access the specified data
/// in the near future.
WILLNEED = 6,
#[doc(hidden)] _NonExhaustive = -1 as isize as u8,
}
/// Enumeration describing the kind of value stored in [`auxv`](struct.auxv.html).
#[repr(u32)]
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
#[non_exhaustive]
pub enum auxtype {
/// Base address of the binary argument data provided to
/// [`proc_exec()`](fn.proc_exec.html).
@ -210,12 +211,12 @@ pub enum auxtype { @@ -210,12 +211,12 @@ pub enum auxtype {
SYSINFO_EHDR = 262,
/// Thread ID of the initial thread of the process.
TID = 261,
#[doc(hidden)] _NonExhaustive = -1 as isize as u32,
}
/// Identifiers for clocks.
#[repr(u32)]
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
#[non_exhaustive]
pub enum clockid {
/// The system-wide monotonic clock, which is defined as a
/// clock measuring real time, whose value cannot be
@ -232,7 +233,6 @@ pub enum clockid { @@ -232,7 +233,6 @@ pub enum clockid {
REALTIME = 3,
/// The CPU-time clock associated with the current thread.
THREAD_CPUTIME_ID = 4,
#[doc(hidden)] _NonExhaustive = -1 as isize as u32,
}
/// A userspace condition variable.
@ -267,6 +267,7 @@ pub const DIRCOOKIE_START: dircookie = dircookie(0); @@ -267,6 +267,7 @@ pub const DIRCOOKIE_START: dircookie = dircookie(0);
/// exclusively or merely provided for alignment with POSIX.
#[repr(u16)]
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
#[non_exhaustive]
pub enum errno {
/// No error occurred. System call completed successfully.
SUCCESS = 0,
@ -422,7 +423,6 @@ pub enum errno { @@ -422,7 +423,6 @@ pub enum errno {
XDEV = 75,
/// Extension: Capabilities insufficient.
NOTCAPABLE = 76,
#[doc(hidden)] _NonExhaustive = -1 as isize as u16,
}
bitflags! {
@ -438,6 +438,7 @@ bitflags! { @@ -438,6 +438,7 @@ bitflags! {
/// Type of a subscription to an event or its occurrence.
#[repr(u8)]
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
#[non_exhaustive]
pub enum eventtype {
/// The time value of clock [`subscription.union.clock.clock_id`](struct.subscription_clock.html#structfield.clock_id)
/// has reached timestamp [`subscription.union.clock.timeout`](struct.subscription_clock.html#structfield.timeout).
@ -463,7 +464,6 @@ pub enum eventtype { @@ -463,7 +464,6 @@ pub enum eventtype {
/// The process associated with process descriptor
/// [`subscription.union.proc_terminate.fd`](struct.subscription_proc_terminate.html#structfield.fd) has terminated.
PROC_TERMINATE = 7,
#[doc(hidden)] _NonExhaustive = -1 as isize as u8,
}
/// Exit code generated by a process when exiting.
@ -530,6 +530,7 @@ pub type filesize = u64; @@ -530,6 +530,7 @@ pub type filesize = u64;
/// The type of a file descriptor or file.
#[repr(u8)]
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
#[non_exhaustive]
pub enum filetype {
/// The type of the file descriptor or file is unknown or
/// is different from any of the other types specified.
@ -558,7 +559,6 @@ pub enum filetype { @@ -558,7 +559,6 @@ pub enum filetype {
SOCKET_STREAM = 130,
/// The file refers to a symbolic link inode.
SYMBOLIC_LINK = 144,
#[doc(hidden)] _NonExhaustive = -1 as isize as u8,
}
bitflags! {
@ -847,12 +847,12 @@ bitflags! { @@ -847,12 +847,12 @@ bitflags! {
/// memory.
#[repr(u8)]
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
#[non_exhaustive]
pub enum scope {
/// The object is stored in private memory.
PRIVATE = 4,
/// The object is stored in shared memory.
SHARED = 8,
#[doc(hidden)] _NonExhaustive = -1 as isize as u8,
}
bitflags! {
@ -878,6 +878,7 @@ bitflags! { @@ -878,6 +878,7 @@ bitflags! {
/// Signal condition.
#[repr(u8)]
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
#[non_exhaustive]
pub enum signal {
/// Process abort signal.
///
@ -983,7 +984,6 @@ pub enum signal { @@ -983,7 +984,6 @@ pub enum signal {
///
/// Action: Terminates the process.
XFSZ = 26,
#[doc(hidden)] _NonExhaustive = -1 as isize as u8,
}
bitflags! {
@ -1049,6 +1049,7 @@ pub type userdata = u64; @@ -1049,6 +1049,7 @@ pub type userdata = u64;
/// should be set.
#[repr(u8)]
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
#[non_exhaustive]
pub enum whence {
/// Seek relative to current position.
CUR = 1,
@ -1056,7 +1057,6 @@ pub enum whence { @@ -1056,7 +1057,6 @@ pub enum whence {
END = 2,
/// Seek relative to start-of-file.
SET = 3,
#[doc(hidden)] _NonExhaustive = -1 as isize as u8,
}
/// Auxiliary vector entry.

18
ctr-std/src/sys/cloudabi/backtrace.rs

@ -64,6 +64,10 @@ extern "C" fn trace_fn( @@ -64,6 +64,10 @@ extern "C" fn trace_fn(
arg: *mut libc::c_void,
) -> uw::_Unwind_Reason_Code {
let cx = unsafe { &mut *(arg as *mut Context) };
if cx.idx >= cx.frames.len() {
return uw::_URC_NORMAL_STOP;
}
let mut ip_before_insn = 0;
let mut ip = unsafe { uw::_Unwind_GetIPInfo(ctx, &mut ip_before_insn) as *mut libc::c_void };
if !ip.is_null() && ip_before_insn == 0 {
@ -73,14 +77,12 @@ extern "C" fn trace_fn( @@ -73,14 +77,12 @@ extern "C" fn trace_fn(
}
let symaddr = unsafe { uw::_Unwind_FindEnclosingFunction(ip) };
if cx.idx < cx.frames.len() {
cx.frames[cx.idx] = Frame {
symbol_addr: symaddr as *mut u8,
exact_position: ip as *mut u8,
inline_context: 0,
};
cx.idx += 1;
}
cx.frames[cx.idx] = Frame {
symbol_addr: symaddr as *mut u8,
exact_position: ip as *mut u8,
inline_context: 0,
};
cx.idx += 1;
uw::_URC_NO_REASON
}

2
ctr-std/src/sys/cloudabi/thread.rs

@ -32,7 +32,7 @@ unsafe impl Send for Thread {} @@ -32,7 +32,7 @@ unsafe impl Send for Thread {}
unsafe impl Sync for Thread {}
impl Thread {
pub unsafe fn new<'a>(stack: usize, p: Box<FnBox() + 'a>) -> io::Result<Thread> {
pub unsafe fn new<'a>(stack: usize, p: Box<dyn FnBox() + 'a>) -> io::Result<Thread> {
let p = box p;
let mut native: libc::pthread_t = mem::zeroed();
let mut attr: libc::pthread_attr_t = mem::zeroed();

13
ctr-std/src/sys/horizon/net.rs

@ -148,7 +148,9 @@ impl Socket { @@ -148,7 +148,9 @@ impl Socket {
let mut pollfd = libc::pollfd {
fd: self.0.raw(),
events: libc::POLLOUT,
// supposed to be `libc::POLLOUT`, but the value in the `libc` crate is currently
// incorrect for the 3DS
events: 0x10,
revents: 0,
};
@ -184,9 +186,9 @@ impl Socket { @@ -184,9 +186,9 @@ impl Socket {
}
0 => {}
_ => {
// linux returns POLLOUT|POLLERR|POLLHUP for refused connections (!), so look
// for POLLHUP rather than read readiness
if pollfd.revents & libc::POLLHUP != 0 {
// `libc::POLLHUP` should be 0x4, but the constant is currently defined
// incorrectly for 3DS. So we just specifiy it manually for now.
if pollfd.revents & 0x4 != 0 {
let e = self.take_error()?
.unwrap_or_else(|| {
io::Error::new(io::ErrorKind::Other, "no error set after POLLHUP")
@ -343,8 +345,7 @@ impl Socket { @@ -343,8 +345,7 @@ impl Socket {
}
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
let mut nonblocking = nonblocking as libc::c_int;
cvt(unsafe { libc::ioctl(*self.as_inner(), libc::FIONBIO as u32, &mut nonblocking) }).map(|_| ())
self.0.set_nonblocking(nonblocking)
}
pub fn take_error(&self) -> io::Result<Option<io::Error>> {

3
ctr-std/src/sys/mod.rs

@ -70,6 +70,7 @@ cfg_if! { @@ -70,6 +70,7 @@ cfg_if! {
// (missing things in `libc` which is empty) so just omit everything
// with an empty module
#[unstable(issue = "0", feature = "std_internals")]
#[allow(missing_docs)]
pub mod unix_ext {}
} else {
// On other platforms like Windows document the bare bones of unix
@ -83,11 +84,13 @@ cfg_if! { @@ -83,11 +84,13 @@ cfg_if! {
cfg_if! {
if #[cfg(windows)] {
// On windows we'll just be documenting what's already available
#[allow(missing_docs)]
pub use self::ext as windows_ext;
} else if #[cfg(any(target_os = "cloudabi", target_arch = "wasm32"))] {
// On CloudABI and wasm right now the shim below doesn't compile, so
// just omit it
#[unstable(issue = "0", feature = "std_internals")]
#[allow(missing_docs)]
pub mod windows_ext {}
} else {
// On all other platforms (aka linux/osx/etc) then pull in a "minimal"

16
ctr-std/src/sys/redox/args.rs

@ -73,17 +73,15 @@ mod imp { @@ -73,17 +73,15 @@ mod imp {
CStr::from_ptr(*argv.offset(i) as *const libc::c_char).to_bytes().to_vec()
}).collect();
LOCK.lock();
let _guard = LOCK.lock();
let ptr = get_global_ptr();
assert!((*ptr).is_none());
(*ptr) = Some(box args);
LOCK.unlock();
}
pub unsafe fn cleanup() {
LOCK.lock();
let _guard = LOCK.lock();
*get_global_ptr() = None;
LOCK.unlock();
}
pub fn args() -> Args {
@ -96,16 +94,14 @@ mod imp { @@ -96,16 +94,14 @@ mod imp {
fn clone() -> Option<Vec<Vec<u8>>> {
unsafe {
LOCK.lock();
let _guard = LOCK.lock();
let ptr = get_global_ptr();
let ret = (*ptr).as_ref().map(|s| (**s).clone());
LOCK.unlock();
return ret
(*ptr).as_ref().map(|s| (**s).clone())
}
}
fn get_global_ptr() -> *mut Option<Box<Vec<Vec<u8>>>> {
unsafe { mem::transmute(&GLOBAL_ARGS_PTR) }
unsafe fn get_global_ptr() -> *mut Option<Box<Vec<Vec<u8>>>> {
mem::transmute(&GLOBAL_ARGS_PTR)
}
}

18
ctr-std/src/sys/redox/backtrace/tracing.rs

@ -68,6 +68,10 @@ pub fn unwind_backtrace(frames: &mut [Frame]) @@ -68,6 +68,10 @@ pub fn unwind_backtrace(frames: &mut [Frame])
extern fn trace_fn(ctx: *mut uw::_Unwind_Context,
arg: *mut libc::c_void) -> uw::_Unwind_Reason_Code {
let cx = unsafe { &mut *(arg as *mut Context) };
if cx.idx >= cx.frames.len() {
return uw::_URC_NORMAL_STOP;
}
let mut ip_before_insn = 0;
let mut ip = unsafe {
uw::_Unwind_GetIPInfo(ctx, &mut ip_before_insn) as *mut libc::c_void
@ -94,14 +98,12 @@ extern fn trace_fn(ctx: *mut uw::_Unwind_Context, @@ -94,14 +98,12 @@ extern fn trace_fn(ctx: *mut uw::_Unwind_Context,
unsafe { uw::_Unwind_FindEnclosingFunction(ip) }
};
if cx.idx < cx.frames.len() {
cx.frames[cx.idx] = Frame {
symbol_addr: symaddr as *mut u8,
exact_position: ip as *mut u8,
inline_context: 0,
};
cx.idx += 1;
}
cx.frames[cx.idx] = Frame {
symbol_addr: symaddr as *mut u8,
exact_position: ip as *mut u8,
inline_context: 0,
};
cx.idx += 1;
uw::_URC_NO_REASON
}

1
ctr-std/src/sys/redox/ext/mod.rs

@ -33,6 +33,7 @@ @@ -33,6 +33,7 @@
pub mod ffi;
pub mod fs;
pub mod io;
pub mod net;
pub mod process;
pub mod thread;

769
ctr-std/src/sys/redox/ext/net.rs

@ -0,0 +1,769 @@ @@ -0,0 +1,769 @@
// 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.
#![stable(feature = "unix_socket_redox", since = "1.29")]
//! Unix-specific networking functionality
use fmt;
use io::{self, Error, ErrorKind, Initializer};
use net::Shutdown;
use os::unix::io::{RawFd, AsRawFd, FromRawFd, IntoRawFd};
use path::Path;
use time::Duration;
use sys::{cvt, fd::FileDesc, syscall};
/// An address associated with a Unix socket.
///
/// # Examples
///
/// ```
/// use std::os::unix::net::UnixListener;
///
/// let socket = match UnixListener::bind("/tmp/sock") {
/// Ok(sock) => sock,
/// Err(e) => {
/// println!("Couldn't bind: {:?}", e);
/// return
/// }
/// };
/// let addr = socket.local_addr().expect("Couldn't get local address");
/// ```
#[derive(Clone)]
#[stable(feature = "unix_socket_redox", since = "1.29")]
pub struct SocketAddr(());
impl SocketAddr {
/// Returns the contents of this address if it is a `pathname` address.
///
/// # Examples
///
/// With a pathname:
///
/// ```no_run
/// use std::os::unix::net::UnixListener;
/// use std::path::Path;
///
/// let socket = UnixListener::bind("/tmp/sock").unwrap();
/// let addr = socket.local_addr().expect("Couldn't get local address");
/// assert_eq!(addr.as_pathname(), Some(Path::new("/tmp/sock")));
/// ```
///
/// Without a pathname:
///
/// ```
/// use std::os::unix::net::UnixDatagram;
///
/// let socket = UnixDatagram::unbound().unwrap();
/// let addr = socket.local_addr().expect("Couldn't get local address");
/// assert_eq!(addr.as_pathname(), None);
/// ```
#[stable(feature = "unix_socket_redox", since = "1.29")]
pub fn as_pathname(&self) -> Option<&Path> {
None
}
/// Returns true if and only if the address is unnamed.
///
/// # Examples
///
/// A named address:
///
/// ```no_run
/// use std::os::unix::net::UnixListener;
///
/// let socket = UnixListener::bind("/tmp/sock").unwrap();
/// let addr = socket.local_addr().expect("Couldn't get local address");
/// assert_eq!(addr.is_unnamed(), false);
/// ```
///
/// An unnamed address:
///
/// ```
/// use std::os::unix::net::UnixDatagram;
///
/// let socket = UnixDatagram::unbound().unwrap();
/// let addr = socket.local_addr().expect("Couldn't get local address");
/// assert_eq!(addr.is_unnamed(), true);
/// ```
#[stable(feature = "unix_socket_redox", since = "1.29")]
pub fn is_unnamed(&self) -> bool {
false
}
}
#[stable(feature = "unix_socket_redox", since = "1.29")]
impl fmt::Debug for SocketAddr {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "SocketAddr")
}
}
/// A Unix stream socket.
///
/// # Examples
///
/// ```no_run
/// use std::os::unix::net::UnixStream;
/// use std::io::prelude::*;
///
/// let mut stream = UnixStream::connect("/path/to/my/socket").unwrap();
/// stream.write_all(b"hello world").unwrap();
/// let mut response = String::new();
/// stream.read_to_string(&mut response).unwrap();
/// println!("{}", response);
/// ```
#[stable(feature = "unix_socket_redox", since = "1.29")]
pub struct UnixStream(FileDesc);
#[stable(feature = "unix_socket_redox", since = "1.29")]
impl fmt::Debug for UnixStream {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
let mut builder = fmt.debug_struct("UnixStream");
builder.field("fd", &self.0.raw());
if let Ok(addr) = self.local_addr() {
builder.field("local", &addr);
}
if let Ok(addr) = self.peer_addr() {
builder.field("peer", &addr);
}
builder.finish()
}
}
impl UnixStream {
/// Connects to the socket named by `path`.
///
/// # Examples
///
/// ```no_run
/// use std::os::unix::net::UnixStream;
///
/// let socket = match UnixStream::connect("/tmp/sock") {
/// Ok(sock) => sock,
/// Err(e) => {
/// println!("Couldn't connect: {:?}", e);
/// return
/// }
/// };
/// ```
#[stable(feature = "unix_socket_redox", since = "1.29")]
pub fn connect<P: AsRef<Path>>(path: P) -> io::Result<UnixStream> {
if let Some(s) = path.as_ref().to_str() {
cvt(syscall::open(format!("chan:{}", s), syscall::O_CLOEXEC))
.map(FileDesc::new)
.map(UnixStream)
} else {
Err(Error::new(
ErrorKind::Other,
"UnixStream::connect: non-utf8 paths not supported on redox"
))
}
}
/// Creates an unnamed pair of connected sockets.
///
/// Returns two `UnixStream`s which are connected to each other.
///
/// # Examples
///
/// ```no_run
/// use std::os::unix::net::UnixStream;
///
/// let (sock1, sock2) = match UnixStream::pair() {
/// Ok((sock1, sock2)) => (sock1, sock2),
/// Err(e) => {
/// println!("Couldn't create a pair of sockets: {:?}", e);
/// return
/// }
/// };
/// ```
#[stable(feature = "unix_socket_redox", since = "1.29")]
pub fn pair() -> io::Result<(UnixStream, UnixStream)> {
let server = cvt(syscall::open("chan:", syscall::O_CREAT | syscall::O_CLOEXEC))
.map(FileDesc::new)?;
let client = server.duplicate_path(b"connect")?;
let stream = server.duplicate_path(b"listen")?;
Ok((UnixStream(client), UnixStream(stream)))
}
/// Creates a new independently owned handle to the underlying socket.
///
/// The returned `UnixStream` is a reference to the same stream that this
/// object references. Both handles will read and write the same stream of
/// data, and options set on one stream will be propagated to the other
/// stream.
///
/// # Examples
///
/// ```no_run
/// use std::os::unix::net::UnixStream;
///
/// let socket = UnixStream::connect("/tmp/sock").unwrap();
/// let sock_copy = socket.try_clone().expect("Couldn't clone socket");
/// ```
#[stable(feature = "unix_socket_redox", since = "1.29")]
pub fn try_clone(&self) -> io::Result<UnixStream> {
self.0.duplicate().map(UnixStream)
}
/// Returns the socket address of the local half of this connection.
///
/// # Examples
///
/// ```no_run
/// use std::os::unix::net::UnixStream;
///
/// let socket = UnixStream::connect("/tmp/sock").unwrap();
/// let addr = socket.local_addr().expect("Couldn't get local address");
/// ```
#[stable(feature = "unix_socket_redox", since = "1.29")]
pub fn local_addr(&self) -> io::Result<SocketAddr> {
Err(Error::new(ErrorKind::Other, "UnixStream::local_addr unimplemented on redox"))
}
/// Returns the socket address of the remote half of this connection.
///
/// # Examples
///
/// ```no_run
/// use std::os::unix::net::UnixStream;
///
/// let socket = UnixStream::connect("/tmp/sock").unwrap();
/// let addr = socket.peer_addr().expect("Couldn't get peer address");
/// ```
#[stable(feature = "unix_socket_redox", since = "1.29")]
pub fn peer_addr(&self) -> io::Result<SocketAddr> {
Err(Error::new(ErrorKind::Other, "UnixStream::peer_addr unimplemented on redox"))
}
/// Sets the read timeout for the socket.
///
/// If the provided value is [`None`], then [`read`] calls will block
/// indefinitely. An [`Err`] is returned if the zero [`Duration`] is passed to this
/// method.
///
/// [`None`]: ../../../../std/option/enum.Option.html#variant.None
/// [`Err`]: ../../../../std/result/enum.Result.html#variant.Err
/// [`read`]: ../../../../std/io/trait.Read.html#tymethod.read
/// [`Duration`]: ../../../../std/time/struct.Duration.html
///
/// # Examples
///
/// ```no_run
/// use std::os::unix::net::UnixStream;
/// use std::time::Duration;
///
/// let socket = UnixStream::connect("/tmp/sock").unwrap();
/// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout");
/// ```
///
/// An [`Err`] is returned if the zero [`Duration`] is passed to this
/// method:
///
/// ```no_run
/// use std::io;
/// use std::os::unix::net::UnixStream;
/// use std::time::Duration;
///
/// let socket = UnixStream::connect("/tmp/sock").unwrap();
/// let result = socket.set_read_timeout(Some(Duration::new(0, 0)));
/// let err = result.unwrap_err();
/// assert_eq!(err.kind(), io::ErrorKind::InvalidInput)
/// ```
#[stable(feature = "unix_socket_redox", since = "1.29")]
pub fn set_read_timeout(&self, _timeout: Option<Duration>) -> io::Result<()> {
Err(Error::new(ErrorKind::Other, "UnixStream::set_read_timeout unimplemented on redox"))
}
/// Sets the write timeout for the socket.
///
/// If the provided value is [`None`], then [`write`] calls will block
/// indefinitely. An [`Err`] is returned if the zero [`Duration`] is
/// passed to this method.
///
/// [`None`]: ../../../../std/option/enum.Option.html#variant.None
/// [`Err`]: ../../../../std/result/enum.Result.html#variant.Err
/// [`write`]: ../../../../std/io/trait.Write.html#tymethod.write
/// [`Duration`]: ../../../../std/time/struct.Duration.html
///
/// # Examples
///
/// ```no_run
/// use std::os::unix::net::UnixStream;
/// use std::time::Duration;
///
/// let socket = UnixStream::connect("/tmp/sock").unwrap();
/// socket.set_write_timeout(Some(Duration::new(1, 0))).expect("Couldn't set write timeout");
/// ```
///
/// An [`Err`] is returned if the zero [`Duration`] is passed to this
/// method:
///
/// ```no_run
/// use std::io;
/// use std::net::UdpSocket;
/// use std::time::Duration;
///
/// let socket = UdpSocket::bind("127.0.0.1:34254").unwrap();
/// let result = socket.set_write_timeout(Some(Duration::new(0, 0)));
/// let err = result.unwrap_err();
/// assert_eq!(err.kind(), io::ErrorKind::InvalidInput)
/// ```
#[stable(feature = "unix_socket_redox", since = "1.29")]
pub fn set_write_timeout(&self, _timeout: Option<Duration>) -> io::Result<()> {
Err(Error::new(ErrorKind::Other, "UnixStream::set_write_timeout unimplemented on redox"))
}
/// Returns the read timeout of this socket.
///
/// # Examples
///
/// ```no_run
/// use std::os::unix::net::UnixStream;
/// use std::time::Duration;
///
/// let socket = UnixStream::connect("/tmp/sock").unwrap();
/// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout");
/// assert_eq!(socket.read_timeout().unwrap(), Some(Duration::new(1, 0)));
/// ```
#[stable(feature = "unix_socket_redox", since = "1.29")]
pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
Err(Error::new(ErrorKind::Other, "UnixStream::read_timeout unimplemented on redox"))
}
/// Returns the write timeout of this socket.
///
/// # Examples
///
/// ```no_run
/// use std::os::unix::net::UnixStream;
/// use std::time::Duration;
///
/// let socket = UnixStream::connect("/tmp/sock").unwrap();
/// socket.set_write_timeout(Some(Duration::new(1, 0))).expect("Couldn't set write timeout");
/// assert_eq!(socket.write_timeout().unwrap(), Some(Duration::new(1, 0)));
/// ```
#[stable(feature = "unix_socket_redox", since = "1.29")]
pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
Err(Error::new(ErrorKind::Other, "UnixStream::write_timeout unimplemented on redox"))
}
/// Moves the socket into or out of nonblocking mode.
///
/// # Examples
///
/// ```no_run
/// use std::os::unix::net::UnixStream;
///
/// let socket = UnixStream::connect("/tmp/sock").unwrap();
/// socket.set_nonblocking(true).expect("Couldn't set nonblocking");
/// ```
#[stable(feature = "unix_socket_redox", since = "1.29")]
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
self.0.set_nonblocking(nonblocking)
}
/// Returns the value of the `SO_ERROR` option.
///
/// # Examples
///
/// ```no_run
/// use std::os::unix::net::UnixStream;
///
/// let socket = UnixStream::connect("/tmp/sock").unwrap();
/// if let Ok(Some(err)) = socket.take_error() {
/// println!("Got error: {:?}", err);
/// }
/// ```
///
/// # Platform specific
/// On Redox this always returns None.
#[stable(feature = "unix_socket_redox", since = "1.29")]
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
Ok(None)
}
/// Shuts down the read, write, or both halves of this connection.
///
/// This function will cause all pending and future I/O calls on the
/// specified portions to immediately return with an appropriate value
/// (see the documentation of [`Shutdown`]).
///
/// [`Shutdown`]: ../../../../std/net/enum.Shutdown.html
///
/// # Examples
///
/// ```no_run
/// use std::os::unix::net::UnixStream;
/// use std::net::Shutdown;
///
/// let socket = UnixStream::connect("/tmp/sock").unwrap();
/// socket.shutdown(Shutdown::Both).expect("shutdown function failed");
/// ```
#[stable(feature = "unix_socket_redox", since = "1.29")]
pub fn shutdown(&self, _how: Shutdown) -> io::Result<()> {
Err(Error::new(ErrorKind::Other, "UnixStream::shutdown unimplemented on redox"))
}
}
#[stable(feature = "unix_socket_redox", since = "1.29")]
impl io::Read for UnixStream {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
io::Read::read(&mut &*self, buf)
}
#[inline]
unsafe fn initializer(&self) -> Initializer {
Initializer::nop()
}
}
#[stable(feature = "unix_socket_redox", since = "1.29")]
impl<'a> io::Read for &'a UnixStream {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.0.read(buf)
}
#[inline]
unsafe fn initializer(&self) -> Initializer {
Initializer::nop()
}
}
#[stable(feature = "unix_socket_redox", since = "1.29")]
impl io::Write for UnixStream {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
io::Write::write(&mut &*self, buf)
}
fn flush(&mut self) -> io::Result<()> {
io::Write::flush(&mut &*self)
}
}
#[stable(feature = "unix_socket_redox", since = "1.29")]
impl<'a> io::Write for &'a UnixStream {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.0.write(buf)
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
#[stable(feature = "unix_socket_redox", since = "1.29")]
impl AsRawFd for UnixStream {
fn as_raw_fd(&self) -> RawFd {
self.0.raw()
}
}
#[stable(feature = "unix_socket_redox", since = "1.29")]
impl FromRawFd for UnixStream {
unsafe fn from_raw_fd(fd: RawFd) -> UnixStream {
UnixStream(FileDesc::new(fd))
}
}
#[stable(feature = "unix_socket_redox", since = "1.29")]
impl IntoRawFd for UnixStream {
fn into_raw_fd(self) -> RawFd {
self.0.into_raw()
}
}
/// A structure representing a Unix domain socket server.
///
/// # Examples
///
/// ```no_run
/// use std::thread;
/// use std::os::unix::net::{UnixStream, UnixListener};
///
/// fn handle_client(stream: UnixStream) {
/// // ...
/// }
///
/// let listener = UnixListener::bind("/path/to/the/socket").unwrap();
///
/// // accept connections and process them, spawning a new thread for each one
/// for stream in listener.incoming() {
/// match stream {
/// Ok(stream) => {
/// /* connection succeeded */
/// thread::spawn(|| handle_client(stream));
/// }
/// Err(err) => {
/// /* connection failed */
/// break;
/// }
/// }
/// }
/// ```
#[stable(feature = "unix_socket_redox", since = "1.29")]
pub struct UnixListener(FileDesc);
#[stable(feature = "unix_socket_redox", since = "1.29")]
impl fmt::Debug for UnixListener {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
let mut builder = fmt.debug_struct("UnixListener");
builder.field("fd", &self.0.raw());
if let Ok(addr) = self.local_addr() {
builder.field("local", &addr);
}
builder.finish()
}
}
impl UnixListener {
/// Creates a new `UnixListener` bound to the specified socket.
///
/// # Examples
///
/// ```no_run
/// use std::os::unix::net::UnixListener;
///
/// let listener = match UnixListener::bind("/path/to/the/socket") {
/// Ok(sock) => sock,
/// Err(e) => {
/// println!("Couldn't connect: {:?}", e);
/// return
/// }
/// };
/// ```
#[stable(feature = "unix_socket_redox", since = "1.29")]
pub fn bind<P: AsRef<Path>>(path: P) -> io::Result<UnixListener> {
if let Some(s) = path.as_ref().to_str() {
cvt(syscall::open(format!("chan:{}", s), syscall::O_CREAT | syscall::O_CLOEXEC))
.map(FileDesc::new)
.map(UnixListener)
} else {
Err(Error::new(
ErrorKind::Other,
"UnixListener::bind: non-utf8 paths not supported on redox"
))
}
}
/// Accepts a new incoming connection to this listener.
///
/// This function will block the calling thread until a new Unix connection
/// is established. When established, the corresponding [`UnixStream`] and
/// the remote peer's address will be returned.
///
/// [`UnixStream`]: ../../../../std/os/unix/net/struct.UnixStream.html
///
/// # Examples
///
/// ```no_run
/// use std::os::unix::net::UnixListener;
///
/// let listener = UnixListener::bind("/path/to/the/socket").unwrap();
///
/// match listener.accept() {
/// Ok((socket, addr)) => println!("Got a client: {:?}", addr),
/// Err(e) => println!("accept function failed: {:?}", e),
/// }
/// ```
#[stable(feature = "unix_socket_redox", since = "1.29")]
pub fn accept(&self) -> io::Result<(UnixStream, SocketAddr)> {
self.0.duplicate_path(b"listen").map(|fd| (UnixStream(fd), SocketAddr(())))
}
/// Creates a new independently owned handle to the underlying socket.
///
/// The returned `UnixListener` is a reference to the same socket that this
/// object references. Both handles can be used to accept incoming
/// connections and options set on one listener will affect the other.
///
/// # Examples
///
/// ```no_run
/// use std::os::unix::net::UnixListener;
///
/// let listener = UnixListener::bind("/path/to/the/socket").unwrap();
///
/// let listener_copy = listener.try_clone().expect("try_clone failed");
/// ```
#[stable(feature = "unix_socket_redox", since = "1.29")]
pub fn try_clone(&self) -> io::Result<UnixListener> {
self.0.duplicate().map(UnixListener)
}
/// Returns the local socket address of this listener.
///
/// # Examples
///
/// ```no_run
/// use std::os::unix::net::UnixListener;
///
/// let listener = UnixListener::bind("/path/to/the/socket").unwrap();
///
/// let addr = listener.local_addr().expect("Couldn't get local address");
/// ```
#[stable(feature = "unix_socket_redox", since = "1.29")]
pub fn local_addr(&self) -> io::Result<SocketAddr> {
Err(Error::new(ErrorKind::Other, "UnixListener::local_addr unimplemented on redox"))
}
/// Moves the socket into or out of nonblocking mode.
///
/// # Examples
///
/// ```no_run
/// use std::os::unix::net::UnixListener;
///
/// let listener = UnixListener::bind("/path/to/the/socket").unwrap();
///
/// listener.set_nonblocking(true).expect("Couldn't set non blocking");
/// ```
#[stable(feature = "unix_socket_redox", since = "1.29")]
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
self.0.set_nonblocking(nonblocking)
}
/// Returns the value of the `SO_ERROR` option.
///
/// # Examples
///
/// ```no_run
/// use std::os::unix::net::UnixListener;
///
/// let listener = UnixListener::bind("/tmp/sock").unwrap();
///
/// if let Ok(Some(err)) = listener.take_error() {
/// println!("Got error: {:?}", err);
/// }
/// ```
///
/// # Platform specific
/// On Redox this always returns None.
#[stable(feature = "unix_socket_redox", since = "1.29")]
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
Ok(None)
}
/// Returns an iterator over incoming connections.
///
/// The iterator will never return [`None`] and will also not yield the
/// peer's [`SocketAddr`] structure.
///
/// [`None`]: ../../../../std/option/enum.Option.html#variant.None
/// [`SocketAddr`]: struct.SocketAddr.html
///
/// # Examples
///
/// ```no_run
/// use std::thread;
/// use std::os::unix::net::{UnixStream, UnixListener};
///
/// fn handle_client(stream: UnixStream) {
/// // ...
/// }
///
/// let listener = UnixListener::bind("/path/to/the/socket").unwrap();
///
/// for stream in listener.incoming() {
/// match stream {
/// Ok(stream) => {
/// thread::spawn(|| handle_client(stream));
/// }
/// Err(err) => {
/// break;
/// }
/// }
/// }
/// ```
#[stable(feature = "unix_socket_redox", since = "1.29")]
pub fn incoming<'a>(&'a self) -> Incoming<'a> {
Incoming { listener: self }
}
}
#[stable(feature = "unix_socket_redox", since = "1.29")]
impl AsRawFd for UnixListener {
fn as_raw_fd(&self) -> RawFd {
self.0.raw()
}
}
#[stable(feature = "unix_socket_redox", since = "1.29")]
impl FromRawFd for UnixListener {
unsafe fn from_raw_fd(fd: RawFd) -> UnixListener {
UnixListener(FileDesc::new(fd))
}
}
#[stable(feature = "unix_socket_redox", since = "1.29")]
impl IntoRawFd for UnixListener {
fn into_raw_fd(self) -> RawFd {
self.0.into_raw()
}
}
#[stable(feature = "unix_socket_redox", since = "1.29")]
impl<'a> IntoIterator for &'a UnixListener {
type Item = io::Result<UnixStream>;
type IntoIter = Incoming<'a>;
fn into_iter(self) -> Incoming<'a> {
self.incoming()
}
}
/// An iterator over incoming connections to a [`UnixListener`].
///
/// It will never return [`None`].
///
/// [`None`]: ../../../../std/option/enum.Option.html#variant.None
/// [`UnixListener`]: struct.UnixListener.html
///
/// # Examples
///
/// ```no_run
/// use std::thread;
/// use std::os::unix::net::{UnixStream, UnixListener};
///
/// fn handle_client(stream: UnixStream) {
/// // ...
/// }
///
/// let listener = UnixListener::bind("/path/to/the/socket").unwrap();
///
/// for stream in listener.incoming() {
/// match stream {
/// Ok(stream) => {
/// thread::spawn(|| handle_client(stream));
/// }
/// Err(err) => {
/// break;
/// }
/// }
/// }
/// ```
#[derive(Debug)]
#[stable(feature = "unix_socket_redox", since = "1.29")]
pub struct Incoming<'a> {
listener: &'a UnixListener,
}
#[stable(feature = "unix_socket_redox", since = "1.29")]
impl<'a> Iterator for Incoming<'a> {
type Item = io::Result<UnixStream>;
fn next(&mut self) -> Option<io::Result<UnixStream>> {
Some(self.listener.accept().map(|s| s.0))
}
fn size_hint(&self) -> (usize, Option<usize>) {
(usize::max_value(), None)
}
}

5
ctr-std/src/sys/redox/fd.rs

@ -47,7 +47,10 @@ impl FileDesc { @@ -47,7 +47,10 @@ impl FileDesc {
}
pub fn duplicate(&self) -> io::Result<FileDesc> {
let new_fd = cvt(syscall::dup(self.fd, &[]))?;
self.duplicate_path(&[])
}
pub fn duplicate_path(&self, path: &[u8]) -> io::Result<FileDesc> {
let new_fd = cvt(syscall::dup(self.fd, path))?;
Ok(FileDesc::new(new_fd))
}

4
ctr-std/src/sys/redox/net/mod.rs

@ -41,12 +41,12 @@ impl Iterator for LookupHost { @@ -41,12 +41,12 @@ impl Iterator for LookupHost {
pub fn lookup_host(host: &str) -> Result<LookupHost> {
let mut ip_string = String::new();
File::open("/etc/net/ip")?.read_to_string(&mut ip_string)?;
let ip: Vec<u8> = ip_string.trim().split(".").map(|part| part.parse::<u8>()
let ip: Vec<u8> = ip_string.trim().split('.').map(|part| part.parse::<u8>()
.unwrap_or(0)).collect();
let mut dns_string = String::new();
File::open("/etc/net/dns")?.read_to_string(&mut dns_string)?;
let dns: Vec<u8> = dns_string.trim().split(".").map(|part| part.parse::<u8>()
let dns: Vec<u8> = dns_string.trim().split('.').map(|part| part.parse::<u8>()
.unwrap_or(0)).collect();
if ip.len() == 4 && dns.len() == 4 {

2
ctr-std/src/sys/redox/net/netc.rs

@ -24,10 +24,10 @@ pub struct in_addr { @@ -24,10 +24,10 @@ pub struct in_addr {
}
#[derive(Copy, Clone)]
#[repr(align(4))]
#[repr(C)]
pub struct in6_addr {
pub s6_addr: [u8; 16],
__align: [u32; 0],
}
#[derive(Copy, Clone)]

2
ctr-std/src/sys/redox/net/udp.rs

@ -58,7 +58,7 @@ impl UdpSocket { @@ -58,7 +58,7 @@ impl UdpSocket {
pub fn recv(&self, buf: &mut [u8]) -> Result<usize> {
if let Some(addr) = *self.get_conn() {
let from = self.0.dup(format!("{}", addr).as_bytes())?;
let from = self.0.dup(addr.to_string().as_bytes())?;
from.read(buf)
} else {
Err(Error::new(ErrorKind::Other, "UdpSocket::recv not connected"))

3
ctr-std/src/sys/redox/os.rs

@ -30,9 +30,6 @@ use sys_common::mutex::Mutex; @@ -30,9 +30,6 @@ use sys_common::mutex::Mutex;
use sys::{cvt, fd, syscall};
use vec;
const TMPBUF_SZ: usize = 128;
static ENV_LOCK: Mutex = Mutex::new();
extern {
#[link_name = "__errno_location"]
fn errno_location() -> *mut i32;

15
ctr-std/src/sys/redox/process.rs

@ -13,6 +13,7 @@ use ffi::OsStr; @@ -13,6 +13,7 @@ use ffi::OsStr;
use os::unix::ffi::OsStrExt;
use fmt;
use io::{self, Error, ErrorKind};
use iter;
use libc::{EXIT_SUCCESS, EXIT_FAILURE};
use path::{Path, PathBuf};
use sys::fd::FileDesc;
@ -51,7 +52,7 @@ pub struct Command { @@ -51,7 +52,7 @@ pub struct Command {
uid: Option<u32>,
gid: Option<u32>,
saw_nul: bool,
closures: Vec<Box<FnMut() -> io::Result<()> + Send + Sync>>,
closures: Vec<Box<dyn FnMut() -> io::Result<()> + Send + Sync>>,
stdin: Option<Stdio>,
stdout: Option<Stdio>,
stderr: Option<Stdio>,
@ -122,7 +123,7 @@ impl Command { @@ -122,7 +123,7 @@ impl Command {
}
pub fn before_exec(&mut self,
f: Box<FnMut() -> io::Result<()> + Send + Sync>) {
f: Box<dyn FnMut() -> io::Result<()> + Send + Sync>) {
self.closures.push(f);
}
@ -296,11 +297,11 @@ impl Command { @@ -296,11 +297,11 @@ impl Command {
t!(callback());
}
let mut args: Vec<[usize; 2]> = Vec::new();
args.push([self.program.as_ptr() as usize, self.program.len()]);
for arg in self.args.iter() {
args.push([arg.as_ptr() as usize, arg.len()]);
}
let args: Vec<[usize; 2]> = iter::once(
[self.program.as_ptr() as usize, self.program.len()]
).chain(
self.args.iter().map(|arg| [arg.as_ptr() as usize, arg.len()])
).collect();
self.env.apply();

2
ctr-std/src/sys/redox/thread.rs

@ -28,7 +28,7 @@ unsafe impl Send for Thread {} @@ -28,7 +28,7 @@ unsafe impl Send for Thread {}
unsafe impl Sync for Thread {}
impl Thread {
pub unsafe fn new<'a>(_stack: usize, p: Box<FnBox() + 'a>) -> io::Result<Thread> {
pub unsafe fn new<'a>(_stack: usize, p: Box<dyn FnBox() + 'a>) -> io::Result<Thread> {
let p = box p;
let id = cvt(syscall::clone(syscall::CLONE_VM | syscall::CLONE_FS | syscall::CLONE_FILES))?;

19
ctr-std/src/sys/unix/args.rs

@ -66,7 +66,8 @@ impl DoubleEndedIterator for Args { @@ -66,7 +66,8 @@ impl DoubleEndedIterator for Args {
target_os = "emscripten",
target_os = "haiku",
target_os = "l4re",
target_os = "fuchsia"))]
target_os = "fuchsia",
target_os = "hermit"))]
mod imp {
use os::unix::prelude::*;
use ptr;
@ -79,20 +80,20 @@ mod imp { @@ -79,20 +80,20 @@ mod imp {
static mut ARGC: isize = 0;
static mut ARGV: *const *const u8 = ptr::null();
// We never call `ENV_LOCK.init()`, so it is UB to attempt to
// acquire this mutex reentrantly!
static LOCK: Mutex = Mutex::new();
pub unsafe fn init(argc: isize, argv: *const *const u8) {
LOCK.lock();
let _guard = LOCK.lock();
ARGC = argc;
ARGV = argv;
LOCK.unlock();
}
pub unsafe fn cleanup() {
LOCK.lock();
let _guard = LOCK.lock();
ARGC = 0;
ARGV = ptr::null();
LOCK.unlock();
}
pub fn args() -> Args {
@ -104,13 +105,11 @@ mod imp { @@ -104,13 +105,11 @@ mod imp {
fn clone() -> Vec<OsString> {
unsafe {
LOCK.lock();
let ret = (0..ARGC).map(|i| {
let _guard = LOCK.lock();
(0..ARGC).map(|i| {
let cstr = CStr::from_ptr(*ARGV.offset(i) as *const libc::c_char);
OsStringExt::from_vec(cstr.to_bytes().to_vec())
}).collect();
LOCK.unlock();
return ret
}).collect()
}
}
}

18
ctr-std/src/sys/unix/backtrace/tracing/gcc_s.rs

@ -68,6 +68,10 @@ pub fn unwind_backtrace(frames: &mut [Frame]) @@ -68,6 +68,10 @@ pub fn unwind_backtrace(frames: &mut [Frame])
extern fn trace_fn(ctx: *mut uw::_Unwind_Context,
arg: *mut libc::c_void) -> uw::_Unwind_Reason_Code {
let cx = unsafe { &mut *(arg as *mut Context) };
if cx.idx >= cx.frames.len() {
return uw::_URC_NORMAL_STOP;
}
let mut ip_before_insn = 0;
let mut ip = unsafe {
uw::_Unwind_GetIPInfo(ctx, &mut ip_before_insn) as *mut libc::c_void
@ -94,14 +98,12 @@ extern fn trace_fn(ctx: *mut uw::_Unwind_Context, @@ -94,14 +98,12 @@ extern fn trace_fn(ctx: *mut uw::_Unwind_Context,
unsafe { uw::_Unwind_FindEnclosingFunction(ip) }
};
if cx.idx < cx.frames.len() {
cx.frames[cx.idx] = Frame {
symbol_addr: symaddr as *mut u8,
exact_position: ip as *mut u8,
inline_context: 0,
};
cx.idx += 1;
}
cx.frames[cx.idx] = Frame {
symbol_addr: symaddr as *mut u8,
exact_position: ip as *mut u8,
inline_context: 0,
};
cx.idx += 1;
uw::_URC_NO_REASON
}

13
ctr-std/src/sys/unix/condvar.rs

@ -41,13 +41,15 @@ impl Condvar { @@ -41,13 +41,15 @@ impl Condvar {
#[cfg(any(target_os = "macos",
target_os = "ios",
target_os = "l4re",
target_os = "android"))]
target_os = "android",
target_os = "hermit"))]
pub unsafe fn init(&mut self) {}
#[cfg(not(any(target_os = "macos",
target_os = "ios",
target_os = "l4re",
target_os = "android")))]
target_os = "android",
target_os = "hermit")))]
pub unsafe fn init(&mut self) {
use mem;
let mut attr: libc::pthread_condattr_t = mem::uninitialized();
@ -83,7 +85,10 @@ impl Condvar { @@ -83,7 +85,10 @@ impl Condvar {
// where we configure condition variable to use monotonic clock (instead of
// default system clock). This approach avoids all problems that result
// from changes made to the system time.
#[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "android")))]
#[cfg(not(any(target_os = "macos",
target_os = "ios",
target_os = "android",
target_os = "hermit")))]
pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
use mem;
@ -113,7 +118,7 @@ impl Condvar { @@ -113,7 +118,7 @@ impl Condvar {
// This implementation is modeled after libcxx's condition_variable
// https://github.com/llvm-mirror/libcxx/blob/release_35/src/condition_variable.cpp#L46
// https://github.com/llvm-mirror/libcxx/blob/release_35/include/__mutex_base#L367
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "android"))]
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "android", target_os = "hermit"))]
pub unsafe fn wait_timeout(&self, mutex: &Mutex, mut dur: Duration) -> bool {
use ptr;
use time::Instant;

11
ctr-std/src/sys/unix/env.rs

@ -172,3 +172,14 @@ pub mod os { @@ -172,3 +172,14 @@ pub mod os {
pub const EXE_SUFFIX: &'static str = "";
pub const EXE_EXTENSION: &'static str = "";
}
#[cfg(target_os = "hermit")]
pub mod os {
pub const FAMILY: &'static str = "unix";
pub const OS: &'static str = "hermit";
pub const DLL_PREFIX: &'static str = "lib";
pub const DLL_SUFFIX: &'static str = ".so";
pub const DLL_EXTENSION: &'static str = "so";
pub const EXE_SUFFIX: &'static str = "";
pub const EXE_EXTENSION: &'static str = "";
}

127
ctr-std/src/sys/unix/ext/fs.rs

@ -59,6 +59,78 @@ pub trait FileExt { @@ -59,6 +59,78 @@ pub trait FileExt {
#[stable(feature = "file_offset", since = "1.15.0")]
fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize>;
/// Reads the exact number of byte required to fill `buf` from the given offset.
///
/// The offset is relative to the start of the file and thus independent
/// from the current cursor.
///
/// The current file cursor is not affected by this function.
///
/// Similar to [`Read::read_exact`] but uses [`read_at`] instead of `read`.
///
/// [`Read::read_exact`]: ../../../../std/io/trait.Read.html#method.read_exact
/// [`read_at`]: #tymethod.read_at
///
/// # Errors
///
/// If this function encounters an error of the kind
/// [`ErrorKind::Interrupted`] then the error is ignored and the operation
/// will continue.
///
/// If this function encounters an "end of file" before completely filling
/// the buffer, it returns an error of the kind [`ErrorKind::UnexpectedEof`].
/// The contents of `buf` are unspecified in this case.
///
/// If any other read error is encountered then this function immediately
/// returns. The contents of `buf` are unspecified in this case.
///
/// If this function returns an error, it is unspecified how many bytes it
/// has read, but it will never read more than would be necessary to
/// completely fill the buffer.
///
/// [`ErrorKind::Interrupted`]: ../../../../std/io/enum.ErrorKind.html#variant.Interrupted
/// [`ErrorKind::UnexpectedEof`]: ../../../../std/io/enum.ErrorKind.html#variant.UnexpectedEof
///
/// # Examples
///
/// ```no_run
/// #![feature(rw_exact_all_at)]
/// use std::io;
/// use std::fs::File;
/// use std::os::unix::prelude::FileExt;
///
/// fn main() -> io::Result<()> {
/// let mut buf = [0u8; 8];
/// let file = File::open("foo.txt")?;
///
/// // We now read exactly 8 bytes from the offset 10.
/// file.read_exact_at(&mut buf, 10)?;
/// println!("read {} bytes: {:?}", buf.len(), buf);
/// Ok(())
/// }
/// ```
#[unstable(feature = "rw_exact_all_at", issue = "51984")]
fn read_exact_at(&self, mut buf: &mut [u8], mut offset: u64) -> io::Result<()> {
while !buf.is_empty() {
match self.read_at(buf, offset) {
Ok(0) => break,
Ok(n) => {
let tmp = buf;
buf = &mut tmp[n..];
offset += n as u64;
}
Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
Err(e) => return Err(e),
}
}
if !buf.is_empty() {
Err(io::Error::new(io::ErrorKind::UnexpectedEof,
"failed to fill whole buffer"))
} else {
Ok(())
}
}
/// Writes a number of bytes starting from a given offset.
///
/// Returns the number of bytes written.
@ -93,6 +165,61 @@ pub trait FileExt { @@ -93,6 +165,61 @@ pub trait FileExt {
/// ```
#[stable(feature = "file_offset", since = "1.15.0")]
fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize>;
/// Attempts to write an entire buffer starting from a given offset.
///
/// The offset is relative to the start of the file and thus independent
/// from the current cursor.
///
/// The current file cursor is not affected by this function.
///
/// This method will continuously call [`write_at`] until there is no more data
/// to be written or an error of non-[`ErrorKind::Interrupted`] kind is
/// returned. This method will not return until the entire buffer has been
/// successfully written or such an error occurs. The first error that is
/// not of [`ErrorKind::Interrupted`] kind generated from this method will be
/// returned.
///
/// # Errors
///
/// This function will return the first error of
/// non-[`ErrorKind::Interrupted`] kind that [`write_at`] returns.
///
/// [`ErrorKind::Interrupted`]: ../../../../std/io/enum.ErrorKind.html#variant.Interrupted
/// [`write_at`]: #tymethod.write_at
///
/// # Examples
///
/// ```no_run
/// #![feature(rw_exact_all_at)]
/// use std::fs::File;
/// use std::io;
/// use std::os::unix::prelude::FileExt;
///
/// fn main() -> io::Result<()> {
/// let file = File::open("foo.txt")?;
///
/// // We now write at the offset 10.
/// file.write_all_at(b"sushi", 10)?;
/// Ok(())
/// }
/// ```
#[unstable(feature = "rw_exact_all_at", issue = "51984")]
fn write_all_at(&self, mut buf: &[u8], mut offset: u64) -> io::Result<()> {
while !buf.is_empty() {
match self.write_at(buf, offset) {
Ok(0) => return Err(io::Error::new(io::ErrorKind::WriteZero,
"failed to write whole buffer")),
Ok(n) => {
buf = &buf[n..];
offset += n as u64
}
Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
Err(e) => return Err(e),
}
}
Ok(())
}
}
#[stable(feature = "file_offset", since = "1.15.0")]

1
ctr-std/src/sys/unix/ext/mod.rs

@ -35,6 +35,7 @@ @@ -35,6 +35,7 @@
#![stable(feature = "rust1", since = "1.0.0")]
#![doc(cfg(unix))]
#![allow(missing_docs)]
pub mod io;
pub mod ffi;

6
ctr-std/src/sys/unix/ext/net.rs

@ -524,6 +524,9 @@ impl UnixStream { @@ -524,6 +524,9 @@ impl UnixStream {
/// println!("Got error: {:?}", err);
/// }
/// ```
///
/// # Platform specific
/// On Redox this always returns None.
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
self.0.take_error()
@ -846,6 +849,9 @@ impl UnixListener { @@ -846,6 +849,9 @@ impl UnixListener {
/// println!("Got error: {:?}", err);
/// }
/// ```
///
/// # Platform specific
/// On Redox this always returns None.
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
self.0.take_error()

7
ctr-std/src/sys/unix/fast_thread_local.rs

@ -20,7 +20,7 @@ @@ -20,7 +20,7 @@
// fallback implementation to use as well.
//
// Due to rust-lang/rust#18804, make sure this is not generic!
#[cfg(target_os = "linux")]
#[cfg(any(target_os = "linux", target_os = "fuchsia", target_os = "hermit"))]
pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) {
use libc;
use mem;
@ -55,11 +55,6 @@ pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) { @@ -55,11 +55,6 @@ pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) {
_tlv_atexit(dtor, t);
}
// Just use the thread_local fallback implementation, at least until there's
// a more direct implementation.
#[cfg(target_os = "fuchsia")]
pub use sys_common::thread_local::register_dtor_fallback as register_dtor;
pub fn requires_move_before_drop() -> bool {
// The macOS implementation of TLS apparently had an odd aspect to it
// where the pointer we have may be overwritten while this destructor

56
ctr-std/src/sys/unix/fs.rs

@ -25,10 +25,12 @@ use sys_common::{AsInner, FromInner}; @@ -25,10 +25,12 @@ use sys_common::{AsInner, FromInner};
#[cfg(any(target_os = "linux", target_os = "emscripten", target_os = "l4re"))]
use libc::{stat64, fstat64, lstat64, off64_t, ftruncate64, lseek64, dirent64, readdir64_r, open64};
#[cfg(any(target_os = "linux", target_os = "emscripten"))]
use libc::fstatat64;
#[cfg(any(target_os = "linux", target_os = "emscripten", target_os = "android"))]
use libc::{fstatat, dirfd};
use libc::dirfd;
#[cfg(target_os = "android")]
use libc::{stat as stat64, fstat as fstat64, lstat as lstat64, lseek64,
use libc::{stat as stat64, fstat as fstat64, fstatat as fstatat64, lstat as lstat64, lseek64,
dirent as dirent64, open as open64};
#[cfg(not(any(target_os = "linux",
target_os = "emscripten",
@ -57,7 +59,10 @@ struct InnerReadDir { @@ -57,7 +59,10 @@ struct InnerReadDir {
}
#[derive(Clone)]
pub struct ReadDir(Arc<InnerReadDir>);
pub struct ReadDir {
inner: Arc<InnerReadDir>,
end_of_stream: bool,
}
struct Dir(*mut libc::DIR);
@ -213,7 +218,7 @@ impl fmt::Debug for ReadDir { @@ -213,7 +218,7 @@ impl fmt::Debug for ReadDir {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// This will only be called from std::fs::ReadDir, which will add a "ReadDir()" frame.
// Thus the result will be e g 'ReadDir("/home")'
fmt::Debug::fmt(&*self.0.root, f)
fmt::Debug::fmt(&*self.inner.root, f)
}
}
@ -229,7 +234,7 @@ impl Iterator for ReadDir { @@ -229,7 +234,7 @@ impl Iterator for ReadDir {
// is safe to use in threaded applications and it is generally preferred
// over the readdir_r(3C) function.
super::os::set_errno(0);
let entry_ptr = libc::readdir(self.0.dirp.0);
let entry_ptr = libc::readdir(self.inner.dirp.0);
if entry_ptr.is_null() {
// NULL can mean either the end is reached or an error occurred.
// So we had to clear errno beforehand to check for an error now.
@ -257,6 +262,10 @@ impl Iterator for ReadDir { @@ -257,6 +262,10 @@ impl Iterator for ReadDir {
#[cfg(not(any(target_os = "solaris", target_os = "fuchsia")))]
fn next(&mut self) -> Option<io::Result<DirEntry>> {
if self.end_of_stream {
return None;
}
unsafe {
let mut ret = DirEntry {
entry: mem::zeroed(),
@ -264,7 +273,14 @@ impl Iterator for ReadDir { @@ -264,7 +273,14 @@ impl Iterator for ReadDir {
};
let mut entry_ptr = ptr::null_mut();
loop {
if readdir64_r(self.0.dirp.0, &mut ret.entry, &mut entry_ptr) != 0 {
if readdir64_r(self.inner.dirp.0, &mut ret.entry, &mut entry_ptr) != 0 {
if entry_ptr.is_null() {
// We encountered an error (which will be returned in this iteration), but
// we also reached the end of the directory stream. The `end_of_stream`
// flag is enabled to make sure that we return `None` in the next iteration
// (instead of looping forever)
self.end_of_stream = true;
}
return Some(Err(Error::last_os_error()))
}
if entry_ptr.is_null() {
@ -287,7 +303,7 @@ impl Drop for Dir { @@ -287,7 +303,7 @@ impl Drop for Dir {
impl DirEntry {
pub fn path(&self) -> PathBuf {
self.dir.0.root.join(OsStr::from_bytes(self.name_bytes()))
self.dir.inner.root.join(OsStr::from_bytes(self.name_bytes()))
}
pub fn file_name(&self) -> OsString {
@ -296,13 +312,10 @@ impl DirEntry { @@ -296,13 +312,10 @@ impl DirEntry {
#[cfg(any(target_os = "linux", target_os = "emscripten", target_os = "android"))]
pub fn metadata(&self) -> io::Result<FileAttr> {
let fd = cvt(unsafe {dirfd(self.dir.0.dirp.0)})?;
let fd = cvt(unsafe {dirfd(self.dir.inner.dirp.0)})?;
let mut stat: stat64 = unsafe { mem::zeroed() };
cvt(unsafe {
fstatat(fd,
self.entry.d_name.as_ptr(),
&mut stat as *mut _ as *mut _,
libc::AT_SYMLINK_NOFOLLOW)
fstatat64(fd, self.entry.d_name.as_ptr(), &mut stat, libc::AT_SYMLINK_NOFOLLOW)
})?;
Ok(FileAttr { stat: stat })
}
@ -312,12 +325,12 @@ impl DirEntry { @@ -312,12 +325,12 @@ impl DirEntry {
lstat(&self.path())
}
#[cfg(any(target_os = "solaris", target_os = "haiku"))]
#[cfg(any(target_os = "solaris", target_os = "haiku", target_os = "hermit"))]
pub fn file_type(&self) -> io::Result<FileType> {
lstat(&self.path()).map(|m| m.file_type())
}
#[cfg(not(any(target_os = "solaris", target_os = "haiku")))]
#[cfg(not(any(target_os = "solaris", target_os = "haiku", target_os = "hermit")))]
pub fn file_type(&self) -> io::Result<FileType> {
match self.entry.d_type {
libc::DT_CHR => Ok(FileType { mode: libc::S_IFCHR }),
@ -339,7 +352,8 @@ impl DirEntry { @@ -339,7 +352,8 @@ impl DirEntry {
target_os = "solaris",
target_os = "haiku",
target_os = "l4re",
target_os = "fuchsia"))]
target_os = "fuchsia",
target_os = "hermit"))]
pub fn ino(&self) -> u64 {
self.entry.d_ino as u64
}
@ -370,7 +384,8 @@ impl DirEntry { @@ -370,7 +384,8 @@ impl DirEntry {
target_os = "linux",
target_os = "emscripten",
target_os = "l4re",
target_os = "haiku"))]
target_os = "haiku",
target_os = "hermit"))]
fn name_bytes(&self) -> &[u8] {
unsafe {
CStr::from_ptr(self.entry.d_name.as_ptr()).to_bytes()
@ -692,7 +707,10 @@ pub fn readdir(p: &Path) -> io::Result<ReadDir> { @@ -692,7 +707,10 @@ pub fn readdir(p: &Path) -> io::Result<ReadDir> {
Err(Error::last_os_error())
} else {
let inner = InnerReadDir { dirp: Dir(ptr), root };
Ok(ReadDir(Arc::new(inner)))
Ok(ReadDir{
inner: Arc::new(inner),
end_of_stream: false,
})
}
}
}
@ -787,7 +805,7 @@ pub fn stat(p: &Path) -> io::Result<FileAttr> { @@ -787,7 +805,7 @@ pub fn stat(p: &Path) -> io::Result<FileAttr> {
let p = cstr(p)?;
let mut stat: stat64 = unsafe { mem::zeroed() };
cvt(unsafe {
stat64(p.as_ptr(), &mut stat as *mut _ as *mut _)
stat64(p.as_ptr(), &mut stat)
})?;
Ok(FileAttr { stat: stat })
}
@ -796,7 +814,7 @@ pub fn lstat(p: &Path) -> io::Result<FileAttr> { @@ -796,7 +814,7 @@ pub fn lstat(p: &Path) -> io::Result<FileAttr> {
let p = cstr(p)?;
let mut stat: stat64 = unsafe { mem::zeroed() };
cvt(unsafe {
lstat64(p.as_ptr(), &mut stat as *mut _ as *mut _)
lstat64(p.as_ptr(), &mut stat)
})?;
Ok(FileAttr { stat: stat })
}

1
ctr-std/src/sys/unix/mod.rs

@ -28,6 +28,7 @@ use libc; @@ -28,6 +28,7 @@ use libc;
#[cfg(all(not(dox), target_os = "emscripten"))] pub use os::emscripten as platform;
#[cfg(all(not(dox), target_os = "fuchsia"))] pub use os::fuchsia as platform;
#[cfg(all(not(dox), target_os = "l4re"))] pub use os::linux as platform;
#[cfg(all(not(dox), target_os = "hermit"))] pub use os::hermit as platform;
pub use self::rand::hashmap_random_keys;
pub use libc::strlen;

9
ctr-std/src/sys/unix/mutex.rs

@ -25,8 +25,10 @@ unsafe impl Sync for Mutex {} @@ -25,8 +25,10 @@ unsafe impl Sync for Mutex {}
#[allow(dead_code)] // sys isn't exported yet
impl Mutex {
pub const fn new() -> Mutex {
// Might be moved and address is changing it is better to avoid
// initialization of potentially opaque OS data before it landed
// Might be moved to a different address, so it is better to avoid
// initialization of potentially opaque OS data before it landed.
// Be very careful using this newly constructed `Mutex`, reentrant
// locking is undefined behavior until `init` is called!
Mutex { inner: UnsafeCell::new(libc::PTHREAD_MUTEX_INITIALIZER) }
}
#[inline]
@ -49,9 +51,6 @@ impl Mutex { @@ -49,9 +51,6 @@ impl Mutex {
// references, we instead create the mutex with type
// PTHREAD_MUTEX_NORMAL which is guaranteed to deadlock if we try to
// re-lock it from the same thread, thus avoiding undefined behavior.
//
// We can't do anything for StaticMutex, but that type is deprecated
// anyways.
let mut attr: libc::pthread_mutexattr_t = mem::uninitialized();
let r = libc::pthread_mutexattr_init(&mut attr);
debug_assert_eq!(r, 0);

39
ctr-std/src/sys/unix/os.rs

@ -33,6 +33,8 @@ use sys::fd; @@ -33,6 +33,8 @@ use sys::fd;
use vec;
const TMPBUF_SZ: usize = 128;
// We never call `ENV_LOCK.init()`, so it is UB to attempt to
// acquire this mutex reentrantly!
static ENV_LOCK: Mutex = Mutex::new();
@ -47,6 +49,7 @@ extern { @@ -47,6 +49,7 @@ extern {
target_os = "netbsd",
target_os = "openbsd",
target_os = "android",
target_os = "hermit",
target_env = "newlib"),
link_name = "__errno")]
#[cfg_attr(target_os = "solaris", link_name = "___errno")]
@ -376,7 +379,7 @@ pub fn current_exe() -> io::Result<PathBuf> { @@ -376,7 +379,7 @@ pub fn current_exe() -> io::Result<PathBuf> {
}
}
#[cfg(any(target_os = "fuchsia", target_os = "l4re"))]
#[cfg(any(target_os = "fuchsia", target_os = "l4re", target_os = "hermit"))]
pub fn current_exe() -> io::Result<PathBuf> {
use io::ErrorKind;
Err(io::Error::new(ErrorKind::Other, "Not yet implemented!"))
@ -409,26 +412,19 @@ pub unsafe fn environ() -> *mut *const *const c_char { @@ -409,26 +412,19 @@ pub unsafe fn environ() -> *mut *const *const c_char {
/// environment variables of the current process.
pub fn env() -> Env {
unsafe {
ENV_LOCK.lock();
let _guard = ENV_LOCK.lock();
let mut environ = *environ();
if environ == ptr::null() {
ENV_LOCK.unlock();
panic!("os::env() failure getting env string from OS: {}",
io::Error::last_os_error());
}
let mut result = Vec::new();
while *environ != ptr::null() {
while environ != ptr::null() && *environ != ptr::null() {
if let Some(key_value) = parse(CStr::from_ptr(*environ).to_bytes()) {
result.push(key_value);
}
environ = environ.offset(1);
}
let ret = Env {
return Env {
iter: result.into_iter(),
_dont_send_or_sync_me: PhantomData,
};
ENV_LOCK.unlock();
return ret
}
}
fn parse(input: &[u8]) -> Option<(OsString, OsString)> {
@ -452,15 +448,14 @@ pub fn getenv(k: &OsStr) -> io::Result<Option<OsString>> { @@ -452,15 +448,14 @@ pub fn getenv(k: &OsStr) -> io::Result<Option<OsString>> {
// always None as well
let k = CString::new(k.as_bytes())?;
unsafe {
ENV_LOCK.lock();
let _guard = ENV_LOCK.lock();
let s = libc::getenv(k.as_ptr()) as *const libc::c_char;
let ret = if s.is_null() {
None
} else {
Some(OsStringExt::from_vec(CStr::from_ptr(s).to_bytes().to_vec()))
};
ENV_LOCK.unlock();
return Ok(ret)
Ok(ret)
}
}
@ -469,10 +464,8 @@ pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> { @@ -469,10 +464,8 @@ pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
let v = CString::new(v.as_bytes())?;
unsafe {
ENV_LOCK.lock();
let ret = cvt(libc::setenv(k.as_ptr(), v.as_ptr(), 1)).map(|_| ());
ENV_LOCK.unlock();
return ret
let _guard = ENV_LOCK.lock();
cvt(libc::setenv(k.as_ptr(), v.as_ptr(), 1)).map(|_| ())
}
}
@ -480,10 +473,8 @@ pub fn unsetenv(n: &OsStr) -> io::Result<()> { @@ -480,10 +473,8 @@ pub fn unsetenv(n: &OsStr) -> io::Result<()> {
let nbuf = CString::new(n.as_bytes())?;
unsafe {
ENV_LOCK.lock();
let ret = cvt(libc::unsetenv(nbuf.as_ptr())).map(|_| ());
ENV_LOCK.unlock();
return ret
let _guard = ENV_LOCK.lock();
cvt(libc::unsetenv(nbuf.as_ptr())).map(|_| ())
}
}
@ -572,7 +563,7 @@ fn glibc_version_cstr() -> Option<&'static CStr> { @@ -572,7 +563,7 @@ fn glibc_version_cstr() -> Option<&'static CStr> {
// ignoring any extra dot-separated parts. Otherwise return None.
#[cfg(target_env = "gnu")]
fn parse_glibc_version(version: &str) -> Option<(usize, usize)> {
let mut parsed_ints = version.split(".").map(str::parse::<usize>).fuse();
let mut parsed_ints = version.split('.').map(str::parse::<usize>).fuse();
match (parsed_ints.next(), parsed_ints.next()) {
(Some(Ok(major)), Some(Ok(minor))) => Some((major, minor)),
_ => None

6
ctr-std/src/sys/unix/process/process_common.rs

@ -52,7 +52,7 @@ pub struct Command { @@ -52,7 +52,7 @@ pub struct Command {
uid: Option<uid_t>,
gid: Option<gid_t>,
saw_nul: bool,
closures: Vec<Box<FnMut() -> io::Result<()> + Send + Sync>>,
closures: Vec<Box<dyn FnMut() -> io::Result<()> + Send + Sync>>,
stdin: Option<Stdio>,
stdout: Option<Stdio>,
stderr: Option<Stdio>,
@ -155,12 +155,12 @@ impl Command { @@ -155,12 +155,12 @@ impl Command {
self.gid
}
pub fn get_closures(&mut self) -> &mut Vec<Box<FnMut() -> io::Result<()> + Send + Sync>> {
pub fn get_closures(&mut self) -> &mut Vec<Box<dyn FnMut() -> io::Result<()> + Send + Sync>> {
&mut self.closures
}
pub fn before_exec(&mut self,
f: Box<FnMut() -> io::Result<()> + Send + Sync>) {
f: Box<dyn FnMut() -> io::Result<()> + Send + Sync>) {
self.closures.push(f);
}

29
ctr-std/src/sys/unix/rand.rs

@ -183,35 +183,10 @@ mod imp { @@ -183,35 +183,10 @@ mod imp {
mod imp {
#[link(name = "zircon")]
extern {
fn zx_cprng_draw(buffer: *mut u8, len: usize, actual: *mut usize) -> i32;
}
fn getrandom(buf: &mut [u8]) -> Result<usize, i32> {
unsafe {
let mut actual = 0;
let status = zx_cprng_draw(buf.as_mut_ptr(), buf.len(), &mut actual);
if status == 0 {
Ok(actual)
} else {
Err(status)
}
}
fn zx_cprng_draw(buffer: *mut u8, len: usize);
}
pub fn fill_bytes(v: &mut [u8]) {
let mut buf = v;
while !buf.is_empty() {
let ret = getrandom(buf);
match ret {
Err(err) => {
panic!("kernel zx_cprng_draw call failed! (returned {}, buf.len() {})",
err, buf.len())
}
Ok(actual) => {
let move_buf = buf;
buf = &mut move_buf[(actual as usize)..];
}
}
}
unsafe { zx_cprng_draw(v.as_mut_ptr(), v.len()) }
}
}

5
ctr-std/src/sys/unix/thread.rs

@ -49,7 +49,7 @@ unsafe fn pthread_attr_setstacksize(_attr: *mut libc::pthread_attr_t, @@ -49,7 +49,7 @@ unsafe fn pthread_attr_setstacksize(_attr: *mut libc::pthread_attr_t,
}
impl Thread {
pub unsafe fn new<'a>(stack: usize, p: Box<FnBox() + 'a>)
pub unsafe fn new<'a>(stack: usize, p: Box<dyn FnBox() + 'a>)
-> io::Result<Thread> {
let p = box p;
let mut native: libc::pthread_t = mem::zeroed();
@ -138,7 +138,8 @@ impl Thread { @@ -138,7 +138,8 @@ impl Thread {
target_os = "solaris",
target_os = "haiku",
target_os = "l4re",
target_os = "emscripten"))]
target_os = "emscripten",
target_os = "hermit"))]
pub fn set_name(_name: &CStr) {
// Newlib, Illumos, Haiku, and Emscripten have no way to set a thread name.
}

4
ctr-std/src/sys/unix/time.rs

@ -345,9 +345,9 @@ mod inner { @@ -345,9 +345,9 @@ mod inner {
}
}
#[cfg(not(target_os = "dragonfly"))]
#[cfg(not(any(target_os = "dragonfly", target_os = "hermit")))]
pub type clock_t = libc::c_int;
#[cfg(target_os = "dragonfly")]
#[cfg(any(target_os = "dragonfly", target_os = "hermit"))]
pub type clock_t = libc::c_ulong;
fn now(clock: clock_t) -> Timespec {

2
ctr-std/src/sys/wasm/os.rs

@ -21,7 +21,7 @@ pub fn errno() -> i32 { @@ -21,7 +21,7 @@ pub fn errno() -> i32 {
}
pub fn error_string(_errno: i32) -> String {
format!("operation successful")
"operation successful".to_string()
}
pub fn getcwd() -> io::Result<PathBuf> {

2
ctr-std/src/sys/wasm/thread.rs

@ -19,7 +19,7 @@ pub struct Thread(Void); @@ -19,7 +19,7 @@ pub struct Thread(Void);
pub const DEFAULT_MIN_STACK_SIZE: usize = 4096;
impl Thread {
pub unsafe fn new<'a>(_stack: usize, _p: Box<FnBox() + 'a>)
pub unsafe fn new<'a>(_stack: usize, _p: Box<dyn FnBox() + 'a>)
-> io::Result<Thread>
{
unsupported()

297
ctr-std/src/sys/windows/backtrace/mod.rs

@ -46,110 +46,281 @@ mod printing; @@ -46,110 +46,281 @@ mod printing;
#[path = "backtrace_gnu.rs"]
pub mod gnu;
pub use self::printing::{resolve_symname, foreach_symbol_fileline};
pub use self::printing::{foreach_symbol_fileline, resolve_symname};
use self::printing::{load_printing_fns_64, load_printing_fns_ex};
pub fn unwind_backtrace(frames: &mut [Frame])
-> io::Result<(usize, BacktraceContext)>
{
pub fn unwind_backtrace(frames: &mut [Frame]) -> io::Result<(usize, BacktraceContext)> {
let dbghelp = DynamicLibrary::open("dbghelp.dll")?;
// Fetch the symbols necessary from dbghelp.dll
let SymInitialize = sym!(dbghelp, "SymInitialize", SymInitializeFn)?;
let SymCleanup = sym!(dbghelp, "SymCleanup", SymCleanupFn)?;
let StackWalkEx = sym!(dbghelp, "StackWalkEx", StackWalkExFn)?;
// StackWalkEx might not be present and we'll fall back to StackWalk64
let sw_var = match sym!(dbghelp, "StackWalkEx", StackWalkExFn) {
Ok(StackWalkEx) => {
StackWalkVariant::StackWalkEx(StackWalkEx, load_printing_fns_ex(&dbghelp)?)
}
Err(e) => match sym!(dbghelp, "StackWalk64", StackWalk64Fn) {
Ok(StackWalk64) => {
StackWalkVariant::StackWalk64(StackWalk64, load_printing_fns_64(&dbghelp)?)
}
Err(..) => return Err(e),
},
};
// 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::STACKFRAME_EX = unsafe { mem::zeroed() };
frame.StackFrameSize = mem::size_of_val(&frame) as c::DWORD;
let image = init_frame(&mut frame, &context);
let backtrace_context = BacktraceContext {
handle: process,
SymCleanup,
StackWalkVariant: sw_var,
dbghelp,
};
// Initialize this process's symbols
let ret = unsafe { SymInitialize(process, ptr::null_mut(), c::TRUE) };
if ret != c::TRUE {
return Ok((0, backtrace_context))
return Ok((0, backtrace_context));
}
// And now that we're done with all the setup, do the stack walking!
match backtrace_context.StackWalkVariant {
StackWalkVariant::StackWalkEx(StackWalkEx, _) => {
set_frames(StackWalkEx, frames).map(|i| (i, backtrace_context))
}
StackWalkVariant::StackWalk64(StackWalk64, _) => {
set_frames(StackWalk64, frames).map(|i| (i, backtrace_context))
}
}
}
fn set_frames<W: StackWalker>(StackWalk: W, frames: &mut [Frame]) -> io::Result<usize> {
let process = unsafe { c::GetCurrentProcess() };
let thread = unsafe { c::GetCurrentProcess() };
let mut context: c::CONTEXT = unsafe { mem::zeroed() };
unsafe { c::RtlCaptureContext(&mut context) };
let mut frame = W::Item::new();
let image = frame.init(&context);
let mut i = 0;
unsafe {
while i < frames.len() &&
StackWalkEx(image, process, thread, &mut frame, &mut context,
ptr::null_mut(),
ptr::null_mut(),
ptr::null_mut(),
ptr::null_mut(),
0) == c::TRUE
{
let addr = (frame.AddrPC.Offset - 1) as *const u8;
frames[i] = Frame {
symbol_addr: addr,
exact_position: addr,
inline_context: frame.InlineFrameContext,
};
i += 1;
while i < frames.len()
&& StackWalk.walk(image, process, thread, &mut frame, &mut context) == c::TRUE
{
let addr = frame.get_addr();
frames[i] = Frame {
symbol_addr: addr,
exact_position: addr,
inline_context: 0,
};
i += 1
}
Ok(i)
}
type SymInitializeFn = unsafe extern "system" fn(c::HANDLE, *mut c_void, c::BOOL) -> c::BOOL;
type SymCleanupFn = unsafe extern "system" fn(c::HANDLE) -> c::BOOL;
type StackWalkExFn = unsafe extern "system" fn(
c::DWORD,
c::HANDLE,
c::HANDLE,
*mut c::STACKFRAME_EX,
*mut c::CONTEXT,
*mut c_void,
*mut c_void,
*mut c_void,
*mut c_void,
c::DWORD,
) -> c::BOOL;
type StackWalk64Fn = 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;
trait StackWalker {
type Item: StackFrame;
fn walk(&self, c::DWORD, c::HANDLE, c::HANDLE, &mut Self::Item, &mut c::CONTEXT) -> c::BOOL;
}
impl StackWalker for StackWalkExFn {
type Item = c::STACKFRAME_EX;
fn walk(
&self,
image: c::DWORD,
process: c::HANDLE,
thread: c::HANDLE,
frame: &mut Self::Item,
context: &mut c::CONTEXT,
) -> c::BOOL {
unsafe {
self(
image,
process,
thread,
frame,
context,
ptr::null_mut(),
ptr::null_mut(),
ptr::null_mut(),
ptr::null_mut(),
0,
)
}
}
}
impl StackWalker for StackWalk64Fn {
type Item = c::STACKFRAME64;
fn walk(
&self,
image: c::DWORD,
process: c::HANDLE,
thread: c::HANDLE,
frame: &mut Self::Item,
context: &mut c::CONTEXT,
) -> c::BOOL {
unsafe {
self(
image,
process,
thread,
frame,
context,
ptr::null_mut(),
ptr::null_mut(),
ptr::null_mut(),
ptr::null_mut(),
)
}
}
}
trait StackFrame {
fn new() -> Self;
fn init(&mut self, ctx: &c::CONTEXT) -> c::DWORD;
fn get_addr(&self) -> *const u8;
}
impl StackFrame for c::STACKFRAME_EX {
fn new() -> c::STACKFRAME_EX {
unsafe { mem::zeroed() }
}
#[cfg(target_arch = "x86")]
fn init(&mut self, ctx: &c::CONTEXT) -> c::DWORD {
self.AddrPC.Offset = ctx.Eip as u64;
self.AddrPC.Mode = c::ADDRESS_MODE::AddrModeFlat;
self.AddrStack.Offset = ctx.Esp as u64;
self.AddrStack.Mode = c::ADDRESS_MODE::AddrModeFlat;
self.AddrFrame.Offset = ctx.Ebp as u64;
self.AddrFrame.Mode = c::ADDRESS_MODE::AddrModeFlat;
c::IMAGE_FILE_MACHINE_I386
}
#[cfg(target_arch = "x86_64")]
fn init(&mut self, ctx: &c::CONTEXT) -> c::DWORD {
self.AddrPC.Offset = ctx.Rip as u64;
self.AddrPC.Mode = c::ADDRESS_MODE::AddrModeFlat;
self.AddrStack.Offset = ctx.Rsp as u64;
self.AddrStack.Mode = c::ADDRESS_MODE::AddrModeFlat;
self.AddrFrame.Offset = ctx.Rbp as u64;
self.AddrFrame.Mode = c::ADDRESS_MODE::AddrModeFlat;
c::IMAGE_FILE_MACHINE_AMD64
}
#[cfg(target_arch = "aarch64")]
fn init(&mut self, ctx: &c::CONTEXT) -> c::DWORD {
self.AddrPC.Offset = ctx.Pc as u64;
self.AddrPC.Mode = c::ADDRESS_MODE::AddrModeFlat;
self.AddrStack.Offset = ctx.Sp as u64;
self.AddrStack.Mode = c::ADDRESS_MODE::AddrModeFlat;
self.AddrFrame.Offset = ctx.Fp as u64;
self.AddrFrame.Mode = c::ADDRESS_MODE::AddrModeFlat;
c::IMAGE_FILE_MACHINE_ARM64
}
Ok((i, backtrace_context))
fn get_addr(&self) -> *const u8 {
(self.AddrPC.Offset - 1) as *const u8
}
}
type SymInitializeFn =
unsafe extern "system" fn(c::HANDLE, *mut c_void,
c::BOOL) -> c::BOOL;
type SymCleanupFn =
unsafe extern "system" fn(c::HANDLE) -> c::BOOL;
type StackWalkExFn =
unsafe extern "system" fn(c::DWORD, c::HANDLE, c::HANDLE,
*mut c::STACKFRAME_EX, *mut c::CONTEXT,
*mut c_void, *mut c_void,
*mut c_void, *mut c_void, c::DWORD) -> c::BOOL;
#[cfg(target_arch = "x86")]
fn init_frame(frame: &mut c::STACKFRAME_EX,
ctx: &c::CONTEXT) -> c::DWORD {
frame.AddrPC.Offset = ctx.Eip as u64;
frame.AddrPC.Mode = c::ADDRESS_MODE::AddrModeFlat;
frame.AddrStack.Offset = ctx.Esp as u64;
frame.AddrStack.Mode = c::ADDRESS_MODE::AddrModeFlat;
frame.AddrFrame.Offset = ctx.Ebp as u64;
frame.AddrFrame.Mode = c::ADDRESS_MODE::AddrModeFlat;
c::IMAGE_FILE_MACHINE_I386
impl StackFrame for c::STACKFRAME64 {
fn new() -> c::STACKFRAME64 {
unsafe { mem::zeroed() }
}
#[cfg(target_arch = "x86")]
fn init(&mut self, ctx: &c::CONTEXT) -> c::DWORD {
self.AddrPC.Offset = ctx.Eip as u64;
self.AddrPC.Mode = c::ADDRESS_MODE::AddrModeFlat;
self.AddrStack.Offset = ctx.Esp as u64;
self.AddrStack.Mode = c::ADDRESS_MODE::AddrModeFlat;
self.AddrFrame.Offset = ctx.Ebp as u64;
self.AddrFrame.Mode = c::ADDRESS_MODE::AddrModeFlat;
c::IMAGE_FILE_MACHINE_I386
}
#[cfg(target_arch = "x86_64")]
fn init(&mut self, ctx: &c::CONTEXT) -> c::DWORD {
self.AddrPC.Offset = ctx.Rip as u64;
self.AddrPC.Mode = c::ADDRESS_MODE::AddrModeFlat;
self.AddrStack.Offset = ctx.Rsp as u64;
self.AddrStack.Mode = c::ADDRESS_MODE::AddrModeFlat;
self.AddrFrame.Offset = ctx.Rbp as u64;
self.AddrFrame.Mode = c::ADDRESS_MODE::AddrModeFlat;
c::IMAGE_FILE_MACHINE_AMD64
}
#[cfg(target_arch = "aarch64")]
fn init(&mut self, ctx: &c::CONTEXT) -> c::DWORD {
self.AddrPC.Offset = ctx.Pc as u64;
self.AddrPC.Mode = c::ADDRESS_MODE::AddrModeFlat;
self.AddrStack.Offset = ctx.Sp as u64;
self.AddrStack.Mode = c::ADDRESS_MODE::AddrModeFlat;
self.AddrFrame.Offset = ctx.Fp as u64;
self.AddrFrame.Mode = c::ADDRESS_MODE::AddrModeFlat;
c::IMAGE_FILE_MACHINE_ARM64
}
fn get_addr(&self) -> *const u8 {
(self.AddrPC.Offset - 1) as *const u8
}
}
#[cfg(target_arch = "x86_64")]
fn init_frame(frame: &mut c::STACKFRAME_EX,
ctx: &c::CONTEXT) -> c::DWORD {
frame.AddrPC.Offset = ctx.Rip as u64;
frame.AddrPC.Mode = c::ADDRESS_MODE::AddrModeFlat;
frame.AddrStack.Offset = ctx.Rsp as u64;
frame.AddrStack.Mode = c::ADDRESS_MODE::AddrModeFlat;
frame.AddrFrame.Offset = ctx.Rbp as u64;
frame.AddrFrame.Mode = c::ADDRESS_MODE::AddrModeFlat;
c::IMAGE_FILE_MACHINE_AMD64
enum StackWalkVariant {
StackWalkEx(StackWalkExFn, printing::PrintingFnsEx),
StackWalk64(StackWalk64Fn, printing::PrintingFns64),
}
pub struct BacktraceContext {
handle: c::HANDLE,
SymCleanup: SymCleanupFn,
// Only used in printing for msvc and not gnu
// The gnu version is effectively a ZST dummy.
#[allow(dead_code)]
StackWalkVariant: StackWalkVariant,
// keeping DynamycLibrary loaded until its functions no longer needed
#[allow(dead_code)]
dbghelp: DynamicLibrary,
}
impl Drop for BacktraceContext {
fn drop(&mut self) {
unsafe { (self.SymCleanup)(self.handle); }
unsafe {
(self.SymCleanup)(self.handle);
}
}
}

14
ctr-std/src/sys/windows/backtrace/printing/mod.rs

@ -15,6 +15,20 @@ mod printing; @@ -15,6 +15,20 @@ mod printing;
#[cfg(target_env = "gnu")]
mod printing {
pub use sys_common::gnu::libbacktrace::{foreach_symbol_fileline, resolve_symname};
// dummy functions to mirror those present in msvc version.
use sys::dynamic_lib::DynamicLibrary;
use io;
pub struct PrintingFnsEx {}
pub struct PrintingFns64 {}
pub fn load_printing_fns_ex(_: &DynamicLibrary) -> io::Result<PrintingFnsEx> {
Ok(PrintingFnsEx{})
}
pub fn load_printing_fns_64(_: &DynamicLibrary) -> io::Result<PrintingFns64> {
Ok(PrintingFns64{})
}
}
pub use self::printing::{foreach_symbol_fileline, resolve_symname};
pub use self::printing::{load_printing_fns_ex, load_printing_fns_64,
PrintingFnsEx, PrintingFns64};

196
ctr-std/src/sys/windows/backtrace/printing/msvc.rs

@ -10,29 +10,108 @@ @@ -10,29 +10,108 @@
use ffi::CStr;
use io;
use libc::{c_ulong, c_char};
use libc::{c_char, c_ulong};
use mem;
use sys::c;
use sys::backtrace::BacktraceContext;
use sys::backtrace::StackWalkVariant;
use sys::c;
use sys::dynamic_lib::DynamicLibrary;
use sys_common::backtrace::Frame;
// Structs holding printing functions and loaders for them
// Two versions depending on whether dbghelp.dll has StackWalkEx or not
// (the former being in newer Windows versions, the older being in Win7 and before)
pub struct PrintingFnsEx {
resolve_symname: SymFromInlineContextFn,
sym_get_line: SymGetLineFromInlineContextFn,
}
pub struct PrintingFns64 {
resolve_symname: SymFromAddrFn,
sym_get_line: SymGetLineFromAddr64Fn,
}
pub fn load_printing_fns_ex(dbghelp: &DynamicLibrary) -> io::Result<PrintingFnsEx> {
Ok(PrintingFnsEx {
resolve_symname: sym!(dbghelp, "SymFromInlineContext", SymFromInlineContextFn)?,
sym_get_line: sym!(
dbghelp,
"SymGetLineFromInlineContext",
SymGetLineFromInlineContextFn
)?,
})
}
pub fn load_printing_fns_64(dbghelp: &DynamicLibrary) -> io::Result<PrintingFns64> {
Ok(PrintingFns64 {
resolve_symname: sym!(dbghelp, "SymFromAddr", SymFromAddrFn)?,
sym_get_line: sym!(dbghelp, "SymGetLineFromAddr64", SymGetLineFromAddr64Fn)?,
})
}
type SymFromAddrFn =
unsafe extern "system" fn(c::HANDLE, u64, *mut u64, *mut c::SYMBOL_INFO) -> c::BOOL;
type SymFromInlineContextFn =
unsafe extern "system" fn(c::HANDLE, u64, c::ULONG,
*mut u64, *mut c::SYMBOL_INFO) -> c::BOOL;
type SymGetLineFromInlineContextFn =
unsafe extern "system" fn(c::HANDLE, u64, c::ULONG,
u64, *mut c::DWORD, *mut c::IMAGEHLP_LINE64) -> c::BOOL;
unsafe extern "system" fn(c::HANDLE, u64, c::ULONG, *mut u64, *mut c::SYMBOL_INFO) -> c::BOOL;
type SymGetLineFromAddr64Fn =
unsafe extern "system" fn(c::HANDLE, u64, *mut u32, *mut c::IMAGEHLP_LINE64) -> c::BOOL;
type SymGetLineFromInlineContextFn = unsafe extern "system" fn(
c::HANDLE,
u64,
c::ULONG,
u64,
*mut c::DWORD,
*mut c::IMAGEHLP_LINE64,
) -> c::BOOL;
/// Converts a pointer to symbol to its string value.
pub fn resolve_symname<F>(frame: Frame,
callback: F,
context: &BacktraceContext) -> io::Result<()>
where F: FnOnce(Option<&str>) -> io::Result<()>
pub fn resolve_symname<F>(frame: Frame, callback: F, context: &BacktraceContext) -> io::Result<()>
where
F: FnOnce(Option<&str>) -> io::Result<()>,
{
let SymFromInlineContext = sym!(&context.dbghelp,
"SymFromInlineContext",
SymFromInlineContextFn)?;
match context.StackWalkVariant {
StackWalkVariant::StackWalkEx(_, ref fns) => resolve_symname_internal(
|process: c::HANDLE,
symbol_address: u64,
inline_context: c::ULONG,
info: *mut c::SYMBOL_INFO| unsafe {
let mut displacement = 0u64;
(fns.resolve_symname)(
process,
symbol_address,
inline_context,
&mut displacement,
info,
)
},
frame,
callback,
context,
),
StackWalkVariant::StackWalk64(_, ref fns) => resolve_symname_internal(
|process: c::HANDLE,
symbol_address: u64,
_inline_context: c::ULONG,
info: *mut c::SYMBOL_INFO| unsafe {
let mut displacement = 0u64;
(fns.resolve_symname)(process, symbol_address, &mut displacement, info)
},
frame,
callback,
context,
),
}
}
fn resolve_symname_internal<F, R>(
mut symbol_resolver: R,
frame: Frame,
callback: F,
context: &BacktraceContext,
) -> io::Result<()>
where
F: FnOnce(Option<&str>) -> io::Result<()>,
R: FnMut(c::HANDLE, u64, c::ULONG, *mut c::SYMBOL_INFO) -> c::BOOL,
{
unsafe {
let mut info: c::SYMBOL_INFO = mem::zeroed();
info.MaxNameLen = c::MAX_SYM_NAME as c_ulong;
@ -41,14 +120,13 @@ pub fn resolve_symname<F>(frame: Frame, @@ -41,14 +120,13 @@ pub fn resolve_symname<F>(frame: Frame,
// due to struct alignment.
info.SizeOfStruct = 88;
let mut displacement = 0u64;
let ret = SymFromInlineContext(context.handle,
frame.symbol_addr as u64,
frame.inline_context,
&mut displacement,
&mut info);
let valid_range = if ret == c::TRUE &&
frame.symbol_addr as usize >= info.Address as usize {
let ret = symbol_resolver(
context.handle,
frame.symbol_addr as u64,
frame.inline_context,
&mut info,
);
let valid_range = if ret == c::TRUE && frame.symbol_addr as usize >= info.Address as usize {
if info.Size != 0 {
(frame.symbol_addr as usize) < info.Address as usize + info.Size as usize
} else {
@ -67,30 +145,72 @@ pub fn resolve_symname<F>(frame: Frame, @@ -67,30 +145,72 @@ pub fn resolve_symname<F>(frame: Frame,
}
}
pub fn foreach_symbol_fileline<F>(frame: Frame,
mut f: F,
context: &BacktraceContext)
-> io::Result<bool>
where F: FnMut(&[u8], u32) -> io::Result<()>
pub fn foreach_symbol_fileline<F>(
frame: Frame,
callback: F,
context: &BacktraceContext,
) -> io::Result<bool>
where
F: FnMut(&[u8], u32) -> io::Result<()>,
{
let SymGetLineFromInlineContext = sym!(&context.dbghelp,
"SymGetLineFromInlineContext",
SymGetLineFromInlineContextFn)?;
match context.StackWalkVariant {
StackWalkVariant::StackWalkEx(_, ref fns) => foreach_symbol_fileline_iternal(
|process: c::HANDLE,
frame_address: u64,
inline_context: c::ULONG,
line: *mut c::IMAGEHLP_LINE64| unsafe {
let mut displacement = 0u32;
(fns.sym_get_line)(
process,
frame_address,
inline_context,
0,
&mut displacement,
line,
)
},
frame,
callback,
context,
),
StackWalkVariant::StackWalk64(_, ref fns) => foreach_symbol_fileline_iternal(
|process: c::HANDLE,
frame_address: u64,
_inline_context: c::ULONG,
line: *mut c::IMAGEHLP_LINE64| unsafe {
let mut displacement = 0u32;
(fns.sym_get_line)(process, frame_address, &mut displacement, line)
},
frame,
callback,
context,
),
}
}
fn foreach_symbol_fileline_iternal<F, G>(
mut line_getter: G,
frame: Frame,
mut callback: F,
context: &BacktraceContext,
) -> io::Result<bool>
where
F: FnMut(&[u8], u32) -> io::Result<()>,
G: FnMut(c::HANDLE, u64, c::ULONG, *mut c::IMAGEHLP_LINE64) -> c::BOOL,
{
unsafe {
let mut line: c::IMAGEHLP_LINE64 = mem::zeroed();
line.SizeOfStruct = ::mem::size_of::<c::IMAGEHLP_LINE64>() as u32;
let mut displacement = 0u32;
let ret = SymGetLineFromInlineContext(context.handle,
frame.exact_position as u64,
frame.inline_context,
0,
&mut displacement,
&mut line);
let ret = line_getter(
context.handle,
frame.exact_position as u64,
frame.inline_context,
&mut line,
);
if ret == c::TRUE {
let name = CStr::from_ptr(line.Filename).to_bytes();
f(name, line.LineNumber as u32)?;
callback(name, line.LineNumber as u32)?;
}
Ok(false)
}

82
ctr-std/src/sys/windows/c.rs

@ -280,6 +280,9 @@ pub const IMAGE_FILE_MACHINE_I386: DWORD = 0x014c; @@ -280,6 +280,9 @@ pub const IMAGE_FILE_MACHINE_I386: DWORD = 0x014c;
#[cfg(target_arch = "x86_64")]
#[cfg(feature = "backtrace")]
pub const IMAGE_FILE_MACHINE_AMD64: DWORD = 0x8664;
#[cfg(target_arch = "aarch64")]
#[cfg(feature = "backtrace")]
pub const IMAGE_FILE_MACHINE_ARM64: DWORD = 0xAA64;
pub const EXCEPTION_CONTINUE_SEARCH: LONG = 0;
pub const EXCEPTION_STACK_OVERFLOW: DWORD = 0xc00000fd;
@ -296,6 +299,8 @@ pub const PIPE_READMODE_BYTE: DWORD = 0x00000000; @@ -296,6 +299,8 @@ pub const PIPE_READMODE_BYTE: DWORD = 0x00000000;
pub const FD_SETSIZE: usize = 64;
pub const STACK_SIZE_PARAM_IS_A_RESERVATION: DWORD = 0x00010000;
#[repr(C)]
#[cfg(not(target_pointer_width = "64"))]
pub struct WSADATA {
@ -635,6 +640,22 @@ pub struct STACKFRAME_EX { @@ -635,6 +640,22 @@ pub struct STACKFRAME_EX {
pub InlineFrameContext: DWORD,
}
#[repr(C)]
#[cfg(feature = "backtrace")]
pub struct STACKFRAME64 {
pub AddrPC: ADDRESS64,
pub AddrReturn: ADDRESS64,
pub AddrFrame: ADDRESS64,
pub AddrStack: ADDRESS64,
pub AddrBStore: ADDRESS64,
pub FuncTableEntry: *mut c_void,
pub Params: [u64; 4],
pub Far: BOOL,
pub Virtual: BOOL,
pub Reserved: [u64; 3],
pub KdHelp: KDHELP64,
}
#[repr(C)]
#[cfg(feature = "backtrace")]
pub struct KDHELP64 {
@ -773,9 +794,68 @@ pub struct FLOATING_SAVE_AREA { @@ -773,9 +794,68 @@ pub struct FLOATING_SAVE_AREA {
// will not appear in the final documentation. This should be also defined for
// other architectures supported by Windows such as ARM, and for historical
// interest, maybe MIPS and PowerPC as well.
#[cfg(all(dox, not(any(target_arch = "x86_64", target_arch = "x86"))))]
#[cfg(all(dox, not(any(target_arch = "x86_64", target_arch = "x86", target_arch = "aarch64"))))]
pub enum CONTEXT {}
#[cfg(target_arch = "aarch64")]
pub const ARM64_MAX_BREAKPOINTS: usize = 8;
#[cfg(target_arch = "aarch64")]
pub const ARM64_MAX_WATCHPOINTS: usize = 2;
#[cfg(target_arch = "aarch64")]
#[repr(C)]
pub struct ARM64_NT_NEON128 {
pub D: [f64; 2],
}
#[cfg(target_arch = "aarch64")]
#[repr(C, align(16))]
pub struct CONTEXT {
pub ContextFlags: DWORD,
pub Cpsr: DWORD,
pub X0: u64,
pub X1: u64,
pub X2: u64,
pub X3: u64,
pub X4: u64,
pub X5: u64,
pub X6: u64,
pub X7: u64,
pub X8: u64,
pub X9: u64,
pub X10: u64,
pub X11: u64,
pub X12: u64,
pub X13: u64,
pub X14: u64,
pub X15: u64,
pub X16: u64,
pub X17: u64,
pub X18: u64,
pub X19: u64,
pub X20: u64,
pub X21: u64,
pub X22: u64,
pub X23: u64,
pub X24: u64,
pub X25: u64,
pub X26: u64,
pub X27: u64,
pub X28: u64,
pub Fp: u64,
pub Lr: u64,
pub Sp: u64,
pub Pc: u64,
pub V: [ARM64_NT_NEON128; 32],
pub Fpcr: DWORD,
pub Fpsr: DWORD,
pub Bcr: [DWORD; ARM64_MAX_BREAKPOINTS],
pub Bvr: [DWORD; ARM64_MAX_BREAKPOINTS],
pub Wcr: [DWORD; ARM64_MAX_WATCHPOINTS],
pub Wvr: [DWORD; ARM64_MAX_WATCHPOINTS],
}
#[repr(C)]
pub struct SOCKADDR_STORAGE_LH {
pub ss_family: ADDRESS_FAMILY,

3
ctr-std/src/sys/windows/ext/ffi.rs

@ -31,7 +31,7 @@ @@ -31,7 +31,7 @@
//!
//! If Rust code *does* need to look into those strings, it can
//! convert them to valid UTF-8, possibly lossily, by substituting
//! invalid sequences with U+FFFD REPLACEMENT CHARACTER, as is
//! invalid sequences with [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD], as is
//! conventionally done in other Rust APIs that deal with string
//! encodings.
//!
@ -65,6 +65,7 @@ @@ -65,6 +65,7 @@
//! [`from_wide`]: trait.OsStringExt.html#tymethod.from_wide
//! [`encode_wide`]: trait.OsStrExt.html#tymethod.encode_wide
//! [`collect`]: ../../../iter/trait.Iterator.html#method.collect
//! [U+FFFD]: ../../../char/constant.REPLACEMENT_CHARACTER.html
#![stable(feature = "rust1", since = "1.0.0")]

1
ctr-std/src/sys/windows/ext/mod.rs

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
#![stable(feature = "rust1", since = "1.0.0")]
#![doc(cfg(windows))]
#![allow(missing_docs)]
pub mod ffi;
pub mod fs;

10
ctr-std/src/sys/windows/mod.rs

@ -266,8 +266,12 @@ pub fn dur2timeout(dur: Duration) -> c::DWORD { @@ -266,8 +266,12 @@ pub fn dur2timeout(dur: Duration) -> c::DWORD {
// handlers.
//
// https://msdn.microsoft.com/en-us/library/dn774154.aspx
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
#[allow(unreachable_code)]
pub unsafe fn abort_internal() -> ! {
asm!("int $$0x29" :: "{ecx}"(7) ::: volatile); // 7 is FAST_FAIL_FATAL_APP_EXIT
::intrinsics::unreachable();
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
{
asm!("int $$0x29" :: "{ecx}"(7) ::: volatile); // 7 is FAST_FAIL_FATAL_APP_EXIT
::intrinsics::unreachable();
}
::intrinsics::abort();
}

8
ctr-std/src/sys/windows/process.rs

@ -487,9 +487,7 @@ fn make_command_line(prog: &OsStr, args: &[OsString]) -> io::Result<Vec<u16>> { @@ -487,9 +487,7 @@ fn make_command_line(prog: &OsStr, args: &[OsString]) -> io::Result<Vec<u16>> {
} else {
if x == '"' as u16 {
// Add n+1 backslashes to total 2n+1 before internal '"'.
for _ in 0..(backslashes+1) {
cmd.push('\\' as u16);
}
cmd.extend((0..(backslashes + 1)).map(|_| '\\' as u16));
}
backslashes = 0;
}
@ -498,9 +496,7 @@ fn make_command_line(prog: &OsStr, args: &[OsString]) -> io::Result<Vec<u16>> { @@ -498,9 +496,7 @@ fn make_command_line(prog: &OsStr, args: &[OsString]) -> io::Result<Vec<u16>> {
if quote {
// Add n backslashes to total 2n before ending '"'.
for _ in 0..backslashes {
cmd.push('\\' as u16);
}
cmd.extend((0..backslashes).map(|_| '\\' as u16));
cmd.push('"' as u16);
}
Ok(())

5
ctr-std/src/sys/windows/thread.rs

@ -28,7 +28,7 @@ pub struct Thread { @@ -28,7 +28,7 @@ pub struct Thread {
}
impl Thread {
pub unsafe fn new<'a>(stack: usize, p: Box<FnBox() + 'a>)
pub unsafe fn new<'a>(stack: usize, p: Box<dyn FnBox() + 'a>)
-> io::Result<Thread> {
let p = box p;
@ -42,7 +42,8 @@ impl Thread { @@ -42,7 +42,8 @@ impl Thread {
let stack_size = (stack + 0xfffe) & (!0xfffe);
let ret = c::CreateThread(ptr::null_mut(), stack_size,
thread_start, &*p as *const _ as *mut _,
0, ptr::null_mut());
c::STACK_SIZE_PARAM_IS_A_RESERVATION,
ptr::null_mut());
return if ret as usize == 0 {
Err(io::Error::last_os_error())

36
ctr-std/src/sys_common/at_exit_imp.rs

@ -14,17 +14,22 @@ @@ -14,17 +14,22 @@
use boxed::FnBox;
use ptr;
use mem;
use sys_common::mutex::Mutex;
type Queue = Vec<Box<FnBox()>>;
type Queue = Vec<Box<dyn FnBox()>>;
// NB these are specifically not types from `std::sync` as they currently rely
// on poisoning and this module needs to operate at a lower level than requiring
// the thread infrastructure to be in place (useful on the borders of
// initialization/destruction).
// We never call `LOCK.init()`, so it is UB to attempt to
// acquire this mutex reentrantly!
static LOCK: Mutex = Mutex::new();
static mut QUEUE: *mut Queue = ptr::null_mut();
const DONE: *mut Queue = 1_usize as *mut _;
// The maximum number of times the cleanup routines will be run. While running
// the at_exit closures new ones may be registered, and this count is the number
// of times the new closures will be allowed to register successfully. After
@ -35,7 +40,7 @@ unsafe fn init() -> bool { @@ -35,7 +40,7 @@ unsafe fn init() -> bool {
if QUEUE.is_null() {
let state: Box<Queue> = box Vec::new();
QUEUE = Box::into_raw(state);
} else if QUEUE as usize == 1 {
} else if QUEUE == DONE {
// can't re-init after a cleanup
return false
}
@ -44,20 +49,21 @@ unsafe fn init() -> bool { @@ -44,20 +49,21 @@ unsafe fn init() -> bool {
}
pub fn cleanup() {
for i in 0..ITERS {
for i in 1..=ITERS {
unsafe {
LOCK.lock();
let queue = QUEUE;
QUEUE = if i == ITERS - 1 {1} else {0} as *mut _;
LOCK.unlock();
let queue = {
let _guard = LOCK.lock();
mem::replace(&mut QUEUE, if i == ITERS { DONE } else { ptr::null_mut() })
};
// make sure we're not recursively cleaning up
assert!(queue as usize != 1);
assert!(queue != DONE);
// If we never called init, not need to cleanup!
if queue as usize != 0 {
if !queue.is_null() {
let queue: Box<Queue> = Box::from_raw(queue);
for to_run in *queue {
// We are not holding any lock, so reentrancy is fine.
to_run();
}
}
@ -65,16 +71,16 @@ pub fn cleanup() { @@ -65,16 +71,16 @@ pub fn cleanup() {
}
}
pub fn push(f: Box<FnBox()>) -> bool {
let mut ret = true;
pub fn push(f: Box<dyn FnBox()>) -> bool {
unsafe {
LOCK.lock();
let _guard = LOCK.lock();
if init() {
// We are just moving `f` around, not calling it.
// There is no possibility of reentrancy here.
(*QUEUE).push(f);
true
} else {
ret = false;
false
}
LOCK.unlock();
}
ret
}

21
ctr-std/src/sys_common/backtrace.rs

@ -49,7 +49,7 @@ pub struct Frame { @@ -49,7 +49,7 @@ pub struct Frame {
const MAX_NB_FRAMES: usize = 100;
/// Prints the current backtrace.
pub fn print(w: &mut Write, format: PrintFormat) -> io::Result<()> {
pub fn print(w: &mut dyn Write, format: PrintFormat) -> io::Result<()> {
static LOCK: Mutex = Mutex::new();
// Use a lock to prevent mixed output in multithreading context.
@ -62,7 +62,7 @@ pub fn print(w: &mut Write, format: PrintFormat) -> io::Result<()> { @@ -62,7 +62,7 @@ pub fn print(w: &mut Write, format: PrintFormat) -> io::Result<()> {
}
}
fn _print(w: &mut Write, format: PrintFormat) -> io::Result<()> {
fn _print(w: &mut dyn Write, format: PrintFormat) -> io::Result<()> {
let mut frames = [Frame {
exact_position: ptr::null(),
symbol_addr: ptr::null(),
@ -156,16 +156,15 @@ pub fn log_enabled() -> Option<PrintFormat> { @@ -156,16 +156,15 @@ pub fn log_enabled() -> Option<PrintFormat> {
_ => return Some(PrintFormat::Full),
}
let val = match env::var_os("RUST_BACKTRACE") {
Some(x) => if &x == "0" {
let val = env::var_os("RUST_BACKTRACE").and_then(|x|
if &x == "0" {
None
} else if &x == "full" {
Some(PrintFormat::Full)
} else {
Some(PrintFormat::Short)
},
None => None,
};
}
);
ENABLED.store(match val {
Some(v) => v as isize,
None => 1,
@ -177,7 +176,7 @@ pub fn log_enabled() -> Option<PrintFormat> { @@ -177,7 +176,7 @@ pub fn log_enabled() -> Option<PrintFormat> {
///
/// These output functions should now be used everywhere to ensure consistency.
/// You may want to also use `output_fileline`.
fn output(w: &mut Write, idx: usize, frame: Frame,
fn output(w: &mut dyn Write, idx: usize, frame: Frame,
s: Option<&str>, format: PrintFormat) -> io::Result<()> {
// Remove the `17: 0x0 - <unknown>` line.
if format == PrintFormat::Short && frame.exact_position == ptr::null() {
@ -202,7 +201,7 @@ fn output(w: &mut Write, idx: usize, frame: Frame, @@ -202,7 +201,7 @@ fn output(w: &mut Write, idx: usize, frame: Frame,
///
/// See also `output`.
#[allow(dead_code)]
fn output_fileline(w: &mut Write,
fn output_fileline(w: &mut dyn Write,
file: &[u8],
line: u32,
format: PrintFormat) -> io::Result<()> {
@ -254,7 +253,7 @@ fn output_fileline(w: &mut Write, @@ -254,7 +253,7 @@ fn output_fileline(w: &mut Write,
// Note that this demangler isn't quite as fancy as it could be. We have lots
// of other information in our symbols like hashes, version, type information,
// etc. Additionally, this doesn't handle glue symbols at all.
pub fn demangle(writer: &mut Write, mut s: &str, format: PrintFormat) -> io::Result<()> {
pub fn demangle(writer: &mut dyn Write, mut s: &str, format: PrintFormat) -> io::Result<()> {
// During ThinLTO LLVM may import and rename internal symbols, so strip out
// those endings first as they're one of the last manglings applied to
// symbol names.
@ -263,7 +262,7 @@ pub fn demangle(writer: &mut Write, mut s: &str, format: PrintFormat) -> io::Res @@ -263,7 +262,7 @@ pub fn demangle(writer: &mut Write, mut s: &str, format: PrintFormat) -> io::Res
let candidate = &s[i + llvm.len()..];
let all_hex = candidate.chars().all(|c| {
match c {
'A' ... 'F' | '0' ... '9' => true,
'A' ..= 'F' | '0' ..= '9' => true,
_ => false,
}
});

32
ctr-std/src/sys_common/mutex.rs

@ -24,11 +24,17 @@ impl Mutex { @@ -24,11 +24,17 @@ impl Mutex {
///
/// Behavior is undefined if the mutex is moved after it is
/// first used with any of the functions below.
/// Also, until `init` is called, behavior is undefined if this
/// mutex is ever used reentrantly, i.e., `raw_lock` or `try_lock`
/// are called by the thread currently holding the lock.
pub const fn new() -> Mutex { Mutex(imp::Mutex::new()) }
/// Prepare the mutex for use.
///
/// This should be called once the mutex is at a stable memory address.
/// If called, this must be the very first thing that happens to the mutex.
/// Calling it in parallel with or after any operation (including another
/// `init()`) is undefined behavior.
#[inline]
pub unsafe fn init(&mut self) { self.0.init() }
@ -37,7 +43,15 @@ impl Mutex { @@ -37,7 +43,15 @@ impl Mutex {
/// Behavior is undefined if the mutex has been moved between this and any
/// previous function call.
#[inline]
pub unsafe fn lock(&self) { self.0.lock() }
pub unsafe fn raw_lock(&self) { self.0.lock() }
/// Calls raw_lock() and then returns an RAII guard to guarantee the mutex
/// will be unlocked.
#[inline]
pub unsafe fn lock(&self) -> MutexGuard {
self.raw_lock();
MutexGuard(&self.0)
}
/// Attempts to lock the mutex without blocking, returning whether it was
/// successfully acquired or not.
@ -51,8 +65,11 @@ impl Mutex { @@ -51,8 +65,11 @@ impl Mutex {
///
/// Behavior is undefined if the current thread does not actually hold the
/// mutex.
///
/// Consider switching from the pair of raw_lock() and raw_unlock() to
/// lock() whenever possible.
#[inline]
pub unsafe fn unlock(&self) { self.0.unlock() }
pub unsafe fn raw_unlock(&self) { self.0.unlock() }
/// Deallocates all resources associated with this mutex.
///
@ -64,3 +81,14 @@ impl Mutex { @@ -64,3 +81,14 @@ impl Mutex {
// not meant to be exported to the outside world, just the containing module
pub fn raw(mutex: &Mutex) -> &imp::Mutex { &mutex.0 }
#[must_use]
/// A simple RAII utility for the above Mutex without the poisoning semantics.
pub struct MutexGuard<'a>(&'a imp::Mutex);
impl<'a> Drop for MutexGuard<'a> {
#[inline]
fn drop(&mut self) {
unsafe { self.0.unlock(); }
}
}

2
ctr-std/src/sys_common/poison.rs

@ -251,7 +251,7 @@ impl<T> Error for TryLockError<T> { @@ -251,7 +251,7 @@ impl<T> Error for TryLockError<T> {
}
}
fn cause(&self) -> Option<&Error> {
fn cause(&self) -> Option<&dyn Error> {
match *self {
TryLockError::Poisoned(ref p) => Some(p),
_ => None

4
ctr-std/src/sys_common/remutex.rs

@ -13,6 +13,7 @@ use marker; @@ -13,6 +13,7 @@ use marker;
use ops::Deref;
use sys_common::poison::{self, TryLockError, TryLockResult, LockResult};
use sys::mutex as sys;
use panic::{UnwindSafe, RefUnwindSafe};
/// A re-entrant mutual exclusion
///
@ -28,6 +29,9 @@ pub struct ReentrantMutex<T> { @@ -28,6 +29,9 @@ pub struct ReentrantMutex<T> {
unsafe impl<T: Send> Send for ReentrantMutex<T> {}
unsafe impl<T: Send> Sync for ReentrantMutex<T> {}
impl<T> UnwindSafe for ReentrantMutex<T> {}
impl<T> RefUnwindSafe for ReentrantMutex<T> {}
/// An RAII implementation of a "scoped lock" of a mutex. When this structure is
/// dropped (falls out of scope), the lock will be unlocked.

2
ctr-std/src/sys_common/thread.rs

@ -21,7 +21,7 @@ pub unsafe fn start_thread(main: *mut u8) { @@ -21,7 +21,7 @@ pub unsafe fn start_thread(main: *mut u8) {
let _handler = stack_overflow::Handler::new();
// Finally, let's run some code.
Box::from_raw(main as *mut Box<FnBox()>)()
Box::from_raw(main as *mut Box<dyn FnBox()>)()
}
pub fn min_stack() -> usize {

5
ctr-std/src/sys_common/thread_local.rs

@ -161,14 +161,15 @@ impl StaticKey { @@ -161,14 +161,15 @@ impl StaticKey {
// Additionally a 0-index of a tls key hasn't been seen on windows, so
// we just simplify the whole branch.
if imp::requires_synchronized_create() {
// We never call `INIT_LOCK.init()`, so it is UB to attempt to
// acquire this mutex reentrantly!
static INIT_LOCK: Mutex = Mutex::new();
INIT_LOCK.lock();
let _guard = INIT_LOCK.lock();
let mut key = self.key.load(Ordering::SeqCst);
if key == 0 {
key = imp::create(self.dtor) as usize;
self.key.store(key, Ordering::SeqCst);
}
INIT_LOCK.unlock();
rtassert!(key != 0);
return key
}

14
ctr-std/src/sys_common/wtf8.rs

@ -76,7 +76,7 @@ impl CodePoint { @@ -76,7 +76,7 @@ impl CodePoint {
#[inline]
pub fn from_u32(value: u32) -> Option<CodePoint> {
match value {
0 ... 0x10FFFF => Some(CodePoint { value: value }),
0 ..= 0x10FFFF => Some(CodePoint { value: value }),
_ => None
}
}
@ -101,7 +101,7 @@ impl CodePoint { @@ -101,7 +101,7 @@ impl CodePoint {
#[inline]
pub fn to_char(&self) -> Option<char> {
match self.value {
0xD800 ... 0xDFFF => None,
0xD800 ..= 0xDFFF => None,
_ => Some(unsafe { char::from_u32_unchecked(self.value) })
}
}
@ -305,7 +305,7 @@ impl Wtf8Buf { @@ -305,7 +305,7 @@ impl Wtf8Buf {
/// like concatenating ill-formed UTF-16 strings effectively would.
#[inline]
pub fn push(&mut self, code_point: CodePoint) {
if let trail @ 0xDC00...0xDFFF = code_point.to_u32() {
if let trail @ 0xDC00..=0xDFFF = code_point.to_u32() {
if let Some(lead) = (&*self).final_lead_surrogate() {
let len_without_lead_surrogate = self.len() - 3;
self.bytes.truncate(len_without_lead_surrogate);
@ -525,7 +525,7 @@ impl Wtf8 { @@ -525,7 +525,7 @@ impl Wtf8 {
#[inline]
pub fn ascii_byte_at(&self, position: usize) -> u8 {
match self.bytes[position] {
ascii_byte @ 0x00 ... 0x7F => ascii_byte,
ascii_byte @ 0x00 ..= 0x7F => ascii_byte,
_ => 0xFF
}
}
@ -630,7 +630,7 @@ impl Wtf8 { @@ -630,7 +630,7 @@ impl Wtf8 {
return None
}
match &self.bytes[(len - 3)..] {
&[0xED, b2 @ 0xA0...0xAF, b3] => Some(decode_surrogate(b2, b3)),
&[0xED, b2 @ 0xA0..=0xAF, b3] => Some(decode_surrogate(b2, b3)),
_ => None
}
}
@ -642,7 +642,7 @@ impl Wtf8 { @@ -642,7 +642,7 @@ impl Wtf8 {
return None
}
match &self.bytes[..3] {
&[0xED, b2 @ 0xB0...0xBF, b3] => Some(decode_surrogate(b2, b3)),
&[0xED, b2 @ 0xB0..=0xBF, b3] => Some(decode_surrogate(b2, b3)),
_ => None
}
}
@ -1245,7 +1245,7 @@ mod tests { @@ -1245,7 +1245,7 @@ mod tests {
#[test]
fn wtf8_display() {
fn d(b: &[u8]) -> String {
format!("{}", &unsafe { Wtf8::from_bytes_unchecked(b) })
(&unsafe { Wtf8::from_bytes_unchecked(b) }).to_string()
}
assert_eq!("", d("".as_bytes()));

3
ctr-std/src/tests/env.rs

@ -11,7 +11,6 @@ @@ -11,7 +11,6 @@
extern crate rand;
use std::env::*;
use std::iter::repeat;
use std::ffi::{OsString, OsStr};
use rand::Rng;
@ -72,7 +71,7 @@ fn test_var_big() { @@ -72,7 +71,7 @@ fn test_var_big() {
#[cfg_attr(target_os = "emscripten", ignore)]
fn test_env_set_get_huge() {
let n = make_rand_name();
let s = repeat("x").take(10000).collect::<String>();
let s = "x".repeat(10000);
set_var(&n, &s);
eq(var_os(&n), Some(&s));
remove_var(&n);

2
ctr-std/src/thread/local.rs

@ -276,7 +276,7 @@ impl<T: 'static> LocalKey<T> { @@ -276,7 +276,7 @@ impl<T: 'static> LocalKey<T> {
///
/// This will lazily initialize the value if this thread has not referenced
/// this key yet. If the key has been destroyed (which may happen if this is called
/// in a destructor), this function will return a `ThreadLocalError`.
/// in a destructor), this function will return an [`AccessError`](struct.AccessError.html).
///
/// # Panics
///

37
ctr-std/src/thread/mod.rs

@ -731,7 +731,8 @@ const NOTIFIED: usize = 2; @@ -731,7 +731,8 @@ const NOTIFIED: usize = 2;
/// specifying a maximum time to block the thread for.
///
/// * The [`unpark`] method on a [`Thread`] atomically makes the token available
/// if it wasn't already.
/// if it wasn't already. Because the token is initially absent, [`unpark`]
/// followed by [`park`] will result in the second call returning immediately.
///
/// In other words, each [`Thread`] acts a bit like a spinlock that can be
/// locked and unlocked using `park` and `unpark`.
@ -766,6 +767,8 @@ const NOTIFIED: usize = 2; @@ -766,6 +767,8 @@ const NOTIFIED: usize = 2;
/// // Let some time pass for the thread to be spawned.
/// thread::sleep(Duration::from_millis(10));
///
/// // There is no race condition here, if `unpark`
/// // happens first, `park` will return immediately.
/// println!("Unpark the thread");
/// parked_thread.thread().unpark();
///
@ -796,7 +799,10 @@ pub fn park() { @@ -796,7 +799,10 @@ pub fn park() {
let mut m = thread.inner.lock.lock().unwrap();
match thread.inner.state.compare_exchange(EMPTY, PARKED, SeqCst, SeqCst) {
Ok(_) => {}
Err(NOTIFIED) => return, // notified after we locked
Err(NOTIFIED) => {
thread.inner.state.store(EMPTY, SeqCst);
return;
} // should consume this notification, so prohibit spurious wakeups in next park.
Err(_) => panic!("inconsistent park state"),
}
loop {
@ -882,7 +888,10 @@ pub fn park_timeout(dur: Duration) { @@ -882,7 +888,10 @@ pub fn park_timeout(dur: Duration) {
let m = thread.inner.lock.lock().unwrap();
match thread.inner.state.compare_exchange(EMPTY, PARKED, SeqCst, SeqCst) {
Ok(_) => {}
Err(NOTIFIED) => return, // notified after we locked
Err(NOTIFIED) => {
thread.inner.state.store(EMPTY, SeqCst);
return;
} // should consume this notification, so prohibit spurious wakeups in next park.
Err(_) => panic!("inconsistent park_timeout state"),
}
@ -931,24 +940,23 @@ pub struct ThreadId(u64); @@ -931,24 +940,23 @@ pub struct ThreadId(u64);
impl ThreadId {
// Generate a new unique thread ID.
fn new() -> ThreadId {
// We never call `GUARD.init()`, so it is UB to attempt to
// acquire this mutex reentrantly!
static GUARD: mutex::Mutex = mutex::Mutex::new();
static mut COUNTER: u64 = 0;
unsafe {
GUARD.lock();
let _guard = GUARD.lock();
// If we somehow use up all our bits, panic so that we're not
// covering up subtle bugs of IDs being reused.
if COUNTER == ::u64::MAX {
GUARD.unlock();
panic!("failed to generate unique thread ID: bitspace exhausted");
}
let id = COUNTER;
COUNTER += 1;
GUARD.unlock();
ThreadId(id)
}
}
@ -1172,7 +1180,7 @@ impl fmt::Debug for Thread { @@ -1172,7 +1180,7 @@ impl fmt::Debug for Thread {
///
/// [`Result`]: ../../std/result/enum.Result.html
#[stable(feature = "rust1", since = "1.0.0")]
pub type Result<T> = ::result::Result<T, Box<Any + Send + 'static>>;
pub type Result<T> = ::result::Result<T, Box<dyn Any + Send + 'static>>;
// This packet is used to communicate the return value between the child thread
// and the parent thread. Memory is shared through the `Arc` within and there's
@ -1273,6 +1281,11 @@ impl<T> JoinInner<T> { @@ -1273,6 +1281,11 @@ impl<T> JoinInner<T> {
#[stable(feature = "rust1", since = "1.0.0")]
pub struct JoinHandle<T>(JoinInner<T>);
#[stable(feature = "joinhandle_impl_send_sync", since = "1.29.0")]
unsafe impl<T> Send for JoinHandle<T> {}
#[stable(feature = "joinhandle_impl_send_sync", since = "1.29.0")]
unsafe impl<T> Sync for JoinHandle<T> {}
impl<T> JoinHandle<T> {
/// Extracts a handle to the underlying thread.
///
@ -1435,7 +1448,7 @@ mod tests { @@ -1435,7 +1448,7 @@ mod tests {
rx.recv().unwrap();
}
fn avoid_copying_the_body<F>(spawnfn: F) where F: FnOnce(Box<Fn() + Send>) {
fn avoid_copying_the_body<F>(spawnfn: F) where F: FnOnce(Box<dyn Fn() + Send>) {
let (tx, rx) = channel();
let x: Box<_> = box 1;
@ -1482,7 +1495,7 @@ mod tests { @@ -1482,7 +1495,7 @@ mod tests {
// (well, it would if the constant were 8000+ - I lowered it to be more
// valgrind-friendly. try this at home, instead..!)
const GENERATIONS: u32 = 16;
fn child_no(x: u32) -> Box<Fn() + Send> {
fn child_no(x: u32) -> Box<dyn Fn() + Send> {
return Box::new(move|| {
if x < GENERATIONS {
thread::spawn(move|| child_no(x+1)());
@ -1528,10 +1541,10 @@ mod tests { @@ -1528,10 +1541,10 @@ mod tests {
#[test]
fn test_try_panic_message_any() {
match thread::spawn(move|| {
panic!(box 413u16 as Box<Any + Send>);
panic!(box 413u16 as Box<dyn Any + Send>);
}).join() {
Err(e) => {
type T = Box<Any + Send>;
type T = Box<dyn Any + Send>;
assert!(e.is::<T>());
let any = e.downcast::<T>().unwrap();
assert!(any.is::<u16>());

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save