From 634f8cc06a88eb978c5e52390014740c4bab1e33 Mon Sep 17 00:00:00 2001 From: John Kåre Alsaker Date: Wed, 15 Nov 2017 18:01:09 +0100 Subject: Print inlined functions on Windows --- src/libstd/sys/windows/backtrace/mod.rs | 31 +++++++------ src/libstd/sys/windows/backtrace/printing/msvc.rs | 54 ++++++++++++++--------- src/libstd/sys/windows/c.rs | 4 +- 3 files changed, 52 insertions(+), 37 deletions(-) (limited to 'src/libstd/sys/windows') diff --git a/src/libstd/sys/windows/backtrace/mod.rs b/src/libstd/sys/windows/backtrace/mod.rs index 176891fff23..82498ad4d58 100644 --- a/src/libstd/sys/windows/backtrace/mod.rs +++ b/src/libstd/sys/windows/backtrace/mod.rs @@ -56,14 +56,15 @@ pub fn unwind_backtrace(frames: &mut [Frame]) // Fetch the symbols necessary from dbghelp.dll let SymInitialize = sym!(dbghelp, "SymInitialize", SymInitializeFn)?; let SymCleanup = sym!(dbghelp, "SymCleanup", SymCleanupFn)?; - let StackWalk64 = sym!(dbghelp, "StackWalk64", StackWalk64Fn)?; + let StackWalkEx = sym!(dbghelp, "StackWalkEx", StackWalkExFn)?; // Allocate necessary structures for doing the stack walk let process = unsafe { c::GetCurrentProcess() }; let thread = unsafe { c::GetCurrentThread() }; let mut context: c::CONTEXT = unsafe { mem::zeroed() }; unsafe { c::RtlCaptureContext(&mut context) }; - let mut frame: c::STACKFRAME64 = unsafe { mem::zeroed() }; + let 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 { @@ -79,24 +80,22 @@ pub fn unwind_backtrace(frames: &mut [Frame]) } // And now that we're done with all the setup, do the stack walking! - // Start from -1 to avoid printing this stack frame, which will - // always be exactly the same. let mut i = 0; unsafe { while i < frames.len() && - StackWalk64(image, process, thread, &mut frame, &mut context, + StackWalkEx(image, process, thread, &mut frame, &mut context, ptr::null_mut(), ptr::null_mut(), ptr::null_mut(), - ptr::null_mut()) == c::TRUE + ptr::null_mut(), + 0) == c::TRUE { - let addr = frame.AddrPC.Offset; - if addr == frame.AddrReturn.Offset || addr == 0 || - frame.AddrReturn.Offset == 0 { break } + let addr = (frame.AddrPC.Offset - 1) as *const u8; frames[i] = Frame { - symbol_addr: (addr - 1) as *const u8, - exact_position: (addr - 1) as *const u8, + symbol_addr: addr, + exact_position: addr, + inline_context: frame.InlineFrameContext, }; i += 1; } @@ -111,14 +110,14 @@ type SymInitializeFn = type SymCleanupFn = unsafe extern "system" fn(c::HANDLE) -> c::BOOL; -type StackWalk64Fn = +type StackWalkExFn = unsafe extern "system" fn(c::DWORD, c::HANDLE, c::HANDLE, - *mut c::STACKFRAME64, *mut c::CONTEXT, + *mut c::STACKFRAME_EX, *mut c::CONTEXT, *mut c_void, *mut c_void, - *mut c_void, *mut c_void) -> c::BOOL; + *mut c_void, *mut c_void, c::DWORD) -> c::BOOL; #[cfg(target_arch = "x86")] -fn init_frame(frame: &mut c::STACKFRAME64, +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; @@ -130,7 +129,7 @@ fn init_frame(frame: &mut c::STACKFRAME64, } #[cfg(target_arch = "x86_64")] -fn init_frame(frame: &mut c::STACKFRAME64, +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; diff --git a/src/libstd/sys/windows/backtrace/printing/msvc.rs b/src/libstd/sys/windows/backtrace/printing/msvc.rs index 5a49b77af8e..967df1c8a2d 100644 --- a/src/libstd/sys/windows/backtrace/printing/msvc.rs +++ b/src/libstd/sys/windows/backtrace/printing/msvc.rs @@ -16,12 +16,12 @@ use sys::c; use sys::backtrace::BacktraceContext; use sys_common::backtrace::Frame; -type SymFromAddrFn = - unsafe extern "system" fn(c::HANDLE, u64, *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 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; /// Converts a pointer to symbol to its string value. pub fn resolve_symname(frame: Frame, @@ -29,7 +29,9 @@ pub fn resolve_symname(frame: Frame, context: &BacktraceContext) -> io::Result<()> where F: FnOnce(Option<&str>) -> io::Result<()> { - let SymFromAddr = sym!(&context.dbghelp, "SymFromAddr", SymFromAddrFn)?; + let SymFromInlineContext = sym!(&context.dbghelp, + "SymFromInlineContext", + SymFromInlineContextFn)?; unsafe { let mut info: c::SYMBOL_INFO = mem::zeroed(); @@ -40,12 +42,22 @@ pub fn resolve_symname(frame: Frame, info.SizeOfStruct = 88; let mut displacement = 0u64; - let ret = SymFromAddr(context.handle, - frame.symbol_addr as u64, - &mut displacement, - &mut info); - - let symname = if ret == c::TRUE { + 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 { + if info.Size != 0 { + (frame.symbol_addr as usize) < info.Address as usize + info.Size as usize + } else { + true + } + } else { + false + }; + let symname = if valid_range { let ptr = info.Name.as_ptr() as *const c_char; CStr::from_ptr(ptr).to_str().ok() } else { @@ -61,19 +73,21 @@ pub fn foreach_symbol_fileline(frame: Frame, -> io::Result where F: FnMut(&[u8], u32) -> io::Result<()> { - let SymGetLineFromAddr64 = sym!(&context.dbghelp, - "SymGetLineFromAddr64", - SymGetLineFromAddr64Fn)?; + let SymGetLineFromInlineContext = sym!(&context.dbghelp, + "SymGetLineFromInlineContext", + SymGetLineFromInlineContextFn)?; unsafe { let mut line: c::IMAGEHLP_LINE64 = mem::zeroed(); line.SizeOfStruct = ::mem::size_of::() as u32; let mut displacement = 0u32; - let ret = SymGetLineFromAddr64(context.handle, - frame.exact_position as u64, - &mut displacement, - &mut line); + let ret = SymGetLineFromInlineContext(context.handle, + frame.exact_position as u64, + frame.inline_context, + 0, + &mut displacement, + &mut line); if ret == c::TRUE { let name = CStr::from_ptr(line.Filename).to_bytes(); f(name, line.LineNumber as u32)?; diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs index 66b44f1402f..6d929f21365 100644 --- a/src/libstd/sys/windows/c.rs +++ b/src/libstd/sys/windows/c.rs @@ -619,7 +619,7 @@ pub struct ADDRESS64 { #[repr(C)] #[cfg(feature = "backtrace")] -pub struct STACKFRAME64 { +pub struct STACKFRAME_EX { pub AddrPC: ADDRESS64, pub AddrReturn: ADDRESS64, pub AddrFrame: ADDRESS64, @@ -631,6 +631,8 @@ pub struct STACKFRAME64 { pub Virtual: BOOL, pub Reserved: [u64; 3], pub KdHelp: KDHELP64, + pub StackFrameSize: DWORD, + pub InlineFrameContext: DWORD, } #[repr(C)] -- cgit 1.4.1-3-g733a5 From 55b54a999bcdb0b1c1f42b6e1ae670beb0717086 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 31 Jan 2018 11:41:29 -0800 Subject: Use a range to identify SIGSEGV in stack guards MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, the `guard::init()` and `guard::current()` functions were returning a `usize` address representing the top of the stack guard, respectively for the main thread and for spawned threads. The `SIGSEGV` handler on `unix` targets checked if a fault was within one page below that address, if so reporting it as a stack overflow. Now `unix` targets report a `Range` representing the guard memory, so it can cover arbitrary guard sizes. Non-`unix` targets which always return `None` for guards now do so with `Option`, so they don't pay any overhead. For `linux-gnu` in particular, the previous guard upper-bound was `stackaddr + guardsize`, as the protected memory was *inside* the stack. This was a glibc bug, and starting from 2.27 they are moving the guard *past* the end of the stack. However, there's no simple way for us to know where the guard page actually lies, so now we declare it as the whole range of `stackaddr ± guardsize`, and any fault therein will be called a stack overflow. This fixes #47863. --- src/libstd/sys/cloudabi/thread.rs | 5 +- src/libstd/sys/redox/thread.rs | 5 +- src/libstd/sys/unix/stack_overflow.rs | 9 +-- src/libstd/sys/unix/thread.rs | 115 +++++++++++++++++++++------------- src/libstd/sys/wasm/thread.rs | 5 +- src/libstd/sys/windows/thread.rs | 5 +- src/libstd/sys_common/thread_info.rs | 9 +-- 7 files changed, 89 insertions(+), 64 deletions(-) (limited to 'src/libstd/sys/windows') diff --git a/src/libstd/sys/cloudabi/thread.rs b/src/libstd/sys/cloudabi/thread.rs index c980ae75261..78a3b82546e 100644 --- a/src/libstd/sys/cloudabi/thread.rs +++ b/src/libstd/sys/cloudabi/thread.rs @@ -111,10 +111,11 @@ impl Drop for Thread { #[cfg_attr(test, allow(dead_code))] pub mod guard { - pub unsafe fn current() -> Option { + pub type Guard = !; + pub unsafe fn current() -> Option { None } - pub unsafe fn init() -> Option { + pub unsafe fn init() -> Option { None } } diff --git a/src/libstd/sys/redox/thread.rs b/src/libstd/sys/redox/thread.rs index c4aad8d86f8..c4719a94c7e 100644 --- a/src/libstd/sys/redox/thread.rs +++ b/src/libstd/sys/redox/thread.rs @@ -88,6 +88,7 @@ impl Thread { } pub mod guard { - pub unsafe fn current() -> Option { None } - pub unsafe fn init() -> Option { None } + pub type Guard = !; + pub unsafe fn current() -> Option { None } + pub unsafe fn init() -> Option { None } } diff --git a/src/libstd/sys/unix/stack_overflow.rs b/src/libstd/sys/unix/stack_overflow.rs index 51adbc24ae0..40453f9b8a1 100644 --- a/src/libstd/sys/unix/stack_overflow.rs +++ b/src/libstd/sys/unix/stack_overflow.rs @@ -57,9 +57,6 @@ mod imp { use sys_common::thread_info; - // This is initialized in init() and only read from after - static mut PAGE_SIZE: usize = 0; - #[cfg(any(target_os = "linux", target_os = "android"))] unsafe fn siginfo_si_addr(info: *mut libc::siginfo_t) -> usize { #[repr(C)] @@ -102,12 +99,12 @@ mod imp { _data: *mut libc::c_void) { use sys_common::util::report_overflow; - let guard = thread_info::stack_guard().unwrap_or(0); + let guard = thread_info::stack_guard().unwrap_or(0..0); let addr = siginfo_si_addr(info); // If the faulting address is within the guard page, then we print a // message saying so and abort. - if guard != 0 && guard - PAGE_SIZE <= addr && addr < guard { + if guard.start <= addr && addr < guard.end { report_overflow(); rtabort!("stack overflow"); } else { @@ -123,8 +120,6 @@ mod imp { static mut MAIN_ALTSTACK: *mut libc::c_void = ptr::null_mut(); pub unsafe fn init() { - PAGE_SIZE = ::sys::os::page_size(); - let mut action: sigaction = mem::zeroed(); action.sa_flags = SA_SIGINFO | SA_ONSTACK; action.sa_sigaction = signal_handler as sighandler_t; diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs index 525882c1e1e..72cdb9440b8 100644 --- a/src/libstd/sys/unix/thread.rs +++ b/src/libstd/sys/unix/thread.rs @@ -205,8 +205,10 @@ impl Drop for Thread { not(target_os = "solaris")))] #[cfg_attr(test, allow(dead_code))] pub mod guard { - pub unsafe fn current() -> Option { None } - pub unsafe fn init() -> Option { None } + use ops::Range; + pub type Guard = Range; + pub unsafe fn current() -> Option { None } + pub unsafe fn init() -> Option { None } } @@ -222,14 +224,43 @@ pub mod guard { use libc; use libc::mmap; use libc::{PROT_NONE, MAP_PRIVATE, MAP_ANON, MAP_FAILED, MAP_FIXED}; + use ops::Range; use sys::os; - #[cfg(any(target_os = "macos", - target_os = "bitrig", - target_os = "openbsd", - target_os = "solaris"))] + // This is initialized in init() and only read from after + static mut PAGE_SIZE: usize = 0; + + pub type Guard = Range; + + #[cfg(target_os = "solaris")] + unsafe fn get_stack_start() -> Option<*mut libc::c_void> { + let mut current_stack: libc::stack_t = ::mem::zeroed(); + assert_eq!(libc::stack_getbounds(&mut current_stack), 0); + Some(current_stack.ss_sp) + } + + #[cfg(target_os = "macos")] unsafe fn get_stack_start() -> Option<*mut libc::c_void> { - current().map(|s| s as *mut libc::c_void) + let stackaddr = libc::pthread_get_stackaddr_np(libc::pthread_self()) as usize - + libc::pthread_get_stacksize_np(libc::pthread_self()); + Some(stackaddr as *mut libc::c_void) + } + + #[cfg(any(target_os = "openbsd", target_os = "bitrig"))] + unsafe fn get_stack_start() -> Option<*mut libc::c_void> { + let mut current_stack: libc::stack_t = ::mem::zeroed(); + assert_eq!(libc::pthread_stackseg_np(libc::pthread_self(), + &mut current_stack), 0); + + let extra = if cfg!(target_os = "bitrig") {3} else {1} * PAGE_SIZE; + let stackaddr = if libc::pthread_main_np() == 1 { + // main thread + current_stack.ss_sp as usize - current_stack.ss_size + extra + } else { + // new thread + current_stack.ss_sp as usize - current_stack.ss_size + }; + Some(stackaddr as *mut libc::c_void) } #[cfg(any(target_os = "android", target_os = "freebsd", @@ -253,8 +284,9 @@ pub mod guard { ret } - pub unsafe fn init() -> Option { - let psize = os::page_size(); + pub unsafe fn init() -> Option { + PAGE_SIZE = os::page_size(); + let mut stackaddr = get_stack_start()?; // Ensure stackaddr is page aligned! A parent process might @@ -263,9 +295,9 @@ pub mod guard { // stackaddr < stackaddr + stacksize, so if stackaddr is not // page-aligned, calculate the fix such that stackaddr < // new_page_aligned_stackaddr < stackaddr + stacksize - let remainder = (stackaddr as usize) % psize; + let remainder = (stackaddr as usize) % PAGE_SIZE; if remainder != 0 { - stackaddr = ((stackaddr as usize) + psize - remainder) + stackaddr = ((stackaddr as usize) + PAGE_SIZE - remainder) as *mut libc::c_void; } @@ -280,60 +312,42 @@ pub mod guard { // Instead, we'll just note where we expect rlimit to start // faulting, so our handler can report "stack overflow", and // trust that the kernel's own stack guard will work. - Some(stackaddr as usize) + let stackaddr = stackaddr as usize; + Some(stackaddr - PAGE_SIZE..stackaddr) } else { // Reallocate the last page of the stack. // This ensures SIGBUS will be raised on // stack overflow. - let result = mmap(stackaddr, psize, PROT_NONE, + let result = mmap(stackaddr, PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0); if result != stackaddr || result == MAP_FAILED { panic!("failed to allocate a guard page"); } + let guardaddr = stackaddr as usize; let offset = if cfg!(target_os = "freebsd") { 2 } else { 1 }; - Some(stackaddr as usize + offset * psize) + Some(guardaddr..guardaddr + offset * PAGE_SIZE) } } - #[cfg(target_os = "solaris")] - pub unsafe fn current() -> Option { - let mut current_stack: libc::stack_t = ::mem::zeroed(); - assert_eq!(libc::stack_getbounds(&mut current_stack), 0); - Some(current_stack.ss_sp as usize) - } - - #[cfg(target_os = "macos")] - pub unsafe fn current() -> Option { - Some(libc::pthread_get_stackaddr_np(libc::pthread_self()) as usize - - libc::pthread_get_stacksize_np(libc::pthread_self())) - } - - #[cfg(any(target_os = "openbsd", target_os = "bitrig"))] - pub unsafe fn current() -> Option { - let mut current_stack: libc::stack_t = ::mem::zeroed(); - assert_eq!(libc::pthread_stackseg_np(libc::pthread_self(), - &mut current_stack), 0); - - let extra = if cfg!(target_os = "bitrig") {3} else {1} * os::page_size(); - Some(if libc::pthread_main_np() == 1 { - // main thread - current_stack.ss_sp as usize - current_stack.ss_size + extra - } else { - // new thread - current_stack.ss_sp as usize - current_stack.ss_size - }) + #[cfg(any(target_os = "macos", + target_os = "bitrig", + target_os = "openbsd", + target_os = "solaris"))] + pub unsafe fn current() -> Option { + let stackaddr = get_stack_start()? as usize; + Some(stackaddr - PAGE_SIZE..stackaddr) } #[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux", target_os = "netbsd", target_os = "l4re"))] - pub unsafe fn current() -> Option { + pub unsafe fn current() -> Option { let mut ret = None; let mut attr: libc::pthread_attr_t = ::mem::zeroed(); assert_eq!(libc::pthread_attr_init(&mut attr), 0); @@ -352,12 +366,23 @@ pub mod guard { assert_eq!(libc::pthread_attr_getstack(&attr, &mut stackaddr, &mut size), 0); + let stackaddr = stackaddr as usize; ret = if cfg!(target_os = "freebsd") { - Some(stackaddr as usize - guardsize) + // FIXME does freebsd really fault *below* the guard addr? + let guardaddr = stackaddr - guardsize; + Some(guardaddr - PAGE_SIZE..guardaddr) } else if cfg!(target_os = "netbsd") { - Some(stackaddr as usize) + Some(stackaddr - guardsize..stackaddr) + } else if cfg!(all(target_os = "linux", target_env = "gnu")) { + // glibc used to include the guard area within the stack, as noted in the BUGS + // section of `man pthread_attr_getguardsize`. This has been corrected starting + // with glibc 2.27, and in some distro backports, so the guard is now placed at the + // end (below) the stack. There's no easy way for us to know which we have at + // runtime, so we'll just match any fault in the range right above or below the + // stack base to call that fault a stack overflow. + Some(stackaddr - guardsize..stackaddr + guardsize) } else { - Some(stackaddr as usize + guardsize) + Some(stackaddr..stackaddr + guardsize) }; } assert_eq!(libc::pthread_attr_destroy(&mut attr), 0); diff --git a/src/libstd/sys/wasm/thread.rs b/src/libstd/sys/wasm/thread.rs index 13980e0cc19..6a066509b49 100644 --- a/src/libstd/sys/wasm/thread.rs +++ b/src/libstd/sys/wasm/thread.rs @@ -43,6 +43,7 @@ impl Thread { } pub mod guard { - pub unsafe fn current() -> Option { None } - pub unsafe fn init() -> Option { None } + pub type Guard = !; + pub unsafe fn current() -> Option { None } + pub unsafe fn init() -> Option { None } } diff --git a/src/libstd/sys/windows/thread.rs b/src/libstd/sys/windows/thread.rs index 74786d09285..43abfbb1f64 100644 --- a/src/libstd/sys/windows/thread.rs +++ b/src/libstd/sys/windows/thread.rs @@ -93,6 +93,7 @@ impl Thread { #[cfg_attr(test, allow(dead_code))] pub mod guard { - pub unsafe fn current() -> Option { None } - pub unsafe fn init() -> Option { None } + pub type Guard = !; + pub unsafe fn current() -> Option { None } + pub unsafe fn init() -> Option { None } } diff --git a/src/libstd/sys_common/thread_info.rs b/src/libstd/sys_common/thread_info.rs index 7970042b1d6..6a2b6742367 100644 --- a/src/libstd/sys_common/thread_info.rs +++ b/src/libstd/sys_common/thread_info.rs @@ -11,10 +11,11 @@ #![allow(dead_code)] // stack_guard isn't used right now on all platforms use cell::RefCell; +use sys::thread::guard::Guard; use thread::Thread; struct ThreadInfo { - stack_guard: Option, + stack_guard: Option, thread: Thread, } @@ -38,11 +39,11 @@ pub fn current_thread() -> Option { ThreadInfo::with(|info| info.thread.clone()) } -pub fn stack_guard() -> Option { - ThreadInfo::with(|info| info.stack_guard).and_then(|o| o) +pub fn stack_guard() -> Option { + ThreadInfo::with(|info| info.stack_guard.clone()).and_then(|o| o) } -pub fn set(stack_guard: Option, thread: Thread) { +pub fn set(stack_guard: Option, thread: Thread) { THREAD_INFO.with(|c| assert!(c.borrow().is_none())); THREAD_INFO.with(move |c| *c.borrow_mut() = Some(ThreadInfo{ stack_guard, -- cgit 1.4.1-3-g733a5 From b1b9edf5ae3c6a8a862e480174f9fefafeba7143 Mon Sep 17 00:00:00 2001 From: Peter Atashian Date: Thu, 1 Feb 2018 20:18:33 -0500 Subject: This is what FileType on Windows should ideally be. --- src/libstd/sys/windows/fs.rs | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) (limited to 'src/libstd/sys/windows') diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs index 165e1b0609b..001e7ceeb71 100644 --- a/src/libstd/sys/windows/fs.rs +++ b/src/libstd/sys/windows/fs.rs @@ -38,8 +38,9 @@ pub struct FileAttr { } #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] -pub enum FileType { - Dir, File, SymlinkFile, SymlinkDir, ReparsePoint, MountPoint, +pub struct FileType { + attributes: c::DWORD, + reparse_tag: c::DWORD, } pub struct ReadDir { @@ -516,30 +517,28 @@ impl FilePermissions { impl FileType { fn new(attrs: c::DWORD, reparse_tag: c::DWORD) -> FileType { - match (attrs & c::FILE_ATTRIBUTE_DIRECTORY != 0, - attrs & c::FILE_ATTRIBUTE_REPARSE_POINT != 0, - reparse_tag) { - (false, false, _) => FileType::File, - (true, false, _) => FileType::Dir, - (false, true, c::IO_REPARSE_TAG_SYMLINK) => FileType::SymlinkFile, - (true, true, c::IO_REPARSE_TAG_SYMLINK) => FileType::SymlinkDir, - (true, true, c::IO_REPARSE_TAG_MOUNT_POINT) => FileType::MountPoint, - (_, true, _) => FileType::ReparsePoint, - // Note: if a _file_ has a reparse tag of the type IO_REPARSE_TAG_MOUNT_POINT it is - // invalid, as junctions always have to be dirs. We set the filetype to ReparsePoint - // to indicate it is something symlink-like, but not something you can follow. + FileType { + attributes: attrs, + reparse_tag: reparse_tag, } } - pub fn is_dir(&self) -> bool { *self == FileType::Dir } - pub fn is_file(&self) -> bool { *self == FileType::File } + pub fn is_dir(&self) -> bool { + self.attributes & c::FILE_ATTRIBUTE_DIRECTORY != 0 + } + pub fn is_file(&self) -> bool { + self.attributes & c::FILE_ATTRIBUTE_DIRECTORY == 0 + } pub fn is_symlink(&self) -> bool { - *self == FileType::SymlinkFile || - *self == FileType::SymlinkDir || - *self == FileType::MountPoint + self.is_reparse_point() && ( + self.reparse_tag == c::IO_REPARSE_TAG_SYMLINK || + self.reparse_tag == c::IO_REPARSE_TAG_MOUNT_POINT) } pub fn is_symlink_dir(&self) -> bool { - *self == FileType::SymlinkDir || *self == FileType::MountPoint + self.is_symlink() && self.is_dir() + } + pub fn is_reparse_point(&self) -> bool { + self.attributes & c::FILE_ATTRIBUTE_REPARSE_POINT != 0 } } -- cgit 1.4.1-3-g733a5 From dcf53c1590b741a16e92c7e5a306e923827ae301 Mon Sep 17 00:00:00 2001 From: Peter Atashian Date: Thu, 1 Feb 2018 20:35:50 -0500 Subject: Rewrite remove_dir_all to be correct The fact that this had to be rewritten does not bode well --- src/libstd/sys/windows/fs.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src/libstd/sys/windows') diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs index 001e7ceeb71..87a09925313 100644 --- a/src/libstd/sys/windows/fs.rs +++ b/src/libstd/sys/windows/fs.rs @@ -611,9 +611,11 @@ fn remove_dir_all_recursive(path: &Path) -> io::Result<()> { let child = child?; let child_type = child.file_type()?; if child_type.is_dir() { - remove_dir_all_recursive(&child.path())?; - } else if child_type.is_symlink_dir() { - rmdir(&child.path())?; + if child_type.is_reparse_point() { + rmdir(&child.path())?; + } else { + remove_dir_all_recursive(&child.path())?; + } } else { unlink(&child.path())?; } -- cgit 1.4.1-3-g733a5 From 259b0329d42ea9ce971c0c8c9ff72f8496a73b9e Mon Sep 17 00:00:00 2001 From: Peter Atashian Date: Thu, 1 Feb 2018 20:42:31 -0500 Subject: This internal only method is no longer needed. --- src/libstd/sys/windows/fs.rs | 3 --- 1 file changed, 3 deletions(-) (limited to 'src/libstd/sys/windows') diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs index 87a09925313..a49c3569b02 100644 --- a/src/libstd/sys/windows/fs.rs +++ b/src/libstd/sys/windows/fs.rs @@ -534,9 +534,6 @@ impl FileType { self.reparse_tag == c::IO_REPARSE_TAG_SYMLINK || self.reparse_tag == c::IO_REPARSE_TAG_MOUNT_POINT) } - pub fn is_symlink_dir(&self) -> bool { - self.is_symlink() && self.is_dir() - } pub fn is_reparse_point(&self) -> bool { self.attributes & c::FILE_ATTRIBUTE_REPARSE_POINT != 0 } -- cgit 1.4.1-3-g733a5 From f4c83693f9e2445b441dfcf43838697d25d1a11f Mon Sep 17 00:00:00 2001 From: Peter Atashian Date: Sat, 3 Feb 2018 01:45:58 -0500 Subject: Go back to files directories and symlinks being mutually exclusive Be smarter about what a symlink is however --- src/libstd/sys/windows/fs.rs | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) (limited to 'src/libstd/sys/windows') diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs index a49c3569b02..512c9cb838c 100644 --- a/src/libstd/sys/windows/fs.rs +++ b/src/libstd/sys/windows/fs.rs @@ -522,21 +522,27 @@ impl FileType { reparse_tag: reparse_tag, } } - pub fn is_dir(&self) -> bool { - self.attributes & c::FILE_ATTRIBUTE_DIRECTORY != 0 + !self.is_symlink() && self.is_directory() } pub fn is_file(&self) -> bool { - self.attributes & c::FILE_ATTRIBUTE_DIRECTORY == 0 + !self.is_symlink() && !self.is_directory() } pub fn is_symlink(&self) -> bool { - self.is_reparse_point() && ( - self.reparse_tag == c::IO_REPARSE_TAG_SYMLINK || - self.reparse_tag == c::IO_REPARSE_TAG_MOUNT_POINT) + self.is_reparse_point() && self.is_reparse_tag_name_surrogate() + } + pub fn is_symlink_dir(&self) -> bool { + self.is_symlink() && self.is_directory() + } + fn is_directory(&self) -> bool { + self.attributes & c::FILE_ATTRIBUTE_DIRECTORY != 0 } - pub fn is_reparse_point(&self) -> bool { + fn is_reparse_point(&self) -> bool { self.attributes & c::FILE_ATTRIBUTE_REPARSE_POINT != 0 } + fn is_reparse_tag_name_surrogate(&self) -> bool { + self.reparse_tag & 0x20000000 != 0 + } } impl DirBuilder { @@ -607,12 +613,10 @@ fn remove_dir_all_recursive(path: &Path) -> io::Result<()> { for child in readdir(path)? { let child = child?; let child_type = child.file_type()?; - if child_type.is_dir() { - if child_type.is_reparse_point() { - rmdir(&child.path())?; - } else { - remove_dir_all_recursive(&child.path())?; - } + if child_type.is_symlink_dir() { + rmdir(&child.path())?; + } else if child_type.is_dir() { + remove_dir_all_recursive(&child.path())?; } else { unlink(&child.path())?; } -- cgit 1.4.1-3-g733a5 From c42d76d3c80b4938e26e628706363b677fde6ca1 Mon Sep 17 00:00:00 2001 From: Peter Atashian Date: Sat, 3 Feb 2018 01:52:04 -0500 Subject: Somehow this function got flipped around Unflip it --- src/libstd/sys/windows/fs.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/libstd/sys/windows') diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs index 512c9cb838c..7e3b16558d4 100644 --- a/src/libstd/sys/windows/fs.rs +++ b/src/libstd/sys/windows/fs.rs @@ -613,10 +613,10 @@ fn remove_dir_all_recursive(path: &Path) -> io::Result<()> { for child in readdir(path)? { let child = child?; let child_type = child.file_type()?; - if child_type.is_symlink_dir() { - rmdir(&child.path())?; - } else if child_type.is_dir() { + if child_type.is_dir() { remove_dir_all_recursive(&child.path())?; + } else if child_type.is_symlink_dir() { + rmdir(&child.path())?; } else { unlink(&child.path())?; } -- cgit 1.4.1-3-g733a5 From 9269e83b37e8e5fd9cef12255fafbc6db6220035 Mon Sep 17 00:00:00 2001 From: Peter Atashian Date: Sun, 11 Feb 2018 13:40:46 -0500 Subject: Add an unstable FileTypeExt extension trait for Windows --- src/libstd/sys/windows/ext/fs.rs | 18 ++++++++++++++++++ src/libstd/sys/windows/fs.rs | 3 +++ 2 files changed, 21 insertions(+) (limited to 'src/libstd/sys/windows') diff --git a/src/libstd/sys/windows/ext/fs.rs b/src/libstd/sys/windows/ext/fs.rs index 24c41046f26..38bf4cca851 100644 --- a/src/libstd/sys/windows/ext/fs.rs +++ b/src/libstd/sys/windows/ext/fs.rs @@ -445,6 +445,24 @@ impl MetadataExt for Metadata { fn file_size(&self) -> u64 { self.as_inner().size() } } +/// Add support for the Windows specific fact that a symbolic link knows whether it is a file +/// or directory. +#[unstable(feature = "windows_file_type_ext", issue = "0")] +pub trait FileTypeExt { + /// Returns whether this file type is a symbolic link that is also a directory. + #[unstable(feature = "windows_file_type_ext", issue = "0")] + fn is_symlink_dir(&self) -> bool; + /// Returns whether this file type is a symbolic link that is also a file. + #[unstable(feature = "windows_file_type_ext", issue = "0")] + fn is_symlink_file(&self) -> bool; +} + +#[unstable(feature = "windows_file_type_ext", issue = "0")] +impl FileTypeExt for fs::FileType { + fn is_symlink_dir(&self) -> bool { self.as_inner().is_symlink_dir() } + fn is_symlink_file(&self) -> bool { self.as_inner().is_symlink_file() } +} + /// Creates a new file symbolic link on the filesystem. /// /// The `dst` path will be a file symbolic link pointing to the `src` diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs index 7e3b16558d4..082d4689c7b 100644 --- a/src/libstd/sys/windows/fs.rs +++ b/src/libstd/sys/windows/fs.rs @@ -534,6 +534,9 @@ impl FileType { pub fn is_symlink_dir(&self) -> bool { self.is_symlink() && self.is_directory() } + pub fn is_symlink_file(&self) -> bool { + self.is_symlink() && !self.is_directory() + } fn is_directory(&self) -> bool { self.attributes & c::FILE_ATTRIBUTE_DIRECTORY != 0 } -- cgit 1.4.1-3-g733a5 From 74c5c6e6cb0425284f57fece6fbf248e827ea06d Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sat, 3 Mar 2018 18:29:30 -0800 Subject: Move process::ExitCode internals to sys Now begins the saga of fixing compilation errors on other platforms... --- src/libstd/process.rs | 29 ++++++++------------------- src/libstd/sys/cloudabi/shims/process.rs | 12 +++++++++++ src/libstd/sys/redox/process.rs | 13 ++++++++++++ src/libstd/sys/unix/process/mod.rs | 2 +- src/libstd/sys/unix/process/process_common.rs | 14 ++++++++++++- src/libstd/sys/wasm/process.rs | 12 +++++++++++ src/libstd/sys/windows/process.rs | 14 ++++++++++++- 7 files changed, 72 insertions(+), 24 deletions(-) (limited to 'src/libstd/sys/windows') diff --git a/src/libstd/process.rs b/src/libstd/process.rs index 5a06bf45aaa..d5ac2d19e83 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -1098,38 +1098,26 @@ impl fmt::Display for ExitStatus { /// /// [RFC #1937]: https://github.com/rust-lang/rfcs/pull/1937 #[derive(Clone, Copy, Debug)] -#[unstable(feature = "process_exitcode_placeholder", issue = "43301")] -pub struct ExitCode(pub i32); +#[unstable(feature = "process_exitcode_placeholder", issue = "48711")] +pub struct ExitCode(imp::ExitCode); -#[cfg(target_arch = "wasm32")] -mod rawexit { - pub const SUCCESS: i32 = 0; - pub const FAILURE: i32 = 1; -} -#[cfg(not(target_arch = "wasm32"))] -mod rawexit { - use libc; - pub const SUCCESS: i32 = libc::EXIT_SUCCESS; - pub const FAILURE: i32 = libc::EXIT_FAILURE; -} - -#[unstable(feature = "process_exitcode_placeholder", issue = "43301")] +#[unstable(feature = "process_exitcode_placeholder", issue = "48711")] impl ExitCode { /// The canonical ExitCode for successful termination on this platform. /// /// Note that a `()`-returning `main` implicitly results in a successful /// termination, so there's no need to return this from `main` unless /// you're also returning other possible codes. - #[unstable(feature = "process_exitcode_placeholder", issue = "43301")] - pub const SUCCESS: ExitCode = ExitCode(rawexit::SUCCESS); + #[unstable(feature = "process_exitcode_placeholder", issue = "48711")] + pub const SUCCESS: ExitCode = ExitCode(imp::ExitCode::SUCCESS); /// The canonical ExitCode for unsuccessful termination on this platform. /// /// If you're only returning this and `SUCCESS` from `main`, consider /// instead returning `Err(_)` and `Ok(())` respectively, which will /// return the same codes (but will also `eprintln!` the error). - #[unstable(feature = "process_exitcode_placeholder", issue = "43301")] - pub const FAILURE: ExitCode = ExitCode(rawexit::FAILURE); + #[unstable(feature = "process_exitcode_placeholder", issue = "48711")] + pub const FAILURE: ExitCode = ExitCode(imp::ExitCode::FAILURE); } impl Child { @@ -1494,8 +1482,7 @@ impl Termination for Result { #[unstable(feature = "termination_trait_lib", issue = "43301")] impl Termination for ExitCode { fn report(self) -> i32 { - let ExitCode(code) = self; - code + self.0.as_i32() } } diff --git a/src/libstd/sys/cloudabi/shims/process.rs b/src/libstd/sys/cloudabi/shims/process.rs index 52e8c82e2b2..fcd40c15c17 100644 --- a/src/libstd/sys/cloudabi/shims/process.rs +++ b/src/libstd/sys/cloudabi/shims/process.rs @@ -126,6 +126,18 @@ impl fmt::Display for ExitStatus { } } +#[derive(PartialEq, Eq, Clone, Copy, Debug)] +pub struct ExitCode(bool); + +impl ExitCode { + pub const SUCCESS: ExitCode = ExitCode(false); + pub const FAILURE: ExitCode = ExitCode(true); + + pub fn as_i32(&self) -> i32 { + self.0 as i32 + } +} + pub struct Process(Void); impl Process { diff --git a/src/libstd/sys/redox/process.rs b/src/libstd/sys/redox/process.rs index 3fd54973896..d0b94e14f54 100644 --- a/src/libstd/sys/redox/process.rs +++ b/src/libstd/sys/redox/process.rs @@ -13,6 +13,7 @@ use ffi::OsStr; use os::unix::ffi::OsStrExt; use fmt; use io::{self, Error, ErrorKind}; +use libc::{EXIT_SUCCESS, EXIT_FAILURE}; use path::{Path, PathBuf}; use sys::fd::FileDesc; use sys::fs::{File, OpenOptions}; @@ -480,6 +481,18 @@ impl fmt::Display for ExitStatus { } } +#[derive(PartialEq, Eq, Clone, Copy, Debug)] +pub struct ExitCode(u8); + +impl ExitCode { + pub const SUCCESS: ExitCode = ExitCode(EXIT_SUCCESS as _); + pub const FAILURE: ExitCode = ExitCode(EXIT_FAILURE as _); + + pub fn as_i32(&self) -> i32 { + self.0 as i32 + } +} + /// The unique id of the process (this should never be negative). pub struct Process { pid: usize, diff --git a/src/libstd/sys/unix/process/mod.rs b/src/libstd/sys/unix/process/mod.rs index 2a331069bc2..d8ac26c45b1 100644 --- a/src/libstd/sys/unix/process/mod.rs +++ b/src/libstd/sys/unix/process/mod.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub use self::process_common::{Command, ExitStatus, Stdio, StdioPipes}; +pub use self::process_common::{Command, ExitStatus, ExitCode, Stdio, StdioPipes}; pub use self::process_inner::Process; mod process_common; diff --git a/src/libstd/sys/unix/process/process_common.rs b/src/libstd/sys/unix/process/process_common.rs index 7e057401fab..d0486f06a14 100644 --- a/src/libstd/sys/unix/process/process_common.rs +++ b/src/libstd/sys/unix/process/process_common.rs @@ -13,7 +13,7 @@ use os::unix::prelude::*; use ffi::{OsString, OsStr, CString, CStr}; use fmt; use io; -use libc::{self, c_int, gid_t, uid_t, c_char}; +use libc::{self, c_int, gid_t, uid_t, c_char, EXIT_SUCCESS, EXIT_FAILURE}; use ptr; use sys::fd::FileDesc; use sys::fs::{File, OpenOptions}; @@ -393,6 +393,18 @@ impl fmt::Display for ExitStatus { } } +#[derive(PartialEq, Eq, Clone, Copy, Debug)] +pub struct ExitCode(u8); + +impl ExitCode { + pub const SUCCESS: ExitCode = ExitCode(EXIT_SUCCESS as _); + pub const FAILURE: ExitCode = ExitCode(EXIT_FAILURE as _); + + pub fn as_i32(&self) -> i32 { + self.0 as i32 + } +} + #[cfg(all(test, not(target_os = "emscripten")))] mod tests { use super::*; diff --git a/src/libstd/sys/wasm/process.rs b/src/libstd/sys/wasm/process.rs index f3f5de350f1..433e9cec7c8 100644 --- a/src/libstd/sys/wasm/process.rs +++ b/src/libstd/sys/wasm/process.rs @@ -129,6 +129,18 @@ impl fmt::Display for ExitStatus { } } +#[derive(PartialEq, Eq, Clone, Copy, Debug)] +pub struct ExitCode(bool); + +impl ExitCode { + pub const SUCCESS: ExitCode = ExitCode(false); + pub const FAILURE: ExitCode = ExitCode(true); + + pub fn as_i32(&self) -> i32 { + self.0 as i32 + } +} + pub struct Process(Void); impl Process { diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs index c93179869a6..f1ab9c47609 100644 --- a/src/libstd/sys/windows/process.rs +++ b/src/libstd/sys/windows/process.rs @@ -18,7 +18,7 @@ use ffi::{OsString, OsStr}; use fmt; use fs; use io::{self, Error, ErrorKind}; -use libc::c_void; +use libc::{c_void, EXIT_SUCCESS, EXIT_FAILURE}; use mem; use os::windows::ffi::OsStrExt; use path::Path; @@ -408,6 +408,18 @@ impl fmt::Display for ExitStatus { } } +#[derive(PartialEq, Eq, Clone, Copy, Debug)] +pub struct ExitCode(c::DWORD); + +impl ExitCode { + pub const SUCCESS: ExitCode = ExitCode(EXIT_SUCCESS as _); + pub const FAILURE: ExitCode = ExitCode(EXIT_FAILURE as _); + + pub fn as_i32(&self) -> i32 { + self.0 as i32 + } +} + fn zeroed_startupinfo() -> c::STARTUPINFO { c::STARTUPINFO { cb: 0, -- cgit 1.4.1-3-g733a5 From c09b9f937250db0f51b705a3110f8cffdad083bb Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Sat, 17 Mar 2018 12:15:24 +0100 Subject: Deprecate the AsciiExt trait in favor of inherent methods The trait and some of its methods are stable and will remain. Some of the newer methods are unstable and can be removed later. Fixes https://github.com/rust-lang/rust/issues/39658 --- src/libcore/tests/ascii.rs | 3 --- src/libstd/ascii.rs | 17 +++++++++++++++++ src/libstd/sys/windows/process.rs | 1 - src/libstd/sys_common/wtf8.rs | 17 +++++++---------- src/test/run-pass/issue-10683.rs | 2 -- 5 files changed, 24 insertions(+), 16 deletions(-) (limited to 'src/libstd/sys/windows') diff --git a/src/libcore/tests/ascii.rs b/src/libcore/tests/ascii.rs index 4d43067ad2c..950222dbcfa 100644 --- a/src/libcore/tests/ascii.rs +++ b/src/libcore/tests/ascii.rs @@ -9,7 +9,6 @@ // except according to those terms. use core::char::from_u32; -use std::ascii::AsciiExt; #[test] fn test_is_ascii() { @@ -143,8 +142,6 @@ macro_rules! assert_all { stringify!($what), b); } } - assert!($str.$what()); - assert!($str.as_bytes().$what()); )+ }}; ($what:ident, $($str:tt),+,) => (assert_all!($what,$($str),+)) diff --git a/src/libstd/ascii.rs b/src/libstd/ascii.rs index 0837ff91c14..6472edb0aa7 100644 --- a/src/libstd/ascii.rs +++ b/src/libstd/ascii.rs @@ -52,6 +52,7 @@ pub use core::ascii::{EscapeDefault, escape_default}; /// /// [combining character]: https://en.wikipedia.org/wiki/Combining_character #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")] pub trait AsciiExt { /// Container type for copied ASCII characters. #[stable(feature = "rust1", since = "1.0.0")] @@ -84,6 +85,7 @@ pub trait AsciiExt { /// [`make_ascii_uppercase`]: #tymethod.make_ascii_uppercase /// [`str::to_uppercase`]: ../primitive.str.html#method.to_uppercase #[stable(feature = "rust1", since = "1.0.0")] + #[allow(deprecated)] fn to_ascii_uppercase(&self) -> Self::Owned; /// Makes a copy of the value in its ASCII lower case equivalent. @@ -104,6 +106,7 @@ pub trait AsciiExt { /// [`make_ascii_lowercase`]: #tymethod.make_ascii_lowercase /// [`str::to_lowercase`]: ../primitive.str.html#method.to_lowercase #[stable(feature = "rust1", since = "1.0.0")] + #[allow(deprecated)] fn to_ascii_lowercase(&self) -> Self::Owned; /// Checks that two values are an ASCII case-insensitive match. @@ -162,6 +165,7 @@ pub trait AsciiExt { /// 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: @@ -174,6 +178,7 @@ pub trait AsciiExt { /// 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: @@ -186,6 +191,7 @@ pub trait AsciiExt { /// 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: @@ -199,6 +205,7 @@ pub trait AsciiExt { /// 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: @@ -211,6 +218,7 @@ pub trait AsciiExt { /// 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: @@ -224,6 +232,7 @@ pub trait AsciiExt { /// 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: @@ -241,6 +250,7 @@ pub trait AsciiExt { /// 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: @@ -253,6 +263,7 @@ pub trait AsciiExt { /// 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: @@ -282,6 +293,7 @@ pub trait AsciiExt { /// 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: @@ -294,6 +306,7 @@ pub trait AsciiExt { /// 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!(); } } @@ -354,6 +367,7 @@ macro_rules! delegating_ascii_ctype_methods { } #[stable(feature = "rust1", since = "1.0.0")] +#[allow(deprecated)] impl AsciiExt for u8 { type Owned = u8; @@ -362,6 +376,7 @@ impl AsciiExt for u8 { } #[stable(feature = "rust1", since = "1.0.0")] +#[allow(deprecated)] impl AsciiExt for char { type Owned = char; @@ -370,6 +385,7 @@ impl AsciiExt for char { } #[stable(feature = "rust1", since = "1.0.0")] +#[allow(deprecated)] impl AsciiExt for [u8] { type Owned = Vec; @@ -427,6 +443,7 @@ impl AsciiExt for [u8] { } #[stable(feature = "rust1", since = "1.0.0")] +#[allow(deprecated)] impl AsciiExt for str { type Owned = String; diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs index f1ab9c47609..afa8e3e1369 100644 --- a/src/libstd/sys/windows/process.rs +++ b/src/libstd/sys/windows/process.rs @@ -10,7 +10,6 @@ #![unstable(feature = "process_internals", issue = "0")] -use ascii::AsciiExt; use collections::BTreeMap; use env::split_paths; use env; diff --git a/src/libstd/sys_common/wtf8.rs b/src/libstd/sys_common/wtf8.rs index 9fff8b91f96..78b2bb5fe6e 100644 --- a/src/libstd/sys_common/wtf8.rs +++ b/src/libstd/sys_common/wtf8.rs @@ -27,7 +27,6 @@ use core::str::next_code_point; -use ascii::*; use borrow::Cow; use char; use fmt; @@ -871,24 +870,22 @@ impl Hash for Wtf8 { } } -impl AsciiExt for Wtf8 { - type Owned = Wtf8Buf; - - fn is_ascii(&self) -> bool { +impl Wtf8 { + pub fn is_ascii(&self) -> bool { self.bytes.is_ascii() } - fn to_ascii_uppercase(&self) -> Wtf8Buf { + pub fn to_ascii_uppercase(&self) -> Wtf8Buf { Wtf8Buf { bytes: self.bytes.to_ascii_uppercase() } } - fn to_ascii_lowercase(&self) -> Wtf8Buf { + pub fn to_ascii_lowercase(&self) -> Wtf8Buf { Wtf8Buf { bytes: self.bytes.to_ascii_lowercase() } } - fn eq_ignore_ascii_case(&self, other: &Wtf8) -> bool { + pub fn eq_ignore_ascii_case(&self, other: &Wtf8) -> bool { self.bytes.eq_ignore_ascii_case(&other.bytes) } - fn make_ascii_uppercase(&mut self) { self.bytes.make_ascii_uppercase() } - fn make_ascii_lowercase(&mut self) { self.bytes.make_ascii_lowercase() } + pub fn make_ascii_uppercase(&mut self) { self.bytes.make_ascii_uppercase() } + pub fn make_ascii_lowercase(&mut self) { self.bytes.make_ascii_lowercase() } } #[cfg(test)] diff --git a/src/test/run-pass/issue-10683.rs b/src/test/run-pass/issue-10683.rs index eb2177202a2..d3ba477fa57 100644 --- a/src/test/run-pass/issue-10683.rs +++ b/src/test/run-pass/issue-10683.rs @@ -10,8 +10,6 @@ // pretty-expanded FIXME #23616 -use std::ascii::AsciiExt; - static NAME: &'static str = "hello world"; fn main() { -- cgit 1.4.1-3-g733a5 From 91279904345e2ecd3f52b17339183bbe3bd11203 Mon Sep 17 00:00:00 2001 From: Tatsuyuki Ishi Date: Sat, 24 Mar 2018 13:47:36 +0900 Subject: Fix build on non-Unix platforms --- src/libstd/sys/cloudabi/thread.rs | 1 + src/libstd/sys/redox/thread.rs | 1 + src/libstd/sys/unix/thread.rs | 1 + src/libstd/sys/wasm/thread.rs | 1 + src/libstd/sys/windows/thread.rs | 1 + 5 files changed, 5 insertions(+) (limited to 'src/libstd/sys/windows') diff --git a/src/libstd/sys/cloudabi/thread.rs b/src/libstd/sys/cloudabi/thread.rs index 78a3b82546e..a22d9053b69 100644 --- a/src/libstd/sys/cloudabi/thread.rs +++ b/src/libstd/sys/cloudabi/thread.rs @@ -118,6 +118,7 @@ pub mod guard { pub unsafe fn init() -> Option { None } + pub unsafe fn deinit() {} } fn min_stack_size(_: *const libc::pthread_attr_t) -> usize { diff --git a/src/libstd/sys/redox/thread.rs b/src/libstd/sys/redox/thread.rs index c4719a94c7e..f20350269b7 100644 --- a/src/libstd/sys/redox/thread.rs +++ b/src/libstd/sys/redox/thread.rs @@ -91,4 +91,5 @@ pub mod guard { pub type Guard = !; pub unsafe fn current() -> Option { None } pub unsafe fn init() -> Option { None } + pub unsafe fn deinit() {} } diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs index 4364089a181..b9ec0d4a403 100644 --- a/src/libstd/sys/unix/thread.rs +++ b/src/libstd/sys/unix/thread.rs @@ -209,6 +209,7 @@ pub mod guard { pub type Guard = Range; pub unsafe fn current() -> Option { None } pub unsafe fn init() -> Option { None } + pub unsafe fn deinit() {} } diff --git a/src/libstd/sys/wasm/thread.rs b/src/libstd/sys/wasm/thread.rs index 6a066509b49..7345843b975 100644 --- a/src/libstd/sys/wasm/thread.rs +++ b/src/libstd/sys/wasm/thread.rs @@ -46,4 +46,5 @@ pub mod guard { pub type Guard = !; pub unsafe fn current() -> Option { None } pub unsafe fn init() -> Option { None } + pub unsafe fn deinit() {} } diff --git a/src/libstd/sys/windows/thread.rs b/src/libstd/sys/windows/thread.rs index 43abfbb1f64..4b3d1b586b5 100644 --- a/src/libstd/sys/windows/thread.rs +++ b/src/libstd/sys/windows/thread.rs @@ -96,4 +96,5 @@ pub mod guard { pub type Guard = !; pub unsafe fn current() -> Option { None } pub unsafe fn init() -> Option { None } + pub unsafe fn deinit() {} } -- cgit 1.4.1-3-g733a5 From 04f6692aaf78809c041ba6145bde2dcbeec9725e Mon Sep 17 00:00:00 2001 From: Diggory Blake Date: Mon, 26 Mar 2018 23:24:31 +0100 Subject: Implement `shrink_to` method on collections --- src/liballoc/binary_heap.rs | 25 ++++++++++++++++++++++++ src/liballoc/string.rs | 28 ++++++++++++++++++++++++++ src/liballoc/vec.rs | 27 ++++++++++++++++++++++++- src/liballoc/vec_deque.rs | 35 ++++++++++++++++++++++++++++++++- src/libstd/collections/hash/map.rs | 40 ++++++++++++++++++++++++++++++++++++++ src/libstd/collections/hash/set.rs | 28 ++++++++++++++++++++++++++ src/libstd/ffi/os_str.rs | 30 ++++++++++++++++++++++++++++ src/libstd/lib.rs | 1 + src/libstd/sys/redox/os_str.rs | 5 +++++ src/libstd/sys/unix/os_str.rs | 5 +++++ src/libstd/sys/wasm/os_str.rs | 5 +++++ src/libstd/sys/windows/os_str.rs | 5 +++++ src/libstd/sys_common/wtf8.rs | 5 +++++ 13 files changed, 237 insertions(+), 2 deletions(-) (limited to 'src/libstd/sys/windows') diff --git a/src/liballoc/binary_heap.rs b/src/liballoc/binary_heap.rs index 8aaac5d6e08..f6a666b599b 100644 --- a/src/liballoc/binary_heap.rs +++ b/src/liballoc/binary_heap.rs @@ -509,6 +509,31 @@ impl BinaryHeap { self.data.shrink_to_fit(); } + /// Discards capacity with a lower bound. + /// + /// The capacity will remain at least as large as both the length + /// and the supplied value. + /// + /// Panics if the current capacity is smaller than the supplied + /// minimum capacity. + /// + /// # Examples + /// + /// ``` + /// #![feature(shrink_to)] + /// use std::collections::BinaryHeap; + /// let mut heap: BinaryHeap = BinaryHeap::with_capacity(100); + /// + /// assert!(heap.capacity() >= 100); + /// heap.shrink_to(10); + /// assert!(heap.capacity() >= 10); + /// ``` + #[inline] + #[unstable(feature = "shrink_to", reason = "new API", issue="0")] + pub fn shrink_to(&mut self, min_capacity: usize) { + self.data.shrink_to(min_capacity) + } + /// Removes the greatest item from the binary heap and returns it, or `None` if it /// is empty. /// diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index e253122ffd6..2bb60a50679 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -1015,6 +1015,34 @@ impl String { self.vec.shrink_to_fit() } + /// Shrinks the capacity of this `String` with a lower bound. + /// + /// The capacity will remain at least as large as both the length + /// and the supplied value. + /// + /// Panics if the current capacity is smaller than the supplied + /// minimum capacity. + /// + /// # Examples + /// + /// ``` + /// #![feature(shrink_to)] + /// let mut s = String::from("foo"); + /// + /// s.reserve(100); + /// assert!(s.capacity() >= 100); + /// + /// s.shrink_to(10); + /// assert!(s.capacity() >= 10); + /// s.shrink_to(0); + /// assert!(s.capacity() >= 3); + /// ``` + #[inline] + #[unstable(feature = "shrink_to", reason = "new API", issue="0")] + pub fn shrink_to(&mut self, min_capacity: usize) { + self.vec.shrink_to(min_capacity) + } + /// Appends the given [`char`] to the end of this `String`. /// /// [`char`]: ../../std/primitive.char.html diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 953f95876be..c9c6cf1cb66 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -66,7 +66,7 @@ #![stable(feature = "rust1", since = "1.0.0")] -use core::cmp::Ordering; +use core::cmp::{self, Ordering}; use core::fmt; use core::hash::{self, Hash}; use core::intrinsics::{arith_offset, assume}; @@ -586,6 +586,31 @@ impl Vec { self.buf.shrink_to_fit(self.len); } + /// Shrinks the capacity of the vector with a lower bound. + /// + /// The capacity will remain at least as large as both the length + /// and the supplied value. + /// + /// Panics if the current capacity is smaller than the supplied + /// minimum capacity. + /// + /// # Examples + /// + /// ``` + /// #![feature(shrink_to)] + /// let mut vec = Vec::with_capacity(10); + /// vec.extend([1, 2, 3].iter().cloned()); + /// assert_eq!(vec.capacity(), 10); + /// vec.shrink_to(4); + /// assert!(vec.capacity() >= 4); + /// vec.shrink_to(0); + /// assert!(vec.capacity() >= 3); + /// ``` + #[unstable(feature = "shrink_to", reason = "new API", issue="0")] + pub fn shrink_to(&mut self, min_capacity: usize) { + self.buf.shrink_to_fit(cmp::max(self.len, min_capacity)); + } + /// Converts the vector into [`Box<[T]>`][owned slice]. /// /// Note that this will drop any excess capacity. diff --git a/src/liballoc/vec_deque.rs b/src/liballoc/vec_deque.rs index 0658777f0a0..be6e8d0f22f 100644 --- a/src/liballoc/vec_deque.rs +++ b/src/liballoc/vec_deque.rs @@ -676,9 +676,42 @@ impl VecDeque { /// ``` #[stable(feature = "deque_extras_15", since = "1.5.0")] pub fn shrink_to_fit(&mut self) { + self.shrink_to(0); + } + + /// Shrinks the capacity of the `VecDeque` with a lower bound. + /// + /// The capacity will remain at least as large as both the length + /// and the supplied value. + /// + /// Panics if the current capacity is smaller than the supplied + /// minimum capacity. + /// + /// # Examples + /// + /// ``` + /// #![feature(shrink_to)] + /// use std::collections::VecDeque; + /// + /// let mut buf = VecDeque::with_capacity(15); + /// buf.extend(0..4); + /// assert_eq!(buf.capacity(), 15); + /// buf.shrink_to(6); + /// assert!(buf.capacity() >= 6); + /// buf.shrink_to(0); + /// assert!(buf.capacity() >= 4); + /// ``` + #[unstable(feature = "shrink_to", reason = "new API", issue="0")] + pub fn shrink_to(&mut self, min_capacity: usize) { + assert!(self.capacity() >= min_capacity, "Tried to shrink to a larger capacity"); + // +1 since the ringbuffer always leaves one space empty // len + 1 can't overflow for an existing, well-formed ringbuffer. - let target_cap = cmp::max(self.len() + 1, MINIMUM_CAPACITY + 1).next_power_of_two(); + let target_cap = cmp::max( + cmp::max(min_capacity, self.len()) + 1, + MINIMUM_CAPACITY + 1 + ).next_power_of_two(); + if target_cap < self.cap() { // There are three cases of interest: // All elements are out of desired bounds diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index b18b38ec302..169d365c0ac 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -910,6 +910,46 @@ impl HashMap } } + /// Shrinks the capacity of the map with a lower limit. It will drop + /// down no lower than the supplied limit while maintaining the internal rules + /// and possibly leaving some space in accordance with the resize policy. + /// + /// Panics if the current capacity is smaller than the supplied + /// minimum capacity. + /// + /// # Examples + /// + /// ``` + /// #![feature(shrink_to)] + /// use std::collections::HashMap; + /// + /// let mut map: HashMap = HashMap::with_capacity(100); + /// map.insert(1, 2); + /// map.insert(3, 4); + /// assert!(map.capacity() >= 100); + /// map.shrink_to(10); + /// assert!(map.capacity() >= 10); + /// map.shrink_to(0); + /// assert!(map.capacity() >= 2); + /// ``` + #[unstable(feature = "shrink_to", reason = "new API", issue="0")] + pub fn shrink_to(&mut self, min_capacity: usize) { + assert!(self.capacity() >= min_capacity, "Tried to shrink to a larger capacity"); + + let new_raw_cap = self.resize_policy.raw_capacity(max(self.len(), min_capacity)); + if self.raw_capacity() != new_raw_cap { + let old_table = replace(&mut self.table, RawTable::new(new_raw_cap)); + let old_size = old_table.size(); + + // Shrink the table. Naive algorithm for resizing: + for (h, k, v) in old_table.into_iter() { + self.insert_hashed_nocheck(h, k, v); + } + + debug_assert_eq!(self.table.size(), old_size); + } + } + /// Insert a pre-hashed key-value pair, without first checking /// that there's enough room in the buckets. Returns a reference to the /// newly insert value. diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index 9e63ba2717a..855563a5cb8 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -292,6 +292,34 @@ impl HashSet self.map.shrink_to_fit() } + /// Shrinks the capacity of the set with a lower limit. It will drop + /// down no lower than the supplied limit while maintaining the internal rules + /// and possibly leaving some space in accordance with the resize policy. + /// + /// Panics if the current capacity is smaller than the supplied + /// minimum capacity. + /// + /// # Examples + /// + /// ``` + /// #![feature(shrink_to)] + /// use std::collections::HashSet; + /// + /// let mut set = HashSet::with_capacity(100); + /// set.insert(1); + /// set.insert(2); + /// assert!(set.capacity() >= 100); + /// set.shrink_to(10); + /// assert!(set.capacity() >= 10); + /// set.shrink_to(0); + /// assert!(set.capacity() >= 2); + /// ``` + #[inline] + #[unstable(feature = "shrink_to", reason = "new API", issue="0")] + pub fn shrink_to(&mut self, min_capacity: usize) { + self.map.shrink_to(min_capacity) + } + /// An iterator visiting all elements in arbitrary order. /// The iterator element type is `&'a T`. /// diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs index 3959e8533be..7520121a8c2 100644 --- a/src/libstd/ffi/os_str.rs +++ b/src/libstd/ffi/os_str.rs @@ -295,6 +295,36 @@ impl OsString { self.inner.shrink_to_fit() } + /// Shrinks the capacity of the `OsString` with a lower bound. + /// + /// The capacity will remain at least as large as both the length + /// and the supplied value. + /// + /// Panics if the current capacity is smaller than the supplied + /// minimum capacity. + /// + /// # Examples + /// + /// ``` + /// #![feature(shrink_to)] + /// use std::ffi::OsString; + /// + /// let mut s = OsString::from("foo"); + /// + /// s.reserve(100); + /// assert!(s.capacity() >= 100); + /// + /// s.shrink_to(10); + /// assert!(s.capacity() >= 10); + /// s.shrink_to(0); + /// assert!(s.capacity() >= 3); + /// ``` + #[inline] + #[unstable(feature = "shrink_to", reason = "new API", issue="0")] + pub fn shrink_to(&mut self, min_capacity: usize) { + self.inner.shrink_to(min_capacity) + } + /// Converts this `OsString` into a boxed [`OsStr`]. /// /// [`OsStr`]: struct.OsStr.html diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 0b06c5d4d65..edecf309d16 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -299,6 +299,7 @@ #![feature(raw)] #![feature(rustc_attrs)] #![feature(stdsimd)] +#![feature(shrink_to)] #![feature(slice_bytes)] #![feature(slice_concat_ext)] #![feature(slice_internals)] diff --git a/src/libstd/sys/redox/os_str.rs b/src/libstd/sys/redox/os_str.rs index 655bfdb9167..da27787babb 100644 --- a/src/libstd/sys/redox/os_str.rs +++ b/src/libstd/sys/redox/os_str.rs @@ -104,6 +104,11 @@ impl Buf { self.inner.shrink_to_fit() } + #[inline] + pub fn shrink_to(&mut self, min_capacity: usize) { + self.inner.shrink_to(min_capacity) + } + pub fn as_slice(&self) -> &Slice { unsafe { mem::transmute(&*self.inner) } } diff --git a/src/libstd/sys/unix/os_str.rs b/src/libstd/sys/unix/os_str.rs index e0349387998..e43bc6da5f1 100644 --- a/src/libstd/sys/unix/os_str.rs +++ b/src/libstd/sys/unix/os_str.rs @@ -104,6 +104,11 @@ impl Buf { self.inner.shrink_to_fit() } + #[inline] + pub fn shrink_to(&mut self, min_capacity: usize) { + self.inner.shrink_to(min_capacity) + } + pub fn as_slice(&self) -> &Slice { unsafe { mem::transmute(&*self.inner) } } diff --git a/src/libstd/sys/wasm/os_str.rs b/src/libstd/sys/wasm/os_str.rs index 543c22ebe18..84f560af69b 100644 --- a/src/libstd/sys/wasm/os_str.rs +++ b/src/libstd/sys/wasm/os_str.rs @@ -104,6 +104,11 @@ impl Buf { self.inner.shrink_to_fit() } + #[inline] + pub fn shrink_to(&mut self, min_capacity: usize) { + self.inner.shrink_to(min_capacity) + } + pub fn as_slice(&self) -> &Slice { unsafe { mem::transmute(&*self.inner) } } diff --git a/src/libstd/sys/windows/os_str.rs b/src/libstd/sys/windows/os_str.rs index 414c9c5418e..bcc66b9954b 100644 --- a/src/libstd/sys/windows/os_str.rs +++ b/src/libstd/sys/windows/os_str.rs @@ -113,6 +113,11 @@ impl Buf { self.inner.shrink_to_fit() } + #[inline] + pub fn shrink_to(&mut self, min_capacity: usize) { + self.inner.shrink_to(min_capacity) + } + #[inline] pub fn into_box(self) -> Box { unsafe { mem::transmute(self.inner.into_box()) } diff --git a/src/libstd/sys_common/wtf8.rs b/src/libstd/sys_common/wtf8.rs index 78b2bb5fe6e..dda4e1bab3b 100644 --- a/src/libstd/sys_common/wtf8.rs +++ b/src/libstd/sys_common/wtf8.rs @@ -253,6 +253,11 @@ impl Wtf8Buf { self.bytes.shrink_to_fit() } + #[inline] + pub fn shrink_to(&mut self, min_capacity: usize) { + self.bytes.shrink_to(min_capacity) + } + /// Returns the number of bytes that this string buffer can hold without reallocating. #[inline] pub fn capacity(&self) -> usize { -- cgit 1.4.1-3-g733a5 From e9dcec070d6097e5a22b6658844dccd9d1f578cf Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Sat, 24 Mar 2018 22:56:07 -0400 Subject: Remove hidden `foo` functions from doc examples; use `Termination` trait. Fixes https://github.com/rust-lang/rust/issues/49233. --- src/libstd/env.rs | 14 +- src/libstd/fs.rs | 528 +++++++++++++++++----------------- src/libstd/io/buffered.rs | 219 +++++++------- src/libstd/io/mod.rs | 605 +++++++++++++++++++-------------------- src/libstd/io/stdio.rs | 106 +++---- src/libstd/io/util.rs | 15 +- src/libstd/net/mod.rs | 10 +- src/libstd/net/tcp.rs | 16 +- src/libstd/net/udp.rs | 28 +- src/libstd/os/linux/fs.rs | 238 +++++++-------- src/libstd/sys/redox/ext/fs.rs | 38 +-- src/libstd/sys/unix/ext/fs.rs | 342 +++++++++++----------- src/libstd/sys/windows/ext/fs.rs | 98 +++---- 13 files changed, 1130 insertions(+), 1127 deletions(-) (limited to 'src/libstd/sys/windows') diff --git a/src/libstd/env.rs b/src/libstd/env.rs index c4946b6b282..320a9f935d4 100644 --- a/src/libstd/env.rs +++ b/src/libstd/env.rs @@ -552,17 +552,17 @@ pub fn home_dir() -> Option { /// /// [msdn]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa364992(v=vs.85).aspx /// -/// ``` +/// ```no_run /// use std::env; /// use std::fs::File; /// -/// # fn foo() -> std::io::Result<()> { -/// let mut dir = env::temp_dir(); -/// dir.push("foo.txt"); +/// fn main() -> std::io::Result<()> { +/// let mut dir = env::temp_dir(); +/// dir.push("foo.txt"); /// -/// let f = File::create(dir)?; -/// # Ok(()) -/// # } +/// let f = File::create(dir)?; +/// Ok(()) +/// } /// ``` #[stable(feature = "env", since = "1.0.0")] pub fn temp_dir() -> PathBuf { diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index db52ed67d3a..46d164e31ba 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -41,11 +41,11 @@ use time::SystemTime; /// use std::fs::File; /// use std::io::prelude::*; /// -/// # fn foo() -> std::io::Result<()> { -/// let mut file = File::create("foo.txt")?; -/// file.write_all(b"Hello, world!")?; -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// let mut file = File::create("foo.txt")?; +/// file.write_all(b"Hello, world!")?; +/// Ok(()) +/// } /// ``` /// /// Read the contents of a file into a [`String`]: @@ -54,13 +54,13 @@ use time::SystemTime; /// use std::fs::File; /// use std::io::prelude::*; /// -/// # fn foo() -> std::io::Result<()> { -/// let mut file = File::open("foo.txt")?; -/// let mut contents = String::new(); -/// file.read_to_string(&mut contents)?; -/// assert_eq!(contents, "Hello, world!"); -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// let mut file = File::open("foo.txt")?; +/// let mut contents = String::new(); +/// file.read_to_string(&mut contents)?; +/// assert_eq!(contents, "Hello, world!"); +/// Ok(()) +/// } /// ``` /// /// It can be more efficient to read the contents of a file with a buffered @@ -71,14 +71,14 @@ use time::SystemTime; /// use std::io::BufReader; /// use std::io::prelude::*; /// -/// # fn foo() -> std::io::Result<()> { -/// let file = File::open("foo.txt")?; -/// let mut buf_reader = BufReader::new(file); -/// let mut contents = String::new(); -/// buf_reader.read_to_string(&mut contents)?; -/// assert_eq!(contents, "Hello, world!"); -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// let file = File::open("foo.txt")?; +/// let mut buf_reader = BufReader::new(file); +/// let mut contents = String::new(); +/// buf_reader.read_to_string(&mut contents)?; +/// assert_eq!(contents, "Hello, world!"); +/// Ok(()) +/// } /// ``` /// /// Note that, although read and write methods require a `&mut File`, because @@ -256,10 +256,10 @@ fn initial_buffer_size(file: &File) -> usize { /// use std::fs; /// use std::net::SocketAddr; /// -/// # fn foo() -> Result<(), Box> { -/// let foo: SocketAddr = String::from_utf8_lossy(&fs::read("address.txt")?).parse()?; -/// # Ok(()) -/// # } +/// fn main() -> Result<(), Box> { +/// let foo: SocketAddr = String::from_utf8_lossy(&fs::read("address.txt")?).parse()?; +/// Ok(()) +/// } /// ``` #[unstable(feature = "fs_read_write", issue = "46588")] pub fn read>(path: P) -> io::Result> { @@ -298,10 +298,10 @@ pub fn read>(path: P) -> io::Result> { /// use std::fs; /// use std::net::SocketAddr; /// -/// # fn foo() -> Result<(), Box> { -/// let foo: SocketAddr = fs::read_string("address.txt")?.parse()?; -/// # Ok(()) -/// # } +/// fn main() -> Result<(), Box> { +/// let foo: SocketAddr = fs::read_string("address.txt")?.parse()?; +/// Ok(()) +/// } /// ``` #[unstable(feature = "fs_read_write", issue = "46588")] pub fn read_string>(path: P) -> io::Result { @@ -329,10 +329,10 @@ pub fn read_string>(path: P) -> io::Result { /// /// use std::fs; /// -/// # fn foo() -> std::io::Result<()> { -/// fs::write("foo.txt", b"Lorem ipsum")?; -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// fs::write("foo.txt", b"Lorem ipsum")?; +/// Ok(()) +/// } /// ``` #[unstable(feature = "fs_read_write", issue = "46588")] pub fn write, C: AsRef<[u8]>>(path: P, contents: C) -> io::Result<()> { @@ -356,7 +356,7 @@ impl File { /// ```no_run /// use std::fs::File; /// - /// # fn foo() -> std::io::Result<()> { + /// fn main() -> std::io::Result<()> { /// let mut f = File::open("foo.txt")?; /// # Ok(()) /// # } @@ -380,10 +380,10 @@ impl File { /// ```no_run /// use std::fs::File; /// - /// # fn foo() -> std::io::Result<()> { - /// let mut f = File::create("foo.txt")?; - /// # Ok(()) - /// # } + /// fn main() -> std::io::Result<()> { + /// let mut f = File::create("foo.txt")?; + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn create>(path: P) -> io::Result { @@ -401,13 +401,13 @@ impl File { /// use std::fs::File; /// use std::io::prelude::*; /// - /// # fn foo() -> std::io::Result<()> { - /// let mut f = File::create("foo.txt")?; - /// f.write_all(b"Hello, world!")?; + /// fn main() -> std::io::Result<()> { + /// let mut f = File::create("foo.txt")?; + /// f.write_all(b"Hello, world!")?; /// - /// f.sync_all()?; - /// # Ok(()) - /// # } + /// f.sync_all()?; + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn sync_all(&self) -> io::Result<()> { @@ -432,13 +432,13 @@ impl File { /// use std::fs::File; /// use std::io::prelude::*; /// - /// # fn foo() -> std::io::Result<()> { - /// let mut f = File::create("foo.txt")?; - /// f.write_all(b"Hello, world!")?; + /// fn main() -> std::io::Result<()> { + /// let mut f = File::create("foo.txt")?; + /// f.write_all(b"Hello, world!")?; /// - /// f.sync_data()?; - /// # Ok(()) - /// # } + /// f.sync_data()?; + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn sync_data(&self) -> io::Result<()> { @@ -466,11 +466,11 @@ impl File { /// ```no_run /// use std::fs::File; /// - /// # fn foo() -> std::io::Result<()> { - /// let mut f = File::create("foo.txt")?; - /// f.set_len(10)?; - /// # Ok(()) - /// # } + /// fn main() -> std::io::Result<()> { + /// let mut f = File::create("foo.txt")?; + /// f.set_len(10)?; + /// Ok(()) + /// } /// ``` /// /// Note that this method alters the content of the underlying file, even @@ -487,11 +487,11 @@ impl File { /// ```no_run /// use std::fs::File; /// - /// # fn foo() -> std::io::Result<()> { - /// let mut f = File::open("foo.txt")?; - /// let metadata = f.metadata()?; - /// # Ok(()) - /// # } + /// fn main() -> std::io::Result<()> { + /// let mut f = File::open("foo.txt")?; + /// let metadata = f.metadata()?; + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn metadata(&self) -> io::Result { @@ -509,11 +509,11 @@ impl File { /// ```no_run /// use std::fs::File; /// - /// # fn foo() -> std::io::Result<()> { - /// let mut file = File::open("foo.txt")?; - /// let file_copy = file.try_clone()?; - /// # Ok(()) - /// # } + /// fn main() -> std::io::Result<()> { + /// let mut file = File::open("foo.txt")?; + /// let file_copy = file.try_clone()?; + /// Ok(()) + /// } /// ``` /// /// Assuming there’s a file named `foo.txt` with contents `abcdef\n`, create @@ -525,17 +525,17 @@ impl File { /// use std::io::SeekFrom; /// use std::io::prelude::*; /// - /// # fn foo() -> std::io::Result<()> { - /// let mut file = File::open("foo.txt")?; - /// let mut file_copy = file.try_clone()?; + /// fn main() -> std::io::Result<()> { + /// let mut file = File::open("foo.txt")?; + /// let mut file_copy = file.try_clone()?; /// - /// file.seek(SeekFrom::Start(3))?; + /// file.seek(SeekFrom::Start(3))?; /// - /// let mut contents = vec![]; - /// file_copy.read_to_end(&mut contents)?; - /// assert_eq!(contents, b"def\n"); - /// # Ok(()) - /// # } + /// let mut contents = vec![]; + /// file_copy.read_to_end(&mut contents)?; + /// assert_eq!(contents, b"def\n"); + /// Ok(()) + /// } /// ``` #[stable(feature = "file_try_clone", since = "1.9.0")] pub fn try_clone(&self) -> io::Result { @@ -562,16 +562,16 @@ impl File { /// /// # Examples /// - /// ``` - /// # fn foo() -> std::io::Result<()> { - /// use std::fs::File; - /// - /// let file = File::open("foo.txt")?; - /// let mut perms = file.metadata()?.permissions(); - /// perms.set_readonly(true); - /// file.set_permissions(perms)?; - /// # Ok(()) - /// # } + /// ```no_run + /// fn main() -> std::io::Result<()> { + /// use std::fs::File; + /// + /// let file = File::open("foo.txt")?; + /// let mut perms = file.metadata()?.permissions(); + /// perms.set_readonly(true); + /// file.set_permissions(perms)?; + /// Ok(()) + /// } /// ``` /// /// Note that this method alters the permissions of the underlying file, @@ -891,15 +891,15 @@ impl Metadata { /// /// # Examples /// - /// ``` - /// # fn foo() -> std::io::Result<()> { - /// use std::fs; + /// ```no_run + /// fn main() -> std::io::Result<()> { + /// use std::fs; /// - /// let metadata = fs::metadata("foo.txt")?; + /// let metadata = fs::metadata("foo.txt")?; /// - /// println!("{:?}", metadata.file_type()); - /// # Ok(()) - /// # } + /// println!("{:?}", metadata.file_type()); + /// Ok(()) + /// } /// ``` #[stable(feature = "file_type", since = "1.1.0")] pub fn file_type(&self) -> FileType { @@ -910,15 +910,15 @@ impl Metadata { /// /// # Examples /// - /// ``` - /// # fn foo() -> std::io::Result<()> { - /// use std::fs; + /// ```no_run + /// fn main() -> std::io::Result<()> { + /// use std::fs; /// - /// let metadata = fs::metadata("foo.txt")?; + /// let metadata = fs::metadata("foo.txt")?; /// - /// assert!(!metadata.is_dir()); - /// # Ok(()) - /// # } + /// assert!(!metadata.is_dir()); + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn is_dir(&self) -> bool { self.file_type().is_dir() } @@ -927,15 +927,15 @@ impl Metadata { /// /// # Examples /// - /// ``` - /// # fn foo() -> std::io::Result<()> { + /// ```no_run /// use std::fs; /// - /// let metadata = fs::metadata("foo.txt")?; + /// fn main() -> std::io::Result<()> { + /// let metadata = fs::metadata("foo.txt")?; /// - /// assert!(metadata.is_file()); - /// # Ok(()) - /// # } + /// assert!(metadata.is_file()); + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn is_file(&self) -> bool { self.file_type().is_file() } @@ -944,15 +944,15 @@ impl Metadata { /// /// # Examples /// - /// ``` - /// # fn foo() -> std::io::Result<()> { + /// ```no_run /// use std::fs; /// - /// let metadata = fs::metadata("foo.txt")?; + /// fn main() -> std::io::Result<()> { + /// let metadata = fs::metadata("foo.txt")?; /// - /// assert_eq!(0, metadata.len()); - /// # Ok(()) - /// # } + /// assert_eq!(0, metadata.len()); + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn len(&self) -> u64 { self.0.size() } @@ -961,15 +961,15 @@ impl Metadata { /// /// # Examples /// - /// ``` - /// # fn foo() -> std::io::Result<()> { + /// ```no_run /// use std::fs; /// - /// let metadata = fs::metadata("foo.txt")?; + /// fn main() -> std::io::Result<()> { + /// let metadata = fs::metadata("foo.txt")?; /// - /// assert!(!metadata.permissions().readonly()); - /// # Ok(()) - /// # } + /// assert!(!metadata.permissions().readonly()); + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn permissions(&self) -> Permissions { @@ -988,19 +988,19 @@ impl Metadata { /// /// # Examples /// - /// ``` - /// # fn foo() -> std::io::Result<()> { + /// ```no_run /// use std::fs; /// - /// let metadata = fs::metadata("foo.txt")?; + /// fn main() -> std::io::Result<()> { + /// let metadata = fs::metadata("foo.txt")?; /// - /// if let Ok(time) = metadata.modified() { - /// println!("{:?}", time); - /// } else { - /// println!("Not supported on this platform"); + /// if let Ok(time) = metadata.modified() { + /// println!("{:?}", time); + /// } else { + /// println!("Not supported on this platform"); + /// } + /// Ok(()) /// } - /// # Ok(()) - /// # } /// ``` #[stable(feature = "fs_time", since = "1.10.0")] pub fn modified(&self) -> io::Result { @@ -1023,19 +1023,19 @@ impl Metadata { /// /// # Examples /// - /// ``` - /// # fn foo() -> std::io::Result<()> { + /// ```no_run /// use std::fs; /// - /// let metadata = fs::metadata("foo.txt")?; + /// fn main() -> std::io::Result<()> { + /// let metadata = fs::metadata("foo.txt")?; /// - /// if let Ok(time) = metadata.accessed() { - /// println!("{:?}", time); - /// } else { - /// println!("Not supported on this platform"); + /// if let Ok(time) = metadata.accessed() { + /// println!("{:?}", time); + /// } else { + /// println!("Not supported on this platform"); + /// } + /// Ok(()) /// } - /// # Ok(()) - /// # } /// ``` #[stable(feature = "fs_time", since = "1.10.0")] pub fn accessed(&self) -> io::Result { @@ -1054,19 +1054,19 @@ impl Metadata { /// /// # Examples /// - /// ``` - /// # fn foo() -> std::io::Result<()> { + /// ```no_run /// use std::fs; /// - /// let metadata = fs::metadata("foo.txt")?; + /// fn main() -> std::io::Result<()> { + /// let metadata = fs::metadata("foo.txt")?; /// - /// if let Ok(time) = metadata.created() { - /// println!("{:?}", time); - /// } else { - /// println!("Not supported on this platform"); + /// if let Ok(time) = metadata.created() { + /// println!("{:?}", time); + /// } else { + /// println!("Not supported on this platform"); + /// } + /// Ok(()) /// } - /// # Ok(()) - /// # } /// ``` #[stable(feature = "fs_time", since = "1.10.0")] pub fn created(&self) -> io::Result { @@ -1098,16 +1098,16 @@ impl Permissions { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs::File; /// - /// # fn foo() -> std::io::Result<()> { - /// let mut f = File::create("foo.txt")?; - /// let metadata = f.metadata()?; + /// fn main() -> std::io::Result<()> { + /// let mut f = File::create("foo.txt")?; + /// let metadata = f.metadata()?; /// - /// assert_eq!(false, metadata.permissions().readonly()); - /// # Ok(()) - /// # } + /// assert_eq!(false, metadata.permissions().readonly()); + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn readonly(&self) -> bool { self.0.readonly() } @@ -1123,23 +1123,23 @@ impl Permissions { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs::File; /// - /// # fn foo() -> std::io::Result<()> { - /// let f = File::create("foo.txt")?; - /// let metadata = f.metadata()?; - /// let mut permissions = metadata.permissions(); + /// fn main() -> std::io::Result<()> { + /// let f = File::create("foo.txt")?; + /// let metadata = f.metadata()?; + /// let mut permissions = metadata.permissions(); /// - /// permissions.set_readonly(true); + /// permissions.set_readonly(true); /// - /// // filesystem doesn't change - /// assert_eq!(false, metadata.permissions().readonly()); + /// // filesystem doesn't change + /// assert_eq!(false, metadata.permissions().readonly()); /// - /// // just this particular `permissions`. - /// assert_eq!(true, permissions.readonly()); - /// # Ok(()) - /// # } + /// // just this particular `permissions`. + /// assert_eq!(true, permissions.readonly()); + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn set_readonly(&mut self, readonly: bool) { @@ -1152,16 +1152,16 @@ impl FileType { /// /// # Examples /// - /// ``` - /// # fn foo() -> std::io::Result<()> { - /// use std::fs; + /// ```no_run + /// fn main() -> std::io::Result<()> { + /// use std::fs; /// - /// let metadata = fs::metadata("foo.txt")?; - /// let file_type = metadata.file_type(); + /// let metadata = fs::metadata("foo.txt")?; + /// let file_type = metadata.file_type(); /// - /// assert_eq!(file_type.is_dir(), false); - /// # Ok(()) - /// # } + /// assert_eq!(file_type.is_dir(), false); + /// Ok(()) + /// } /// ``` #[stable(feature = "file_type", since = "1.1.0")] pub fn is_dir(&self) -> bool { self.0.is_dir() } @@ -1170,16 +1170,16 @@ impl FileType { /// /// # Examples /// - /// ``` - /// # fn foo() -> std::io::Result<()> { - /// use std::fs; + /// ```no_run + /// fn main() -> std::io::Result<()> { + /// use std::fs; /// - /// let metadata = fs::metadata("foo.txt")?; - /// let file_type = metadata.file_type(); + /// let metadata = fs::metadata("foo.txt")?; + /// let file_type = metadata.file_type(); /// - /// assert_eq!(file_type.is_file(), true); - /// # Ok(()) - /// # } + /// assert_eq!(file_type.is_file(), true); + /// Ok(()) + /// } /// ``` #[stable(feature = "file_type", since = "1.1.0")] pub fn is_file(&self) -> bool { self.0.is_file() } @@ -1199,16 +1199,16 @@ impl FileType { /// /// # Examples /// - /// ``` - /// # fn foo() -> std::io::Result<()> { + /// ```no_run /// use std::fs; /// - /// let metadata = fs::symlink_metadata("foo.txt")?; - /// let file_type = metadata.file_type(); + /// fn main() -> std::io::Result<()> { + /// let metadata = fs::symlink_metadata("foo.txt")?; + /// let file_type = metadata.file_type(); /// - /// assert_eq!(file_type.is_symlink(), false); - /// # Ok(()) - /// # } + /// assert_eq!(file_type.is_symlink(), false); + /// Ok(()) + /// } /// ``` #[stable(feature = "file_type", since = "1.1.0")] pub fn is_symlink(&self) -> bool { self.0.is_symlink() } @@ -1245,15 +1245,16 @@ impl DirEntry { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; - /// # fn foo() -> std::io::Result<()> { - /// for entry in fs::read_dir(".")? { - /// let dir = entry?; - /// println!("{:?}", dir.path()); + /// + /// fn main() -> std::io::Result<()> { + /// for entry in fs::read_dir(".")? { + /// let dir = entry?; + /// println!("{:?}", dir.path()); + /// } + /// Ok(()) /// } - /// # Ok(()) - /// # } /// ``` /// /// This prints output like: @@ -1398,13 +1399,13 @@ impl AsInner for DirEntry { /// /// # Examples /// -/// ``` +/// ```no_run /// use std::fs; /// -/// # fn foo() -> std::io::Result<()> { -/// fs::remove_file("a.txt")?; -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// fs::remove_file("a.txt")?; +/// Ok(()) +/// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn remove_file>(path: P) -> io::Result<()> { @@ -1435,14 +1436,14 @@ pub fn remove_file>(path: P) -> io::Result<()> { /// /// # Examples /// -/// ```rust -/// # fn foo() -> std::io::Result<()> { +/// ```rust,no_run /// use std::fs; /// -/// let attr = fs::metadata("/some/file/path.txt")?; -/// // inspect attr ... -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// let attr = fs::metadata("/some/file/path.txt")?; +/// // inspect attr ... +/// Ok(()) +/// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn metadata>(path: P) -> io::Result { @@ -1469,14 +1470,14 @@ pub fn metadata>(path: P) -> io::Result { /// /// # Examples /// -/// ```rust -/// # fn foo() -> std::io::Result<()> { +/// ```rust,no_run /// use std::fs; /// -/// let attr = fs::symlink_metadata("/some/file/path.txt")?; -/// // inspect attr ... -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// let attr = fs::symlink_metadata("/some/file/path.txt")?; +/// // inspect attr ... +/// Ok(()) +/// } /// ``` #[stable(feature = "symlink_metadata", since = "1.1.0")] pub fn symlink_metadata>(path: P) -> io::Result { @@ -1513,13 +1514,13 @@ pub fn symlink_metadata>(path: P) -> io::Result { /// /// # Examples /// -/// ``` +/// ```no_run /// use std::fs; /// -/// # fn foo() -> std::io::Result<()> { -/// fs::rename("a.txt", "b.txt")?; // Rename a.txt to b.txt -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// fs::rename("a.txt", "b.txt")?; // Rename a.txt to b.txt +/// Ok(()) +/// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn rename, Q: AsRef>(from: P, to: Q) -> io::Result<()> { @@ -1564,9 +1565,10 @@ pub fn rename, Q: AsRef>(from: P, to: Q) -> io::Result<()> /// ```no_run /// use std::fs; /// -/// # fn foo() -> std::io::Result<()> { -/// fs::copy("foo.txt", "bar.txt")?; // Copy foo.txt to bar.txt -/// # Ok(()) } +/// fn main() -> std::io::Result<()> { +/// fs::copy("foo.txt", "bar.txt")?; // Copy foo.txt to bar.txt +/// Ok(()) +/// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn copy, Q: AsRef>(from: P, to: Q) -> io::Result { @@ -1595,13 +1597,13 @@ pub fn copy, Q: AsRef>(from: P, to: Q) -> io::Result { /// /// # Examples /// -/// ``` +/// ```no_run /// use std::fs; /// -/// # fn foo() -> std::io::Result<()> { -/// fs::hard_link("a.txt", "b.txt")?; // Hard link a.txt to b.txt -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// fs::hard_link("a.txt", "b.txt")?; // Hard link a.txt to b.txt +/// Ok(()) +/// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn hard_link, Q: AsRef>(src: P, dst: Q) -> io::Result<()> { @@ -1618,13 +1620,13 @@ pub fn hard_link, Q: AsRef>(src: P, dst: Q) -> io::Result<( /// /// # Examples /// -/// ``` +/// ```no_run /// use std::fs; /// -/// # fn foo() -> std::io::Result<()> { -/// fs::soft_link("a.txt", "b.txt")?; -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// fs::soft_link("a.txt", "b.txt")?; +/// Ok(()) +/// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_deprecated(since = "1.1.0", @@ -1655,13 +1657,13 @@ pub fn soft_link, Q: AsRef>(src: P, dst: Q) -> io::Result<( /// /// # Examples /// -/// ``` +/// ```no_run /// use std::fs; /// -/// # fn foo() -> std::io::Result<()> { -/// let path = fs::read_link("a.txt")?; -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// let path = fs::read_link("a.txt")?; +/// Ok(()) +/// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn read_link>(path: P) -> io::Result { @@ -1689,13 +1691,13 @@ pub fn read_link>(path: P) -> io::Result { /// /// # Examples /// -/// ``` +/// ```no_run /// use std::fs; /// -/// # fn foo() -> std::io::Result<()> { -/// let path = fs::canonicalize("../a/../foo.txt")?; -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// let path = fs::canonicalize("../a/../foo.txt")?; +/// Ok(()) +/// } /// ``` #[stable(feature = "fs_canonicalize", since = "1.5.0")] pub fn canonicalize>(path: P) -> io::Result { @@ -1722,13 +1724,13 @@ pub fn canonicalize>(path: P) -> io::Result { /// /// # Examples /// -/// ``` +/// ```no_run /// use std::fs; /// -/// # fn foo() -> std::io::Result<()> { -/// fs::create_dir("/some/dir")?; -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// fs::create_dir("/some/dir")?; +/// Ok(()) +/// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn create_dir>(path: P) -> io::Result<()> { @@ -1764,13 +1766,13 @@ pub fn create_dir>(path: P) -> io::Result<()> { /// /// # Examples /// -/// ``` +/// ```no_run /// use std::fs; /// -/// # fn foo() -> std::io::Result<()> { -/// fs::create_dir_all("/some/dir")?; -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// fs::create_dir_all("/some/dir")?; +/// Ok(()) +/// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn create_dir_all>(path: P) -> io::Result<()> { @@ -1797,13 +1799,13 @@ pub fn create_dir_all>(path: P) -> io::Result<()> { /// /// # Examples /// -/// ``` +/// ```no_run /// use std::fs; /// -/// # fn foo() -> std::io::Result<()> { -/// fs::remove_dir("/some/dir")?; -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// fs::remove_dir("/some/dir")?; +/// Ok(()) +/// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn remove_dir>(path: P) -> io::Result<()> { @@ -1831,13 +1833,13 @@ pub fn remove_dir>(path: P) -> io::Result<()> { /// /// # Examples /// -/// ``` +/// ```no_run /// use std::fs; /// -/// # fn foo() -> std::io::Result<()> { -/// fs::remove_dir_all("/some/dir")?; -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// fs::remove_dir_all("/some/dir")?; +/// Ok(()) +/// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn remove_dir_all>(path: P) -> io::Result<()> { @@ -1917,15 +1919,15 @@ pub fn read_dir>(path: P) -> io::Result { /// /// # Examples /// -/// ``` -/// # fn foo() -> std::io::Result<()> { +/// ```no_run /// use std::fs; /// -/// let mut perms = fs::metadata("foo.txt")?.permissions(); -/// perms.set_readonly(true); -/// fs::set_permissions("foo.txt", perms)?; -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// let mut perms = fs::metadata("foo.txt")?.permissions(); +/// perms.set_readonly(true); +/// fs::set_permissions("foo.txt", perms)?; +/// Ok(()) +/// } /// ``` #[stable(feature = "set_permissions", since = "1.1.0")] pub fn set_permissions>(path: P, perm: Permissions) diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index ccaa19acc83..cefff2f143c 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -31,20 +31,20 @@ use memchr; /// /// # Examples /// -/// ``` +/// ```no_run /// use std::io::prelude::*; /// use std::io::BufReader; /// use std::fs::File; /// -/// # fn foo() -> std::io::Result<()> { -/// let f = File::open("log.txt")?; -/// let mut reader = BufReader::new(f); +/// fn main() -> std::io::Result<()> { +/// let f = File::open("log.txt")?; +/// let mut reader = BufReader::new(f); /// -/// let mut line = String::new(); -/// let len = reader.read_line(&mut line)?; -/// println!("First line is {} bytes long", len); -/// # Ok(()) -/// # } +/// let mut line = String::new(); +/// let len = reader.read_line(&mut line)?; +/// println!("First line is {} bytes long", len); +/// Ok(()) +/// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub struct BufReader { @@ -59,15 +59,15 @@ impl BufReader { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::io::BufReader; /// use std::fs::File; /// - /// # fn foo() -> std::io::Result<()> { - /// let f = File::open("log.txt")?; - /// let reader = BufReader::new(f); - /// # Ok(()) - /// # } + /// fn main() -> std::io::Result<()> { + /// let f = File::open("log.txt")?; + /// let reader = BufReader::new(f); + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn new(inner: R) -> BufReader { @@ -80,15 +80,15 @@ impl BufReader { /// /// Creating a buffer with ten bytes of capacity: /// - /// ``` + /// ```no_run /// use std::io::BufReader; /// use std::fs::File; /// - /// # fn foo() -> std::io::Result<()> { - /// let f = File::open("log.txt")?; - /// let reader = BufReader::with_capacity(10, f); - /// # Ok(()) - /// # } + /// fn main() -> std::io::Result<()> { + /// let f = File::open("log.txt")?; + /// let reader = BufReader::with_capacity(10, f); + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn with_capacity(cap: usize, inner: R) -> BufReader { @@ -111,17 +111,17 @@ impl BufReader { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::io::BufReader; /// use std::fs::File; /// - /// # fn foo() -> std::io::Result<()> { - /// let f1 = File::open("log.txt")?; - /// let reader = BufReader::new(f1); + /// fn main() -> std::io::Result<()> { + /// let f1 = File::open("log.txt")?; + /// let reader = BufReader::new(f1); /// - /// let f2 = reader.get_ref(); - /// # Ok(()) - /// # } + /// let f2 = reader.get_ref(); + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn get_ref(&self) -> &R { &self.inner } @@ -132,17 +132,17 @@ impl BufReader { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::io::BufReader; /// use std::fs::File; /// - /// # fn foo() -> std::io::Result<()> { - /// let f1 = File::open("log.txt")?; - /// let mut reader = BufReader::new(f1); + /// fn main() -> std::io::Result<()> { + /// let f1 = File::open("log.txt")?; + /// let mut reader = BufReader::new(f1); /// - /// let f2 = reader.get_mut(); - /// # Ok(()) - /// # } + /// let f2 = reader.get_mut(); + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn get_mut(&mut self) -> &mut R { &mut self.inner } @@ -150,22 +150,23 @@ impl BufReader { /// 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 foo() -> std::io::Result<()> { - /// let f1 = File::open("log.txt")?; - /// let mut reader = BufReader::new(f1); - /// assert!(reader.is_empty()); + /// 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()); + /// if reader.fill_buf()?.len() > 0 { + /// assert!(!reader.is_empty()); + /// } + /// Ok(()) /// } - /// # Ok(()) - /// # } /// ``` #[unstable(feature = "bufreader_is_empty", issue = "45323", reason = "recently added")] #[rustc_deprecated(since = "1.26.0", reason = "use .buffer().is_empty() instead")] @@ -179,21 +180,21 @@ impl BufReader { /// /// # Examples /// - /// ``` + /// ```no_ru /// # #![feature(bufreader_buffer)] /// use std::io::{BufReader, BufRead}; /// use std::fs::File; /// - /// # fn foo() -> std::io::Result<()> { - /// let f = File::open("log.txt")?; - /// let mut reader = BufReader::new(f); - /// assert!(reader.buffer().is_empty()); + /// fn main() -> std::io::Result<()> { + /// let f = File::open("log.txt")?; + /// let mut reader = BufReader::new(f); + /// assert!(reader.buffer().is_empty()); /// - /// if reader.fill_buf()?.len() > 0 { - /// assert!(!reader.buffer().is_empty()); + /// if reader.fill_buf()?.len() > 0 { + /// assert!(!reader.buffer().is_empty()); + /// } + /// Ok(()) /// } - /// # Ok(()) - /// # } /// ``` #[unstable(feature = "bufreader_buffer", issue = "45323")] pub fn buffer(&self) -> &[u8] { @@ -206,17 +207,17 @@ impl BufReader { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::io::BufReader; /// use std::fs::File; /// - /// # fn foo() -> std::io::Result<()> { - /// let f1 = File::open("log.txt")?; - /// let reader = BufReader::new(f1); + /// fn main() -> std::io::Result<()> { + /// let f1 = File::open("log.txt")?; + /// let reader = BufReader::new(f1); /// - /// let f2 = reader.into_inner(); - /// # Ok(()) - /// # } + /// let f2 = reader.into_inner(); + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn into_inner(self) -> R { self.inner } @@ -724,34 +725,34 @@ impl fmt::Display for IntoInnerError { /// We can use `LineWriter` to write one line at a time, significantly /// reducing the number of actual writes to the file. /// -/// ``` +/// ```no_run /// use std::fs::File; /// use std::io::prelude::*; /// use std::io::LineWriter; /// -/// # fn foo() -> std::io::Result<()> { -/// let road_not_taken = b"I shall be telling this with a sigh +/// fn main() -> std::io::Result<()> { +/// let road_not_taken = b"I shall be telling this with a sigh /// 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."; /// -/// let file = File::create("poem.txt")?; -/// let mut file = LineWriter::new(file); +/// let file = File::create("poem.txt")?; +/// let mut file = LineWriter::new(file); /// -/// for &byte in road_not_taken.iter() { -/// file.write(&[byte]).unwrap(); -/// } +/// for &byte in road_not_taken.iter() { +/// file.write(&[byte]).unwrap(); +/// } /// -/// // let's check we did the right thing. -/// let mut file = File::open("poem.txt")?; -/// let mut contents = String::new(); +/// // let's check we did the right thing. +/// let mut file = File::open("poem.txt")?; +/// let mut contents = String::new(); /// -/// file.read_to_string(&mut contents)?; +/// file.read_to_string(&mut contents)?; /// -/// assert_eq!(contents.as_bytes(), &road_not_taken[..]); -/// # Ok(()) -/// # } +/// assert_eq!(contents.as_bytes(), &road_not_taken[..]); +/// Ok(()) +/// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub struct LineWriter { @@ -764,15 +765,15 @@ impl LineWriter { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs::File; /// use std::io::LineWriter; /// - /// # fn foo() -> std::io::Result<()> { - /// let file = File::create("poem.txt")?; - /// let file = LineWriter::new(file); - /// # Ok(()) - /// # } + /// fn main() -> std::io::Result<()> { + /// let file = File::create("poem.txt")?; + /// let file = LineWriter::new(file); + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn new(inner: W) -> LineWriter { @@ -785,15 +786,15 @@ impl LineWriter { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs::File; /// use std::io::LineWriter; /// - /// # fn foo() -> std::io::Result<()> { - /// let file = File::create("poem.txt")?; - /// let file = LineWriter::with_capacity(100, file); - /// # Ok(()) - /// # } + /// fn main() -> std::io::Result<()> { + /// let file = File::create("poem.txt")?; + /// let file = LineWriter::with_capacity(100, file); + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn with_capacity(cap: usize, inner: W) -> LineWriter { @@ -807,17 +808,17 @@ impl LineWriter { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs::File; /// use std::io::LineWriter; /// - /// # fn foo() -> std::io::Result<()> { - /// let file = File::create("poem.txt")?; - /// let file = LineWriter::new(file); + /// fn main() -> std::io::Result<()> { + /// let file = File::create("poem.txt")?; + /// let file = LineWriter::new(file); /// - /// let reference = file.get_ref(); - /// # Ok(()) - /// # } + /// let reference = file.get_ref(); + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn get_ref(&self) -> &W { self.inner.get_ref() } @@ -829,18 +830,18 @@ impl LineWriter { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs::File; /// use std::io::LineWriter; /// - /// # fn foo() -> std::io::Result<()> { - /// let file = File::create("poem.txt")?; - /// let mut file = LineWriter::new(file); + /// fn main() -> std::io::Result<()> { + /// let file = File::create("poem.txt")?; + /// let mut file = LineWriter::new(file); /// - /// // we can use reference just like file - /// let reference = file.get_mut(); - /// # Ok(()) - /// # } + /// // we can use reference just like file + /// let reference = file.get_mut(); + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn get_mut(&mut self) -> &mut W { self.inner.get_mut() } @@ -855,18 +856,18 @@ impl LineWriter { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs::File; /// use std::io::LineWriter; /// - /// # fn foo() -> std::io::Result<()> { - /// let file = File::create("poem.txt")?; + /// fn main() -> std::io::Result<()> { + /// let file = File::create("poem.txt")?; /// - /// let writer: LineWriter = LineWriter::new(file); + /// let writer: LineWriter = LineWriter::new(file); /// - /// let file: File = writer.into_inner()?; - /// # Ok(()) - /// # } + /// let file: File = writer.into_inner()?; + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn into_inner(self) -> Result>> { diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index d403bf6bfe5..63b631ace96 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -24,21 +24,21 @@ //! example, [`Read`] adds a [`read`][`Read::read`] method, which we can use on //! [`File`]s: //! -//! ``` +//! ```no_run //! use std::io; //! use std::io::prelude::*; //! use std::fs::File; //! -//! # fn foo() -> io::Result<()> { -//! let mut f = File::open("foo.txt")?; -//! let mut buffer = [0; 10]; +//! fn main() -> io::Result<()> { +//! let mut f = File::open("foo.txt")?; +//! let mut buffer = [0; 10]; //! -//! // read up to 10 bytes -//! f.read(&mut buffer)?; +//! // read up to 10 bytes +//! f.read(&mut buffer)?; //! -//! println!("The bytes: {:?}", buffer); -//! # Ok(()) -//! # } +//! println!("The bytes: {:?}", buffer); +//! Ok(()) +//! } //! ``` //! //! [`Read`] and [`Write`] are so important, implementors of the two traits have a @@ -52,25 +52,25 @@ //! how the reading happens. [`Seek`] lets you control where the next byte is //! coming from: //! -//! ``` +//! ```no_run //! use std::io; //! use std::io::prelude::*; //! use std::io::SeekFrom; //! use std::fs::File; //! -//! # fn foo() -> io::Result<()> { -//! let mut f = File::open("foo.txt")?; -//! let mut buffer = [0; 10]; +//! fn main() -> io::Result<()> { +//! let mut f = File::open("foo.txt")?; +//! let mut buffer = [0; 10]; //! -//! // skip to the last 10 bytes of the file -//! f.seek(SeekFrom::End(-10))?; +//! // skip to the last 10 bytes of the file +//! f.seek(SeekFrom::End(-10))?; //! -//! // read up to 10 bytes -//! f.read(&mut buffer)?; +//! // read up to 10 bytes +//! f.read(&mut buffer)?; //! -//! println!("The bytes: {:?}", buffer); -//! # Ok(()) -//! # } +//! println!("The bytes: {:?}", buffer); +//! Ok(()) +//! } //! ``` //! //! [`BufRead`] uses an internal buffer to provide a number of other ways to read, but @@ -87,70 +87,70 @@ //! For example, [`BufReader`] works with the [`BufRead`] trait to add extra //! methods to any reader: //! -//! ``` +//! ```no_run //! use std::io; //! use std::io::prelude::*; //! use std::io::BufReader; //! use std::fs::File; //! -//! # fn foo() -> io::Result<()> { -//! let f = File::open("foo.txt")?; -//! let mut reader = BufReader::new(f); -//! let mut buffer = String::new(); +//! fn main() -> io::Result<()> { +//! let f = File::open("foo.txt")?; +//! let mut reader = BufReader::new(f); +//! let mut buffer = String::new(); //! -//! // read a line into buffer -//! reader.read_line(&mut buffer)?; +//! // read a line into buffer +//! reader.read_line(&mut buffer)?; //! -//! println!("{}", buffer); -//! # Ok(()) -//! # } +//! println!("{}", buffer); +//! Ok(()) +//! } //! ``` //! //! [`BufWriter`] doesn't add any new ways of writing; it just buffers every call //! to [`write`][`Write::write`]: //! -//! ``` +//! ```no_run //! use std::io; //! use std::io::prelude::*; //! use std::io::BufWriter; //! use std::fs::File; //! -//! # fn foo() -> io::Result<()> { -//! let f = File::create("foo.txt")?; -//! { -//! let mut writer = BufWriter::new(f); +//! fn main() -> io::Result<()> { +//! let f = File::create("foo.txt")?; +//! { +//! let mut writer = BufWriter::new(f); //! -//! // write a byte to the buffer -//! writer.write(&[42])?; +//! // write a byte to the buffer +//! writer.write(&[42])?; //! -//! } // the buffer is flushed once writer goes out of scope +//! } // the buffer is flushed once writer goes out of scope //! -//! # Ok(()) -//! # } +//! Ok(()) +//! } //! ``` //! //! ## Standard input and output //! //! A very common source of input is standard input: //! -//! ``` +//! ```no_run //! use std::io; //! -//! # fn foo() -> io::Result<()> { -//! let mut input = String::new(); +//! fn main() -> io::Result<()> { +//! let mut input = String::new(); //! -//! io::stdin().read_line(&mut input)?; +//! io::stdin().read_line(&mut input)?; //! -//! println!("You typed: {}", input.trim()); -//! # Ok(()) -//! # } +//! println!("You typed: {}", input.trim()); +//! Ok(()) +//! } //! ``` //! //! Note that you cannot use the [`?` operator] in functions that do not return //! a [`Result`][`Result`] (e.g. `main`). Instead, you can call [`.unwrap()`] //! or `match` on the return value to catch any possible errors: //! -//! ``` +//! ```no_run //! use std::io; //! //! let mut input = String::new(); @@ -160,14 +160,14 @@ //! //! And a very common source of output is standard output: //! -//! ``` +//! ```no_run //! use std::io; //! use std::io::prelude::*; //! -//! # fn foo() -> io::Result<()> { -//! io::stdout().write(&[42])?; -//! # Ok(()) -//! # } +//! fn main() -> io::Result<()> { +//! io::stdout().write(&[42])?; +//! Ok(()) +//! } //! ``` //! //! Of course, using [`io::stdout`] directly is less common than something like @@ -179,22 +179,21 @@ //! ways of iterating over I/O. For example, [`Lines`] is used to split over //! lines: //! -//! ``` +//! ```no_run //! use std::io; //! use std::io::prelude::*; //! use std::io::BufReader; //! use std::fs::File; //! -//! # fn foo() -> io::Result<()> { -//! let f = File::open("foo.txt")?; -//! let reader = BufReader::new(f); +//! fn main() -> io::Result<()> { +//! let f = File::open("foo.txt")?; +//! let reader = BufReader::new(f); //! -//! for line in reader.lines() { -//! println!("{}", line?); +//! for line in reader.lines() { +//! println!("{}", line?); +//! } +//! Ok(()) //! } -//! -//! # Ok(()) -//! # } //! ``` //! //! ## Functions @@ -203,13 +202,13 @@ //! features. For example, we can use three of these functions to copy everything //! from standard input to standard output: //! -//! ``` +//! ```no_run //! use std::io; //! -//! # fn foo() -> io::Result<()> { -//! io::copy(&mut io::stdin(), &mut io::stdout())?; -//! # Ok(()) -//! # } +//! fn main() -> io::Result<()> { +//! io::copy(&mut io::stdin(), &mut io::stdout())?; +//! Ok(()) +//! } //! ``` //! //! [functions-list]: #functions-1 @@ -416,47 +415,47 @@ fn read_to_end(r: &mut R, buf: &mut Vec) -> Result /// /// [`File`]s implement `Read`: /// -/// ``` -/// # use std::io; +/// ```no_run +/// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// -/// # fn foo() -> io::Result<()> { -/// let mut f = File::open("foo.txt")?; -/// let mut buffer = [0; 10]; +/// fn main() -> io::Result<()> { +/// let mut f = File::open("foo.txt")?; +/// let mut buffer = [0; 10]; /// -/// // read up to 10 bytes -/// f.read(&mut buffer)?; +/// // read up to 10 bytes +/// f.read(&mut buffer)?; /// -/// let mut buffer = vec![0; 10]; -/// // read the whole file -/// f.read_to_end(&mut buffer)?; +/// let mut buffer = vec![0; 10]; +/// // read the whole file +/// f.read_to_end(&mut buffer)?; /// -/// // read into a String, so that you don't need to do the conversion. -/// let mut buffer = String::new(); -/// f.read_to_string(&mut buffer)?; +/// // read into a String, so that you don't need to do the conversion. +/// let mut buffer = String::new(); +/// f.read_to_string(&mut buffer)?; /// -/// // and more! See the other methods for more details. -/// # Ok(()) -/// # } +/// // and more! See the other methods for more details. +/// Ok(()) +/// } /// ``` /// /// Read from [`&str`] because [`&[u8]`][slice] implements `Read`: /// -/// ``` +/// ```no_run /// # use std::io; /// use std::io::prelude::*; /// -/// # fn foo() -> io::Result<()> { -/// let mut b = "This string will be read".as_bytes(); -/// let mut buffer = [0; 10]; +/// fn main() -> io::Result<()> { +/// let mut b = "This string will be read".as_bytes(); +/// let mut buffer = [0; 10]; /// -/// // read up to 10 bytes -/// b.read(&mut buffer)?; +/// // read up to 10 bytes +/// b.read(&mut buffer)?; /// -/// // etc... it works exactly as a File does! -/// # Ok(()) -/// # } +/// // etc... it works exactly as a File does! +/// Ok(()) +/// } /// ``` /// /// [`read()`]: trait.Read.html#tymethod.read @@ -509,19 +508,19 @@ pub trait Read { /// [`ErrorKind::Interrupted`]: ../../std/io/enum.ErrorKind.html#variant.Interrupted /// [`File`]: ../fs/struct.File.html /// - /// ``` + /// ```no_run /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// - /// # fn foo() -> io::Result<()> { - /// let mut f = File::open("foo.txt")?; - /// let mut buffer = [0; 10]; + /// fn main() -> io::Result<()> { + /// let mut f = File::open("foo.txt")?; + /// let mut buffer = [0; 10]; /// - /// // read up to 10 bytes - /// f.read(&mut buffer[..])?; - /// # Ok(()) - /// # } + /// // read up to 10 bytes + /// f.read(&mut buffer[..])?; + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn read(&mut self, buf: &mut [u8]) -> Result; @@ -582,19 +581,19 @@ pub trait Read { /// [`ErrorKind::Interrupted`]: ../../std/io/enum.ErrorKind.html#variant.Interrupted /// [`File`]: ../fs/struct.File.html /// - /// ``` + /// ```no_run /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// - /// # fn foo() -> io::Result<()> { - /// let mut f = File::open("foo.txt")?; - /// let mut buffer = Vec::new(); + /// fn main() -> io::Result<()> { + /// let mut f = File::open("foo.txt")?; + /// let mut buffer = Vec::new(); /// - /// // read the whole file - /// f.read_to_end(&mut buffer)?; - /// # Ok(()) - /// # } + /// // read the whole file + /// f.read_to_end(&mut buffer)?; + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn read_to_end(&mut self, buf: &mut Vec) -> Result { @@ -621,18 +620,18 @@ pub trait Read { /// /// [file]: ../fs/struct.File.html /// - /// ``` + /// ```no_run /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// - /// # fn foo() -> io::Result<()> { - /// let mut f = File::open("foo.txt")?; - /// let mut buffer = String::new(); + /// fn main() -> io::Result<()> { + /// let mut f = File::open("foo.txt")?; + /// let mut buffer = String::new(); /// - /// f.read_to_string(&mut buffer)?; - /// # Ok(()) - /// # } + /// f.read_to_string(&mut buffer)?; + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn read_to_string(&mut self, buf: &mut String) -> Result { @@ -683,19 +682,19 @@ pub trait Read { /// [`ErrorKind::Interrupted`]: ../../std/io/enum.ErrorKind.html#variant.Interrupted /// [`ErrorKind::UnexpectedEof`]: ../../std/io/enum.ErrorKind.html#variant.UnexpectedEof /// - /// ``` + /// ```no_run /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// - /// # fn foo() -> io::Result<()> { - /// let mut f = File::open("foo.txt")?; - /// let mut buffer = [0; 10]; + /// fn main() -> io::Result<()> { + /// let mut f = File::open("foo.txt")?; + /// let mut buffer = [0; 10]; /// - /// // read exactly 10 bytes - /// f.read_exact(&mut buffer)?; - /// # Ok(()) - /// # } + /// // read exactly 10 bytes + /// f.read_exact(&mut buffer)?; + /// Ok(()) + /// } /// ``` #[stable(feature = "read_exact", since = "1.6.0")] fn read_exact(&mut self, mut buf: &mut [u8]) -> Result<()> { @@ -726,28 +725,28 @@ pub trait Read { /// /// [file]: ../fs/struct.File.html /// - /// ``` + /// ```no_run /// use std::io; /// use std::io::Read; /// use std::fs::File; /// - /// # fn foo() -> io::Result<()> { - /// let mut f = File::open("foo.txt")?; - /// let mut buffer = Vec::new(); - /// let mut other_buffer = Vec::new(); + /// fn main() -> io::Result<()> { + /// let mut f = File::open("foo.txt")?; + /// let mut buffer = Vec::new(); + /// let mut other_buffer = Vec::new(); /// - /// { - /// let reference = f.by_ref(); + /// { + /// let reference = f.by_ref(); /// - /// // read at most 5 bytes - /// reference.take(5).read_to_end(&mut buffer)?; + /// // read at most 5 bytes + /// reference.take(5).read_to_end(&mut buffer)?; /// - /// } // drop our &mut reference so we can use f again + /// } // drop our &mut reference so we can use f again /// - /// // original file still usable, read the rest - /// f.read_to_end(&mut other_buffer)?; - /// # Ok(()) - /// # } + /// // original file still usable, read the rest + /// f.read_to_end(&mut other_buffer)?; + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn by_ref(&mut self) -> &mut Self where Self: Sized { self } @@ -772,19 +771,19 @@ pub trait Read { /// [`Err`]: ../../std/result/enum.Result.html#variant.Err /// [`None`]: ../../std/option/enum.Option.html#variant.None /// - /// ``` + /// ```no_run /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// - /// # fn foo() -> io::Result<()> { - /// let mut f = File::open("foo.txt")?; + /// fn main() -> io::Result<()> { + /// let mut f = File::open("foo.txt")?; /// - /// for byte in f.bytes() { - /// println!("{}", byte.unwrap()); + /// for byte in f.bytes() { + /// println!("{}", byte.unwrap()); + /// } + /// Ok(()) /// } - /// # Ok(()) - /// # } /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn bytes(self) -> Bytes where Self: Sized { @@ -812,20 +811,20 @@ pub trait Read { /// [`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 foo() -> io::Result<()> { - /// let mut f = File::open("foo.txt")?; + /// fn main() -> io::Result<()> { + /// let mut f = File::open("foo.txt")?; /// - /// for c in f.chars() { - /// println!("{}", c.unwrap()); + /// for c in f.chars() { + /// println!("{}", c.unwrap()); + /// } + /// Ok(()) /// } - /// # Ok(()) - /// # } /// ``` #[unstable(feature = "io", reason = "the semantics of a partial read/write \ of where errors happen is currently \ @@ -847,23 +846,23 @@ pub trait Read { /// /// [file]: ../fs/struct.File.html /// - /// ``` + /// ```no_run /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// - /// # fn foo() -> io::Result<()> { - /// let mut f1 = File::open("foo.txt")?; - /// let mut f2 = File::open("bar.txt")?; + /// fn main() -> io::Result<()> { + /// let mut f1 = File::open("foo.txt")?; + /// let mut f2 = File::open("bar.txt")?; /// - /// let mut handle = f1.chain(f2); - /// let mut buffer = String::new(); + /// let mut handle = f1.chain(f2); + /// let mut buffer = String::new(); /// - /// // read the value into a String. We could use any Read method here, - /// // this is just one example. - /// handle.read_to_string(&mut buffer)?; - /// # Ok(()) - /// # } + /// // read the value into a String. We could use any Read method here, + /// // this is just one example. + /// handle.read_to_string(&mut buffer)?; + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn chain(self, next: R) -> Chain where Self: Sized { @@ -885,21 +884,21 @@ pub trait Read { /// [`Ok(0)`]: ../../std/result/enum.Result.html#variant.Ok /// [`read()`]: trait.Read.html#tymethod.read /// - /// ``` + /// ```no_run /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// - /// # fn foo() -> io::Result<()> { - /// let mut f = File::open("foo.txt")?; - /// let mut buffer = [0; 5]; + /// fn main() -> io::Result<()> { + /// let mut f = File::open("foo.txt")?; + /// let mut buffer = [0; 5]; /// - /// // read at most five bytes - /// let mut handle = f.take(5); + /// // read at most five bytes + /// let mut handle = f.take(5); /// - /// handle.read(&mut buffer)?; - /// # Ok(()) - /// # } + /// handle.read(&mut buffer)?; + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn take(self, limit: u64) -> Take where Self: Sized { @@ -974,16 +973,16 @@ impl Initializer { /// /// # Examples /// -/// ``` +/// ```no_run /// use std::io::prelude::*; /// use std::fs::File; /// -/// # fn foo() -> std::io::Result<()> { -/// let mut buffer = File::create("foo.txt")?; +/// fn main() -> std::io::Result<()> { +/// let mut buffer = File::create("foo.txt")?; /// -/// buffer.write(b"some bytes")?; -/// # Ok(()) -/// # } +/// buffer.write(b"some bytes")?; +/// Ok(()) +/// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[doc(spotlight)] @@ -1022,17 +1021,17 @@ pub trait Write { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::io::prelude::*; /// use std::fs::File; /// - /// # fn foo() -> std::io::Result<()> { - /// let mut buffer = File::create("foo.txt")?; + /// fn main() -> std::io::Result<()> { + /// let mut buffer = File::create("foo.txt")?; /// - /// // Writes some prefix of the byte string, not necessarily all of it. - /// buffer.write(b"some bytes")?; - /// # Ok(()) - /// # } + /// // Writes some prefix of the byte string, not necessarily all of it. + /// buffer.write(b"some bytes")?; + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn write(&mut self, buf: &[u8]) -> Result; @@ -1047,18 +1046,18 @@ pub trait Write { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::io::prelude::*; /// use std::io::BufWriter; /// use std::fs::File; /// - /// # fn foo() -> std::io::Result<()> { - /// let mut buffer = BufWriter::new(File::create("foo.txt")?); + /// fn main() -> std::io::Result<()> { + /// let mut buffer = BufWriter::new(File::create("foo.txt")?); /// - /// buffer.write(b"some bytes")?; - /// buffer.flush()?; - /// # Ok(()) - /// # } + /// buffer.write(b"some bytes")?; + /// buffer.flush()?; + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn flush(&mut self) -> Result<()>; @@ -1082,16 +1081,16 @@ pub trait Write { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::io::prelude::*; /// use std::fs::File; /// - /// # fn foo() -> std::io::Result<()> { - /// let mut buffer = File::create("foo.txt")?; + /// fn main() -> std::io::Result<()> { + /// let mut buffer = File::create("foo.txt")?; /// - /// buffer.write_all(b"some bytes")?; - /// # Ok(()) - /// # } + /// buffer.write_all(b"some bytes")?; + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn write_all(&mut self, mut buf: &[u8]) -> Result<()> { @@ -1131,19 +1130,19 @@ pub trait Write { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::io::prelude::*; /// use std::fs::File; /// - /// # fn foo() -> std::io::Result<()> { - /// let mut buffer = File::create("foo.txt")?; + /// fn main() -> std::io::Result<()> { + /// let mut buffer = File::create("foo.txt")?; /// - /// // this call - /// write!(buffer, "{:.*}", 2, 1.234567)?; - /// // turns into this: - /// buffer.write_fmt(format_args!("{:.*}", 2, 1.234567))?; - /// # Ok(()) - /// # } + /// // this call + /// write!(buffer, "{:.*}", 2, 1.234567)?; + /// // turns into this: + /// buffer.write_fmt(format_args!("{:.*}", 2, 1.234567))?; + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn write_fmt(&mut self, fmt: fmt::Arguments) -> Result<()> { @@ -1187,19 +1186,19 @@ pub trait Write { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::io::Write; /// use std::fs::File; /// - /// # fn foo() -> std::io::Result<()> { - /// let mut buffer = File::create("foo.txt")?; + /// fn main() -> std::io::Result<()> { + /// let mut buffer = File::create("foo.txt")?; /// - /// let reference = buffer.by_ref(); + /// let reference = buffer.by_ref(); /// - /// // we can use reference just like our original buffer - /// reference.write_all(b"some bytes")?; - /// # Ok(()) - /// # } + /// // we can use reference just like our original buffer + /// reference.write_all(b"some bytes")?; + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn by_ref(&mut self) -> &mut Self where Self: Sized { self } @@ -1217,19 +1216,19 @@ pub trait Write { /// /// [file]: ../fs/struct.File.html /// -/// ``` +/// ```no_run /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// use std::io::SeekFrom; /// -/// # fn foo() -> io::Result<()> { -/// let mut f = File::open("foo.txt")?; +/// fn main() -> io::Result<()> { +/// let mut f = File::open("foo.txt")?; /// -/// // move the cursor 42 bytes from the start of the file -/// f.seek(SeekFrom::Start(42))?; -/// # Ok(()) -/// # } +/// // move the cursor 42 bytes from the start of the file +/// f.seek(SeekFrom::Start(42))?; +/// Ok(()) +/// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub trait Seek { @@ -1320,7 +1319,7 @@ fn read_until(r: &mut R, delim: u8, buf: &mut Vec) /// /// A locked standard input implements `BufRead`: /// -/// ``` +/// ```no_run /// use std::io; /// use std::io::prelude::*; /// @@ -1342,21 +1341,21 @@ fn read_until(r: &mut R, delim: u8, buf: &mut Vec) /// [`lines`]: #method.lines /// [`Read`]: trait.Read.html /// -/// ``` +/// ```no_run /// use std::io::{self, BufReader}; /// use std::io::prelude::*; /// use std::fs::File; /// -/// # fn foo() -> io::Result<()> { -/// let f = File::open("foo.txt")?; -/// let f = BufReader::new(f); +/// fn main() -> io::Result<()> { +/// let f = File::open("foo.txt")?; +/// let f = BufReader::new(f); /// -/// for line in f.lines() { -/// println!("{}", line.unwrap()); -/// } +/// for line in f.lines() { +/// println!("{}", line.unwrap()); +/// } /// -/// # Ok(()) -/// # } +/// Ok(()) +/// } /// ``` /// #[stable(feature = "rust1", since = "1.0.0")] @@ -1383,7 +1382,7 @@ pub trait BufRead: Read { /// /// A locked standard input implements `BufRead`: /// - /// ``` + /// ```no_run /// use std::io; /// use std::io::prelude::*; /// @@ -1645,19 +1644,19 @@ impl Chain { /// /// # Examples /// - /// ``` - /// # use std::io; + /// ```no_run + /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// - /// # fn foo() -> io::Result<()> { - /// let mut foo_file = File::open("foo.txt")?; - /// let mut bar_file = File::open("bar.txt")?; + /// fn main() -> io::Result<()> { + /// let mut foo_file = File::open("foo.txt")?; + /// let mut bar_file = File::open("bar.txt")?; /// - /// let chain = foo_file.chain(bar_file); - /// let (foo_file, bar_file) = chain.into_inner(); - /// # Ok(()) - /// # } + /// let chain = foo_file.chain(bar_file); + /// let (foo_file, bar_file) = chain.into_inner(); + /// Ok(()) + /// } /// ``` #[stable(feature = "more_io_inner_methods", since = "1.20.0")] pub fn into_inner(self) -> (T, U) { @@ -1668,19 +1667,19 @@ impl Chain { /// /// # Examples /// - /// ``` - /// # use std::io; + /// ```no_run + /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// - /// # fn foo() -> io::Result<()> { - /// let mut foo_file = File::open("foo.txt")?; - /// let mut bar_file = File::open("bar.txt")?; + /// fn main() -> io::Result<()> { + /// let mut foo_file = File::open("foo.txt")?; + /// let mut bar_file = File::open("bar.txt")?; /// - /// let chain = foo_file.chain(bar_file); - /// let (foo_file, bar_file) = chain.get_ref(); - /// # Ok(()) - /// # } + /// let chain = foo_file.chain(bar_file); + /// let (foo_file, bar_file) = chain.get_ref(); + /// Ok(()) + /// } /// ``` #[stable(feature = "more_io_inner_methods", since = "1.20.0")] pub fn get_ref(&self) -> (&T, &U) { @@ -1695,19 +1694,19 @@ impl Chain { /// /// # Examples /// - /// ``` - /// # use std::io; + /// ```no_run + /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// - /// # fn foo() -> io::Result<()> { - /// let mut foo_file = File::open("foo.txt")?; - /// let mut bar_file = File::open("bar.txt")?; + /// fn main() -> io::Result<()> { + /// let mut foo_file = File::open("foo.txt")?; + /// let mut bar_file = File::open("bar.txt")?; /// - /// let mut chain = foo_file.chain(bar_file); - /// let (foo_file, bar_file) = chain.get_mut(); - /// # Ok(()) - /// # } + /// let mut chain = foo_file.chain(bar_file); + /// let (foo_file, bar_file) = chain.get_mut(); + /// Ok(()) + /// } /// ``` #[stable(feature = "more_io_inner_methods", since = "1.20.0")] pub fn get_mut(&mut self) -> (&mut T, &mut U) { @@ -1794,20 +1793,20 @@ impl Take { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// - /// # fn foo() -> io::Result<()> { - /// let f = File::open("foo.txt")?; + /// fn main() -> io::Result<()> { + /// let f = File::open("foo.txt")?; /// - /// // read at most five bytes - /// let handle = f.take(5); + /// // read at most five bytes + /// let handle = f.take(5); /// - /// println!("limit: {}", handle.limit()); - /// # Ok(()) - /// # } + /// println!("limit: {}", handle.limit()); + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn limit(&self) -> u64 { self.limit } @@ -1819,22 +1818,22 @@ impl Take { /// /// # Examples /// - /// ``` + /// ```no_run /// #![feature(take_set_limit)] /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// - /// # fn foo() -> io::Result<()> { - /// let f = File::open("foo.txt")?; + /// fn main() -> io::Result<()> { + /// let f = File::open("foo.txt")?; /// - /// // read at most five bytes - /// let mut handle = f.take(5); - /// handle.set_limit(10); + /// // read at most five bytes + /// let mut handle = f.take(5); + /// handle.set_limit(10); /// - /// assert_eq!(handle.limit(), 10); - /// # Ok(()) - /// # } + /// assert_eq!(handle.limit(), 10); + /// Ok(()) + /// } /// ``` #[unstable(feature = "take_set_limit", issue = "42781")] pub fn set_limit(&mut self, limit: u64) { @@ -1845,21 +1844,21 @@ impl Take { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// - /// # fn foo() -> io::Result<()> { - /// let mut file = File::open("foo.txt")?; + /// fn main() -> io::Result<()> { + /// let mut file = File::open("foo.txt")?; /// - /// let mut buffer = [0; 5]; - /// let mut handle = file.take(5); - /// handle.read(&mut buffer)?; + /// let mut buffer = [0; 5]; + /// let mut handle = file.take(5); + /// handle.read(&mut buffer)?; /// - /// let file = handle.into_inner(); - /// # Ok(()) - /// # } + /// let file = handle.into_inner(); + /// Ok(()) + /// } /// ``` #[stable(feature = "io_take_into_inner", since = "1.15.0")] pub fn into_inner(self) -> T { @@ -1870,21 +1869,21 @@ impl Take { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// - /// # fn foo() -> io::Result<()> { - /// let mut file = File::open("foo.txt")?; + /// fn main() -> io::Result<()> { + /// let mut file = File::open("foo.txt")?; /// - /// let mut buffer = [0; 5]; - /// let mut handle = file.take(5); - /// handle.read(&mut buffer)?; + /// let mut buffer = [0; 5]; + /// let mut handle = file.take(5); + /// handle.read(&mut buffer)?; /// - /// let file = handle.get_ref(); - /// # Ok(()) - /// # } + /// let file = handle.get_ref(); + /// Ok(()) + /// } /// ``` #[stable(feature = "more_io_inner_methods", since = "1.20.0")] pub fn get_ref(&self) -> &T { @@ -1899,21 +1898,21 @@ impl Take { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// - /// # fn foo() -> io::Result<()> { - /// let mut file = File::open("foo.txt")?; + /// fn main() -> io::Result<()> { + /// let mut file = File::open("foo.txt")?; /// - /// let mut buffer = [0; 5]; - /// let mut handle = file.take(5); - /// handle.read(&mut buffer)?; + /// let mut buffer = [0; 5]; + /// let mut handle = file.take(5); + /// handle.read(&mut buffer)?; /// - /// let file = handle.get_mut(); - /// # Ok(()) - /// # } + /// let file = handle.get_mut(); + /// Ok(()) + /// } /// ``` #[stable(feature = "more_io_inner_methods", since = "1.20.0")] pub fn get_mut(&mut self) -> &mut T { diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs index 1f73054e3be..2472bed5ba4 100644 --- a/src/libstd/io/stdio.rs +++ b/src/libstd/io/stdio.rs @@ -171,29 +171,29 @@ pub struct StdinLock<'a> { /// /// Using implicit synchronization: /// -/// ``` +/// ```no_run /// use std::io::{self, Read}; /// -/// # fn foo() -> io::Result { -/// let mut buffer = String::new(); -/// io::stdin().read_to_string(&mut buffer)?; -/// # Ok(buffer) -/// # } +/// fn main() -> io::Result<()> { +/// let mut buffer = String::new(); +/// io::stdin().read_to_string(&mut buffer)?; +/// Ok(()) +/// } /// ``` /// /// Using explicit synchronization: /// -/// ``` +/// ```no_run /// use std::io::{self, Read}; /// -/// # fn foo() -> io::Result { -/// let mut buffer = String::new(); -/// let stdin = io::stdin(); -/// let mut handle = stdin.lock(); +/// fn main() -> io::Result<()> { +/// let mut buffer = String::new(); +/// let stdin = io::stdin(); +/// let mut handle = stdin.lock(); /// -/// handle.read_to_string(&mut buffer)?; -/// # Ok(buffer) -/// # } +/// handle.read_to_string(&mut buffer)?; +/// Ok(()) +/// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn stdin() -> Stdin { @@ -225,17 +225,17 @@ impl Stdin { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::io::{self, Read}; /// - /// # fn foo() -> io::Result { - /// let mut buffer = String::new(); - /// let stdin = io::stdin(); - /// let mut handle = stdin.lock(); + /// fn main() -> io::Result<()> { + /// let mut buffer = String::new(); + /// let stdin = io::stdin(); + /// let mut handle = stdin.lock(); /// - /// handle.read_to_string(&mut buffer)?; - /// # Ok(buffer) - /// # } + /// handle.read_to_string(&mut buffer)?; + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn lock(&self) -> StdinLock { @@ -369,29 +369,29 @@ pub struct StdoutLock<'a> { /// /// Using implicit synchronization: /// -/// ``` +/// ```no_run /// use std::io::{self, Write}; /// -/// # fn foo() -> io::Result<()> { -/// io::stdout().write(b"hello world")?; +/// fn main() -> io::Result<()> { +/// io::stdout().write(b"hello world")?; /// -/// # Ok(()) -/// # } +/// Ok(()) +/// } /// ``` /// /// Using explicit synchronization: /// -/// ``` +/// ```no_run /// use std::io::{self, Write}; /// -/// # fn foo() -> io::Result<()> { -/// let stdout = io::stdout(); -/// let mut handle = stdout.lock(); +/// fn main() -> io::Result<()> { +/// let stdout = io::stdout(); +/// let mut handle = stdout.lock(); /// -/// handle.write(b"hello world")?; +/// handle.write(b"hello world")?; /// -/// # Ok(()) -/// # } +/// Ok(()) +/// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn stdout() -> Stdout { @@ -419,17 +419,17 @@ impl Stdout { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::io::{self, Write}; /// - /// # fn foo() -> io::Result<()> { - /// let stdout = io::stdout(); - /// let mut handle = stdout.lock(); + /// fn main() -> io::Result<()> { + /// let stdout = io::stdout(); + /// let mut handle = stdout.lock(); /// - /// handle.write(b"hello world")?; + /// handle.write(b"hello world")?; /// - /// # Ok(()) - /// # } + /// Ok(()) + /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn lock(&self) -> StdoutLock { @@ -505,29 +505,29 @@ pub struct StderrLock<'a> { /// /// Using implicit synchronization: /// -/// ``` +/// ```no_run /// use std::io::{self, Write}; /// -/// # fn foo() -> io::Result<()> { -/// io::stderr().write(b"hello world")?; +/// fn main() -> io::Result<()> { +/// io::stderr().write(b"hello world")?; /// -/// # Ok(()) -/// # } +/// Ok(()) +/// } /// ``` /// /// Using explicit synchronization: /// -/// ``` +/// ```no_run /// use std::io::{self, Write}; /// -/// # fn foo() -> io::Result<()> { -/// let stderr = io::stderr(); -/// let mut handle = stderr.lock(); +/// fn main() -> io::Result<()> { +/// let stderr = io::stderr(); +/// let mut handle = stderr.lock(); /// -/// handle.write(b"hello world")?; +/// handle.write(b"hello world")?; /// -/// # Ok(()) -/// # } +/// Ok(()) +/// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn stderr() -> Stderr { diff --git a/src/libstd/io/util.rs b/src/libstd/io/util.rs index 45d281ee34a..195310a26fe 100644 --- a/src/libstd/io/util.rs +++ b/src/libstd/io/util.rs @@ -34,16 +34,15 @@ use mem; /// ``` /// use std::io; /// -/// # fn foo() -> io::Result<()> { -/// let mut reader: &[u8] = b"hello"; -/// let mut writer: Vec = vec![]; +/// fn main() -> io::Result<()> { +/// let mut reader: &[u8] = b"hello"; +/// let mut writer: Vec = vec![]; /// -/// io::copy(&mut reader, &mut writer)?; +/// io::copy(&mut reader, &mut writer)?; /// -/// assert_eq!(&b"hello"[..], &writer[..]); -/// # Ok(()) -/// # } -/// # foo().unwrap(); +/// assert_eq!(&b"hello"[..], &writer[..]); +/// Ok(()) +/// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn copy(reader: &mut R, writer: &mut W) -> io::Result diff --git a/src/libstd/net/mod.rs b/src/libstd/net/mod.rs index eef043683b0..b0d5e563cb9 100644 --- a/src/libstd/net/mod.rs +++ b/src/libstd/net/mod.rs @@ -175,12 +175,12 @@ impl fmt::Debug for LookupHost { /// /// use std::net; /// -/// # fn foo() -> std::io::Result<()> { -/// for host in net::lookup_host("rust-lang.org")? { -/// println!("found address: {}", host); +/// fn main() -> std::io::Result<()> { +/// for host in net::lookup_host("rust-lang.org")? { +/// println!("found address: {}", host); +/// } +/// Ok(()) /// } -/// # Ok(()) -/// # } /// ``` #[unstable(feature = "lookup_host", reason = "unsure about the returned \ iterator and returning socket \ diff --git a/src/libstd/net/tcp.rs b/src/libstd/net/tcp.rs index e28ccdb766a..0f60b5b3ee4 100644 --- a/src/libstd/net/tcp.rs +++ b/src/libstd/net/tcp.rs @@ -72,7 +72,7 @@ pub struct TcpStream(net_imp::TcpStream); /// /// # Examples /// -/// ``` +/// ```no_run /// # use std::io; /// use std::net::{TcpListener, TcpStream}; /// @@ -80,15 +80,15 @@ pub struct TcpStream(net_imp::TcpStream); /// // ... /// } /// -/// # fn process() -> io::Result<()> { -/// let listener = TcpListener::bind("127.0.0.1:80").unwrap(); +/// fn main() -> io::Result<()> { +/// let listener = TcpListener::bind("127.0.0.1:80").unwrap(); /// -/// // accept connections and process them serially -/// for stream in listener.incoming() { -/// handle_client(stream?); +/// // accept connections and process them serially +/// for stream in listener.incoming() { +/// handle_client(stream?); +/// } +/// Ok(()) /// } -/// # Ok(()) -/// # } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub struct TcpListener(net_imp::TcpListener); diff --git a/src/libstd/net/udp.rs b/src/libstd/net/udp.rs index 8e56954bea4..d25e29999cb 100644 --- a/src/libstd/net/udp.rs +++ b/src/libstd/net/udp.rs @@ -44,22 +44,22 @@ use time::Duration; /// ```no_run /// use std::net::UdpSocket; /// -/// # fn foo() -> std::io::Result<()> { -/// { -/// let mut socket = UdpSocket::bind("127.0.0.1:34254")?; +/// fn main() -> std::io::Result<()> { +/// { +/// let mut socket = UdpSocket::bind("127.0.0.1:34254")?; /// -/// // Receives a single datagram message on the socket. If `buf` is too small to hold -/// // the message, it will be cut off. -/// let mut buf = [0; 10]; -/// let (amt, src) = socket.recv_from(&mut buf)?; +/// // Receives a single datagram message on the socket. If `buf` is too small to hold +/// // the message, it will be cut off. +/// let mut buf = [0; 10]; +/// let (amt, src) = socket.recv_from(&mut buf)?; /// -/// // Redeclare `buf` as slice of the received data and send reverse data back to origin. -/// let buf = &mut buf[..amt]; -/// buf.reverse(); -/// socket.send_to(buf, &src)?; -/// # Ok(()) -/// } // the socket is closed here -/// # } +/// // Redeclare `buf` as slice of the received data and send reverse data back to origin. +/// let buf = &mut buf[..amt]; +/// buf.reverse(); +/// socket.send_to(buf, &src)?; +/// } // the socket is closed here +/// Ok(()) +/// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub struct UdpSocket(net_imp::UdpSocket); diff --git a/src/libstd/os/linux/fs.rs b/src/libstd/os/linux/fs.rs index 5d37d970e89..2be2fbcb2db 100644 --- a/src/libstd/os/linux/fs.rs +++ b/src/libstd/os/linux/fs.rs @@ -32,16 +32,16 @@ pub trait MetadataExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; + /// use std::io; /// use std::os::linux::fs::MetadataExt; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let stat = meta.as_raw_stat(); - /// # Ok(()) - /// # } + /// 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", @@ -54,16 +54,16 @@ pub trait MetadataExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; + /// use std::io; /// use std::os::linux::fs::MetadataExt; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// println!("{}", meta.st_dev()); - /// # Ok(()) - /// # } + /// 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; @@ -71,16 +71,16 @@ pub trait MetadataExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; + /// use std::io; /// use std::os::linux::fs::MetadataExt; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// println!("{}", meta.st_ino()); - /// # Ok(()) - /// # } + /// 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; @@ -88,16 +88,16 @@ pub trait MetadataExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; + /// use std::io; /// use std::os::linux::fs::MetadataExt; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// println!("{}", meta.st_mode()); - /// # Ok(()) - /// # } + /// 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; @@ -105,16 +105,16 @@ pub trait MetadataExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; + /// use std::io; /// use std::os::linux::fs::MetadataExt; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// println!("{}", meta.st_nlink()); - /// # Ok(()) - /// # } + /// 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; @@ -122,16 +122,16 @@ pub trait MetadataExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; + /// use std::io; /// use std::os::linux::fs::MetadataExt; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// println!("{}", meta.st_uid()); - /// # Ok(()) - /// # } + /// 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; @@ -139,16 +139,16 @@ pub trait MetadataExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; + /// use std::io; /// use std::os::linux::fs::MetadataExt; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// println!("{}", meta.st_gid()); - /// # Ok(()) - /// # } + /// 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; @@ -156,16 +156,16 @@ pub trait MetadataExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; + /// use std::io; /// use std::os::linux::fs::MetadataExt; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// println!("{}", meta.st_rdev()); - /// # Ok(()) - /// # } + /// 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; @@ -176,16 +176,16 @@ pub trait MetadataExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; + /// use std::io; /// use std::os::linux::fs::MetadataExt; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// println!("{}", meta.st_size()); - /// # Ok(()) - /// # } + /// 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; @@ -193,16 +193,16 @@ pub trait MetadataExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; + /// use std::io; /// use std::os::linux::fs::MetadataExt; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// println!("{}", meta.st_atime()); - /// # Ok(()) - /// # } + /// 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; @@ -210,16 +210,16 @@ pub trait MetadataExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; + /// use std::io; /// use std::os::linux::fs::MetadataExt; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// println!("{}", meta.st_atime_nsec()); - /// # Ok(()) - /// # } + /// 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; @@ -227,16 +227,16 @@ pub trait MetadataExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; + /// use std::io; /// use std::os::linux::fs::MetadataExt; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// println!("{}", meta.st_mtime()); - /// # Ok(()) - /// # } + /// 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; @@ -244,16 +244,16 @@ pub trait MetadataExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; + /// use std::io; /// use std::os::linux::fs::MetadataExt; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// println!("{}", meta.st_mtime_nsec()); - /// # Ok(()) - /// # } + /// 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; @@ -261,16 +261,16 @@ pub trait MetadataExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; + /// use std::io; /// use std::os::linux::fs::MetadataExt; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// println!("{}", meta.st_ctime()); - /// # Ok(()) - /// # } + /// 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; @@ -278,16 +278,16 @@ pub trait MetadataExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; + /// use std::io; /// use std::os::linux::fs::MetadataExt; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// println!("{}", meta.st_ctime_nsec()); - /// # Ok(()) - /// # } + /// 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; @@ -295,16 +295,16 @@ pub trait MetadataExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; + /// use std::io; /// use std::os::linux::fs::MetadataExt; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// println!("{}", meta.st_blksize()); - /// # Ok(()) - /// # } + /// 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; @@ -312,16 +312,16 @@ pub trait MetadataExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; + /// use std::io; /// use std::os::linux::fs::MetadataExt; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// println!("{}", meta.st_blocks()); - /// # Ok(()) - /// # } + /// 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; diff --git a/src/libstd/sys/redox/ext/fs.rs b/src/libstd/sys/redox/ext/fs.rs index 5d4edc2cf92..0f4762aa881 100644 --- a/src/libstd/sys/redox/ext/fs.rs +++ b/src/libstd/sys/redox/ext/fs.rs @@ -30,13 +30,14 @@ pub trait PermissionsExt { /// use std::fs::File; /// use std::os::redox::fs::PermissionsExt; /// - /// # fn run() -> std::io::Result<()> { - /// let f = File::create("foo.txt")?; - /// let metadata = f.metadata()?; - /// let permissions = metadata.permissions(); + /// fn main() -> std::io::Result<()> { + /// let f = File::create("foo.txt")?; + /// let metadata = f.metadata()?; + /// let permissions = metadata.permissions(); /// - /// println!("permissions: {}", permissions.mode()); - /// # Ok(()) } + /// println!("permissions: {}", permissions.mode()); + /// Ok(()) + /// } /// ``` #[stable(feature = "fs_ext", since = "1.1.0")] fn mode(&self) -> u32; @@ -49,14 +50,15 @@ pub trait PermissionsExt { /// use std::fs::File; /// use std::os::redox::fs::PermissionsExt; /// - /// # fn run() -> std::io::Result<()> { - /// let f = File::create("foo.txt")?; - /// let metadata = f.metadata()?; - /// let mut permissions = metadata.permissions(); + /// fn main() -> std::io::Result<()> { + /// let f = File::create("foo.txt")?; + /// let metadata = f.metadata()?; + /// let mut permissions = metadata.permissions(); /// - /// permissions.set_mode(0o644); // Read/write for owner and read for others. - /// assert_eq!(permissions.mode(), 0o644); - /// # Ok(()) } + /// permissions.set_mode(0o644); // Read/write for owner and read for others. + /// assert_eq!(permissions.mode(), 0o644); + /// Ok(()) + /// } /// ``` #[stable(feature = "fs_ext", since = "1.1.0")] fn set_mode(&mut self, mode: u32); @@ -291,13 +293,13 @@ impl FileTypeExt for fs::FileType { /// /// # Examples /// -/// ``` +/// ```no_run /// use std::os::redox::fs; /// -/// # fn foo() -> std::io::Result<()> { -/// fs::symlink("a.txt", "b.txt")?; -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// fs::symlink("a.txt", "b.txt")?; +/// Ok(()) +/// } /// ``` #[stable(feature = "symlink", since = "1.1.0")] pub fn symlink, Q: AsRef>(src: P, dst: Q) -> io::Result<()> diff --git a/src/libstd/sys/unix/ext/fs.rs b/src/libstd/sys/unix/ext/fs.rs index 2e17fd58e0a..3c5b9424fb0 100644 --- a/src/libstd/sys/unix/ext/fs.rs +++ b/src/libstd/sys/unix/ext/fs.rs @@ -41,20 +41,20 @@ pub trait FileExt { /// /// # Examples /// - /// ``` - /// use std::os::unix::prelude::FileExt; + /// ```no_run + /// use std::io; /// use std::fs::File; + /// use std::os::unix::prelude::FileExt; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let mut buf = [0u8; 8]; - /// let file = File::open("foo.txt")?; + /// fn main() -> io::Result<()> { + /// let mut buf = [0u8; 8]; + /// let file = File::open("foo.txt")?; /// - /// // We now read 8 bytes from the offset 10. - /// let num_bytes_read = file.read_at(&mut buf, 10)?; - /// println!("read {} bytes: {:?}", num_bytes_read, buf); - /// # Ok(()) - /// # } + /// // We now read 8 bytes from the offset 10. + /// let num_bytes_read = file.read_at(&mut buf, 10)?; + /// println!("read {} bytes: {:?}", num_bytes_read, buf); + /// Ok(()) + /// } /// ``` #[stable(feature = "file_offset", since = "1.15.0")] fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result; @@ -78,18 +78,18 @@ pub trait FileExt { /// /// # Examples /// - /// ``` - /// use std::os::unix::prelude::FileExt; + /// ```no_run /// use std::fs::File; + /// use std::io; + /// use std::os::unix::prelude::FileExt; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let file = File::open("foo.txt")?; + /// fn main() -> io::Result<()> { + /// let file = File::open("foo.txt")?; /// - /// // We now write at the offset 10. - /// file.write_at(b"sushi", 10)?; - /// # Ok(()) - /// # } + /// // We now write at the offset 10. + /// file.write_at(b"sushi", 10)?; + /// Ok(()) + /// } /// ``` #[stable(feature = "file_offset", since = "1.15.0")] fn write_at(&self, buf: &[u8], offset: u64) -> io::Result; @@ -117,13 +117,13 @@ pub trait PermissionsExt { /// use std::fs::File; /// use std::os::unix::fs::PermissionsExt; /// - /// # fn run() -> std::io::Result<()> { - /// let f = File::create("foo.txt")?; - /// let metadata = f.metadata()?; - /// let permissions = metadata.permissions(); + /// fn main() -> std::io::Result<()> { + /// let f = File::create("foo.txt")?; + /// let metadata = f.metadata()?; + /// let permissions = metadata.permissions(); /// - /// println!("permissions: {}", permissions.mode()); - /// # Ok(()) } + /// println!("permissions: {}", permissions.mode()); + /// Ok(()) } /// ``` #[stable(feature = "fs_ext", since = "1.1.0")] fn mode(&self) -> u32; @@ -136,14 +136,14 @@ pub trait PermissionsExt { /// use std::fs::File; /// use std::os::unix::fs::PermissionsExt; /// - /// # fn run() -> std::io::Result<()> { - /// let f = File::create("foo.txt")?; - /// let metadata = f.metadata()?; - /// let mut permissions = metadata.permissions(); + /// fn main() -> std::io::Result<()> { + /// let f = File::create("foo.txt")?; + /// let metadata = f.metadata()?; + /// let mut permissions = metadata.permissions(); /// - /// permissions.set_mode(0o644); // Read/write for owner and read for others. - /// assert_eq!(permissions.mode(), 0o644); - /// # Ok(()) } + /// permissions.set_mode(0o644); // Read/write for owner and read for others. + /// assert_eq!(permissions.mode(), 0o644); + /// Ok(()) } /// ``` #[stable(feature = "fs_ext", since = "1.1.0")] fn set_mode(&mut self, mode: u32); @@ -260,15 +260,15 @@ pub trait MetadataExt { /// # Examples /// /// ```no_run + /// use std::io; /// use std::fs; /// use std::os::unix::fs::MetadataExt; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let dev_id = meta.dev(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let dev_id = meta.dev(); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn dev(&self) -> u64; @@ -279,13 +279,13 @@ pub trait MetadataExt { /// ```no_run /// use std::fs; /// use std::os::unix::fs::MetadataExt; + /// use std::io; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let inode = meta.ino(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let inode = meta.ino(); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn ino(&self) -> u64; @@ -296,17 +296,17 @@ pub trait MetadataExt { /// ```no_run /// use std::fs; /// use std::os::unix::fs::MetadataExt; - /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let mode = meta.mode(); - /// let user_has_write_access = mode & 0o200; - /// let user_has_read_write_access = mode & 0o600; - /// let group_has_read_access = mode & 0o040; - /// let others_have_exec_access = mode & 0o001; - /// # Ok(()) - /// # } + /// use std::io; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let mode = meta.mode(); + /// let user_has_write_access = mode & 0o200; + /// let user_has_read_write_access = mode & 0o600; + /// let group_has_read_access = mode & 0o040; + /// let others_have_exec_access = mode & 0o001; + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn mode(&self) -> u32; @@ -317,13 +317,13 @@ pub trait MetadataExt { /// ```no_run /// use std::fs; /// use std::os::unix::fs::MetadataExt; + /// use std::io; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let nb_hard_links = meta.nlink(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let nb_hard_links = meta.nlink(); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn nlink(&self) -> u64; @@ -334,13 +334,13 @@ pub trait MetadataExt { /// ```no_run /// use std::fs; /// use std::os::unix::fs::MetadataExt; + /// use std::io; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let user_id = meta.uid(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let user_id = meta.uid(); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn uid(&self) -> u32; @@ -351,13 +351,13 @@ pub trait MetadataExt { /// ```no_run /// use std::fs; /// use std::os::unix::fs::MetadataExt; + /// use std::io; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let group_id = meta.gid(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let group_id = meta.gid(); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn gid(&self) -> u32; @@ -368,13 +368,13 @@ pub trait MetadataExt { /// ```no_run /// use std::fs; /// use std::os::unix::fs::MetadataExt; + /// use std::io; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let device_id = meta.rdev(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let device_id = meta.rdev(); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn rdev(&self) -> u64; @@ -385,13 +385,13 @@ pub trait MetadataExt { /// ```no_run /// use std::fs; /// use std::os::unix::fs::MetadataExt; + /// use std::io; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let file_size = meta.size(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let file_size = meta.size(); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn size(&self) -> u64; @@ -402,13 +402,13 @@ pub trait MetadataExt { /// ```no_run /// use std::fs; /// use std::os::unix::fs::MetadataExt; + /// use std::io; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let last_access_time = meta.atime(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let last_access_time = meta.atime(); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn atime(&self) -> i64; @@ -419,13 +419,13 @@ pub trait MetadataExt { /// ```no_run /// use std::fs; /// use std::os::unix::fs::MetadataExt; + /// use std::io; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let nano_last_access_time = meta.atime_nsec(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let nano_last_access_time = meta.atime_nsec(); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn atime_nsec(&self) -> i64; @@ -436,13 +436,13 @@ pub trait MetadataExt { /// ```no_run /// use std::fs; /// use std::os::unix::fs::MetadataExt; + /// use std::io; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let last_modification_time = meta.mtime(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let last_modification_time = meta.mtime(); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn mtime(&self) -> i64; @@ -453,13 +453,13 @@ pub trait MetadataExt { /// ```no_run /// use std::fs; /// use std::os::unix::fs::MetadataExt; + /// use std::io; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let nano_last_modification_time = meta.mtime_nsec(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let nano_last_modification_time = meta.mtime_nsec(); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn mtime_nsec(&self) -> i64; @@ -470,13 +470,13 @@ pub trait MetadataExt { /// ```no_run /// use std::fs; /// use std::os::unix::fs::MetadataExt; + /// use std::io; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let last_status_change_time = meta.ctime(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let last_status_change_time = meta.ctime(); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn ctime(&self) -> i64; @@ -487,13 +487,13 @@ pub trait MetadataExt { /// ```no_run /// use std::fs; /// use std::os::unix::fs::MetadataExt; + /// use std::io; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let nano_last_status_change_time = meta.ctime_nsec(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let nano_last_status_change_time = meta.ctime_nsec(); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn ctime_nsec(&self) -> i64; @@ -504,13 +504,13 @@ pub trait MetadataExt { /// ```no_run /// use std::fs; /// use std::os::unix::fs::MetadataExt; + /// use std::io; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let blocksize = meta.blksize(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let blocksize = meta.blksize(); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn blksize(&self) -> u64; @@ -523,13 +523,13 @@ pub trait MetadataExt { /// ```no_run /// use std::fs; /// use std::os::unix::fs::MetadataExt; + /// use std::io; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let blocks = meta.blocks(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let blocks = meta.blocks(); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn blocks(&self) -> u64; @@ -562,17 +562,17 @@ pub trait FileTypeExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; /// use std::os::unix::fs::FileTypeExt; + /// use std::io; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("block_device_file")?; - /// let file_type = meta.file_type(); - /// assert!(file_type.is_block_device()); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("block_device_file")?; + /// let file_type = meta.file_type(); + /// assert!(file_type.is_block_device()); + /// Ok(()) + /// } /// ``` #[stable(feature = "file_type_ext", since = "1.5.0")] fn is_block_device(&self) -> bool; @@ -580,17 +580,17 @@ pub trait FileTypeExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; /// use std::os::unix::fs::FileTypeExt; + /// use std::io; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("char_device_file")?; - /// let file_type = meta.file_type(); - /// assert!(file_type.is_char_device()); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("char_device_file")?; + /// let file_type = meta.file_type(); + /// assert!(file_type.is_char_device()); + /// Ok(()) + /// } /// ``` #[stable(feature = "file_type_ext", since = "1.5.0")] fn is_char_device(&self) -> bool; @@ -598,17 +598,17 @@ pub trait FileTypeExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; /// use std::os::unix::fs::FileTypeExt; + /// use std::io; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("fifo_file")?; - /// let file_type = meta.file_type(); - /// assert!(file_type.is_fifo()); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("fifo_file")?; + /// let file_type = meta.file_type(); + /// assert!(file_type.is_fifo()); + /// Ok(()) + /// } /// ``` #[stable(feature = "file_type_ext", since = "1.5.0")] fn is_fifo(&self) -> bool; @@ -616,17 +616,17 @@ pub trait FileTypeExt { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::fs; /// use std::os::unix::fs::FileTypeExt; + /// use std::io; /// - /// # use std::io; - /// # fn f() -> io::Result<()> { - /// let meta = fs::metadata("unix.socket")?; - /// let file_type = meta.file_type(); - /// assert!(file_type.is_socket()); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("unix.socket")?; + /// let file_type = meta.file_type(); + /// assert!(file_type.is_socket()); + /// Ok(()) + /// } /// ``` #[stable(feature = "file_type_ext", since = "1.5.0")] fn is_socket(&self) -> bool; @@ -687,13 +687,13 @@ impl DirEntryExt for fs::DirEntry { /// /// # Examples /// -/// ``` +/// ```no_run /// use std::os::unix::fs; /// -/// # fn foo() -> std::io::Result<()> { -/// fs::symlink("a.txt", "b.txt")?; -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// fs::symlink("a.txt", "b.txt")?; +/// Ok(()) +/// } /// ``` #[stable(feature = "symlink", since = "1.1.0")] pub fn symlink, Q: AsRef>(src: P, dst: Q) -> io::Result<()> diff --git a/src/libstd/sys/windows/ext/fs.rs b/src/libstd/sys/windows/ext/fs.rs index 38bf4cca851..e5cd51b6550 100644 --- a/src/libstd/sys/windows/ext/fs.rs +++ b/src/libstd/sys/windows/ext/fs.rs @@ -45,15 +45,15 @@ pub trait FileExt { /// use std::fs::File; /// use std::os::windows::prelude::*; /// - /// # fn foo() -> io::Result<()> { - /// let mut file = File::open("foo.txt")?; - /// let mut buffer = [0; 10]; - /// - /// // Read 10 bytes, starting 72 bytes from the - /// // start of the file. - /// file.seek_read(&mut buffer[..], 72)?; - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let mut file = File::open("foo.txt")?; + /// let mut buffer = [0; 10]; + /// + /// // Read 10 bytes, starting 72 bytes from the + /// // start of the file. + /// file.seek_read(&mut buffer[..], 72)?; + /// Ok(()) + /// } /// ``` #[stable(feature = "file_offset", since = "1.15.0")] fn seek_read(&self, buf: &mut [u8], offset: u64) -> io::Result; @@ -79,14 +79,14 @@ pub trait FileExt { /// use std::fs::File; /// use std::os::windows::prelude::*; /// - /// # fn foo() -> std::io::Result<()> { - /// let mut buffer = File::create("foo.txt")?; + /// fn main() -> std::io::Result<()> { + /// let mut buffer = File::create("foo.txt")?; /// - /// // Write a byte string starting 72 bytes from - /// // the start of the file. - /// buffer.seek_write(b"some bytes", 72)?; - /// # Ok(()) - /// # } + /// // Write a byte string starting 72 bytes from + /// // the start of the file. + /// buffer.seek_write(b"some bytes", 72)?; + /// Ok(()) + /// } /// ``` #[stable(feature = "file_offset", since = "1.15.0")] fn seek_write(&self, buf: &[u8], offset: u64) -> io::Result; @@ -305,11 +305,11 @@ pub trait MetadataExt { /// use std::fs; /// use std::os::windows::prelude::*; /// - /// # fn foo() -> io::Result<()> { - /// let metadata = fs::metadata("foo.txt")?; - /// let attributes = metadata.file_attributes(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let metadata = fs::metadata("foo.txt")?; + /// let attributes = metadata.file_attributes(); + /// Ok(()) + /// } /// ``` /// /// [File Attribute Constants]: @@ -335,11 +335,11 @@ pub trait MetadataExt { /// use std::fs; /// use std::os::windows::prelude::*; /// - /// # fn foo() -> io::Result<()> { - /// let metadata = fs::metadata("foo.txt")?; - /// let creation_time = metadata.creation_time(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let metadata = fs::metadata("foo.txt")?; + /// let creation_time = metadata.creation_time(); + /// Ok(()) + /// } /// ``` /// /// [`FILETIME`]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724284.aspx @@ -370,11 +370,11 @@ pub trait MetadataExt { /// use std::fs; /// use std::os::windows::prelude::*; /// - /// # fn foo() -> io::Result<()> { - /// let metadata = fs::metadata("foo.txt")?; - /// let last_access_time = metadata.last_access_time(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let metadata = fs::metadata("foo.txt")?; + /// let last_access_time = metadata.last_access_time(); + /// Ok(()) + /// } /// ``` /// /// [`FILETIME`]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724284.aspx @@ -403,11 +403,11 @@ pub trait MetadataExt { /// use std::fs; /// use std::os::windows::prelude::*; /// - /// # fn foo() -> io::Result<()> { - /// let metadata = fs::metadata("foo.txt")?; - /// let last_write_time = metadata.last_write_time(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let metadata = fs::metadata("foo.txt")?; + /// let last_write_time = metadata.last_write_time(); + /// Ok(()) + /// } /// ``` /// /// [`FILETIME`]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724284.aspx @@ -426,11 +426,11 @@ pub trait MetadataExt { /// use std::fs; /// use std::os::windows::prelude::*; /// - /// # fn foo() -> io::Result<()> { - /// let metadata = fs::metadata("foo.txt")?; - /// let file_size = metadata.file_size(); - /// # Ok(()) - /// # } + /// fn main() -> io::Result<()> { + /// let metadata = fs::metadata("foo.txt")?; + /// let file_size = metadata.file_size(); + /// Ok(()) + /// } /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] fn file_size(&self) -> u64; @@ -473,10 +473,10 @@ impl FileTypeExt for fs::FileType { /// ```no_run /// use std::os::windows::fs; /// -/// # fn foo() -> std::io::Result<()> { -/// fs::symlink_file("a.txt", "b.txt")?; -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// fs::symlink_file("a.txt", "b.txt")?; +/// Ok(()) +/// } /// ``` #[stable(feature = "symlink", since = "1.1.0")] pub fn symlink_file, Q: AsRef>(src: P, dst: Q) @@ -494,10 +494,10 @@ pub fn symlink_file, Q: AsRef>(src: P, dst: Q) /// ```no_run /// use std::os::windows::fs; /// -/// # fn foo() -> std::io::Result<()> { -/// fs::symlink_dir("a", "b")?; -/// # Ok(()) -/// # } +/// fn main() -> std::io::Result<()> { +/// fs::symlink_dir("a", "b")?; +/// Ok(()) +/// } /// ``` #[stable(feature = "symlink", since = "1.1.0")] pub fn symlink_dir, Q: AsRef>(src: P, dst: Q) -- cgit 1.4.1-3-g733a5 From 4577da75f4badd66a337eb15da76ca836ab1ad6e Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Wed, 4 Apr 2018 19:30:46 +0900 Subject: Use box syntax instead of Box::new in Mutex::remutex on Windows The Box::new(mem::uninitialized()) pattern actually actively copies uninitialized bytes from the stack into the box, which is a waste of time. Using the box syntax instead avoids the useless copy. --- src/libstd/sys/windows/mutex.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/libstd/sys/windows') diff --git a/src/libstd/sys/windows/mutex.rs b/src/libstd/sys/windows/mutex.rs index 85560368590..9bf9f749d4d 100644 --- a/src/libstd/sys/windows/mutex.rs +++ b/src/libstd/sys/windows/mutex.rs @@ -117,7 +117,7 @@ impl Mutex { 0 => {} n => return n as *mut _, } - let mut re = Box::new(ReentrantMutex::uninitialized()); + let mut re = box ReentrantMutex::uninitialized(); re.init(); let re = Box::into_raw(re); match self.lock.compare_and_swap(0, re as usize, Ordering::SeqCst) { -- cgit 1.4.1-3-g733a5 From 64ddb390efb2143f11c1583d52c78da5a290e097 Mon Sep 17 00:00:00 2001 From: memoryleak47 Date: Thu, 5 Apr 2018 13:04:00 +0200 Subject: typos --- src/libstd/lib.rs | 2 +- src/libstd/panic.rs | 2 +- src/libstd/sys/windows/pipe.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/libstd/sys/windows') diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 36eb7291822..67ef47569d6 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -380,7 +380,7 @@ extern crate compiler_builtins; // During testing, this crate is not actually the "real" std library, but rather // it links to the real std library, which was compiled from this same source // code. So any lang items std defines are conditionally excluded (or else they -// wolud generate duplicate lang item errors), and any globals it defines are +// would generate duplicate lang item errors), and any globals it defines are // _not_ the globals used by "real" std. So this import, defined only during // testing gives test-std access to real-std lang items and globals. See #2912 #[cfg(test)] extern crate std as realstd; diff --git a/src/libstd/panic.rs b/src/libstd/panic.rs index 79857104b9b..28c178307a5 100644 --- a/src/libstd/panic.rs +++ b/src/libstd/panic.rs @@ -188,7 +188,7 @@ pub struct AssertUnwindSafe( // * By default everything is unwind safe // * pointers T contains mutability of some form are not unwind safe // * Unique, an owning pointer, lifts an implementation -// * Types like Mutex/RwLock which are explicilty poisoned are unwind safe +// * Types like Mutex/RwLock which are explicitly poisoned are unwind safe // * Our custom AssertUnwindSafe wrapper is indeed unwind safe #[stable(feature = "catch_unwind", since = "1.9.0")] diff --git a/src/libstd/sys/windows/pipe.rs b/src/libstd/sys/windows/pipe.rs index f3b1185c6ea..df1dd7401af 100644 --- a/src/libstd/sys/windows/pipe.rs +++ b/src/libstd/sys/windows/pipe.rs @@ -236,7 +236,7 @@ enum State { impl<'a> AsyncPipe<'a> { fn new(pipe: Handle, dst: &'a mut Vec) -> io::Result> { // Create an event which we'll use to coordinate our overlapped - // opreations, this event will be used in WaitForMultipleObjects + // operations, this event will be used in WaitForMultipleObjects // and passed as part of the OVERLAPPED handle. // // Note that we do a somewhat clever thing here by flagging the -- cgit 1.4.1-3-g733a5 From 323f8087910b0d63815003970bb8a45e3ccfdb17 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 5 Apr 2018 11:07:19 -0700 Subject: std: Inline some Termination-related methods These were showing up in tests and in binaries but are trivially optimize-able away, so add `#[inline]` attributes so LLVM has an opportunity to optimize them out. --- src/libstd/process.rs | 2 ++ src/libstd/sys/unix/process/process_common.rs | 1 + src/libstd/sys/windows/process.rs | 1 + 3 files changed, 4 insertions(+) (limited to 'src/libstd/sys/windows') diff --git a/src/libstd/process.rs b/src/libstd/process.rs index 40bc84f4bc1..92f0406c09b 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -1452,6 +1452,7 @@ pub trait Termination { #[unstable(feature = "termination_trait_lib", issue = "43301")] impl Termination for () { + #[inline] fn report(self) -> i32 { ExitCode::SUCCESS.report() } } @@ -1481,6 +1482,7 @@ impl Termination for Result { #[unstable(feature = "termination_trait_lib", issue = "43301")] impl Termination for ExitCode { + #[inline] fn report(self) -> i32 { self.0.as_i32() } diff --git a/src/libstd/sys/unix/process/process_common.rs b/src/libstd/sys/unix/process/process_common.rs index b7f30600b8a..6396bb3a49e 100644 --- a/src/libstd/sys/unix/process/process_common.rs +++ b/src/libstd/sys/unix/process/process_common.rs @@ -404,6 +404,7 @@ impl ExitCode { pub const SUCCESS: ExitCode = ExitCode(EXIT_SUCCESS as _); pub const FAILURE: ExitCode = ExitCode(EXIT_FAILURE as _); + #[inline] pub fn as_i32(&self) -> i32 { self.0 as i32 } diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs index afa8e3e1369..bd5507e8f89 100644 --- a/src/libstd/sys/windows/process.rs +++ b/src/libstd/sys/windows/process.rs @@ -414,6 +414,7 @@ impl ExitCode { pub const SUCCESS: ExitCode = ExitCode(EXIT_SUCCESS as _); pub const FAILURE: ExitCode = ExitCode(EXIT_FAILURE as _); + #[inline] pub fn as_i32(&self) -> i32 { self.0 as i32 } -- cgit 1.4.1-3-g733a5 From 1b895d8b88413f72230fbc0f00c67328870a2e9a Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Tue, 3 Apr 2018 14:36:57 +0200 Subject: Import the `alloc` crate as `alloc_crate` in std MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit … to make the name `alloc` available. --- src/libstd/collections/hash/map.rs | 4 +--- src/libstd/collections/hash/table.rs | 5 +---- src/libstd/collections/mod.rs | 10 +++++----- src/libstd/error.rs | 10 +++++----- src/libstd/heap.rs | 2 +- src/libstd/lib.rs | 18 +++++++++--------- src/libstd/sync/mod.rs | 2 +- src/libstd/sync/mpsc/mpsc_queue.rs | 3 +-- src/libstd/sync/mpsc/spsc_queue.rs | 2 +- src/libstd/sys/cloudabi/thread.rs | 2 +- src/libstd/sys/redox/thread.rs | 2 +- src/libstd/sys/unix/thread.rs | 2 +- src/libstd/sys/wasm/thread.rs | 2 +- src/libstd/sys/windows/process.rs | 2 +- src/libstd/sys/windows/thread.rs | 2 +- src/libstd/sys_common/at_exit_imp.rs | 2 +- src/libstd/sys_common/process.rs | 2 +- src/libstd/sys_common/thread.rs | 2 +- 18 files changed, 34 insertions(+), 40 deletions(-) (limited to 'src/libstd/sys/windows') diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index e0b48e565d0..73a5df8dc28 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -11,15 +11,13 @@ use self::Entry::*; use self::VacantEntryState::*; -use alloc::heap::Heap; -use alloc::allocator::CollectionAllocErr; use cell::Cell; -use core::heap::Alloc; use borrow::Borrow; use cmp::max; use fmt::{self, Debug}; #[allow(deprecated)] use hash::{Hash, Hasher, BuildHasher, SipHasher13}; +use heap::{Heap, Alloc, CollectionAllocErr}; use iter::{FromIterator, FusedIterator}; use mem::{self, replace}; use ops::{Deref, Index}; diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs index fa6053d3f6d..878cd82a258 100644 --- a/src/libstd/collections/hash/table.rs +++ b/src/libstd/collections/hash/table.rs @@ -8,17 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use alloc::heap::Heap; -use core::heap::{Alloc, Layout}; - use cmp; use hash::{BuildHasher, Hash, Hasher}; +use heap::{Heap, Alloc, Layout, CollectionAllocErr}; use marker; use mem::{align_of, size_of, needs_drop}; use mem; use ops::{Deref, DerefMut}; use ptr::{self, Unique, NonNull}; -use alloc::allocator::CollectionAllocErr; use self::BucketState::*; diff --git a/src/libstd/collections/mod.rs b/src/libstd/collections/mod.rs index c7ad27d8d26..9cf73824dea 100644 --- a/src/libstd/collections/mod.rs +++ b/src/libstd/collections/mod.rs @@ -424,13 +424,13 @@ #[doc(hidden)] pub use ops::Bound; #[stable(feature = "rust1", since = "1.0.0")] -pub use alloc::{BinaryHeap, BTreeMap, BTreeSet}; +pub use alloc_crate::{BinaryHeap, BTreeMap, BTreeSet}; #[stable(feature = "rust1", since = "1.0.0")] -pub use alloc::{LinkedList, VecDeque}; +pub use alloc_crate::{LinkedList, VecDeque}; #[stable(feature = "rust1", since = "1.0.0")] -pub use alloc::{binary_heap, btree_map, btree_set}; +pub use alloc_crate::{binary_heap, btree_map, btree_set}; #[stable(feature = "rust1", since = "1.0.0")] -pub use alloc::{linked_list, vec_deque}; +pub use alloc_crate::{linked_list, vec_deque}; #[stable(feature = "rust1", since = "1.0.0")] pub use self::hash_map::HashMap; @@ -446,7 +446,7 @@ pub mod range { } #[unstable(feature = "try_reserve", reason = "new API", issue="48043")] -pub use alloc::allocator::CollectionAllocErr; +pub use heap::CollectionAllocErr; mod hash; diff --git a/src/libstd/error.rs b/src/libstd/error.rs index 3d0c96585b5..4edb897350e 100644 --- a/src/libstd/error.rs +++ b/src/libstd/error.rs @@ -51,13 +51,13 @@ // coherence challenge (e.g., specialization, neg impls, etc) we can // reconsider what crate these items belong in. -use alloc::allocator; use any::TypeId; use borrow::Cow; use cell; use char; use core::array; use fmt::{self, Debug, Display}; +use heap::{AllocErr, CannotReallocInPlace}; use mem::transmute; use num; use str; @@ -241,18 +241,18 @@ impl Error for ! { #[unstable(feature = "allocator_api", reason = "the precise API and guarantees it provides may be tweaked.", issue = "32838")] -impl Error for allocator::AllocErr { +impl Error for AllocErr { fn description(&self) -> &str { - allocator::AllocErr::description(self) + AllocErr::description(self) } } #[unstable(feature = "allocator_api", reason = "the precise API and guarantees it provides may be tweaked.", issue = "32838")] -impl Error for allocator::CannotReallocInPlace { +impl Error for CannotReallocInPlace { fn description(&self) -> &str { - allocator::CannotReallocInPlace::description(self) + CannotReallocInPlace::description(self) } } diff --git a/src/libstd/heap.rs b/src/libstd/heap.rs index 2cf06018087..b42a1052c49 100644 --- a/src/libstd/heap.rs +++ b/src/libstd/heap.rs @@ -12,7 +12,7 @@ #![unstable(issue = "32838", feature = "allocator_api")] -pub use alloc::heap::Heap; +pub use alloc_crate::heap::Heap; pub use alloc_system::System; #[doc(inline)] pub use core::heap::*; diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index c82d600e4a1..ef4205e7a62 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -351,7 +351,7 @@ extern crate core as __core; #[macro_use] #[macro_reexport(vec, format)] -extern crate alloc; +extern crate alloc as alloc_crate; extern crate alloc_system; #[doc(masked)] extern crate libc; @@ -437,21 +437,21 @@ pub use core::u32; #[stable(feature = "rust1", since = "1.0.0")] pub use core::u64; #[stable(feature = "rust1", since = "1.0.0")] -pub use alloc::boxed; +pub use alloc_crate::boxed; #[stable(feature = "rust1", since = "1.0.0")] -pub use alloc::rc; +pub use alloc_crate::rc; #[stable(feature = "rust1", since = "1.0.0")] -pub use alloc::borrow; +pub use alloc_crate::borrow; #[stable(feature = "rust1", since = "1.0.0")] -pub use alloc::fmt; +pub use alloc_crate::fmt; #[stable(feature = "rust1", since = "1.0.0")] -pub use alloc::slice; +pub use alloc_crate::slice; #[stable(feature = "rust1", since = "1.0.0")] -pub use alloc::str; +pub use alloc_crate::str; #[stable(feature = "rust1", since = "1.0.0")] -pub use alloc::string; +pub use alloc_crate::string; #[stable(feature = "rust1", since = "1.0.0")] -pub use alloc::vec; +pub use alloc_crate::vec; #[stable(feature = "rust1", since = "1.0.0")] pub use core::char; #[stable(feature = "i128", since = "1.26.0")] diff --git a/src/libstd/sync/mod.rs b/src/libstd/sync/mod.rs index 289b47b3484..642b284c6c7 100644 --- a/src/libstd/sync/mod.rs +++ b/src/libstd/sync/mod.rs @@ -18,7 +18,7 @@ #![stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")] -pub use alloc::arc::{Arc, Weak}; +pub use alloc_crate::arc::{Arc, Weak}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::sync::atomic; diff --git a/src/libstd/sync/mpsc/mpsc_queue.rs b/src/libstd/sync/mpsc/mpsc_queue.rs index 296773d20f6..df945ac3859 100644 --- a/src/libstd/sync/mpsc/mpsc_queue.rs +++ b/src/libstd/sync/mpsc/mpsc_queue.rs @@ -23,10 +23,9 @@ pub use self::PopResult::*; -use alloc::boxed::Box; use core::ptr; use core::cell::UnsafeCell; - +use boxed::Box; use sync::atomic::{AtomicPtr, Ordering}; /// A result of the `pop` function. diff --git a/src/libstd/sync/mpsc/spsc_queue.rs b/src/libstd/sync/mpsc/spsc_queue.rs index cc4be92276a..9482f6958b3 100644 --- a/src/libstd/sync/mpsc/spsc_queue.rs +++ b/src/libstd/sync/mpsc/spsc_queue.rs @@ -16,7 +16,7 @@ // http://www.1024cores.net/home/lock-free-algorithms/queues/unbounded-spsc-queue -use alloc::boxed::Box; +use boxed::Box; use core::ptr; use core::cell::UnsafeCell; diff --git a/src/libstd/sys/cloudabi/thread.rs b/src/libstd/sys/cloudabi/thread.rs index a22d9053b69..5d66936b2a4 100644 --- a/src/libstd/sys/cloudabi/thread.rs +++ b/src/libstd/sys/cloudabi/thread.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use alloc::boxed::FnBox; +use boxed::FnBox; use cmp; use ffi::CStr; use io; diff --git a/src/libstd/sys/redox/thread.rs b/src/libstd/sys/redox/thread.rs index f20350269b7..110d46ca3ab 100644 --- a/src/libstd/sys/redox/thread.rs +++ b/src/libstd/sys/redox/thread.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use alloc::boxed::FnBox; +use boxed::FnBox; use ffi::CStr; use io; use mem; diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs index 2db3d4a5744..9e388808030 100644 --- a/src/libstd/sys/unix/thread.rs +++ b/src/libstd/sys/unix/thread.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use alloc::boxed::FnBox; +use boxed::FnBox; use cmp; use ffi::CStr; use io; diff --git a/src/libstd/sys/wasm/thread.rs b/src/libstd/sys/wasm/thread.rs index 7345843b975..728e678a2e8 100644 --- a/src/libstd/sys/wasm/thread.rs +++ b/src/libstd/sys/wasm/thread.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use alloc::boxed::FnBox; +use boxed::FnBox; use ffi::CStr; use io; use sys::{unsupported, Void}; diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs index bd5507e8f89..be442f41374 100644 --- a/src/libstd/sys/windows/process.rs +++ b/src/libstd/sys/windows/process.rs @@ -31,7 +31,7 @@ use sys::stdio; use sys::cvt; use sys_common::{AsInner, FromInner, IntoInner}; use sys_common::process::{CommandEnv, EnvKey}; -use alloc::borrow::Borrow; +use borrow::Borrow; //////////////////////////////////////////////////////////////////////////////// // Command diff --git a/src/libstd/sys/windows/thread.rs b/src/libstd/sys/windows/thread.rs index 4b3d1b586b5..b6f63303dc2 100644 --- a/src/libstd/sys/windows/thread.rs +++ b/src/libstd/sys/windows/thread.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use alloc::boxed::FnBox; +use boxed::FnBox; use io; use ffi::CStr; use mem; diff --git a/src/libstd/sys_common/at_exit_imp.rs b/src/libstd/sys_common/at_exit_imp.rs index ce6fd4cb075..26da51c9825 100644 --- a/src/libstd/sys_common/at_exit_imp.rs +++ b/src/libstd/sys_common/at_exit_imp.rs @@ -12,7 +12,7 @@ //! //! Documentation can be found on the `rt::at_exit` function. -use alloc::boxed::FnBox; +use boxed::FnBox; use ptr; use sys_common::mutex::Mutex; diff --git a/src/libstd/sys_common/process.rs b/src/libstd/sys_common/process.rs index d0c5951bd6c..ddf0ebe603e 100644 --- a/src/libstd/sys_common/process.rs +++ b/src/libstd/sys_common/process.rs @@ -14,7 +14,7 @@ use ffi::{OsStr, OsString}; use env; use collections::BTreeMap; -use alloc::borrow::Borrow; +use borrow::Borrow; pub trait EnvKey: From + Into + diff --git a/src/libstd/sys_common/thread.rs b/src/libstd/sys_common/thread.rs index f1379b6ec63..da6f58ef6bb 100644 --- a/src/libstd/sys_common/thread.rs +++ b/src/libstd/sys_common/thread.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use alloc::boxed::FnBox; +use boxed::FnBox; use env; use sync::atomic::{self, Ordering}; use sys::stack_overflow; -- cgit 1.4.1-3-g733a5 From c3a5d6b130e27d7d7587f56581247d5b08c38594 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 29 Mar 2018 14:59:13 -0700 Subject: std: Minimize size of panicking on wasm This commit applies a few code size optimizations for the wasm target to the standard library, namely around panics. We notably know that in most configurations it's impossible for us to print anything in wasm32-unknown-unknown so we can skip larger portions of panicking that are otherwise simply informative. This allows us to get quite a nice size reduction. Finally we can also tweak where the allocation happens for the `Box` that we panic with. By only allocating once unwinding starts we can reduce the size of a panicking wasm module from 44k to 350 bytes. --- src/ci/docker/wasm32-unknown/Dockerfile | 6 ++ src/libcore/panic.rs | 10 ++++ src/libpanic_abort/lib.rs | 2 +- src/libpanic_unwind/lib.rs | 12 ++-- src/libstd/lib.rs | 1 + src/libstd/panicking.rs | 88 ++++++++++++++++++++++------- src/libstd/sys/cloudabi/stdio.rs | 4 ++ src/libstd/sys/redox/stdio.rs | 4 ++ src/libstd/sys/unix/stdio.rs | 4 ++ src/libstd/sys/wasm/rwlock.rs | 4 +- src/libstd/sys/wasm/stdio.rs | 4 ++ src/libstd/sys/windows/stdio.rs | 4 ++ src/libstd/sys_common/backtrace.rs | 13 ++--- src/libstd/sys_common/mod.rs | 14 +++-- src/libstd/sys_common/thread_local.rs | 4 +- src/libstd/sys_common/util.rs | 5 +- src/libstd/thread/local.rs | 41 +++++++++++++- src/libstd/thread/mod.rs | 3 + src/test/run-make/wasm-panic-small/Makefile | 11 ++++ src/test/run-make/wasm-panic-small/foo.rs | 16 ++++++ 20 files changed, 205 insertions(+), 45 deletions(-) create mode 100644 src/test/run-make/wasm-panic-small/Makefile create mode 100644 src/test/run-make/wasm-panic-small/foo.rs (limited to 'src/libstd/sys/windows') diff --git a/src/ci/docker/wasm32-unknown/Dockerfile b/src/ci/docker/wasm32-unknown/Dockerfile index 853923ad947..56eda548071 100644 --- a/src/ci/docker/wasm32-unknown/Dockerfile +++ b/src/ci/docker/wasm32-unknown/Dockerfile @@ -25,6 +25,12 @@ ENV RUST_CONFIGURE_ARGS \ --set build.nodejs=/node-v9.2.0-linux-x64/bin/node \ --set rust.lld +# Some run-make tests have assertions about code size, and enabling debug +# assertions in libstd causes the binary to be much bigger than it would +# otherwise normally be. We already test libstd with debug assertions in lots of +# other contexts as well +ENV NO_DEBUG_ASSERTIONS=1 + ENV SCRIPT python2.7 /checkout/x.py test --target $TARGETS \ src/test/run-make \ src/test/ui \ diff --git a/src/libcore/panic.rs b/src/libcore/panic.rs index 1720c9d8c60..37c79f2fafe 100644 --- a/src/libcore/panic.rs +++ b/src/libcore/panic.rs @@ -251,3 +251,13 @@ impl<'a> fmt::Display for Location<'a> { write!(formatter, "{}:{}:{}", self.file, self.line, self.col) } } + +/// An internal trait used by libstd to pass data from libstd to `panic_unwind` +/// and other panic runtimes. Not intended to be stabilized any time soon, do +/// not use. +#[unstable(feature = "std_internals", issue = "0")] +#[doc(hidden)] +pub unsafe trait BoxMeUp { + fn box_me_up(&mut self) -> *mut (Any + Send); + fn get(&self) -> &(Any + Send); +} diff --git a/src/libpanic_abort/lib.rs b/src/libpanic_abort/lib.rs index 43c5bbbc618..392bf17968f 100644 --- a/src/libpanic_abort/lib.rs +++ b/src/libpanic_abort/lib.rs @@ -52,7 +52,7 @@ pub unsafe extern fn __rust_maybe_catch_panic(f: fn(*mut u8), // now hopefully. #[no_mangle] #[rustc_std_internal_symbol] -pub unsafe extern fn __rust_start_panic(_data: usize, _vtable: usize) -> u32 { +pub unsafe extern fn __rust_start_panic(_payload: usize) -> u32 { abort(); #[cfg(any(unix, target_os = "cloudabi"))] diff --git a/src/libpanic_unwind/lib.rs b/src/libpanic_unwind/lib.rs index 9321d6917d1..6c52c0fa10c 100644 --- a/src/libpanic_unwind/lib.rs +++ b/src/libpanic_unwind/lib.rs @@ -29,6 +29,7 @@ html_root_url = "https://doc.rust-lang.org/nightly/", issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/")] +#![feature(allocator_api)] #![feature(alloc)] #![feature(core_intrinsics)] #![feature(lang_items)] @@ -36,6 +37,7 @@ #![feature(panic_unwind)] #![feature(raw)] #![feature(staged_api)] +#![feature(std_internals)] #![feature(unwind_attributes)] #![cfg_attr(target_env = "msvc", feature(raw))] @@ -47,9 +49,11 @@ extern crate libc; #[cfg(not(any(target_env = "msvc", all(windows, target_arch = "x86_64", target_env = "gnu"))))] extern crate unwind; +use alloc::boxed::Box; use core::intrinsics; use core::mem; use core::raw; +use core::panic::BoxMeUp; // Rust runtime's startup objects depend on these symbols, so make them public. #[cfg(all(target_os="windows", target_arch = "x86", target_env="gnu"))] @@ -112,9 +116,7 @@ pub unsafe extern "C" fn __rust_maybe_catch_panic(f: fn(*mut u8), // implementation. #[no_mangle] #[unwind(allowed)] -pub unsafe extern "C" fn __rust_start_panic(data: usize, vtable: usize) -> u32 { - imp::panic(mem::transmute(raw::TraitObject { - data: data as *mut (), - vtable: vtable as *mut (), - })) +pub unsafe extern "C" fn __rust_start_panic(payload: usize) -> u32 { + let payload = payload as *mut &mut BoxMeUp; + imp::panic(Box::from_raw((*payload).box_me_up())) } diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index a34fcb5a7f9..dd96c57538c 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -292,6 +292,7 @@ #![feature(rand)] #![feature(raw)] #![feature(rustc_attrs)] +#![feature(std_internals)] #![feature(stdsimd)] #![feature(shrink_to)] #![feature(slice_bytes)] diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs index fba3269204e..715fd45e490 100644 --- a/src/libstd/panicking.rs +++ b/src/libstd/panicking.rs @@ -17,6 +17,8 @@ //! * Executing a panic up to doing the actual implementation //! * Shims around "try" +use core::panic::BoxMeUp; + use io::prelude::*; use any::Any; @@ -27,7 +29,7 @@ use intrinsics; use mem; use ptr; use raw; -use sys::stdio::Stderr; +use sys::stdio::{Stderr, stderr_prints_nothing}; use sys_common::rwlock::RWLock; use sys_common::thread_info; use sys_common::util; @@ -56,7 +58,7 @@ extern { data_ptr: *mut usize, vtable_ptr: *mut usize) -> u32; #[unwind(allowed)] - fn __rust_start_panic(data: usize, vtable: usize) -> u32; + fn __rust_start_panic(payload: usize) -> u32; } #[derive(Copy, Clone)] @@ -163,6 +165,12 @@ fn default_hook(info: &PanicInfo) { #[cfg(feature = "backtrace")] use sys_common::backtrace; + // Some platforms know that printing to stderr won't ever actually print + // anything, and if that's the case we can skip everything below. + if stderr_prints_nothing() { + return + } + // If this is a double panic, make sure that we print a backtrace // for this panic. Otherwise only print it if logging is enabled. #[cfg(feature = "backtrace")] @@ -212,15 +220,15 @@ fn default_hook(info: &PanicInfo) { let prev = LOCAL_STDERR.with(|s| s.borrow_mut().take()); match (prev, err.as_mut()) { - (Some(mut stderr), _) => { - write(&mut *stderr); - let mut s = Some(stderr); - LOCAL_STDERR.with(|slot| { - *slot.borrow_mut() = s.take(); - }); - } - (None, Some(ref mut err)) => { write(err) } - _ => {} + (Some(mut stderr), _) => { + write(&mut *stderr); + let mut s = Some(stderr); + LOCAL_STDERR.with(|slot| { + *slot.borrow_mut() = s.take(); + }); + } + (None, Some(ref mut err)) => { write(err) } + _ => {} } } @@ -344,7 +352,7 @@ pub fn begin_panic_fmt(msg: &fmt::Arguments, let mut s = String::new(); let _ = s.write_fmt(*msg); - rust_panic_with_hook(Box::new(s), Some(msg), file_line_col) + rust_panic_with_hook(&mut PanicPayload::new(s), Some(msg), file_line_col) } /// This is the entry point of panicking for panic!() and assert!(). @@ -360,7 +368,34 @@ pub fn begin_panic(msg: M, file_line_col: &(&'static str, u32, u3 // be performed in the parent of this thread instead of the thread that's // panicking. - rust_panic_with_hook(Box::new(msg), None, file_line_col) + rust_panic_with_hook(&mut PanicPayload::new(msg), None, file_line_col) +} + +struct PanicPayload { + inner: Option, +} + +impl PanicPayload { + fn new(inner: A) -> PanicPayload { + PanicPayload { inner: Some(inner) } + } +} + +unsafe impl BoxMeUp for PanicPayload { + fn box_me_up(&mut self) -> *mut (Any + Send) { + let data = match self.inner.take() { + Some(a) => Box::new(a) as Box, + None => Box::new(()), + }; + Box::into_raw(data) + } + + fn get(&self) -> &(Any + Send) { + match self.inner { + Some(ref a) => a, + None => &(), + } + } } /// Executes the primary logic for a panic, including checking for recursive @@ -369,9 +404,7 @@ pub fn begin_panic(msg: M, file_line_col: &(&'static str, u32, u3 /// This is the entry point or panics from libcore, formatted panics, and /// `Box` panics. Here we'll verify that we're not panicking recursively, /// run panic hooks, and then delegate to the actual implementation of panics. -#[inline(never)] -#[cold] -fn rust_panic_with_hook(payload: Box, +fn rust_panic_with_hook(payload: &mut BoxMeUp, message: Option<&fmt::Arguments>, file_line_col: &(&'static str, u32, u32)) -> ! { let (file, line, col) = *file_line_col; @@ -391,7 +424,7 @@ fn rust_panic_with_hook(payload: Box, unsafe { let info = PanicInfo::internal_constructor( - &*payload, + payload.get(), message, Location::internal_constructor(file, line, col), ); @@ -419,16 +452,29 @@ fn rust_panic_with_hook(payload: Box, /// Shim around rust_panic. Called by resume_unwind. pub fn update_count_then_panic(msg: Box) -> ! { update_panic_count(1); - rust_panic(msg) + + struct RewrapBox(Box); + + unsafe impl BoxMeUp for RewrapBox { + fn box_me_up(&mut self) -> *mut (Any + Send) { + Box::into_raw(mem::replace(&mut self.0, Box::new(()))) + } + + fn get(&self) -> &(Any + Send) { + &*self.0 + } + } + + rust_panic(&mut RewrapBox(msg)) } /// 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(msg: Box) -> ! { +pub fn rust_panic(mut msg: &mut BoxMeUp) -> ! { let code = unsafe { - let obj = mem::transmute::<_, raw::TraitObject>(msg); - __rust_start_panic(obj.data as usize, obj.vtable as usize) + let obj = &mut msg as *mut &mut BoxMeUp; + __rust_start_panic(obj as usize) }; rtabort!("failed to initiate panic, error {}", code) } diff --git a/src/libstd/sys/cloudabi/stdio.rs b/src/libstd/sys/cloudabi/stdio.rs index 9519a926471..1d7344f921c 100644 --- a/src/libstd/sys/cloudabi/stdio.rs +++ b/src/libstd/sys/cloudabi/stdio.rs @@ -77,3 +77,7 @@ pub fn is_ebadf(err: &io::Error) -> bool { } pub const STDIN_BUF_SIZE: usize = ::sys_common::io::DEFAULT_BUF_SIZE; + +pub fn stderr_prints_nothing() -> bool { + false +} diff --git a/src/libstd/sys/redox/stdio.rs b/src/libstd/sys/redox/stdio.rs index 3abb094ac34..7a4d11b0ecb 100644 --- a/src/libstd/sys/redox/stdio.rs +++ b/src/libstd/sys/redox/stdio.rs @@ -75,3 +75,7 @@ pub fn is_ebadf(err: &io::Error) -> bool { } pub const STDIN_BUF_SIZE: usize = ::sys_common::io::DEFAULT_BUF_SIZE; + +pub fn stderr_prints_nothing() -> bool { + false +} diff --git a/src/libstd/sys/unix/stdio.rs b/src/libstd/sys/unix/stdio.rs index e9b3d4affc7..87ba2aef4f1 100644 --- a/src/libstd/sys/unix/stdio.rs +++ b/src/libstd/sys/unix/stdio.rs @@ -75,3 +75,7 @@ pub fn is_ebadf(err: &io::Error) -> bool { } pub const STDIN_BUF_SIZE: usize = ::sys_common::io::DEFAULT_BUF_SIZE; + +pub fn stderr_prints_nothing() -> bool { + false +} diff --git a/src/libstd/sys/wasm/rwlock.rs b/src/libstd/sys/wasm/rwlock.rs index 8b06f541674..6516010af47 100644 --- a/src/libstd/sys/wasm/rwlock.rs +++ b/src/libstd/sys/wasm/rwlock.rs @@ -30,7 +30,7 @@ impl RWLock { if *mode >= 0 { *mode += 1; } else { - panic!("rwlock locked for writing"); + rtabort!("rwlock locked for writing"); } } @@ -51,7 +51,7 @@ impl RWLock { if *mode == 0 { *mode = -1; } else { - panic!("rwlock locked for reading") + rtabort!("rwlock locked for reading") } } diff --git a/src/libstd/sys/wasm/stdio.rs b/src/libstd/sys/wasm/stdio.rs index beb19c0ed2c..023f29576a2 100644 --- a/src/libstd/sys/wasm/stdio.rs +++ b/src/libstd/sys/wasm/stdio.rs @@ -69,3 +69,7 @@ pub const STDIN_BUF_SIZE: usize = 0; pub fn is_ebadf(_err: &io::Error) -> bool { true } + +pub fn stderr_prints_nothing() -> bool { + !cfg!(feature = "wasm_syscall") +} diff --git a/src/libstd/sys/windows/stdio.rs b/src/libstd/sys/windows/stdio.rs index b43df20bddd..81b89da21d3 100644 --- a/src/libstd/sys/windows/stdio.rs +++ b/src/libstd/sys/windows/stdio.rs @@ -227,3 +227,7 @@ pub fn is_ebadf(err: &io::Error) -> bool { // idea is that on windows we use a slightly smaller buffer that's // been seen to be acceptable. pub const STDIN_BUF_SIZE: usize = 8 * 1024; + +pub fn stderr_prints_nothing() -> bool { + false +} diff --git a/src/libstd/sys_common/backtrace.rs b/src/libstd/sys_common/backtrace.rs index 1955f3ec9a2..20109d2d0d5 100644 --- a/src/libstd/sys_common/backtrace.rs +++ b/src/libstd/sys_common/backtrace.rs @@ -139,10 +139,10 @@ pub fn __rust_begin_short_backtrace(f: F) -> T /// Controls how the backtrace should be formatted. #[derive(Debug, Copy, Clone, Eq, PartialEq)] pub enum PrintFormat { - /// Show all the frames with absolute path for files. - Full = 2, /// Show only relevant data from the backtrace. - Short = 3, + Short = 2, + /// Show all the frames with absolute path for files. + Full = 3, } // For now logging is turned off by default, and this function checks to see @@ -150,11 +150,10 @@ pub enum PrintFormat { pub fn log_enabled() -> Option { static ENABLED: atomic::AtomicIsize = atomic::AtomicIsize::new(0); match ENABLED.load(Ordering::SeqCst) { - 0 => {}, + 0 => {} 1 => return None, - 2 => return Some(PrintFormat::Full), - 3 => return Some(PrintFormat::Short), - _ => unreachable!(), + 2 => return Some(PrintFormat::Short), + _ => return Some(PrintFormat::Full), } let val = match env::var_os("RUST_BACKTRACE") { diff --git a/src/libstd/sys_common/mod.rs b/src/libstd/sys_common/mod.rs index 27504d374dd..d0c4d6a7737 100644 --- a/src/libstd/sys_common/mod.rs +++ b/src/libstd/sys_common/mod.rs @@ -28,6 +28,16 @@ use sync::Once; use sys; +macro_rules! rtabort { + ($($t:tt)*) => (::sys_common::util::abort(format_args!($($t)*))) +} + +macro_rules! rtassert { + ($e:expr) => (if !$e { + rtabort!(concat!("assertion failed: ", stringify!($e))); + }) +} + pub mod at_exit_imp; #[cfg(feature = "backtrace")] pub mod backtrace; @@ -101,10 +111,6 @@ pub fn at_exit(f: F) -> Result<(), ()> { if at_exit_imp::push(Box::new(f)) {Ok(())} else {Err(())} } -macro_rules! rtabort { - ($($t:tt)*) => (::sys_common::util::abort(format_args!($($t)*))) -} - /// One-time runtime cleanup. pub fn cleanup() { static CLEANUP: Once = Once::new(); diff --git a/src/libstd/sys_common/thread_local.rs b/src/libstd/sys_common/thread_local.rs index a4aa3d96d25..d0d6224de0a 100644 --- a/src/libstd/sys_common/thread_local.rs +++ b/src/libstd/sys_common/thread_local.rs @@ -169,7 +169,7 @@ impl StaticKey { self.key.store(key, Ordering::SeqCst); } INIT_LOCK.unlock(); - assert!(key != 0); + rtassert!(key != 0); return key } @@ -190,7 +190,7 @@ impl StaticKey { imp::destroy(key1); key2 }; - assert!(key != 0); + rtassert!(key != 0); match self.key.compare_and_swap(0, key as usize, Ordering::SeqCst) { // The CAS succeeded, so we've created the actual key 0 => key as usize, diff --git a/src/libstd/sys_common/util.rs b/src/libstd/sys_common/util.rs index a391c7cc6ef..a373e980b97 100644 --- a/src/libstd/sys_common/util.rs +++ b/src/libstd/sys_common/util.rs @@ -10,10 +10,13 @@ use fmt; use io::prelude::*; -use sys::stdio::Stderr; +use sys::stdio::{Stderr, stderr_prints_nothing}; use thread; pub fn dumb_print(args: fmt::Arguments) { + if stderr_prints_nothing() { + return + } let _ = Stderr::new().map(|mut stderr| stderr.write_fmt(args)); } diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs index 99479bc56ef..40d3280baa6 100644 --- a/src/libstd/thread/local.rs +++ b/src/libstd/thread/local.rs @@ -172,12 +172,16 @@ macro_rules! __thread_local_inner { &'static $crate::cell::UnsafeCell< $crate::option::Option<$t>>> { + #[cfg(target_arch = "wasm32")] + static __KEY: $crate::thread::__StaticLocalKeyInner<$t> = + $crate::thread::__StaticLocalKeyInner::new(); + #[thread_local] - #[cfg(target_thread_local)] + #[cfg(all(target_thread_local, not(target_arch = "wasm32")))] static __KEY: $crate::thread::__FastLocalKeyInner<$t> = $crate::thread::__FastLocalKeyInner::new(); - #[cfg(not(target_thread_local))] + #[cfg(all(not(target_thread_local), not(target_arch = "wasm32")))] static __KEY: $crate::thread::__OsLocalKeyInner<$t> = $crate::thread::__OsLocalKeyInner::new(); @@ -295,6 +299,39 @@ impl LocalKey { } } +/// On some platforms like wasm32 there's no threads, so no need to generate +/// thread locals and we can instead just use plain statics! +#[doc(hidden)] +#[cfg(target_arch = "wasm32")] +pub mod statik { + use cell::UnsafeCell; + use fmt; + + pub struct Key { + inner: UnsafeCell>, + } + + unsafe impl ::marker::Sync for Key { } + + impl fmt::Debug for Key { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("Key { .. }") + } + } + + impl Key { + pub const fn new() -> Key { + Key { + inner: UnsafeCell::new(None), + } + } + + pub unsafe fn get(&self) -> Option<&'static UnsafeCell>> { + Some(&*(&self.inner as *const _)) + } + } +} + #[doc(hidden)] #[cfg(target_thread_local)] pub mod fast { diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 71aee673cfe..1b976b79b4c 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -202,6 +202,9 @@ pub use self::local::{LocalKey, AccessError}; // where fast TLS was not available; end-user code is compiled with fast TLS // where available, but both are needed. +#[unstable(feature = "libstd_thread_internals", issue = "0")] +#[cfg(target_arch = "wasm32")] +#[doc(hidden)] pub use self::local::statik::Key as __StaticLocalKeyInner; #[unstable(feature = "libstd_thread_internals", issue = "0")] #[cfg(target_thread_local)] #[doc(hidden)] pub use self::local::fast::Key as __FastLocalKeyInner; diff --git a/src/test/run-make/wasm-panic-small/Makefile b/src/test/run-make/wasm-panic-small/Makefile new file mode 100644 index 00000000000..a11fba23595 --- /dev/null +++ b/src/test/run-make/wasm-panic-small/Makefile @@ -0,0 +1,11 @@ +-include ../../run-make-fulldeps/tools.mk + +ifeq ($(TARGET),wasm32-unknown-unknown) +all: + $(RUSTC) foo.rs -C lto -O --target wasm32-unknown-unknown + wc -c < $(TMPDIR)/foo.wasm + [ "`wc -c < $(TMPDIR)/foo.wasm`" -lt "1024" ] +else +all: +endif + diff --git a/src/test/run-make/wasm-panic-small/foo.rs b/src/test/run-make/wasm-panic-small/foo.rs new file mode 100644 index 00000000000..9654d5f7c09 --- /dev/null +++ b/src/test/run-make/wasm-panic-small/foo.rs @@ -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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_type = "cdylib"] + +#[no_mangle] +pub fn foo() { + panic!("test"); +} -- cgit 1.4.1-3-g733a5 From 182d99cfd1a551b9daa3d7f6896775278fb2962e Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Mon, 9 Apr 2018 17:44:28 -0700 Subject: Add doc links to `std::os` extension traits Add documentation links to the original type for various OS-specific extension traits and normalize the language for introducing such traits. Also, remove some outdated comments around the extension trait definitions. --- src/libstd/os/android/fs.rs | 4 +++- src/libstd/os/bitrig/fs.rs | 4 +++- src/libstd/os/dragonfly/fs.rs | 4 +++- src/libstd/os/emscripten/fs.rs | 4 +++- src/libstd/os/freebsd/fs.rs | 4 +++- src/libstd/os/fuchsia/fs.rs | 4 +++- src/libstd/os/haiku/fs.rs | 4 +++- src/libstd/os/ios/fs.rs | 4 +++- src/libstd/os/linux/fs.rs | 4 +++- src/libstd/os/macos/fs.rs | 4 +++- src/libstd/os/netbsd/fs.rs | 4 +++- src/libstd/os/openbsd/fs.rs | 4 +++- src/libstd/os/solaris/fs.rs | 4 +++- src/libstd/sys/redox/ext/ffi.rs | 10 +++++++--- src/libstd/sys/redox/ext/fs.rs | 36 ++++++++++++++++++++++++----------- src/libstd/sys/redox/ext/process.rs | 10 +++++++--- src/libstd/sys/redox/ext/thread.rs | 6 ++++-- src/libstd/sys/unix/ext/ffi.rs | 8 ++++++-- src/libstd/sys/unix/ext/fs.rs | 33 ++++++++++++++++++-------------- src/libstd/sys/unix/ext/process.rs | 8 ++++++-- src/libstd/sys/unix/ext/thread.rs | 4 +++- src/libstd/sys/windows/ext/ffi.rs | 8 ++++++-- src/libstd/sys/windows/ext/fs.rs | 20 ++++++++++--------- src/libstd/sys/windows/ext/process.rs | 8 ++++++-- 24 files changed, 139 insertions(+), 64 deletions(-) (limited to 'src/libstd/sys/windows') diff --git a/src/libstd/os/android/fs.rs b/src/libstd/os/android/fs.rs index a51b4655985..5899dc688e2 100644 --- a/src/libstd/os/android/fs.rs +++ b/src/libstd/os/android/fs.rs @@ -18,7 +18,9 @@ use sys_common::AsInner; #[allow(deprecated)] use os::android::raw; -/// OS-specific extension methods for `fs::Metadata` +/// 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 diff --git a/src/libstd/os/bitrig/fs.rs b/src/libstd/os/bitrig/fs.rs index e4f1c9432f3..24caf326ab0 100644 --- a/src/libstd/os/bitrig/fs.rs +++ b/src/libstd/os/bitrig/fs.rs @@ -18,7 +18,9 @@ use sys_common::AsInner; #[allow(deprecated)] use os::bitrig::raw; -/// OS-specific extension methods for `fs::Metadata` +/// 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 diff --git a/src/libstd/os/dragonfly/fs.rs b/src/libstd/os/dragonfly/fs.rs index db672e56435..6aea450774f 100644 --- a/src/libstd/os/dragonfly/fs.rs +++ b/src/libstd/os/dragonfly/fs.rs @@ -18,7 +18,9 @@ use sys_common::AsInner; #[allow(deprecated)] use os::dragonfly::raw; -/// OS-specific extension methods for `fs::Metadata` +/// 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 diff --git a/src/libstd/os/emscripten/fs.rs b/src/libstd/os/emscripten/fs.rs index 8056ce4fdc4..e0e197dc122 100644 --- a/src/libstd/os/emscripten/fs.rs +++ b/src/libstd/os/emscripten/fs.rs @@ -18,7 +18,9 @@ use sys_common::AsInner; #[allow(deprecated)] use os::emscripten::raw; -/// OS-specific extension methods for `fs::Metadata` +/// 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 diff --git a/src/libstd/os/freebsd/fs.rs b/src/libstd/os/freebsd/fs.rs index 2f17d2f7409..5f24cd636d5 100644 --- a/src/libstd/os/freebsd/fs.rs +++ b/src/libstd/os/freebsd/fs.rs @@ -18,7 +18,9 @@ use sys_common::AsInner; #[allow(deprecated)] use os::freebsd::raw; -/// OS-specific extension methods for `fs::Metadata` +/// 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 diff --git a/src/libstd/os/fuchsia/fs.rs b/src/libstd/os/fuchsia/fs.rs index d22f9a628bd..16802576356 100644 --- a/src/libstd/os/fuchsia/fs.rs +++ b/src/libstd/os/fuchsia/fs.rs @@ -13,7 +13,9 @@ use fs::Metadata; use sys_common::AsInner; -/// OS-specific extension methods for `fs::Metadata` +/// OS-specific extensions to [`fs::Metadata`]. +/// +/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html #[stable(feature = "metadata_ext", since = "1.1.0")] pub trait MetadataExt { #[stable(feature = "metadata_ext2", since = "1.8.0")] diff --git a/src/libstd/os/haiku/fs.rs b/src/libstd/os/haiku/fs.rs index 54f8ea1b71b..453136e0ac8 100644 --- a/src/libstd/os/haiku/fs.rs +++ b/src/libstd/os/haiku/fs.rs @@ -18,7 +18,9 @@ use sys_common::AsInner; #[allow(deprecated)] use os::haiku::raw; -/// OS-specific extension methods for `fs::Metadata` +/// 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 diff --git a/src/libstd/os/ios/fs.rs b/src/libstd/os/ios/fs.rs index 275daf3d3a0..296ce69ff43 100644 --- a/src/libstd/os/ios/fs.rs +++ b/src/libstd/os/ios/fs.rs @@ -18,7 +18,9 @@ use sys_common::AsInner; #[allow(deprecated)] use os::ios::raw; -/// OS-specific extension methods for `fs::Metadata` +/// 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 diff --git a/src/libstd/os/linux/fs.rs b/src/libstd/os/linux/fs.rs index 2be2fbcb2db..76fb10da850 100644 --- a/src/libstd/os/linux/fs.rs +++ b/src/libstd/os/linux/fs.rs @@ -18,7 +18,9 @@ use sys_common::AsInner; #[allow(deprecated)] use os::linux::raw; -/// OS-specific extension methods for `fs::Metadata` +/// 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 diff --git a/src/libstd/os/macos/fs.rs b/src/libstd/os/macos/fs.rs index 12b44901d03..0b14c05cb55 100644 --- a/src/libstd/os/macos/fs.rs +++ b/src/libstd/os/macos/fs.rs @@ -18,7 +18,9 @@ use sys_common::AsInner; #[allow(deprecated)] use os::macos::raw; -/// OS-specific extension methods for `fs::Metadata` +/// 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 diff --git a/src/libstd/os/netbsd/fs.rs b/src/libstd/os/netbsd/fs.rs index cd7d5fafd1c..e9cad33fee6 100644 --- a/src/libstd/os/netbsd/fs.rs +++ b/src/libstd/os/netbsd/fs.rs @@ -18,7 +18,9 @@ use sys_common::AsInner; #[allow(deprecated)] use os::netbsd::raw; -/// OS-specific extension methods for `fs::Metadata` +/// 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 diff --git a/src/libstd/os/openbsd/fs.rs b/src/libstd/os/openbsd/fs.rs index cc812fcf12c..0f6b83b6e32 100644 --- a/src/libstd/os/openbsd/fs.rs +++ b/src/libstd/os/openbsd/fs.rs @@ -18,7 +18,9 @@ use sys_common::AsInner; #[allow(deprecated)] use os::openbsd::raw; -/// OS-specific extension methods for `fs::Metadata` +/// 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 diff --git a/src/libstd/os/solaris/fs.rs b/src/libstd/os/solaris/fs.rs index 5dc43d03a86..19dce1ba34c 100644 --- a/src/libstd/os/solaris/fs.rs +++ b/src/libstd/os/solaris/fs.rs @@ -18,7 +18,9 @@ use sys_common::AsInner; #[allow(deprecated)] use os::solaris::raw; -/// OS-specific extension methods for `fs::Metadata` +/// 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 diff --git a/src/libstd/sys/redox/ext/ffi.rs b/src/libstd/sys/redox/ext/ffi.rs index d59b4fc0b70..060edbd22e4 100644 --- a/src/libstd/sys/redox/ext/ffi.rs +++ b/src/libstd/sys/redox/ext/ffi.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Unix-specific extension to the primitives in the `std::ffi` module +//! Redox-specific extension to the primitives in the `std::ffi` module. #![stable(feature = "rust1", since = "1.0.0")] @@ -17,7 +17,9 @@ use mem; use sys::os_str::Buf; use sys_common::{FromInner, IntoInner, AsInner}; -/// Unix-specific extensions to `OsString`. +/// Redox-specific extensions to [`ffi::OsString`]. +/// +/// [`ffi::OsString`]: ../../../../std/ffi/struct.OsString.html #[stable(feature = "rust1", since = "1.0.0")] pub trait OsStringExt { /// Creates an `OsString` from a byte vector. @@ -39,7 +41,9 @@ impl OsStringExt for OsString { } } -/// Unix-specific extensions to `OsStr`. +/// Redox-specific extensions to [`ffi::OsStr`]. +/// +/// [`ffi::OsStr`]: ../../../../std/ffi/struct.OsStr.html #[stable(feature = "rust1", since = "1.0.0")] pub trait OsStrExt { #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libstd/sys/redox/ext/fs.rs b/src/libstd/sys/redox/ext/fs.rs index 0f4762aa881..b39c6f5d022 100644 --- a/src/libstd/sys/redox/ext/fs.rs +++ b/src/libstd/sys/redox/ext/fs.rs @@ -18,7 +18,9 @@ use path::Path; use sys; use sys_common::{FromInner, AsInner, AsInnerMut}; -/// Redox-specific extensions to `Permissions` +/// Redox-specific extensions to [`fs::Permissions`]. +/// +/// [`fs::Permissions`]: ../../../../std/fs/struct.Permissions.html #[stable(feature = "fs_ext", since = "1.1.0")] pub trait PermissionsExt { /// Returns the underlying raw `mode_t` bits that are the standard Redox @@ -95,7 +97,9 @@ impl PermissionsExt for Permissions { } } -/// Redox-specific extensions to `OpenOptions` +/// Redox-specific extensions to [`fs::OpenOptions`]. +/// +/// [`fs::OpenOptions`]: ../../../../std/fs/struct.OpenOptions.html #[stable(feature = "fs_ext", since = "1.1.0")] pub trait OpenOptionsExt { /// Sets the mode bits that a new file will be created with. @@ -163,13 +167,9 @@ impl OpenOptionsExt for OpenOptions { } } -// Hm, why are there casts here to the returned type, shouldn't the types always -// be the same? Right you are! Turns out, however, on android at least the types -// in the raw `stat` structure are not the same as the types being returned. Who -// knew! -// -// As a result to make sure this compiles for all platforms we do the manual -// casts and rely on manual lowering to `stat` if the raw type is desired. +/// Redox-specific extensions to [`fs::Metadata`]. +/// +/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html #[stable(feature = "metadata_ext", since = "1.1.0")] pub trait MetadataExt { #[stable(feature = "metadata_ext", since = "1.1.0")] @@ -204,6 +204,13 @@ pub trait MetadataExt { fn blocks(&self) -> u64; } +// Hm, why are there casts here to the returned type, shouldn't the types always +// be the same? Right you are! Turns out, however, on android at least the types +// in the raw `stat` structure are not the same as the types being returned. Who +// knew! +// +// As a result to make sure this compiles for all platforms we do the manual +// casts and rely on manual lowering to `stat` if the raw type is desired. #[stable(feature = "metadata_ext", since = "1.1.0")] impl MetadataExt for fs::Metadata { fn dev(&self) -> u64 { @@ -253,7 +260,12 @@ impl MetadataExt for fs::Metadata { } } -/// Add special Redox types (block/char device, fifo and socket) +/// Redox-specific extensions for [`fs::FileType`]. +/// +/// Adds support for special Unix file types such as block/character devices, +/// pipes, and sockets. +/// +/// [`fs::FileType`]: ../../../../std/fs/struct.FileType.html #[stable(feature = "file_type_ext", since = "1.5.0")] pub trait FileTypeExt { /// Returns whether this file type is a block device. @@ -307,8 +319,10 @@ pub fn symlink, Q: AsRef>(src: P, dst: Q) -> io::Result<()> sys::fs::symlink(src.as_ref(), dst.as_ref()) } +/// Redox-specific extensions to [`fs::DirBuilder`]. +/// +/// [`fs::DirBuilder`]: ../../../../std/fs/struct.DirBuilder.html #[stable(feature = "dir_builder", since = "1.6.0")] -/// An extension trait for `fs::DirBuilder` for Redox-specific options. pub trait DirBuilderExt { /// Sets the mode to create new directories with. This option defaults to /// 0o777. diff --git a/src/libstd/sys/redox/ext/process.rs b/src/libstd/sys/redox/ext/process.rs index e68e180acf1..608740a5cf7 100644 --- a/src/libstd/sys/redox/ext/process.rs +++ b/src/libstd/sys/redox/ext/process.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Unix-specific extensions to primitives in the `std::process` module. +//! Redox-specific extensions to primitives in the `std::process` module. #![stable(feature = "rust1", since = "1.0.0")] @@ -18,7 +18,9 @@ use process; use sys; use sys_common::{AsInnerMut, AsInner, FromInner, IntoInner}; -/// Unix-specific extensions to the `std::process::Command` builder +/// Redox-specific extensions to the [`process::Command`] builder. +/// +/// [`process::Command`]: ../../../../std/process/struct.Command.html #[stable(feature = "rust1", since = "1.0.0")] pub trait CommandExt { /// Sets the child process's user id. This translates to a @@ -107,7 +109,9 @@ impl CommandExt for process::Command { } } -/// Unix-specific extensions to `std::process::ExitStatus` +/// Redox-specific extensions to [`process::ExitStatus`]. +/// +/// [`process::ExitStatus`]: ../../../../std/process/struct.ExitStatus.html #[stable(feature = "rust1", since = "1.0.0")] pub trait ExitStatusExt { /// Creates a new `ExitStatus` from the raw underlying `i32` return value of diff --git a/src/libstd/sys/redox/ext/thread.rs b/src/libstd/sys/redox/ext/thread.rs index 52be2ccd9f9..71ff0d46b91 100644 --- a/src/libstd/sys/redox/ext/thread.rs +++ b/src/libstd/sys/redox/ext/thread.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Unix-specific extensions to primitives in the `std::thread` module. +//! Redox-specific extensions to primitives in the `std::thread` module. #![stable(feature = "thread_extensions", since = "1.9.0")] @@ -19,7 +19,9 @@ use thread::JoinHandle; #[allow(deprecated)] pub type RawPthread = usize; -/// Unix-specific extensions to `std::thread::JoinHandle` +/// Redox-specific extensions to [`thread::JoinHandle`]. +/// +/// [`thread::JoinHandle`]: ../../../../std/thread/struct.JoinHandle.html #[stable(feature = "thread_extensions", since = "1.9.0")] pub trait JoinHandleExt { /// Extracts the raw pthread_t without taking ownership diff --git a/src/libstd/sys/unix/ext/ffi.rs b/src/libstd/sys/unix/ext/ffi.rs index fb9984ccbdd..3103ad0416e 100644 --- a/src/libstd/sys/unix/ext/ffi.rs +++ b/src/libstd/sys/unix/ext/ffi.rs @@ -17,7 +17,9 @@ use mem; use sys::os_str::Buf; use sys_common::{FromInner, IntoInner, AsInner}; -/// Unix-specific extensions to `OsString`. +/// Unix-specific extensions to [`ffi::OsString`]. +/// +/// [`ffi::OsString`]: ../../../../std/ffi/struct.OsString.html #[stable(feature = "rust1", since = "1.0.0")] pub trait OsStringExt { /// Creates an [`OsString`] from a byte vector. @@ -66,7 +68,9 @@ impl OsStringExt for OsString { } } -/// Unix-specific extensions to `OsStr`. +/// Unix-specific extensions to [`ffi::OsStr`]. +/// +/// [`ffi::OsStr`]: ../../../../std/ffi/struct.OsStr.html #[stable(feature = "rust1", since = "1.0.0")] pub trait OsStrExt { #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libstd/sys/unix/ext/fs.rs b/src/libstd/sys/unix/ext/fs.rs index 3c5b9424fb0..844e0106df0 100644 --- a/src/libstd/sys/unix/ext/fs.rs +++ b/src/libstd/sys/unix/ext/fs.rs @@ -20,9 +20,9 @@ use sys; use sys_common::{FromInner, AsInner, AsInnerMut}; use sys::platform::fs::MetadataExt as UnixMetadataExt; -/// Unix-specific extensions to [`File`]. +/// Unix-specific extensions to [`fs::File`]. /// -/// [`File`]: ../../../../std/fs/struct.File.html +/// [`fs::File`]: ../../../../std/fs/struct.File.html #[stable(feature = "file_offset", since = "1.15.0")] pub trait FileExt { /// Reads a number of bytes starting from a given offset. @@ -105,7 +105,9 @@ impl FileExt for fs::File { } } -/// Unix-specific extensions to `Permissions` +/// Unix-specific extensions to [`fs::Permissions`]. +/// +/// [`fs::Permissions`]: ../../../../std/fs/struct.Permissions.html #[stable(feature = "fs_ext", since = "1.1.0")] pub trait PermissionsExt { /// Returns the underlying raw `st_mode` bits that contain the standard @@ -180,7 +182,9 @@ impl PermissionsExt for Permissions { } } -/// Unix-specific extensions to `OpenOptions` +/// Unix-specific extensions to [`fs::OpenOptions`]. +/// +/// [`fs::OpenOptions`]: ../../../../std/fs/struct.OpenOptions.html #[stable(feature = "fs_ext", since = "1.1.0")] pub trait OpenOptionsExt { /// Sets the mode bits that a new file will be created with. @@ -246,13 +250,9 @@ impl OpenOptionsExt for OpenOptions { } } -// Hm, why are there casts here to the returned type, shouldn't the types always -// be the same? Right you are! Turns out, however, on android at least the types -// in the raw `stat` structure are not the same as the types being returned. Who -// knew! -// -// As a result to make sure this compiles for all platforms we do the manual -// casts and rely on manual lowering to `stat` if the raw type is desired. +/// Unix-specific extensions to [`fs::Metadata`]. +/// +/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html #[stable(feature = "metadata_ext", since = "1.1.0")] pub trait MetadataExt { /// Returns the ID of the device containing the file. @@ -555,7 +555,12 @@ impl MetadataExt for fs::Metadata { fn blocks(&self) -> u64 { self.st_blocks() } } -/// Add support for special unix types (block/char device, fifo and socket). +/// Unix-specific extensions for [`fs::FileType`]. +/// +/// Adds support for special Unix file types such as block/character devices, +/// pipes, and sockets. +/// +/// [`fs::FileType`]: ../../../../std/fs/struct.FileType.html #[stable(feature = "file_type_ext", since = "1.5.0")] pub trait FileTypeExt { /// Returns whether this file type is a block device. @@ -701,10 +706,10 @@ pub fn symlink, Q: AsRef>(src: P, dst: Q) -> io::Result<()> sys::fs::symlink(src.as_ref(), dst.as_ref()) } -#[stable(feature = "dir_builder", since = "1.6.0")] -/// An extension trait for [`fs::DirBuilder`] for unix-specific options. +/// Unix-specific extensions to [`fs::DirBuilder`]. /// /// [`fs::DirBuilder`]: ../../../../std/fs/struct.DirBuilder.html +#[stable(feature = "dir_builder", since = "1.6.0")] pub trait DirBuilderExt { /// Sets the mode to create new directories with. This option defaults to /// 0o777. diff --git a/src/libstd/sys/unix/ext/process.rs b/src/libstd/sys/unix/ext/process.rs index 7b4ec20d91f..21630ae9746 100644 --- a/src/libstd/sys/unix/ext/process.rs +++ b/src/libstd/sys/unix/ext/process.rs @@ -18,7 +18,9 @@ use process; use sys; use sys_common::{AsInnerMut, AsInner, FromInner, IntoInner}; -/// Unix-specific extensions to the `std::process::Command` builder +/// Unix-specific extensions to the [`process::Command`] builder. +/// +/// [`process::Command`]: ../../../../std/process/struct.Command.html #[stable(feature = "rust1", since = "1.0.0")] pub trait CommandExt { /// Sets the child process's user id. This translates to a @@ -117,7 +119,9 @@ impl CommandExt for process::Command { } } -/// Unix-specific extensions to `std::process::ExitStatus` +/// Unix-specific extensions to [`process::ExitStatus`]. +/// +/// [`process::ExitStatus`]: ../../../../std/process/struct.ExitStatus.html #[stable(feature = "rust1", since = "1.0.0")] pub trait ExitStatusExt { /// Creates a new `ExitStatus` from the raw underlying `i32` return value of diff --git a/src/libstd/sys/unix/ext/thread.rs b/src/libstd/sys/unix/ext/thread.rs index fe2a48764dc..8dadf29945c 100644 --- a/src/libstd/sys/unix/ext/thread.rs +++ b/src/libstd/sys/unix/ext/thread.rs @@ -21,7 +21,9 @@ use thread::JoinHandle; #[allow(deprecated)] pub type RawPthread = pthread_t; -/// Unix-specific extensions to `std::thread::JoinHandle` +/// Unix-specific extensions to [`thread::JoinHandle`]. +/// +/// [`thread::JoinHandle`]: ../../../../std/thread/struct.JoinHandle.html #[stable(feature = "thread_extensions", since = "1.9.0")] pub trait JoinHandleExt { /// Extracts the raw pthread_t without taking ownership diff --git a/src/libstd/sys/windows/ext/ffi.rs b/src/libstd/sys/windows/ext/ffi.rs index d6b8896ac09..b3f7635efd3 100644 --- a/src/libstd/sys/windows/ext/ffi.rs +++ b/src/libstd/sys/windows/ext/ffi.rs @@ -76,7 +76,9 @@ use sys_common::{FromInner, AsInner}; #[stable(feature = "rust1", since = "1.0.0")] pub use sys_common::wtf8::EncodeWide; -/// Windows-specific extensions to `OsString`. +/// Windows-specific extensions to [`ffi::OsString`]. +/// +/// [`ffi::OsString`]: ../../../../std/ffi/struct.OsString.html #[stable(feature = "rust1", since = "1.0.0")] pub trait OsStringExt { /// Creates an `OsString` from a potentially ill-formed UTF-16 slice of @@ -109,7 +111,9 @@ impl OsStringExt for OsString { } } -/// Windows-specific extensions to `OsStr`. +/// Windows-specific extensions to [`ffi::OsStr`]. +/// +/// [`ffi::OsStr`]: ../../../../std/ffi/struct.OsStr.html #[stable(feature = "rust1", since = "1.0.0")] pub trait OsStrExt { /// Re-encodes an `OsStr` as a wide character sequence, i.e. potentially diff --git a/src/libstd/sys/windows/ext/fs.rs b/src/libstd/sys/windows/ext/fs.rs index e5cd51b6550..5daeb5282cd 100644 --- a/src/libstd/sys/windows/ext/fs.rs +++ b/src/libstd/sys/windows/ext/fs.rs @@ -18,9 +18,9 @@ use path::Path; use sys; use sys_common::{AsInnerMut, AsInner}; -/// Windows-specific extensions to [`File`]. +/// Windows-specific extensions to [`fs::File`]. /// -/// [`File`]: ../../../fs/struct.File.html +/// [`fs::File`]: ../../../fs/struct.File.html #[stable(feature = "file_offset", since = "1.15.0")] pub trait FileExt { /// Seeks to a given position and reads a number of bytes. @@ -103,9 +103,9 @@ impl FileExt for fs::File { } } -/// Windows-specific extensions to [`OpenOptions`]. +/// Windows-specific extensions to [`fs::OpenOptions`]. /// -/// [`OpenOptions`]: ../../../fs/struct.OpenOptions.html +/// [`fs::OpenOptions`]: ../../../../std/fs/struct.OpenOptions.html #[stable(feature = "open_options_ext", since = "1.10.0")] pub trait OpenOptionsExt { /// Overrides the `dwDesiredAccess` argument to the call to [`CreateFile`] @@ -281,13 +281,12 @@ impl OpenOptionsExt for OpenOptions { } } -/// Extension methods for [`fs::Metadata`] to access the raw fields contained -/// within. +/// Windows-specific extensions to [`fs::Metadata`]. /// /// The data members that this trait exposes correspond to the members /// of the [`BY_HANDLE_FILE_INFORMATION`] structure. /// -/// [`fs::Metadata`]: ../../../fs/struct.Metadata.html +/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html /// [`BY_HANDLE_FILE_INFORMATION`]: /// https://msdn.microsoft.com/en-us/library/windows/desktop/aa363788.aspx #[stable(feature = "metadata_ext", since = "1.1.0")] @@ -445,8 +444,11 @@ impl MetadataExt for Metadata { fn file_size(&self) -> u64 { self.as_inner().size() } } -/// Add support for the Windows specific fact that a symbolic link knows whether it is a file -/// or directory. +/// Windows-specific extensions to [`fs::FileType`]. +/// +/// On Windows, a symbolic link knows whether it is a file or directory. +/// +/// [`fs::FileType`]: ../../../../std/fs/struct.FileType.html #[unstable(feature = "windows_file_type_ext", issue = "0")] pub trait FileTypeExt { /// Returns whether this file type is a symbolic link that is also a directory. diff --git a/src/libstd/sys/windows/ext/process.rs b/src/libstd/sys/windows/ext/process.rs index 759f055c4b1..a02bcbe0c87 100644 --- a/src/libstd/sys/windows/ext/process.rs +++ b/src/libstd/sys/windows/ext/process.rs @@ -82,7 +82,9 @@ impl IntoRawHandle for process::ChildStderr { } } -/// Windows-specific extensions to `std::process::ExitStatus` +/// Windows-specific extensions to [`process::ExitStatus`]. +/// +/// [`process::ExitStatus`]: ../../../../std/process/struct.ExitStatus.html #[stable(feature = "exit_status_from", since = "1.12.0")] pub trait ExitStatusExt { /// Creates a new `ExitStatus` from the raw underlying `u32` return value of @@ -98,7 +100,9 @@ impl ExitStatusExt for process::ExitStatus { } } -/// Windows-specific extensions to the `std::process::Command` builder +/// Windows-specific extensions to the [`process::Command`] builder. +/// +/// [`process::Command`]: ../../../../std/process/struct.Command.html #[stable(feature = "windows_process_extensions", since = "1.16.0")] pub trait CommandExt { /// Sets the [process creation flags][1] to be passed to `CreateProcess`. -- cgit 1.4.1-3-g733a5 From d5bee64df400126279e71562352936d5e4d14433 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Tue, 10 Apr 2018 17:03:07 -0700 Subject: Prefer unprefixed paths for well known structs --- src/libstd/sys/redox/ext/ffi.rs | 8 ++++---- src/libstd/sys/redox/ext/fs.rs | 4 ++-- src/libstd/sys/redox/ext/process.rs | 2 +- src/libstd/sys/unix/ext/ffi.rs | 8 ++++---- src/libstd/sys/unix/ext/fs.rs | 8 ++++---- src/libstd/sys/windows/ext/ffi.rs | 8 ++++---- src/libstd/sys/windows/ext/fs.rs | 8 ++++---- 7 files changed, 23 insertions(+), 23 deletions(-) (limited to 'src/libstd/sys/windows') diff --git a/src/libstd/sys/redox/ext/ffi.rs b/src/libstd/sys/redox/ext/ffi.rs index 060edbd22e4..cd88c8f46b3 100644 --- a/src/libstd/sys/redox/ext/ffi.rs +++ b/src/libstd/sys/redox/ext/ffi.rs @@ -17,9 +17,9 @@ use mem; use sys::os_str::Buf; use sys_common::{FromInner, IntoInner, AsInner}; -/// Redox-specific extensions to [`ffi::OsString`]. +/// Redox-specific extensions to [`OsString`]. /// -/// [`ffi::OsString`]: ../../../../std/ffi/struct.OsString.html +/// [`OsString`]: ../../../../std/ffi/struct.OsString.html #[stable(feature = "rust1", since = "1.0.0")] pub trait OsStringExt { /// Creates an `OsString` from a byte vector. @@ -41,9 +41,9 @@ impl OsStringExt for OsString { } } -/// Redox-specific extensions to [`ffi::OsStr`]. +/// Redox-specific extensions to [`OsStr`]. /// -/// [`ffi::OsStr`]: ../../../../std/ffi/struct.OsStr.html +/// [`OsStr`]: ../../../../std/ffi/struct.OsStr.html #[stable(feature = "rust1", since = "1.0.0")] pub trait OsStrExt { #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libstd/sys/redox/ext/fs.rs b/src/libstd/sys/redox/ext/fs.rs index b39c6f5d022..c1dba6edda4 100644 --- a/src/libstd/sys/redox/ext/fs.rs +++ b/src/libstd/sys/redox/ext/fs.rs @@ -260,12 +260,12 @@ impl MetadataExt for fs::Metadata { } } -/// Redox-specific extensions for [`fs::FileType`]. +/// Redox-specific extensions for [`FileType`]. /// /// Adds support for special Unix file types such as block/character devices, /// pipes, and sockets. /// -/// [`fs::FileType`]: ../../../../std/fs/struct.FileType.html +/// [`FileType`]: ../../../../std/fs/struct.FileType.html #[stable(feature = "file_type_ext", since = "1.5.0")] pub trait FileTypeExt { /// Returns whether this file type is a block device. diff --git a/src/libstd/sys/redox/ext/process.rs b/src/libstd/sys/redox/ext/process.rs index 608740a5cf7..cfb6d5fc703 100644 --- a/src/libstd/sys/redox/ext/process.rs +++ b/src/libstd/sys/redox/ext/process.rs @@ -18,7 +18,7 @@ use process; use sys; use sys_common::{AsInnerMut, AsInner, FromInner, IntoInner}; -/// Redox-specific extensions to the [`process::Command`] builder. +/// Redox-specific extensions to the [`process::Command`] builder, /// /// [`process::Command`]: ../../../../std/process/struct.Command.html #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libstd/sys/unix/ext/ffi.rs b/src/libstd/sys/unix/ext/ffi.rs index 3103ad0416e..8347145db5a 100644 --- a/src/libstd/sys/unix/ext/ffi.rs +++ b/src/libstd/sys/unix/ext/ffi.rs @@ -17,9 +17,9 @@ use mem; use sys::os_str::Buf; use sys_common::{FromInner, IntoInner, AsInner}; -/// Unix-specific extensions to [`ffi::OsString`]. +/// Unix-specific extensions to [`OsString`]. /// -/// [`ffi::OsString`]: ../../../../std/ffi/struct.OsString.html +/// [`OsString`]: ../../../../std/ffi/struct.OsString.html #[stable(feature = "rust1", since = "1.0.0")] pub trait OsStringExt { /// Creates an [`OsString`] from a byte vector. @@ -68,9 +68,9 @@ impl OsStringExt for OsString { } } -/// Unix-specific extensions to [`ffi::OsStr`]. +/// Unix-specific extensions to [`OsStr`]. /// -/// [`ffi::OsStr`]: ../../../../std/ffi/struct.OsStr.html +/// [`OsStr`]: ../../../../std/ffi/struct.OsStr.html #[stable(feature = "rust1", since = "1.0.0")] pub trait OsStrExt { #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libstd/sys/unix/ext/fs.rs b/src/libstd/sys/unix/ext/fs.rs index 844e0106df0..4e981012669 100644 --- a/src/libstd/sys/unix/ext/fs.rs +++ b/src/libstd/sys/unix/ext/fs.rs @@ -20,9 +20,9 @@ use sys; use sys_common::{FromInner, AsInner, AsInnerMut}; use sys::platform::fs::MetadataExt as UnixMetadataExt; -/// Unix-specific extensions to [`fs::File`]. +/// Unix-specific extensions to [`File`]. /// -/// [`fs::File`]: ../../../../std/fs/struct.File.html +/// [`File`]: ../../../../std/fs/struct.File.html #[stable(feature = "file_offset", since = "1.15.0")] pub trait FileExt { /// Reads a number of bytes starting from a given offset. @@ -555,12 +555,12 @@ impl MetadataExt for fs::Metadata { fn blocks(&self) -> u64 { self.st_blocks() } } -/// Unix-specific extensions for [`fs::FileType`]. +/// Unix-specific extensions for [`FileType`]. /// /// Adds support for special Unix file types such as block/character devices, /// pipes, and sockets. /// -/// [`fs::FileType`]: ../../../../std/fs/struct.FileType.html +/// [`FileType`]: ../../../../std/fs/struct.FileType.html #[stable(feature = "file_type_ext", since = "1.5.0")] pub trait FileTypeExt { /// Returns whether this file type is a block device. diff --git a/src/libstd/sys/windows/ext/ffi.rs b/src/libstd/sys/windows/ext/ffi.rs index b3f7635efd3..98d43552489 100644 --- a/src/libstd/sys/windows/ext/ffi.rs +++ b/src/libstd/sys/windows/ext/ffi.rs @@ -76,9 +76,9 @@ use sys_common::{FromInner, AsInner}; #[stable(feature = "rust1", since = "1.0.0")] pub use sys_common::wtf8::EncodeWide; -/// Windows-specific extensions to [`ffi::OsString`]. +/// Windows-specific extensions to [`OsString`]. /// -/// [`ffi::OsString`]: ../../../../std/ffi/struct.OsString.html +/// [`OsString`]: ../../../../std/ffi/struct.OsString.html #[stable(feature = "rust1", since = "1.0.0")] pub trait OsStringExt { /// Creates an `OsString` from a potentially ill-formed UTF-16 slice of @@ -111,9 +111,9 @@ impl OsStringExt for OsString { } } -/// Windows-specific extensions to [`ffi::OsStr`]. +/// Windows-specific extensions to [`OsStr`]. /// -/// [`ffi::OsStr`]: ../../../../std/ffi/struct.OsStr.html +/// [`OsStr`]: ../../../../std/ffi/struct.OsStr.html #[stable(feature = "rust1", since = "1.0.0")] pub trait OsStrExt { /// Re-encodes an `OsStr` as a wide character sequence, i.e. potentially diff --git a/src/libstd/sys/windows/ext/fs.rs b/src/libstd/sys/windows/ext/fs.rs index 5daeb5282cd..78c9e95a055 100644 --- a/src/libstd/sys/windows/ext/fs.rs +++ b/src/libstd/sys/windows/ext/fs.rs @@ -18,9 +18,9 @@ use path::Path; use sys; use sys_common::{AsInnerMut, AsInner}; -/// Windows-specific extensions to [`fs::File`]. +/// Windows-specific extensions to [`File`]. /// -/// [`fs::File`]: ../../../fs/struct.File.html +/// [`File`]: ../../../fs/struct.File.html #[stable(feature = "file_offset", since = "1.15.0")] pub trait FileExt { /// Seeks to a given position and reads a number of bytes. @@ -444,11 +444,11 @@ impl MetadataExt for Metadata { fn file_size(&self) -> u64 { self.as_inner().size() } } -/// Windows-specific extensions to [`fs::FileType`]. +/// Windows-specific extensions to [`FileType`]. /// /// On Windows, a symbolic link knows whether it is a file or directory. /// -/// [`fs::FileType`]: ../../../../std/fs/struct.FileType.html +/// [`FileType`]: ../../../../std/fs/struct.FileType.html #[unstable(feature = "windows_file_type_ext", issue = "0")] pub trait FileTypeExt { /// Returns whether this file type is a symbolic link that is also a directory. -- cgit 1.4.1-3-g733a5 From 231c61a76bba716ad0a7d571f64825d57be2a75e Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 13 Jun 2018 22:28:21 +0200 Subject: Add missing allow_missing_docs --- src/libstd/sys/windows/ext/mod.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'src/libstd/sys/windows') diff --git a/src/libstd/sys/windows/ext/mod.rs b/src/libstd/sys/windows/ext/mod.rs index 4b458d293bc..1f10609f32c 100644 --- a/src/libstd/sys/windows/ext/mod.rs +++ b/src/libstd/sys/windows/ext/mod.rs @@ -18,6 +18,7 @@ #![stable(feature = "rust1", since = "1.0.0")] #![doc(cfg(windows))] +#![allow(missing_docs)] pub mod ffi; pub mod fs; -- cgit 1.4.1-3-g733a5 From d39c66bf4ff2b49957edadf10afcc4050c3fc60b Mon Sep 17 00:00:00 2001 From: moxian Date: Tue, 8 May 2018 06:19:55 +0000 Subject: Add a fallback for stacktrace printing for older Windows versions. PR #47252 switched stack inspection functions of dbghelp.dll to their newer alternatives that also capture inlined context. Unfortunately, said new alternatives are not present in older dbghelp.dll versions. In particular Windows 7 at the time of writing has dbghelp.dll version 6.1.7601 from 2010, that lacks StackWalkEx and friends. Fixes #50138 --- src/libstd/sys/windows/backtrace/mod.rs | 170 +++++++++++---- src/libstd/sys/windows/backtrace/printing/msvc.rs | 253 ++++++++++++++++------ src/libstd/sys/windows/c.rs | 16 ++ 3 files changed, 331 insertions(+), 108 deletions(-) (limited to 'src/libstd/sys/windows') diff --git a/src/libstd/sys/windows/backtrace/mod.rs b/src/libstd/sys/windows/backtrace/mod.rs index 82498ad4d58..8e879e0f49e 100644 --- a/src/libstd/sys/windows/backtrace/mod.rs +++ b/src/libstd/sys/windows/backtrace/mod.rs @@ -48,24 +48,21 @@ pub mod gnu; pub use self::printing::{resolve_symname, foreach_symbol_fileline}; -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 ResStackWalkEx = sym!(dbghelp, "StackWalkEx", StackWalkExFn); + let ResStackWalk64 = sym!(dbghelp, "StackWalk64", StackWalk64Fn); // 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, @@ -76,49 +73,139 @@ pub fn unwind_backtrace(frames: &mut [Frame]) // 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! - 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; + match (ResStackWalkEx, ResStackWalk64) { + (Ok(StackWalkEx), _) => { + let mut frame: c::STACKFRAME_EX = unsafe { mem::zeroed() }; + frame.StackFrameSize = mem::size_of_val(&frame) as c::DWORD; + let image = init_frame_ex(&mut frame, &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; + } + } + + Ok((i, backtrace_context)) } + (_, Ok(StackWalk64)) => { + let mut frame: c::STACKFRAME64 = unsafe { mem::zeroed() }; + let image = init_frame_64(&mut frame, &context); + + // Start from -1 to avoid printing this stack frame, which will + // always be exactly the same. + let mut i = 0; + unsafe { + while i < frames.len() + && StackWalk64( + image, + process, + thread, + &mut frame, + &mut context, + ptr::null_mut(), + ptr::null_mut(), + ptr::null_mut(), + ptr::null_mut(), + ) == c::TRUE + { + let addr = frame.AddrPC.Offset; + if addr == frame.AddrReturn.Offset || addr == 0 || frame.AddrReturn.Offset == 0 + { + break; + } + + frames[i] = Frame { + symbol_addr: (addr - 1) as *const u8, + exact_position: (addr - 1) as *const u8, + inline_context: 0, + }; + i += 1; + } + } + + Ok((i, backtrace_context)) + } + (Err(e), _) => Err(e), } - - Ok((i, backtrace_context)) } -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 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; -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_ex(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 +} + +#[cfg(target_arch = "x86_64")] +fn init_frame_ex(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 +} #[cfg(target_arch = "x86")] -fn init_frame(frame: &mut c::STACKFRAME_EX, - ctx: &c::CONTEXT) -> c::DWORD { +fn init_frame_64(frame: &mut c::STACKFRAME64, 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; @@ -129,8 +216,7 @@ fn init_frame(frame: &mut c::STACKFRAME_EX, } #[cfg(target_arch = "x86_64")] -fn init_frame(frame: &mut c::STACKFRAME_EX, - ctx: &c::CONTEXT) -> c::DWORD { +fn init_frame_64(frame: &mut c::STACKFRAME64, 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; diff --git a/src/libstd/sys/windows/backtrace/printing/msvc.rs b/src/libstd/sys/windows/backtrace/printing/msvc.rs index 967df1c8a2d..e26d95a4f9d 100644 --- a/src/libstd/sys/windows/backtrace/printing/msvc.rs +++ b/src/libstd/sys/windows/backtrace/printing/msvc.rs @@ -10,88 +10,209 @@ 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::c; use sys_common::backtrace::Frame; 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 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; + +type SymFromAddrFn = + unsafe extern "system" fn(c::HANDLE, u64, *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; /// Converts a pointer to symbol to its string value. -pub fn resolve_symname(frame: Frame, - callback: F, - context: &BacktraceContext) -> io::Result<()> - where F: FnOnce(Option<&str>) -> io::Result<()> +pub fn resolve_symname(frame: Frame, callback: F, context: &BacktraceContext) -> io::Result<()> +where + F: FnOnce(Option<&str>) -> io::Result<()>, { - let SymFromInlineContext = sym!(&context.dbghelp, - "SymFromInlineContext", - SymFromInlineContextFn)?; + match ( + sym!( + &context.dbghelp, + "SymFromInlineContext", + SymFromInlineContextFn + ), + sym!(&context.dbghelp, "SymFromAddr", SymFromAddrFn), + ) { + (Ok(SymFromInlineContext), _) => unsafe { + let mut info: c::SYMBOL_INFO = mem::zeroed(); + info.MaxNameLen = c::MAX_SYM_NAME as c_ulong; + // the struct size in C. the value is different to + // `size_of::() - MAX_SYM_NAME + 1` (== 81) + // due to struct alignment. + info.SizeOfStruct = 88; - unsafe { - let mut info: c::SYMBOL_INFO = mem::zeroed(); - info.MaxNameLen = c::MAX_SYM_NAME as c_ulong; - // the struct size in C. the value is different to - // `size_of::() - MAX_SYM_NAME + 1` (== 81) - // 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 { + if info.Size != 0 { + (frame.symbol_addr as usize) < info.Address as usize + info.Size as usize + } else { + true + } + } else { + false + }; + let symname = if valid_range { + let ptr = info.Name.as_ptr() as *const c_char; + CStr::from_ptr(ptr).to_str().ok() + } else { + None + }; + callback(symname) +{ + match ( + sym!( + &context.dbghelp, + "SymFromInlineContext", + SymFromInlineContextFn + ), + sym!(&context.dbghelp, "SymFromAddr", SymFromAddrFn), + ) { + (Ok(SymFromInlineContext), _) => unsafe { + let mut info: c::SYMBOL_INFO = mem::zeroed(); + info.MaxNameLen = c::MAX_SYM_NAME as c_ulong; + // the struct size in C. the value is different to + // `size_of::() - MAX_SYM_NAME + 1` (== 81) + // 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 { - if info.Size != 0 { - (frame.symbol_addr as usize) < info.Address as usize + info.Size as usize + 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 { + if info.Size != 0 { + (frame.symbol_addr as usize) < info.Address as usize + info.Size as usize + } else { + true + } + } else { + false + }; + let symname = if valid_range { + let ptr = info.Name.as_ptr() as *const c_char; + CStr::from_ptr(ptr).to_str().ok() } else { - true - } - } else { - false - }; - let symname = if valid_range { - let ptr = info.Name.as_ptr() as *const c_char; - CStr::from_ptr(ptr).to_str().ok() - } else { - None - }; - callback(symname) + None + }; + callback(symname) + }, + (_, Ok(SymFromAddr)) => unsafe { + } else { + None + }; + callback(symname) + }, + (_, Ok(SymFromAddr)) => unsafe { + let mut info: c::SYMBOL_INFO = mem::zeroed(); + info.MaxNameLen = c::MAX_SYM_NAME as c_ulong; + // the struct size in C. the value is different to + // `size_of::() - MAX_SYM_NAME + 1` (== 81) + // due to struct alignment. + info.SizeOfStruct = 88; + + let mut displacement = 0u64; + let ret = SymFromAddr( + context.handle, + frame.symbol_addr as u64, + &mut displacement, + &mut info, + ); + + let symname = if ret == c::TRUE { + let ptr = info.Name.as_ptr() as *const c_char; + CStr::from_ptr(ptr).to_str().ok() + } else { + None + }; + callback(symname) + }, + (Err(e), _) => Err(e), } } -pub fn foreach_symbol_fileline(frame: Frame, - mut f: F, - context: &BacktraceContext) - -> io::Result - where F: FnMut(&[u8], u32) -> io::Result<()> +pub fn foreach_symbol_fileline( + frame: Frame, + mut f: F, + context: &BacktraceContext, +) -> io::Result +where + F: FnMut(&[u8], u32) -> io::Result<()>, { - let SymGetLineFromInlineContext = sym!(&context.dbghelp, - "SymGetLineFromInlineContext", - SymGetLineFromInlineContextFn)?; + match ( + sym!( + &context.dbghelp, + "SymGetLineFromInlineContext", + SymGetLineFromInlineContextFn + ), + sym!( + &context.dbghelp, + "SymGetLineFromAddr64", + SymGetLineFromAddr64Fn + ), + ) { + (Ok(SymGetLineFromInlineContext), _) => unsafe { + let mut line: c::IMAGEHLP_LINE64 = mem::zeroed(); + line.SizeOfStruct = ::mem::size_of::() as u32; - unsafe { - let mut line: c::IMAGEHLP_LINE64 = mem::zeroed(); - line.SizeOfStruct = ::mem::size_of::() as u32; + let mut displacement = 0u32; + let ret = SymGetLineFromInlineContext( + context.handle, + frame.exact_position as u64, + frame.inline_context, + 0, + &mut displacement, + &mut line, + ); + if ret == c::TRUE { + let name = CStr::from_ptr(line.Filename).to_bytes(); + f(name, line.LineNumber as u32)?; + } + Ok(false) + }, + (_, Ok(SymGetLineFromAddr64)) => unsafe { + let mut line: c::IMAGEHLP_LINE64 = mem::zeroed(); + line.SizeOfStruct = ::mem::size_of::() as u32; - let mut displacement = 0u32; - let ret = SymGetLineFromInlineContext(context.handle, - frame.exact_position as u64, - frame.inline_context, - 0, - &mut displacement, - &mut line); - if ret == c::TRUE { - let name = CStr::from_ptr(line.Filename).to_bytes(); - f(name, line.LineNumber as u32)?; - } - Ok(false) + let mut displacement = 0u32; + let ret = SymGetLineFromAddr64( + context.handle, + frame.exact_position as u64, + &mut displacement, + &mut line, + ); + if ret == c::TRUE { + let name = CStr::from_ptr(line.Filename).to_bytes(); + f(name, line.LineNumber as u32)?; + } + Ok(false) + }, + (Err(e), _) => Err(e), } } diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs index 6d929f21365..30aba2f400f 100644 --- a/src/libstd/sys/windows/c.rs +++ b/src/libstd/sys/windows/c.rs @@ -635,6 +635,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 { -- cgit 1.4.1-3-g733a5 From 3245a475ab92b5ab77cf69e336279420c86a83eb Mon Sep 17 00:00:00 2001 From: moxian Date: Sun, 13 May 2018 04:38:43 +0000 Subject: Split separate stackwalk variants into their own functions .. rather than having them be one giant match statement. --- src/libstd/sys/windows/backtrace/mod.rs | 194 ++++++++++------- src/libstd/sys/windows/backtrace/printing/msvc.rs | 248 +++++++++++----------- 2 files changed, 238 insertions(+), 204 deletions(-) (limited to 'src/libstd/sys/windows') diff --git a/src/libstd/sys/windows/backtrace/mod.rs b/src/libstd/sys/windows/backtrace/mod.rs index 8e879e0f49e..884ec4e9fad 100644 --- a/src/libstd/sys/windows/backtrace/mod.rs +++ b/src/libstd/sys/windows/backtrace/mod.rs @@ -46,7 +46,7 @@ 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}; pub fn unwind_backtrace(frames: &mut [Frame]) -> io::Result<(usize, BacktraceContext)> { let dbghelp = DynamicLibrary::open("dbghelp.dll")?; @@ -54,19 +54,30 @@ pub fn unwind_backtrace(frames: &mut [Frame]) -> io::Result<(usize, BacktraceCon // Fetch the symbols necessary from dbghelp.dll let SymInitialize = sym!(dbghelp, "SymInitialize", SymInitializeFn)?; let SymCleanup = sym!(dbghelp, "SymCleanup", SymCleanupFn)?; + + // enum for holding the StackWalk function. Different from StackWalkVariant + // below, since there's no need to pass the function itself into + // the BacktraceContext + enum sw_fn_local { + SWExFn(StackWalkExFn), + SW64Fn(StackWalk64Fn), + } // StackWalkEx might not be present and we'll fall back to StackWalk64 - let ResStackWalkEx = sym!(dbghelp, "StackWalkEx", StackWalkExFn); - let ResStackWalk64 = sym!(dbghelp, "StackWalk64", StackWalk64Fn); + let (StackWalkFn, variant) = + sym!(dbghelp, "StackWalkEx", StackWalkExFn) + .map(|f| (sw_fn_local::SWExFn(f), StackWalkVariant::StackWalkEx)) + .or_else(|_| + sym!(dbghelp, "StackWalk64", StackWalk64Fn) + .map(|f| (sw_fn_local::SW64Fn(f), StackWalkVariant::StackWalk64)) + )?; // 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 backtrace_context = BacktraceContext { handle: process, SymCleanup, + StackWalkVariant: variant, dbghelp, }; @@ -77,81 +88,102 @@ pub fn unwind_backtrace(frames: &mut [Frame]) -> io::Result<(usize, BacktraceCon } // And now that we're done with all the setup, do the stack walking! - match (ResStackWalkEx, ResStackWalk64) { - (Ok(StackWalkEx), _) => { - let mut frame: c::STACKFRAME_EX = unsafe { mem::zeroed() }; - frame.StackFrameSize = mem::size_of_val(&frame) as c::DWORD; - let image = init_frame_ex(&mut frame, &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; - } - } + match StackWalkFn { + sw_fn_local::SWExFn(f) => set_frames_ex(f, frames, backtrace_context, process), + sw_fn_local::SW64Fn(f) => set_frames_64(f, frames, backtrace_context, process), + } +} - Ok((i, backtrace_context)) +fn set_frames_ex( + StackWalkEx: StackWalkExFn, + frames: &mut [Frame], + backtrace_context: BacktraceContext, + process: c::HANDLE, +) -> io::Result<(usize, BacktraceContext)> { + let thread = unsafe { c::GetCurrentProcess() }; + 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_ex(&mut frame, &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; } - (_, Ok(StackWalk64)) => { - let mut frame: c::STACKFRAME64 = unsafe { mem::zeroed() }; - let image = init_frame_64(&mut frame, &context); - - // Start from -1 to avoid printing this stack frame, which will - // always be exactly the same. - let mut i = 0; - unsafe { - while i < frames.len() - && StackWalk64( - image, - process, - thread, - &mut frame, - &mut context, - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - ) == c::TRUE - { - let addr = frame.AddrPC.Offset; - if addr == frame.AddrReturn.Offset || addr == 0 || frame.AddrReturn.Offset == 0 - { - break; - } - - frames[i] = Frame { - symbol_addr: (addr - 1) as *const u8, - exact_position: (addr - 1) as *const u8, - inline_context: 0, - }; - i += 1; - } + } + + Ok((i, backtrace_context)) +} + +fn set_frames_64( + StackWalk64: StackWalk64Fn, + frames: &mut [Frame], + backtrace_context: BacktraceContext, + process: c::HANDLE, +) -> io::Result<(usize, BacktraceContext)> { + let thread = unsafe { c::GetCurrentProcess() }; + let mut context: c::CONTEXT = unsafe { mem::zeroed() }; + unsafe { c::RtlCaptureContext(&mut context) }; + + let mut frame: c::STACKFRAME64 = unsafe { mem::zeroed() }; + let image = init_frame_64(&mut frame, &context); + + // Start from -1 to avoid printing this stack frame, which will + // always be exactly the same. + let mut i = 0; + unsafe { + while i < frames.len() + && StackWalk64( + image, + process, + thread, + &mut frame, + &mut context, + ptr::null_mut(), + ptr::null_mut(), + ptr::null_mut(), + ptr::null_mut(), + ) == c::TRUE + { + let addr = frame.AddrPC.Offset; + if addr == frame.AddrReturn.Offset || addr == 0 || frame.AddrReturn.Offset == 0 + { + break; } - Ok((i, backtrace_context)) + frames[i] = Frame { + symbol_addr: (addr - 1) as *const u8, + exact_position: (addr - 1) as *const u8, + inline_context: 0, + }; + i += 1; } - (Err(e), _) => Err(e), } + + Ok((i, backtrace_context)) } type SymInitializeFn = unsafe extern "system" fn(c::HANDLE, *mut c_void, c::BOOL) -> c::BOOL; @@ -226,16 +258,26 @@ fn init_frame_64(frame: &mut c::STACKFRAME64, ctx: &c::CONTEXT) -> c::DWORD { c::IMAGE_FILE_MACHINE_AMD64 } +enum StackWalkVariant { + StackWalkEx, + StackWalk64, +} + + pub struct BacktraceContext { handle: c::HANDLE, SymCleanup: SymCleanupFn, // Only used in printing for msvc and not gnu #[allow(dead_code)] + StackWalkVariant: StackWalkVariant, + #[allow(dead_code)] dbghelp: DynamicLibrary, } impl Drop for BacktraceContext { fn drop(&mut self) { - unsafe { (self.SymCleanup)(self.handle); } + unsafe { + (self.SymCleanup)(self.handle); + } } } diff --git a/src/libstd/sys/windows/backtrace/printing/msvc.rs b/src/libstd/sys/windows/backtrace/printing/msvc.rs index e26d95a4f9d..9d7accb7ad7 100644 --- a/src/libstd/sys/windows/backtrace/printing/msvc.rs +++ b/src/libstd/sys/windows/backtrace/printing/msvc.rs @@ -13,11 +13,10 @@ use io; use libc::{c_char, c_ulong}; use mem; use sys::backtrace::BacktraceContext; +use sys::backtrace::StackWalkVariant; use sys::c; use sys_common::backtrace::Frame; -type SymFromInlineContextFn = - unsafe extern "system" fn(c::HANDLE, u64, c::ULONG, *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( @@ -39,57 +38,26 @@ pub fn resolve_symname(frame: Frame, callback: F, context: &BacktraceContext) where F: FnOnce(Option<&str>) -> io::Result<()>, { - match ( - sym!( - &context.dbghelp, - "SymFromInlineContext", - SymFromInlineContextFn - ), - sym!(&context.dbghelp, "SymFromAddr", SymFromAddrFn), - ) { - (Ok(SymFromInlineContext), _) => unsafe { - let mut info: c::SYMBOL_INFO = mem::zeroed(); - info.MaxNameLen = c::MAX_SYM_NAME as c_ulong; - // the struct size in C. the value is different to - // `size_of::() - MAX_SYM_NAME + 1` (== 81) - // due to struct alignment. - info.SizeOfStruct = 88; + match context.StackWalkVariant { + StackWalkVariant::StackWalkEx => { + let SymFromInlineContext = + sym!(&context.dbghelp, "SymFromInlineContext",SymFromInlineContextFn)?; + resolve_symname_from_inline_context(SymFromInlineContext, frame, callback, context) + }, + StackWalkVariant::StackWalk64 => { + let SymFromAddr = sym!(&context.dbghelp, "SymFromAddr", SymFromAddrFn)?; + resolve_symname_from_addr(SymFromAddr, frame, callback, context) + } + } +} - 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 { - if info.Size != 0 { - (frame.symbol_addr as usize) < info.Address as usize + info.Size as usize - } else { - true - } - } else { - false - }; - let symname = if valid_range { - let ptr = info.Name.as_ptr() as *const c_char; - CStr::from_ptr(ptr).to_str().ok() - } else { - None - }; - callback(symname) +fn resolve_symname_from_inline_context( + SymFromInlineContext: SymFromInlineContextFn, + frame: Frame, callback: F, context: &BacktraceContext) -> io::Result<()> +where + F: FnOnce(Option<&str>) -> io::Result<()>, { - match ( - sym!( - &context.dbghelp, - "SymFromInlineContext", - SymFromInlineContextFn - ), - sym!(&context.dbghelp, "SymFromAddr", SymFromAddrFn), - ) { - (Ok(SymFromInlineContext), _) => unsafe { + unsafe { let mut info: c::SYMBOL_INFO = mem::zeroed(); info.MaxNameLen = c::MAX_SYM_NAME as c_ulong; // the struct size in C. the value is different to @@ -122,42 +90,69 @@ where None }; callback(symname) - }, - (_, Ok(SymFromAddr)) => unsafe { - } else { - None - }; - callback(symname) - }, - (_, Ok(SymFromAddr)) => unsafe { - let mut info: c::SYMBOL_INFO = mem::zeroed(); - info.MaxNameLen = c::MAX_SYM_NAME as c_ulong; - // the struct size in C. the value is different to - // `size_of::() - MAX_SYM_NAME + 1` (== 81) - // due to struct alignment. - info.SizeOfStruct = 88; + } +} - let mut displacement = 0u64; - let ret = SymFromAddr( - context.handle, - frame.symbol_addr as u64, - &mut displacement, - &mut info, - ); +fn resolve_symname_from_addr( + SymFromAddr: SymFromAddrFn, + frame: Frame, callback: F, context: &BacktraceContext) -> io::Result<()> +where + F: FnOnce(Option<&str>) -> io::Result<()>, +{ + unsafe { + let mut info: c::SYMBOL_INFO = mem::zeroed(); + info.MaxNameLen = c::MAX_SYM_NAME as c_ulong; + // the struct size in C. the value is different to + // `size_of::() - MAX_SYM_NAME + 1` (== 81) + // due to struct alignment. + info.SizeOfStruct = 88; - let symname = if ret == c::TRUE { - let ptr = info.Name.as_ptr() as *const c_char; - CStr::from_ptr(ptr).to_str().ok() - } else { - None - }; - callback(symname) - }, - (Err(e), _) => Err(e), + let mut displacement = 0u64; + let ret = SymFromAddr( + context.handle, + frame.symbol_addr as u64, + &mut displacement, + &mut info, + ); + + let symname = if ret == c::TRUE { + let ptr = info.Name.as_ptr() as *const c_char; + CStr::from_ptr(ptr).to_str().ok() + } else { + None + }; + callback(symname) } } pub fn foreach_symbol_fileline( + frame: Frame, + f: F, + context: &BacktraceContext, +) -> io::Result +where + F: FnMut(&[u8], u32) -> io::Result<()>, +{ + match context.StackWalkVariant { + StackWalkVariant::StackWalkEx => { + let SymGetLineFromInlineContext = + sym!(&context.dbghelp, "SymGetLineFromInlineContext", + SymGetLineFromInlineContextFn)?; + foreach_symbol_fileline_ex(SymGetLineFromInlineContext, + frame, f, context) + }, + StackWalkVariant::StackWalk64 => { + let SymGetLineFromAddr64 = + sym!(&context.dbghelp, "SymGetLineFromAddr64", + SymGetLineFromAddr64Fn)?; + foreach_symbol_fileline_64(SymGetLineFromAddr64, + frame, f, context) + } + } +} + +fn foreach_symbol_fileline_ex( + SymGetLineFromInlineContext: SymGetLineFromInlineContextFn, frame: Frame, mut f: F, context: &BacktraceContext, @@ -165,54 +160,51 @@ pub fn foreach_symbol_fileline( where F: FnMut(&[u8], u32) -> io::Result<()>, { - match ( - sym!( - &context.dbghelp, - "SymGetLineFromInlineContext", - SymGetLineFromInlineContextFn - ), - sym!( - &context.dbghelp, - "SymGetLineFromAddr64", - SymGetLineFromAddr64Fn - ), - ) { - (Ok(SymGetLineFromInlineContext), _) => unsafe { - let mut line: c::IMAGEHLP_LINE64 = mem::zeroed(); - line.SizeOfStruct = ::mem::size_of::() as u32; + unsafe { + let mut line: c::IMAGEHLP_LINE64 = mem::zeroed(); + line.SizeOfStruct = ::mem::size_of::() as u32; - let mut displacement = 0u32; - let ret = SymGetLineFromInlineContext( - context.handle, - frame.exact_position as u64, - frame.inline_context, - 0, - &mut displacement, - &mut line, - ); - if ret == c::TRUE { - let name = CStr::from_ptr(line.Filename).to_bytes(); - f(name, line.LineNumber as u32)?; - } - Ok(false) - }, - (_, Ok(SymGetLineFromAddr64)) => unsafe { - let mut line: c::IMAGEHLP_LINE64 = mem::zeroed(); - line.SizeOfStruct = ::mem::size_of::() as u32; + let mut displacement = 0u32; + let ret = SymGetLineFromInlineContext( + context.handle, + frame.exact_position as u64, + frame.inline_context, + 0, + &mut displacement, + &mut line, + ); + if ret == c::TRUE { + let name = CStr::from_ptr(line.Filename).to_bytes(); + f(name, line.LineNumber as u32)?; + } + Ok(false) + } +} - let mut displacement = 0u32; - let ret = SymGetLineFromAddr64( - context.handle, - frame.exact_position as u64, - &mut displacement, - &mut line, - ); - if ret == c::TRUE { - let name = CStr::from_ptr(line.Filename).to_bytes(); - f(name, line.LineNumber as u32)?; - } - Ok(false) - }, - (Err(e), _) => Err(e), +fn foreach_symbol_fileline_64( + SymGetLineFromAddr64: SymGetLineFromAddr64Fn, + frame: Frame, + mut f: F, + context: &BacktraceContext, +) -> io::Result +where + F: FnMut(&[u8], u32) -> io::Result<()>, +{ + unsafe { + let mut line: c::IMAGEHLP_LINE64 = mem::zeroed(); + line.SizeOfStruct = ::mem::size_of::() as u32; + + let mut displacement = 0u32; + let ret = SymGetLineFromAddr64( + context.handle, + frame.exact_position as u64, + &mut displacement, + &mut line, + ); + if ret == c::TRUE { + let name = CStr::from_ptr(line.Filename).to_bytes(); + f(name, line.LineNumber as u32)?; + } + Ok(false) } } -- cgit 1.4.1-3-g733a5 From c0b280f5f594fc6ff34ddcf35aa26cc46a073808 Mon Sep 17 00:00:00 2001 From: moxian Date: Sun, 13 May 2018 08:41:24 +0000 Subject: Load backtrace-related functions only once .. and pass them around in BacktraceContext. --- src/libstd/sys/windows/backtrace/mod.rs | 45 +++++++++-------- src/libstd/sys/windows/backtrace/printing/mod.rs | 14 ++++++ src/libstd/sys/windows/backtrace/printing/msvc.rs | 59 +++++++++++++++-------- 3 files changed, 77 insertions(+), 41 deletions(-) (limited to 'src/libstd/sys/windows') diff --git a/src/libstd/sys/windows/backtrace/mod.rs b/src/libstd/sys/windows/backtrace/mod.rs index 884ec4e9fad..23bb4ab6dfe 100644 --- a/src/libstd/sys/windows/backtrace/mod.rs +++ b/src/libstd/sys/windows/backtrace/mod.rs @@ -47,6 +47,7 @@ mod printing; pub mod gnu; pub use self::printing::{foreach_symbol_fileline, resolve_symname}; +use self::printing::{load_printing_fns_ex, load_printing_fns_64}; pub fn unwind_backtrace(frames: &mut [Frame]) -> io::Result<(usize, BacktraceContext)> { let dbghelp = DynamicLibrary::open("dbghelp.dll")?; @@ -55,21 +56,23 @@ pub fn unwind_backtrace(frames: &mut [Frame]) -> io::Result<(usize, BacktraceCon let SymInitialize = sym!(dbghelp, "SymInitialize", SymInitializeFn)?; let SymCleanup = sym!(dbghelp, "SymCleanup", SymCleanupFn)?; - // enum for holding the StackWalk function. Different from StackWalkVariant - // below, since there's no need to pass the function itself into - // the BacktraceContext - enum sw_fn_local { - SWExFn(StackWalkExFn), - SW64Fn(StackWalk64Fn), - } + // StackWalkEx might not be present and we'll fall back to StackWalk64 - let (StackWalkFn, variant) = - sym!(dbghelp, "StackWalkEx", StackWalkExFn) - .map(|f| (sw_fn_local::SWExFn(f), StackWalkVariant::StackWalkEx)) - .or_else(|_| - sym!(dbghelp, "StackWalk64", StackWalk64Fn) - .map(|f| (sw_fn_local::SW64Fn(f), StackWalkVariant::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() }; @@ -77,7 +80,7 @@ pub fn unwind_backtrace(frames: &mut [Frame]) -> io::Result<(usize, BacktraceCon let backtrace_context = BacktraceContext { handle: process, SymCleanup, - StackWalkVariant: variant, + StackWalkVariant: sw_var, dbghelp, }; @@ -88,9 +91,9 @@ pub fn unwind_backtrace(frames: &mut [Frame]) -> io::Result<(usize, BacktraceCon } // And now that we're done with all the setup, do the stack walking! - match StackWalkFn { - sw_fn_local::SWExFn(f) => set_frames_ex(f, frames, backtrace_context, process), - sw_fn_local::SW64Fn(f) => set_frames_64(f, frames, backtrace_context, process), + match backtrace_context.StackWalkVariant { + StackWalkVariant::StackWalkEx(f, _) => set_frames_ex(f, frames, backtrace_context, process), + StackWalkVariant::StackWalk64(f, _) => set_frames_64(f, frames, backtrace_context, process), } } @@ -259,8 +262,8 @@ fn init_frame_64(frame: &mut c::STACKFRAME64, ctx: &c::CONTEXT) -> c::DWORD { } enum StackWalkVariant { - StackWalkEx, - StackWalk64, + StackWalkEx(StackWalkExFn, printing::PrintingFnsEx), + StackWalk64(StackWalk64Fn, printing::PrintingFns64), } @@ -268,8 +271,10 @@ 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, } diff --git a/src/libstd/sys/windows/backtrace/printing/mod.rs b/src/libstd/sys/windows/backtrace/printing/mod.rs index 3e566f6e2bd..251d5028aea 100644 --- a/src/libstd/sys/windows/backtrace/printing/mod.rs +++ b/src/libstd/sys/windows/backtrace/printing/mod.rs @@ -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 { + Ok(PrintingFnsEx{}) + } + pub fn load_printing_fns_64(_: &DynamicLibrary) -> io::Result { + 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}; diff --git a/src/libstd/sys/windows/backtrace/printing/msvc.rs b/src/libstd/sys/windows/backtrace/printing/msvc.rs index 9d7accb7ad7..9cfc2c3d352 100644 --- a/src/libstd/sys/windows/backtrace/printing/msvc.rs +++ b/src/libstd/sys/windows/backtrace/printing/msvc.rs @@ -15,8 +15,38 @@ use mem; 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 { + 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 { + Ok(PrintingFns64{ + resolve_symname: sym!(dbghelp, "SymFromAddr", SymFromAddrFn)?, + sym_get_line: sym!(dbghelp, "SymGetLineFromAddr64", + SymGetLineFromAddr64Fn)?, + }) +} + 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( @@ -39,14 +69,11 @@ where F: FnOnce(Option<&str>) -> io::Result<()>, { match context.StackWalkVariant { - StackWalkVariant::StackWalkEx => { - let SymFromInlineContext = - sym!(&context.dbghelp, "SymFromInlineContext",SymFromInlineContextFn)?; - resolve_symname_from_inline_context(SymFromInlineContext, frame, callback, context) + StackWalkVariant::StackWalkEx(_, ref fns) => { + resolve_symname_from_inline_context(fns.resolve_symname, frame, callback, context) }, - StackWalkVariant::StackWalk64 => { - let SymFromAddr = sym!(&context.dbghelp, "SymFromAddr", SymFromAddrFn)?; - resolve_symname_from_addr(SymFromAddr, frame, callback, context) + StackWalkVariant::StackWalk64(_, ref fns) => { + resolve_symname_from_addr(fns.resolve_symname, frame, callback, context) } } } @@ -134,20 +161,10 @@ where F: FnMut(&[u8], u32) -> io::Result<()>, { match context.StackWalkVariant { - StackWalkVariant::StackWalkEx => { - let SymGetLineFromInlineContext = - sym!(&context.dbghelp, "SymGetLineFromInlineContext", - SymGetLineFromInlineContextFn)?; - foreach_symbol_fileline_ex(SymGetLineFromInlineContext, - frame, f, context) - }, - StackWalkVariant::StackWalk64 => { - let SymGetLineFromAddr64 = - sym!(&context.dbghelp, "SymGetLineFromAddr64", - SymGetLineFromAddr64Fn)?; - foreach_symbol_fileline_64(SymGetLineFromAddr64, - frame, f, context) - } + StackWalkVariant::StackWalkEx(_, ref fns) => + foreach_symbol_fileline_ex(fns.sym_get_line, frame, f, context), + StackWalkVariant::StackWalk64(_, ref fns) => + foreach_symbol_fileline_64(fns.sym_get_line, frame, f, context), } } -- cgit 1.4.1-3-g733a5 From a0b15012a17594566311ea490eda243b6bd9d92b Mon Sep 17 00:00:00 2001 From: moxian Date: Fri, 18 May 2018 11:38:50 +0000 Subject: Make stackwalking generic instead of matching on enum variants. --- src/libstd/sys/windows/backtrace/mod.rs | 280 +++++++++++++++++--------------- 1 file changed, 147 insertions(+), 133 deletions(-) (limited to 'src/libstd/sys/windows') diff --git a/src/libstd/sys/windows/backtrace/mod.rs b/src/libstd/sys/windows/backtrace/mod.rs index 23bb4ab6dfe..7ef4e203571 100644 --- a/src/libstd/sys/windows/backtrace/mod.rs +++ b/src/libstd/sys/windows/backtrace/mod.rs @@ -47,7 +47,7 @@ mod printing; pub mod gnu; pub use self::printing::{foreach_symbol_fileline, resolve_symname}; -use self::printing::{load_printing_fns_ex, load_printing_fns_64}; +use self::printing::{load_printing_fns_64, load_printing_fns_ex}; pub fn unwind_backtrace(frames: &mut [Frame]) -> io::Result<(usize, BacktraceContext)> { let dbghelp = DynamicLibrary::open("dbghelp.dll")?; @@ -56,20 +56,15 @@ pub fn unwind_backtrace(frames: &mut [Frame]) -> io::Result<(usize, BacktraceCon let SymInitialize = sym!(dbghelp, "SymInitialize", SymInitializeFn)?; let SymCleanup = sym!(dbghelp, "SymCleanup", SymCleanupFn)?; - // 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)?, - ), + 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)?, - ), + Ok(StackWalk64) => { + StackWalkVariant::StackWalk64(StackWalk64, load_printing_fns_64(&dbghelp)?) + } Err(..) => return Err(e), }, }; @@ -92,101 +87,38 @@ pub fn unwind_backtrace(frames: &mut [Frame]) -> io::Result<(usize, BacktraceCon // And now that we're done with all the setup, do the stack walking! match backtrace_context.StackWalkVariant { - StackWalkVariant::StackWalkEx(f, _) => set_frames_ex(f, frames, backtrace_context, process), - StackWalkVariant::StackWalk64(f, _) => set_frames_64(f, frames, backtrace_context, process), - } -} - -fn set_frames_ex( - StackWalkEx: StackWalkExFn, - frames: &mut [Frame], - backtrace_context: BacktraceContext, - process: c::HANDLE, -) -> io::Result<(usize, BacktraceContext)> { - let thread = unsafe { c::GetCurrentProcess() }; - 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_ex(&mut frame, &context); + StackWalkVariant::StackWalkEx(StackWalkEx, _) => { + set_frames(StackWalkEx, frames).map(|i| (i, backtrace_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; + StackWalkVariant::StackWalk64(StackWalk64, _) => { + set_frames(StackWalk64, frames).map(|i| (i, backtrace_context)) } } - - Ok((i, backtrace_context)) } -fn set_frames_64( - StackWalk64: StackWalk64Fn, - frames: &mut [Frame], - backtrace_context: BacktraceContext, - process: c::HANDLE, -) -> io::Result<(usize, BacktraceContext)> { +fn set_frames(StackWalk: W, frames: &mut [Frame]) -> io::Result { + 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 frame: c::STACKFRAME64 = unsafe { mem::zeroed() }; - let image = init_frame_64(&mut frame, &context); - - // Start from -1 to avoid printing this stack frame, which will - // always be exactly the same. let mut i = 0; - unsafe { - while i < frames.len() - && StackWalk64( - image, - process, - thread, - &mut frame, - &mut context, - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - ) == c::TRUE - { - let addr = frame.AddrPC.Offset; - if addr == frame.AddrReturn.Offset || addr == 0 || frame.AddrReturn.Offset == 0 - { - break; - } - - frames[i] = Frame { - symbol_addr: (addr - 1) as *const u8, - exact_position: (addr - 1) as *const u8, - inline_context: 0, - }; - 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, backtrace_context)) + Ok(i) } type SymInitializeFn = unsafe extern "system" fn(c::HANDLE, *mut c_void, c::BOOL) -> c::BOOL; @@ -217,48 +149,131 @@ type StackWalk64Fn = unsafe extern "system" fn( *mut c_void, ) -> c::BOOL; -#[cfg(target_arch = "x86")] -fn init_frame_ex(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 +trait StackWalker { + type Item: StackFrame; + + fn walk(&self, c::DWORD, c::HANDLE, c::HANDLE, &mut Self::Item, &mut c::CONTEXT) -> c::BOOL; } -#[cfg(target_arch = "x86_64")] -fn init_frame_ex(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 +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; } -#[cfg(target_arch = "x86")] -fn init_frame_64(frame: &mut c::STACKFRAME64, 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::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 + } + + fn get_addr(&self) -> *const u8 { + (self.AddrPC.Offset - 1) as *const u8 + } } -#[cfg(target_arch = "x86_64")] -fn init_frame_64(frame: &mut c::STACKFRAME64, 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 +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 + } + + fn get_addr(&self) -> *const u8 { + (self.AddrPC.Offset - 1) as *const u8 + } } enum StackWalkVariant { @@ -266,7 +281,6 @@ enum StackWalkVariant { StackWalk64(StackWalk64Fn, printing::PrintingFns64), } - pub struct BacktraceContext { handle: c::HANDLE, SymCleanup: SymCleanupFn, -- cgit 1.4.1-3-g733a5 From 9d426ac387f2d42c998349c76ac1c2aea044e0ec Mon Sep 17 00:00:00 2001 From: moxian Date: Fri, 18 May 2018 12:33:23 +0000 Subject: Make msvc symbol extraction/printing functions generic. --- src/libstd/sys/windows/backtrace/printing/msvc.rs | 240 ++++++++++++---------- 1 file changed, 137 insertions(+), 103 deletions(-) (limited to 'src/libstd/sys/windows') diff --git a/src/libstd/sys/windows/backtrace/printing/msvc.rs b/src/libstd/sys/windows/backtrace/printing/msvc.rs index 9cfc2c3d352..d8f0a4d8208 100644 --- a/src/libstd/sys/windows/backtrace/printing/msvc.rs +++ b/src/libstd/sys/windows/backtrace/printing/msvc.rs @@ -18,7 +18,6 @@ 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) @@ -32,23 +31,29 @@ pub struct PrintingFns64 { } pub fn load_printing_fns_ex(dbghelp: &DynamicLibrary) -> io::Result { - Ok(PrintingFnsEx{ - resolve_symname: sym!(dbghelp, "SymFromInlineContext", - SymFromInlineContextFn)?, - sym_get_line: sym!(dbghelp, "SymGetLineFromInlineContext", - SymGetLineFromInlineContextFn)?, + 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 { - Ok(PrintingFns64{ + Ok(PrintingFns64 { resolve_symname: sym!(dbghelp, "SymFromAddr", SymFromAddrFn)?, - sym_get_line: sym!(dbghelp, "SymGetLineFromAddr64", - SymGetLineFromAddr64Fn)?, + 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 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, @@ -58,11 +63,6 @@ type SymGetLineFromInlineContextFn = unsafe extern "system" fn( *mut c::IMAGEHLP_LINE64, ) -> c::BOOL; -type SymFromAddrFn = - unsafe extern "system" fn(c::HANDLE, u64, *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; - /// Converts a pointer to symbol to its string value. pub fn resolve_symname(frame: Frame, callback: F, context: &BacktraceContext) -> io::Result<()> where @@ -70,61 +70,23 @@ where { match context.StackWalkVariant { StackWalkVariant::StackWalkEx(_, ref fns) => { - resolve_symname_from_inline_context(fns.resolve_symname, frame, callback, context) - }, + resolve_symname_internal(fns.resolve_symname, frame, callback, context) + } StackWalkVariant::StackWalk64(_, ref fns) => { - resolve_symname_from_addr(fns.resolve_symname, frame, callback, context) + resolve_symname_internal(fns.resolve_symname, frame, callback, context) } } } -fn resolve_symname_from_inline_context( - SymFromInlineContext: SymFromInlineContextFn, - frame: Frame, callback: F, context: &BacktraceContext) -> io::Result<()> -where - F: FnOnce(Option<&str>) -> io::Result<()>, -{ - unsafe { - let mut info: c::SYMBOL_INFO = mem::zeroed(); - info.MaxNameLen = c::MAX_SYM_NAME as c_ulong; - // the struct size in C. the value is different to - // `size_of::() - MAX_SYM_NAME + 1` (== 81) - // 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 { - if info.Size != 0 { - (frame.symbol_addr as usize) < info.Address as usize + info.Size as usize - } else { - true - } - } else { - false - }; - let symname = if valid_range { - let ptr = info.Name.as_ptr() as *const c_char; - CStr::from_ptr(ptr).to_str().ok() - } else { - None - }; - callback(symname) - } -} - -fn resolve_symname_from_addr( - SymFromAddr: SymFromAddrFn, - frame: Frame, callback: F, context: &BacktraceContext) -> io::Result<()> +fn resolve_symname_internal( + symbol_resolver: R, + frame: Frame, + callback: F, + context: &BacktraceContext, +) -> io::Result<()> where F: FnOnce(Option<&str>) -> io::Result<()>, + R: SymbolResolver, { unsafe { let mut info: c::SYMBOL_INFO = mem::zeroed(); @@ -134,15 +96,22 @@ where // due to struct alignment. info.SizeOfStruct = 88; - let mut displacement = 0u64; - let ret = SymFromAddr( + let ret = symbol_resolver.resolve_symbol( context.handle, frame.symbol_addr as u64, - &mut displacement, + frame.inline_context, &mut info, ); - - let symname = if ret == c::TRUE { + 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 { + true + } + } else { + false + }; + let symname = if valid_range { let ptr = info.Name.as_ptr() as *const c_char; CStr::from_ptr(ptr).to_str().ok() } else { @@ -152,76 +121,141 @@ where } } +trait SymbolResolver { + fn resolve_symbol( + &self, + process: c::HANDLE, + symbol_address: u64, + inline_context: c::ULONG, + info: *mut c::SYMBOL_INFO, + ) -> c::BOOL; +} + +impl SymbolResolver for SymFromAddrFn { + fn resolve_symbol( + &self, + process: c::HANDLE, + symbol_address: u64, + _inline_context: c::ULONG, + info: *mut c::SYMBOL_INFO, + ) -> c::BOOL { + unsafe { + let mut displacement = 0u64; + self(process, symbol_address, &mut displacement, info) + } + } +} + +impl SymbolResolver for SymFromInlineContextFn { + fn resolve_symbol( + &self, + process: c::HANDLE, + symbol_address: u64, + inline_context: c::ULONG, + info: *mut c::SYMBOL_INFO, + ) -> c::BOOL { + unsafe { + let mut displacement = 0u64; + self( + process, + symbol_address, + inline_context, + &mut displacement, + info, + ) + } + } +} + pub fn foreach_symbol_fileline( frame: Frame, - f: F, + callback: F, context: &BacktraceContext, ) -> io::Result where F: FnMut(&[u8], u32) -> io::Result<()>, { match context.StackWalkVariant { - StackWalkVariant::StackWalkEx(_, ref fns) => - foreach_symbol_fileline_ex(fns.sym_get_line, frame, f, context), - StackWalkVariant::StackWalk64(_, ref fns) => - foreach_symbol_fileline_64(fns.sym_get_line, frame, f, context), + StackWalkVariant::StackWalkEx(_, ref fns) => { + foreach_symbol_fileline_iternal(fns.sym_get_line, frame, callback, context) + } + StackWalkVariant::StackWalk64(_, ref fns) => { + foreach_symbol_fileline_iternal(fns.sym_get_line, frame, callback, context) + } } } -fn foreach_symbol_fileline_ex( - SymGetLineFromInlineContext: SymGetLineFromInlineContextFn, +fn foreach_symbol_fileline_iternal( + line_getter: G, frame: Frame, - mut f: F, + mut callback: F, context: &BacktraceContext, ) -> io::Result where F: FnMut(&[u8], u32) -> io::Result<()>, + G: LineGetter, { unsafe { let mut line: c::IMAGEHLP_LINE64 = mem::zeroed(); line.SizeOfStruct = ::mem::size_of::() as u32; - let mut displacement = 0u32; - let ret = SymGetLineFromInlineContext( + let ret = line_getter.get_line( context.handle, frame.exact_position as u64, frame.inline_context, - 0, - &mut displacement, &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) } } -fn foreach_symbol_fileline_64( - SymGetLineFromAddr64: SymGetLineFromAddr64Fn, - frame: Frame, - mut f: F, - context: &BacktraceContext, -) -> io::Result -where - F: FnMut(&[u8], u32) -> io::Result<()>, -{ - unsafe { - let mut line: c::IMAGEHLP_LINE64 = mem::zeroed(); - line.SizeOfStruct = ::mem::size_of::() as u32; +trait LineGetter { + fn get_line( + &self, + process: c::HANDLE, + frame_address: u64, + inline_context: c::ULONG, + line: *mut c::IMAGEHLP_LINE64, + ) -> c::BOOL; +} - let mut displacement = 0u32; - let ret = SymGetLineFromAddr64( - context.handle, - frame.exact_position as u64, - &mut displacement, - &mut line, - ); - if ret == c::TRUE { - let name = CStr::from_ptr(line.Filename).to_bytes(); - f(name, line.LineNumber as u32)?; +impl LineGetter for SymGetLineFromAddr64Fn { + fn get_line( + &self, + process: c::HANDLE, + frame_address: u64, + _inline_context: c::ULONG, + line: *mut c::IMAGEHLP_LINE64, + ) -> c::BOOL { + unsafe { + let mut displacement = 0u32; + self(process, frame_address, &mut displacement, line) + } + } +} + +impl LineGetter for SymGetLineFromInlineContextFn { + fn get_line( + &self, + process: c::HANDLE, + frame_address: u64, + inline_context: c::ULONG, + line: *mut c::IMAGEHLP_LINE64, + ) -> c::BOOL { + unsafe { + let mut displacement = 0u32; + self( + process, + frame_address, + inline_context, + 0, + &mut displacement, + line, + ) } - Ok(false) } } -- cgit 1.4.1-3-g733a5 From be7f619870085121bdd7911aa882c35e70aedb8a Mon Sep 17 00:00:00 2001 From: moxian Date: Mon, 4 Jun 2018 11:00:12 +0000 Subject: Change traits to bare FnMut where possible. --- src/libstd/sys/windows/backtrace/printing/msvc.rs | 178 ++++++++-------------- 1 file changed, 67 insertions(+), 111 deletions(-) (limited to 'src/libstd/sys/windows') diff --git a/src/libstd/sys/windows/backtrace/printing/msvc.rs b/src/libstd/sys/windows/backtrace/printing/msvc.rs index d8f0a4d8208..c8b946bf13a 100644 --- a/src/libstd/sys/windows/backtrace/printing/msvc.rs +++ b/src/libstd/sys/windows/backtrace/printing/msvc.rs @@ -69,24 +69,48 @@ where F: FnOnce(Option<&str>) -> io::Result<()>, { match context.StackWalkVariant { - StackWalkVariant::StackWalkEx(_, ref fns) => { - resolve_symname_internal(fns.resolve_symname, frame, callback, context) - } - StackWalkVariant::StackWalk64(_, ref fns) => { - resolve_symname_internal(fns.resolve_symname, frame, callback, context) - } + 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( - symbol_resolver: R, + mut symbol_resolver: R, frame: Frame, callback: F, context: &BacktraceContext, ) -> io::Result<()> where F: FnOnce(Option<&str>) -> io::Result<()>, - R: SymbolResolver, + R: FnMut(c::HANDLE, u64, c::ULONG, *mut c::SYMBOL_INFO) -> c::BOOL, { unsafe { let mut info: c::SYMBOL_INFO = mem::zeroed(); @@ -96,7 +120,7 @@ where // due to struct alignment. info.SizeOfStruct = 88; - let ret = symbol_resolver.resolve_symbol( + let ret = symbol_resolver( context.handle, frame.symbol_addr as u64, frame.inline_context, @@ -121,52 +145,6 @@ where } } -trait SymbolResolver { - fn resolve_symbol( - &self, - process: c::HANDLE, - symbol_address: u64, - inline_context: c::ULONG, - info: *mut c::SYMBOL_INFO, - ) -> c::BOOL; -} - -impl SymbolResolver for SymFromAddrFn { - fn resolve_symbol( - &self, - process: c::HANDLE, - symbol_address: u64, - _inline_context: c::ULONG, - info: *mut c::SYMBOL_INFO, - ) -> c::BOOL { - unsafe { - let mut displacement = 0u64; - self(process, symbol_address, &mut displacement, info) - } - } -} - -impl SymbolResolver for SymFromInlineContextFn { - fn resolve_symbol( - &self, - process: c::HANDLE, - symbol_address: u64, - inline_context: c::ULONG, - info: *mut c::SYMBOL_INFO, - ) -> c::BOOL { - unsafe { - let mut displacement = 0u64; - self( - process, - symbol_address, - inline_context, - &mut displacement, - info, - ) - } - } -} - pub fn foreach_symbol_fileline( frame: Frame, callback: F, @@ -176,30 +154,55 @@ where F: FnMut(&[u8], u32) -> io::Result<()>, { match context.StackWalkVariant { - StackWalkVariant::StackWalkEx(_, ref fns) => { - foreach_symbol_fileline_iternal(fns.sym_get_line, frame, callback, context) - } - StackWalkVariant::StackWalk64(_, ref fns) => { - foreach_symbol_fileline_iternal(fns.sym_get_line, frame, callback, context) - } + 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( - line_getter: G, + mut line_getter: G, frame: Frame, mut callback: F, context: &BacktraceContext, ) -> io::Result where F: FnMut(&[u8], u32) -> io::Result<()>, - G: LineGetter, + 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::() as u32; - let ret = line_getter.get_line( + let ret = line_getter( context.handle, frame.exact_position as u64, frame.inline_context, @@ -212,50 +215,3 @@ where Ok(false) } } - -trait LineGetter { - fn get_line( - &self, - process: c::HANDLE, - frame_address: u64, - inline_context: c::ULONG, - line: *mut c::IMAGEHLP_LINE64, - ) -> c::BOOL; -} - -impl LineGetter for SymGetLineFromAddr64Fn { - fn get_line( - &self, - process: c::HANDLE, - frame_address: u64, - _inline_context: c::ULONG, - line: *mut c::IMAGEHLP_LINE64, - ) -> c::BOOL { - unsafe { - let mut displacement = 0u32; - self(process, frame_address, &mut displacement, line) - } - } -} - -impl LineGetter for SymGetLineFromInlineContextFn { - fn get_line( - &self, - process: c::HANDLE, - frame_address: u64, - inline_context: c::ULONG, - line: *mut c::IMAGEHLP_LINE64, - ) -> c::BOOL { - unsafe { - let mut displacement = 0u32; - self( - process, - frame_address, - inline_context, - 0, - &mut displacement, - line, - ) - } - } -} -- cgit 1.4.1-3-g733a5 From 560d8079ec26f2a45ecb80e95d24917025e02104 Mon Sep 17 00:00:00 2001 From: ljedrz Date: Tue, 10 Jul 2018 20:35:36 +0200 Subject: Deny bare trait objects in `src/libstd`. --- src/libstd/error.rs | 86 ++++++++++++++++++------------------ src/libstd/ffi/c_str.rs | 2 +- src/libstd/io/error.rs | 14 +++--- src/libstd/io/mod.rs | 4 +- src/libstd/io/stdio.rs | 8 ++-- src/libstd/lib.rs | 1 + src/libstd/net/parser.rs | 2 +- src/libstd/panic.rs | 2 +- src/libstd/panicking.rs | 36 +++++++-------- src/libstd/process.rs | 4 +- src/libstd/rt.rs | 2 +- src/libstd/sync/mpsc/mod.rs | 10 ++--- src/libstd/sync/mpsc/select.rs | 2 +- src/libstd/sync/once.rs | 2 +- src/libstd/sys/windows/thread.rs | 2 +- src/libstd/sys_common/at_exit_imp.rs | 4 +- src/libstd/sys_common/backtrace.rs | 10 ++--- src/libstd/sys_common/poison.rs | 2 +- src/libstd/sys_common/thread.rs | 2 +- src/libstd/thread/mod.rs | 2 +- 20 files changed, 99 insertions(+), 98 deletions(-) (limited to 'src/libstd/sys/windows') diff --git a/src/libstd/error.rs b/src/libstd/error.rs index 1958915602f..8d715ac0ec3 100644 --- a/src/libstd/error.rs +++ b/src/libstd/error.rs @@ -138,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)] @@ -151,22 +151,22 @@ pub trait Error: Debug + Display { } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, E: Error + 'a> From for Box { - fn from(err: E) -> Box { +impl<'a, E: Error + 'a> From for Box { + fn from(err: E) -> Box { Box::new(err) } } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, E: Error + Send + Sync + 'a> From for Box { - fn from(err: E) -> Box { +impl<'a, E: Error + Send + Sync + 'a> From for Box { + fn from(err: E) -> Box { Box::new(err) } } #[stable(feature = "rust1", since = "1.0.0")] -impl From for Box { - fn from(err: String) -> Box { +impl From for Box { + fn from(err: String) -> Box { #[derive(Debug)] struct StringError(String); @@ -185,38 +185,38 @@ impl From for Box { } #[stable(feature = "string_box_error", since = "1.6.0")] -impl From for Box { - fn from(str_err: String) -> Box { - let err1: Box = From::from(str_err); - let err2: Box = err1; +impl From for Box { + fn from(str_err: String) -> Box { + let err1: Box = From::from(str_err); + let err2: Box = err1; err2 } } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, 'b> From<&'b str> for Box { - fn from(err: &'b str) -> Box { +impl<'a, 'b> From<&'b str> for Box { + fn from(err: &'b str) -> Box { From::from(String::from(err)) } } #[stable(feature = "string_box_error", since = "1.6.0")] -impl<'a> From<&'a str> for Box { - fn from(err: &'a str) -> Box { +impl<'a> From<&'a str> for Box { + fn from(err: &'a str) -> Box { From::from(String::from(err)) } } #[stable(feature = "cow_box_error", since = "1.22.0")] -impl<'a, 'b> From> for Box { - fn from(err: Cow<'b, str>) -> Box { +impl<'a, 'b> From> for Box { + fn from(err: Cow<'b, str>) -> Box { From::from(String::from(err)) } } #[stable(feature = "cow_box_error", since = "1.22.0")] -impl<'a> From> for Box { - fn from(err: Cow<'a, str>) -> Box { +impl<'a> From> for Box { + fn from(err: Cow<'a, str>) -> Box { From::from(String::from(err)) } } @@ -327,7 +327,7 @@ impl Error for Box { Error::description(&**self) } - fn cause(&self) -> Option<&Error> { + fn cause(&self) -> Option<&dyn Error> { Error::cause(&**self) } } @@ -368,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] @@ -390,7 +390,7 @@ impl Error + 'static { pub fn downcast_ref(&self) -> Option<&T> { if self.is::() { unsafe { - Some(&*(self as *const Error as *const T)) + Some(&*(self as *const dyn Error as *const T)) } } else { None @@ -404,7 +404,7 @@ impl Error + 'static { pub fn downcast_mut(&mut self) -> Option<&mut T> { if self.is::() { unsafe { - Some(&mut *(self as *mut Error as *mut T)) + Some(&mut *(self as *mut dyn Error as *mut T)) } } else { None @@ -412,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(&self) -> bool { - ::is::(self) + ::is::(self) } /// Forwards to the method defined on the type `Any`. #[stable(feature = "error_downcast", since = "1.3.0")] #[inline] pub fn downcast_ref(&self) -> Option<&T> { - ::downcast_ref::(self) + ::downcast_ref::(self) } /// Forwards to the method defined on the type `Any`. #[stable(feature = "error_downcast", since = "1.3.0")] #[inline] pub fn downcast_mut(&mut self) -> Option<&mut T> { - ::downcast_mut::(self) + ::downcast_mut::(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(&self) -> bool { - ::is::(self) + ::is::(self) } /// Forwards to the method defined on the type `Any`. #[stable(feature = "error_downcast", since = "1.3.0")] #[inline] pub fn downcast_ref(&self) -> Option<&T> { - ::downcast_ref::(self) + ::downcast_ref::(self) } /// Forwards to the method defined on the type `Any`. #[stable(feature = "error_downcast", since = "1.3.0")] #[inline] pub fn downcast_mut(&mut self) -> Option<&mut T> { - ::downcast_mut::(self) + ::downcast_mut::(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(self: Box) -> Result, Box> { + pub fn downcast(self: Box) -> Result, Box> { if self.is::() { 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 { @@ -474,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(self: Box) - -> Result, Box> { - let err: Box = self; - ::downcast(err).map_err(|s| unsafe { + -> Result, Box> { + let err: Box = self; + ::downcast(err).map_err(|s| unsafe { // reapply the Send marker - transmute::, Box>(s) + transmute::, Box>(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(self: Box) -> Result, Box> { - let err: Box = self; - ::downcast(err).map_err(|s| unsafe { + let err: Box = self; + ::downcast(err).map_err(|s| unsafe { // reapply the Send+Sync marker - transmute::, Box>(s) + transmute::, Box>(s) }) } } diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index 6513d11dd51..03e0d0aa6dd 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -883,7 +883,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) } } diff --git a/src/libstd/io/error.rs b/src/libstd/io/error.rs index bdd675e6e2b..02a3ce8b9c4 100644 --- a/src/libstd/io/error.rs +++ b/src/libstd/io/error.rs @@ -83,7 +83,7 @@ enum Repr { #[derive(Debug)] struct Custom { kind: ErrorKind, - error: Box, + error: Box, } /// A list specifying general categories of I/O error. @@ -250,12 +250,12 @@ impl Error { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn new(kind: ErrorKind, error: E) -> Error - where E: Into> + where E: Into> { Self::_new(kind, error.into()) } - fn _new(kind: ErrorKind, error: Box) -> Error { + fn _new(kind: ErrorKind, error: Box) -> Error { Error { repr: Repr::Custom(Box::new(Custom { kind, @@ -373,7 +373,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 +444,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 +478,7 @@ impl Error { /// } /// ``` #[stable(feature = "io_error_inner", since = "1.3.0")] - pub fn into_inner(self) -> Option> { + pub fn into_inner(self) -> Option> { match self.repr { Repr::Os(..) => None, Repr::Simple(..) => None, @@ -551,7 +551,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, diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 2b4644bd013..85304874848 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -1972,7 +1972,7 @@ impl BufRead for Take { } } -fn read_one_byte(reader: &mut Read) -> Option> { +fn read_one_byte(reader: &mut dyn Read) -> Option> { let mut buf = [0]; loop { return match reader.read(&mut buf) { @@ -2081,7 +2081,7 @@ impl std_error::Error for CharsError { CharsError::Other(ref e) => std_error::Error::description(e), } } - fn cause(&self) -> Option<&std_error::Error> { + fn cause(&self) -> Option<&dyn std_error::Error> { match *self { CharsError::NotUtf8 => None, CharsError::Other(ref e) => e.cause(), diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs index fce85a200ba..fffe8fc559b 100644 --- a/src/libstd/io/stdio.rs +++ b/src/libstd/io/stdio.rs @@ -21,7 +21,7 @@ use thread::LocalKey; /// Stdout used by print! and println! macros thread_local! { - static LOCAL_STDOUT: RefCell>> = { + static LOCAL_STDOUT: RefCell>> = { RefCell::new(None) } } @@ -624,7 +624,7 @@ impl<'a> fmt::Debug for StderrLock<'a> { with a more general mechanism", issue = "0")] #[doc(hidden)] -pub fn set_panic(sink: Option>) -> Option> { +pub fn set_panic(sink: Option>) -> Option> { use panicking::LOCAL_STDERR; use mem; LOCAL_STDERR.with(move |slot| { @@ -648,7 +648,7 @@ pub fn set_panic(sink: Option>) -> Option> { with a more general mechanism", issue = "0")] #[doc(hidden)] -pub fn set_print(sink: Option>) -> Option> { +pub fn set_print(sink: Option>) -> Option> { use mem; LOCAL_STDOUT.with(move |slot| { mem::replace(&mut *slot.borrow_mut(), sink) @@ -670,7 +670,7 @@ pub fn set_print(sink: Option>) -> Option> { /// However, if the actual I/O causes an error, this function does panic. fn print_to( args: fmt::Arguments, - local_s: &'static LocalKey>>>, + local_s: &'static LocalKey>>>, global_s: fn() -> T, label: &str, ) diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index d73cb1f8349..006922383cf 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -221,6 +221,7 @@ // Don't link to std. We are std. #![no_std] +#![deny(bare_trait_objects)] #![deny(missing_docs)] #![deny(missing_debug_implementations)] diff --git a/src/libstd/net/parser.rs b/src/libstd/net/parser.rs index ae5037cc44e..234c5618a06 100644 --- a/src/libstd/net/parser.rs +++ b/src/libstd/net/parser.rs @@ -61,7 +61,7 @@ impl<'a> Parser<'a> { } // Return result of first successful parser - fn read_or(&mut self, parsers: &mut [Box Option + 'static>]) + fn read_or(&mut self, parsers: &mut [Box Option + 'static>]) -> Option { for pf in parsers { if let Some(r) = self.read_atomically(|p: &mut Parser| pf(p)) { diff --git a/src/libstd/panic.rs b/src/libstd/panic.rs index 451420ae88a..b8c1c4f9e68 100644 --- a/src/libstd/panic.rs +++ b/src/libstd/panic.rs @@ -421,6 +421,6 @@ pub fn catch_unwind R + UnwindSafe, R>(f: F) -> Result { /// } /// ``` #[stable(feature = "resume_unwind", since = "1.9.0")] -pub fn resume_unwind(payload: Box) -> ! { +pub fn resume_unwind(payload: Box) -> ! { panicking::update_count_then_panic(payload) } diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs index 46b6cf60705..283fd36af41 100644 --- a/src/libstd/panicking.rs +++ b/src/libstd/panicking.rs @@ -36,7 +36,7 @@ use sys_common::util; use thread; thread_local! { - pub static LOCAL_STDERR: RefCell>> = { + pub static LOCAL_STDERR: RefCell>> = { RefCell::new(None) } } @@ -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; /// panic!("Normal panic"); /// ``` #[stable(feature = "panic_hooks", since = "1.10.0")] -pub fn set_hook(hook: Box) { +pub fn set_hook(hook: Box) { if thread::panicking() { panic!("cannot modify the panic hook from a panicking thread"); } @@ -149,7 +149,7 @@ pub fn set_hook(hook: Box) { /// panic!("Normal panic"); /// ``` #[stable(feature = "panic_hooks", since = "1.10.0")] -pub fn take_hook() -> Box { +pub fn take_hook() -> Box { if thread::panicking() { panic!("cannot modify the panic hook from a panicking thread"); } @@ -197,7 +197,7 @@ fn default_hook(info: &PanicInfo) { let thread = thread_info::current_thread(); let name = thread.as_ref().and_then(|t| t.name()).unwrap_or(""); - let write = |err: &mut ::io::Write| { + let write = |err: &mut dyn (::io::Write)| { let _ = writeln!(err, "thread '{}' panicked at '{}', {}", name, msg, location); @@ -248,7 +248,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: F) -> Result> { +pub unsafe fn try R>(f: F) -> Result> { #[allow(unions_with_drop_fields)] union Data { f: F, @@ -369,12 +369,12 @@ fn continue_panic_fmt(info: &PanicInfo) -> ! { } unsafe impl<'a> BoxMeUp for PanicPayload<'a> { - fn box_me_up(&mut self) -> *mut (Any + Send) { + fn box_me_up(&mut self) -> *mut (dyn Any + Send) { let contents = mem::replace(self.fill(), String::new()); Box::into_raw(Box::new(contents)) } - fn get(&mut self) -> &(Any + Send) { + fn get(&mut self) -> &(dyn Any + Send) { self.fill() } } @@ -419,15 +419,15 @@ pub fn begin_panic(msg: M, file_line_col: &(&'static str, u32, u3 } unsafe impl BoxMeUp for PanicPayload { - 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, + Some(a) => Box::new(a) as Box, 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 => &(), @@ -441,7 +441,7 @@ pub fn begin_panic(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; @@ -496,17 +496,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) -> ! { +pub fn update_count_then_panic(msg: Box) -> ! { update_panic_count(1); - struct RewrapBox(Box); + struct RewrapBox(Box); 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 } } @@ -517,9 +517,9 @@ pub fn update_count_then_panic(msg: Box) -> ! { /// 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) diff --git a/src/libstd/process.rs b/src/libstd/process.rs index 00051d4487a..39692836866 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -813,13 +813,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 }; diff --git a/src/libstd/rt.rs b/src/libstd/rt.rs index 8f945470b7e..9e957bd87d7 100644 --- a/src/libstd/rt.rs +++ b/src/libstd/rt.rs @@ -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; diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs index 2dd3aebe610..1dc0b1c0042 100644 --- a/src/libstd/sync/mpsc/mod.rs +++ b/src/libstd/sync/mpsc/mod.rs @@ -1638,7 +1638,7 @@ impl error::Error for SendError { "sending on a closed channel" } - fn cause(&self) -> Option<&error::Error> { + fn cause(&self) -> Option<&dyn error::Error> { None } } @@ -1681,7 +1681,7 @@ impl error::Error for TrySendError { } } - fn cause(&self) -> Option<&error::Error> { + fn cause(&self) -> Option<&dyn error::Error> { None } } @@ -1709,7 +1709,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 +1742,7 @@ impl error::Error for TryRecvError { } } - fn cause(&self) -> Option<&error::Error> { + fn cause(&self) -> Option<&dyn error::Error> { None } } @@ -1783,7 +1783,7 @@ impl error::Error for RecvTimeoutError { } } - fn cause(&self) -> Option<&error::Error> { + fn cause(&self) -> Option<&dyn error::Error> { None } } diff --git a/src/libstd/sync/mpsc/select.rs b/src/libstd/sync/mpsc/select.rs index 9310dad9172..a7a284cfb79 100644 --- a/src/libstd/sync/mpsc/select.rs +++ b/src/libstd/sync/mpsc/select.rs @@ -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) diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs index 7eb7be23128..1c63f99753a 100644 --- a/src/libstd/sync/once.rs +++ b/src/libstd/sync/once.rs @@ -301,7 +301,7 @@ impl Once { #[cold] fn call_inner(&'static self, ignore_poisoning: bool, - init: &mut FnMut(bool)) { + init: &mut dyn FnMut(bool)) { let mut state = self.state.load(Ordering::SeqCst); 'outer: loop { diff --git a/src/libstd/sys/windows/thread.rs b/src/libstd/sys/windows/thread.rs index b6f63303dc2..44ec872b244 100644 --- a/src/libstd/sys/windows/thread.rs +++ b/src/libstd/sys/windows/thread.rs @@ -28,7 +28,7 @@ pub struct Thread { } impl Thread { - pub unsafe fn new<'a>(stack: usize, p: Box) + pub unsafe fn new<'a>(stack: usize, p: Box) -> io::Result { let p = box p; diff --git a/src/libstd/sys_common/at_exit_imp.rs b/src/libstd/sys_common/at_exit_imp.rs index d268d9ad6f9..b28a4d2f8be 100644 --- a/src/libstd/sys_common/at_exit_imp.rs +++ b/src/libstd/sys_common/at_exit_imp.rs @@ -17,7 +17,7 @@ use ptr; use mem; use sys_common::mutex::Mutex; -type Queue = Vec>; +type Queue = Vec>; // 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 @@ -68,7 +68,7 @@ pub fn cleanup() { } } -pub fn push(f: Box) -> bool { +pub fn push(f: Box) -> bool { unsafe { let _guard = LOCK.lock(); if init() { diff --git a/src/libstd/sys_common/backtrace.rs b/src/libstd/sys_common/backtrace.rs index 61d7ed463dd..6184ba4ded6 100644 --- a/src/libstd/sys_common/backtrace.rs +++ b/src/libstd/sys_common/backtrace.rs @@ -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<()> { } } -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(), @@ -177,7 +177,7 @@ pub fn log_enabled() -> Option { /// /// 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 - ` line. if format == PrintFormat::Short && frame.exact_position == ptr::null() { @@ -202,7 +202,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 +254,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. diff --git a/src/libstd/sys_common/poison.rs b/src/libstd/sys_common/poison.rs index e74c40ae04b..1625efe4a2a 100644 --- a/src/libstd/sys_common/poison.rs +++ b/src/libstd/sys_common/poison.rs @@ -251,7 +251,7 @@ impl Error for TryLockError { } } - fn cause(&self) -> Option<&Error> { + fn cause(&self) -> Option<&dyn Error> { match *self { TryLockError::Poisoned(ref p) => Some(p), _ => None diff --git a/src/libstd/sys_common/thread.rs b/src/libstd/sys_common/thread.rs index da6f58ef6bb..86a5e2b8694 100644 --- a/src/libstd/sys_common/thread.rs +++ b/src/libstd/sys_common/thread.rs @@ -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)() + Box::from_raw(main as *mut Box)() } pub fn min_stack() -> usize { diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 90f054186d1..cc0ec8a5b4d 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -1175,7 +1175,7 @@ impl fmt::Debug for Thread { /// /// [`Result`]: ../../std/result/enum.Result.html #[stable(feature = "rust1", since = "1.0.0")] -pub type Result = ::result::Result>; +pub type Result = ::result::Result>; // 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 -- cgit 1.4.1-3-g733a5 From 59c8a279daf6912b99ba089ff6dafbfc3469831e Mon Sep 17 00:00:00 2001 From: ljedrz Date: Thu, 26 Jul 2018 17:11:10 +0200 Subject: Replace push loops with collect() and extend() where possible --- src/bootstrap/util.rs | 5 +--- src/librustc/cfg/construct.rs | 10 ++++---- src/librustc/infer/outlives/obligations.rs | 11 ++++----- src/librustc/middle/reachable.rs | 8 ++---- src/librustc/mir/traversal.rs | 4 +-- src/librustc/session/config.rs | 4 +-- src/librustc/traits/specialize/mod.rs | 6 ++--- src/librustc_codegen_llvm/back/rpath.rs | 4 +-- src/librustc_codegen_llvm/debuginfo/metadata.rs | 23 +++++++++-------- src/librustc_codegen_llvm/debuginfo/mod.rs | 7 +++--- src/librustc_driver/lib.rs | 5 +--- src/librustc_driver/profile/trace.rs | 7 +++--- src/librustc_llvm/lib.rs | 6 +---- src/librustc_mir/transform/inline.rs | 7 +++--- src/librustc_resolve/lib.rs | 6 ++--- src/librustc_save_analysis/dump_visitor.rs | 11 ++++----- src/librustc_typeck/collect.rs | 33 ++++++++++++------------- src/librustdoc/core.rs | 4 +-- src/librustdoc/lib.rs | 4 +-- src/libserialize/json.rs | 12 +++------ src/libstd/sys/redox/process.rs | 11 +++++---- src/libstd/sys/windows/process.rs | 8 ++---- src/libsyntax/ast.rs | 10 ++------ src/libsyntax/parse/lexer/mod.rs | 4 +-- src/libsyntax_ext/deriving/decodable.rs | 4 +-- src/libsyntax_ext/deriving/generic/mod.rs | 17 ++++++------- src/libsyntax_ext/deriving/hash.rs | 5 ++-- src/libsyntax_ext/format.rs | 15 ++++++----- 28 files changed, 101 insertions(+), 150 deletions(-) (limited to 'src/libstd/sys/windows') diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs index 9a2b9e90440..be03796921a 100644 --- a/src/bootstrap/util.rs +++ b/src/bootstrap/util.rs @@ -92,10 +92,7 @@ pub fn push_exe_path(mut buf: PathBuf, components: &[&str]) -> PathBuf { file.push_str(".exe"); } - for c in components { - buf.push(c); - } - + buf.extend(components); buf.push(file); buf diff --git a/src/librustc/cfg/construct.rs b/src/librustc/cfg/construct.rs index f1e27946915..98cfa094c16 100644 --- a/src/librustc/cfg/construct.rs +++ b/src/librustc/cfg/construct.rs @@ -567,12 +567,12 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { fn add_returning_edge(&mut self, _from_expr: &hir::Expr, from_index: CFGIndex) { - let mut data = CFGEdgeData { - exiting_scopes: vec![], + let data = CFGEdgeData { + exiting_scopes: self.loop_scopes.iter() + .rev() + .map(|&LoopScope { loop_id: id, .. }| id) + .collect() }; - for &LoopScope { loop_id: id, .. } in self.loop_scopes.iter().rev() { - data.exiting_scopes.push(id); - } self.graph.add_edge(from_index, self.fn_exit, data); } diff --git a/src/librustc/infer/outlives/obligations.rs b/src/librustc/infer/outlives/obligations.rs index b8991a0366a..c74783f5e4d 100644 --- a/src/librustc/infer/outlives/obligations.rs +++ b/src/librustc/infer/outlives/obligations.rs @@ -151,13 +151,12 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { debug!("process_registered_region_obligations()"); // pull out the region obligations with the given `body_id` (leaving the rest) - let mut my_region_obligations = Vec::with_capacity(self.region_obligations.borrow().len()); - { + let my_region_obligations = { let mut r_o = self.region_obligations.borrow_mut(); - for (_, obligation) in r_o.drain_filter(|(ro_body_id, _)| *ro_body_id == body_id) { - my_region_obligations.push(obligation); - } - } + let my_r_o = r_o.drain_filter(|(ro_body_id, _)| *ro_body_id == body_id) + .map(|(_, obligation)| obligation).collect::>(); + my_r_o + }; let outlives = &mut TypeOutlives::new( self, diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index 7f4b0bb126b..19c82d7d27c 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -367,9 +367,7 @@ impl<'a, 'tcx: 'a> ItemLikeVisitor<'tcx> for CollectPrivateImplItemsVisitor<'a, // We need only trait impls here, not inherent impls, and only non-exported ones if let hir::ItemKind::Impl(.., Some(ref trait_ref), _, ref impl_item_refs) = item.node { if !self.access_levels.is_reachable(item.id) { - for impl_item_ref in impl_item_refs { - self.worklist.push(impl_item_ref.id.node_id); - } + self.worklist.extend(impl_item_refs.iter().map(|r| r.id.node_id)); let trait_def_id = match trait_ref.path.def { Def::Trait(def_id) => def_id, @@ -426,9 +424,7 @@ fn reachable_set<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum) -> // If other crates link to us, they're going to expect to be able to // use the lang items, so we need to be sure to mark them as // exported. - for (id, _) in &access_levels.map { - reachable_context.worklist.push(*id); - } + reachable_context.worklist.extend(access_levels.map.iter().map(|(id, _)| *id)); for item in tcx.lang_items().items().iter() { if let Some(did) = *item { if let Some(node_id) = tcx.hir.as_local_node_id(did) { diff --git a/src/librustc/mir/traversal.rs b/src/librustc/mir/traversal.rs index 87ba3420eec..86fd825850f 100644 --- a/src/librustc/mir/traversal.rs +++ b/src/librustc/mir/traversal.rs @@ -64,9 +64,7 @@ impl<'a, 'tcx> Iterator for Preorder<'a, 'tcx> { let data = &self.mir[idx]; if let Some(ref term) = data.terminator { - for &succ in term.successors() { - self.worklist.push(succ); - } + self.worklist.extend(term.successors()); } return Some((idx, data)); diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 8f3ed3106d5..e0532a3320b 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -899,9 +899,7 @@ macro_rules! options { -> bool { match v { Some(s) => { - for s in s.split_whitespace() { - slot.push(s.to_string()); - } + slot.extend(s.split_whitespace().map(|s| s.to_string())); true }, None => false, diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index f151f3b2531..1ed9ae4392f 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -438,9 +438,9 @@ fn to_pretty_impl_header(tcx: TyCtxt, impl_def_id: DefId) -> Option { } pretty_predicates.push(p.to_string()); } - for ty in types_without_default_bounds { - pretty_predicates.push(format!("{}: ?Sized", ty)); - } + pretty_predicates.extend( + types_without_default_bounds.iter().map(|ty| format!("{}: ?Sized", ty)) + ); if !pretty_predicates.is_empty() { write!(w, "\n where {}", pretty_predicates.join(", ")).unwrap(); } diff --git a/src/librustc_codegen_llvm/back/rpath.rs b/src/librustc_codegen_llvm/back/rpath.rs index e73073cfad0..2c3a143646c 100644 --- a/src/librustc_codegen_llvm/back/rpath.rs +++ b/src/librustc_codegen_llvm/back/rpath.rs @@ -152,9 +152,7 @@ fn path_relative_from(path: &Path, base: &Path) -> Option { (Some(_), Some(b)) if b == Component::ParentDir => return None, (Some(a), Some(_)) => { comps.push(Component::ParentDir); - for _ in itb { - comps.push(Component::ParentDir); - } + comps.extend(itb.map(|_| Component::ParentDir)); comps.push(a); comps.extend(ita.by_ref()); break; diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index 6d727f7b048..2f4dd5a7ce5 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -39,6 +39,7 @@ use rustc::util::common::path2cstr; use libc::{c_uint, c_longlong}; use std::ffi::CString; use std::fmt::Write; +use std::iter; use std::ptr; use std::path::{Path, PathBuf}; use syntax::ast; @@ -364,18 +365,16 @@ fn subroutine_type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, &signature, ); - let mut signature_metadata: Vec = Vec::with_capacity(signature.inputs().len() + 1); - - // return type - signature_metadata.push(match signature.output().sty { - ty::TyTuple(ref tys) if tys.is_empty() => ptr::null_mut(), - _ => type_metadata(cx, signature.output(), span) - }); - - // regular arguments - for &argument_type in signature.inputs() { - signature_metadata.push(type_metadata(cx, argument_type, span)); - } + let signature_metadata: Vec = iter::once( + // return type + match signature.output().sty { + ty::TyTuple(ref tys) if tys.is_empty() => ptr::null_mut(), + _ => type_metadata(cx, signature.output(), span) + } + ).chain( + // regular arguments + signature.inputs().iter().map(|argument_type| type_metadata(cx, argument_type, span)) + ).collect(); return_if_metadata_created_in_meantime!(cx, unique_type_id); diff --git a/src/librustc_codegen_llvm/debuginfo/mod.rs b/src/librustc_codegen_llvm/debuginfo/mod.rs index 068dd9821ac..9671db75baf 100644 --- a/src/librustc_codegen_llvm/debuginfo/mod.rs +++ b/src/librustc_codegen_llvm/debuginfo/mod.rs @@ -352,9 +352,10 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, if sig.abi == Abi::RustCall && !sig.inputs().is_empty() { if let ty::TyTuple(args) = sig.inputs()[sig.inputs().len() - 1].sty { - for &argument_type in args { - signature.push(type_metadata(cx, argument_type, syntax_pos::DUMMY_SP)); - } + signature.extend( + args.iter().map(|argument_type| + type_metadata(cx, argument_type, syntax_pos::DUMMY_SP)) + ); } } diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 29b9990de34..e25da0632c0 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -1588,10 +1588,7 @@ pub fn in_rustc_thread(f: F) -> Result> /// debugging, since some ICEs only happens with non-default compiler flags /// (and the users don't always report them). fn extra_compiler_flags() -> Option<(Vec, bool)> { - let mut args = Vec::new(); - for arg in env::args_os() { - args.push(arg.to_string_lossy().to_string()); - } + let args = env::args_os().map(|arg| arg.to_string_lossy().to_string()).collect::>(); // Avoid printing help because of empty args. This can suggest the compiler // itself is not the program root (consider RLS). diff --git a/src/librustc_driver/profile/trace.rs b/src/librustc_driver/profile/trace.rs index 797ed4505b4..3d4f4b029e5 100644 --- a/src/librustc_driver/profile/trace.rs +++ b/src/librustc_driver/profile/trace.rs @@ -204,10 +204,9 @@ pub fn write_counts(count_file: &mut File, counts: &mut HashMap>(); data.sort_by_key(|k| Reverse(k.3)); for (cons, count, dur_total, dur_self) in data { write!(count_file, "{}, {}, {}, {}\n", diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index 741758cb954..91f9b4ac03b 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -275,12 +275,8 @@ pub fn get_param(llfn: ValueRef, index: c_uint) -> ValueRef { fn get_params(llfn: ValueRef) -> Vec { unsafe { let num_params = LLVMCountParams(llfn); - let mut params = Vec::with_capacity(num_params as usize); - for idx in 0..num_params { - params.push(LLVMGetParam(llfn, idx)); - } - params + (0..num_params).map(|idx| LLVMGetParam(llfn, idx)).collect() } } diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index a0a5980d141..46fab544aaf 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -406,10 +406,9 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> { local_map.push(idx); } - for p in callee_mir.promoted.iter().cloned() { - let idx = caller_mir.promoted.push(p); - promoted_map.push(idx); - } + promoted_map.extend( + callee_mir.promoted.iter().cloned().map(|p| caller_mir.promoted.push(p)) + ); // If the call is something like `a[*i] = f(i)`, where // `i : &mut usize`, then just duplicating the `a[*i]` diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 725b3b4f150..b6f0ff291d4 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -3831,9 +3831,9 @@ impl<'a> Resolver<'a> { } // Add primitive types to the mix if filter_fn(Def::PrimTy(TyBool)) { - for (name, _) in &self.primitive_type_table.primitive_types { - names.push(*name); - } + names.extend( + self.primitive_type_table.primitive_types.iter().map(|(name, _)| name) + ) } } else { // Search in module. diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index ac7085a55cf..04a4bca4ffb 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -1318,14 +1318,13 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { }; // Make a comma-separated list of names of imported modules. - let mut names = vec![]; let glob_map = &self.save_ctxt.analysis.glob_map; let glob_map = glob_map.as_ref().unwrap(); - if glob_map.contains_key(&id) { - for n in glob_map.get(&id).unwrap() { - names.push(n.to_string()); - } - } + let names = if glob_map.contains_key(&id) { + glob_map.get(&id).unwrap().iter().map(|n| n.to_string()).collect() + } else { + Vec::new() + }; let sub_span = self.span.sub_span_of_token(use_tree.span, token::BinOp(token::Star)); diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index cd84a61bb2c..77b02d9ff5b 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -962,19 +962,21 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, &["", ""][..] }; - for (i, &arg) in dummy_args.iter().enumerate() { - params.push(ty::GenericParamDef { - index: type_start + i as u32, - name: Symbol::intern(arg).as_interned_str(), - def_id, - pure_wrt_drop: false, - kind: ty::GenericParamDefKind::Type { - has_default: false, - object_lifetime_default: rl::Set1::Empty, - synthetic: None, - }, - }); - } + params.extend( + dummy_args.iter().enumerate().map(|(i, &arg)| + ty::GenericParamDef { + index: type_start + i as u32, + name: Symbol::intern(arg).as_interned_str(), + def_id, + pure_wrt_drop: false, + kind: ty::GenericParamDefKind::Type { + has_default: false, + object_lifetime_default: rl::Set1::Empty, + synthetic: None, + }, + } + ) + ); tcx.with_freevars(node_id, |fv| { params.extend(fv.iter().zip((dummy_args.len() as u32)..).map(|(_, i)| { @@ -1651,10 +1653,7 @@ fn explicit_predicates_of<'a, 'tcx>( &mut projections); predicates.push(trait_ref.to_predicate()); - - for projection in &projections { - predicates.push(projection.to_predicate()); - } + predicates.extend(projections.iter().map(|p| p.to_predicate())); } &hir::GenericBound::Outlives(ref lifetime) => { diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 77375442d4c..769c9804a35 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -203,9 +203,7 @@ pub fn run_core(search_paths: SearchPaths, intra_link_resolution_failure_name.to_owned(), missing_docs.to_owned()]; - for (lint, _) in &cmd_lints { - whitelisted_lints.push(lint.clone()); - } + whitelisted_lints.extend(cmd_lints.iter().map(|(lint, _)| lint).cloned()); let lints = lint::builtin::HardwiredLints.get_lints() .into_iter() diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 00cad5e376a..613ca01ff82 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -722,9 +722,7 @@ where R: 'static + Send, }, _ => continue, }; - for p in value.as_str().split_whitespace() { - sink.push(p.to_string()); - } + sink.extend(value.as_str().split_whitespace().map(|p| p.to_string())); } if attr.is_word() && name == Some("document_private_items") { diff --git a/src/libserialize/json.rs b/src/libserialize/json.rs index 88cc9373113..b5986e88b66 100644 --- a/src/libserialize/json.rs +++ b/src/libserialize/json.rs @@ -1364,9 +1364,7 @@ impl Stack { // Used by Parser to insert StackElement::Key elements at the top of the stack. fn push_key(&mut self, key: string::String) { self.stack.push(InternalKey(self.str_buffer.len() as u16, key.len() as u16)); - for c in key.as_bytes() { - self.str_buffer.push(*c); - } + self.str_buffer.extend(key.as_bytes()); } // Used by Parser to insert StackElement::Index elements at the top of the stack. @@ -2212,9 +2210,7 @@ impl ::Decoder for Decoder { }; match o.remove(&"fields".to_string()) { Some(Json::Array(l)) => { - for field in l.into_iter().rev() { - self.stack.push(field); - } + self.stack.extend(l.into_iter().rev()); }, Some(val) => { return Err(ExpectedError("Array".to_owned(), format!("{}", val))) @@ -2346,9 +2342,7 @@ impl ::Decoder for Decoder { { let array = expect!(self.pop(), Array)?; let len = array.len(); - for v in array.into_iter().rev() { - self.stack.push(v); - } + self.stack.extend(array.into_iter().rev()); f(self, len) } diff --git a/src/libstd/sys/redox/process.rs b/src/libstd/sys/redox/process.rs index 02bc467541e..2037616e6ac 100644 --- a/src/libstd/sys/redox/process.rs +++ b/src/libstd/sys/redox/process.rs @@ -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; @@ -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(); diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs index be442f41374..4974a8de89c 100644 --- a/src/libstd/sys/windows/process.rs +++ b/src/libstd/sys/windows/process.rs @@ -487,9 +487,7 @@ fn make_command_line(prog: &OsStr, args: &[OsString]) -> io::Result> { } 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> { 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(()) diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 1b6b47f5489..d59c9dd6b53 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -500,10 +500,7 @@ impl Pat { PatKind::Slice(pats, None, _) if pats.len() == 1 => pats[0].to_ty().map(TyKind::Slice)?, PatKind::Tuple(pats, None) => { - let mut tys = Vec::new(); - for pat in pats { - tys.push(pat.to_ty()?); - } + let tys = pats.iter().map(|pat| pat.to_ty()).collect::>>()?; TyKind::Tup(tys) } _ => return None, @@ -949,10 +946,7 @@ impl Expr { ExprKind::Array(exprs) if exprs.len() == 1 => exprs[0].to_ty().map(TyKind::Slice)?, ExprKind::Tup(exprs) => { - let mut tys = Vec::new(); - for expr in exprs { - tys.push(expr.to_ty()?); - } + let tys = exprs.iter().map(|expr| expr.to_ty()).collect::>>()?; TyKind::Tup(tys) } ExprKind::Binary(binop, lhs, rhs) if binop.node == BinOpKind::Add => diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index 4b077aa8dd4..f9b9e95ead1 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -265,9 +265,7 @@ impl<'a> StringReader<'a> { m.push(c); } _ => { - for c in c.escape_default() { - m.push(c); - } + m.extend(c.escape_default()); } } } diff --git a/src/libsyntax_ext/deriving/decodable.rs b/src/libsyntax_ext/deriving/decodable.rs index 1e04d8fa22a..c2b92944999 100644 --- a/src/libsyntax_ext/deriving/decodable.rs +++ b/src/libsyntax_ext/deriving/decodable.rs @@ -131,8 +131,8 @@ fn decodable_substructure(cx: &mut ExtCtxt, StaticEnum(_, ref fields) => { let variant = cx.ident_of("i"); - let mut arms = Vec::new(); - let mut variants = Vec::new(); + let mut arms = Vec::with_capacity(fields.len() + 1); + let mut variants = Vec::with_capacity(fields.len()); let rvariant_arg = cx.ident_of("read_enum_variant_arg"); for (i, &(ident, v_span, ref parts)) in fields.iter().enumerate() { diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index a9f60fd053c..e0f985c26c7 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -188,6 +188,7 @@ pub use self::StaticFields::*; pub use self::SubstructureFields::*; use std::cell::RefCell; +use std::iter; use std::vec; use rustc_target::spec::abi::Abi; @@ -558,15 +559,13 @@ impl<'a> TraitDef<'a> { // type being derived upon self.additional_bounds.iter().map(|p| { cx.trait_bound(p.to_path(cx, self.span, type_ident, generics)) - }).collect(); - - // require the current trait - bounds.push(cx.trait_bound(trait_path.clone())); - - // also add in any bounds from the declaration - for declared_bound in ¶m.bounds { - bounds.push((*declared_bound).clone()); - } + }).chain( + // require the current trait + iter::once(cx.trait_bound(trait_path.clone())) + ).chain( + // also add in any bounds from the declaration + param.bounds.iter().cloned() + ).collect(); cx.typaram(self.span, param.ident, vec![], bounds, None) } diff --git a/src/libsyntax_ext/deriving/hash.rs b/src/libsyntax_ext/deriving/hash.rs index 7d22998487b..950e8c84f17 100644 --- a/src/libsyntax_ext/deriving/hash.rs +++ b/src/libsyntax_ext/deriving/hash.rs @@ -95,9 +95,8 @@ fn hash_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) _ => cx.span_bug(trait_span, "impossible substructure in `derive(Hash)`"), }; - for &FieldInfo { ref self_, span, .. } in fields { - stmts.push(call_hash(span, self_.clone())); - } + stmts.extend(fields.iter().map(|FieldInfo { ref self_, span, .. }| + call_hash(*span, self_.clone()))); cx.expr_block(cx.block(trait_span, stmts)) } diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index 98de3d80b1e..46c85497ee7 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -406,10 +406,7 @@ impl<'a, 'b> Context<'a, 'b> { // Map the arguments for i in 0..args_len { let ref arg_types = self.arg_types[i]; - let mut arg_offsets = Vec::with_capacity(arg_types.len()); - for offset in arg_types { - arg_offsets.push(sofar + *offset); - } + let arg_offsets = arg_types.iter().map(|offset| sofar + *offset).collect::>(); self.arg_index_map.push(arg_offsets); sofar += self.arg_unique_types[i].len(); } @@ -581,10 +578,12 @@ impl<'a, 'b> Context<'a, 'b> { /// Actually builds the expression which the format_args! block will be /// expanded to fn into_expr(self) -> P { - let mut locals = Vec::new(); - let mut counts = Vec::new(); - let mut pats = Vec::new(); - let mut heads = Vec::new(); + let mut locals = Vec::with_capacity( + (0..self.args.len()).map(|i| self.arg_unique_types[i].len()).sum() + ); + let mut counts = Vec::with_capacity(self.count_args.len()); + let mut pats = Vec::with_capacity(self.args.len()); + let mut heads = Vec::with_capacity(self.args.len()); let names_pos: Vec<_> = (0..self.args.len()) .map(|i| self.ecx.ident_of(&format!("arg{}", i)).gensym()) -- cgit 1.4.1-3-g733a5 From fc8bb9c42c998dc5e82347d53f318b28d91fc9e3 Mon Sep 17 00:00:00 2001 From: Xidorn Quan Date: Mon, 30 Jul 2018 14:02:09 +1000 Subject: Don't commit thread stack on Windows --- src/libstd/sys/windows/c.rs | 2 ++ src/libstd/sys/windows/thread.rs | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'src/libstd/sys/windows') diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs index 30aba2f400f..6f81afe66f9 100644 --- a/src/libstd/sys/windows/c.rs +++ b/src/libstd/sys/windows/c.rs @@ -296,6 +296,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 { diff --git a/src/libstd/sys/windows/thread.rs b/src/libstd/sys/windows/thread.rs index 44ec872b244..85588cc6c8e 100644 --- a/src/libstd/sys/windows/thread.rs +++ b/src/libstd/sys/windows/thread.rs @@ -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()) -- cgit 1.4.1-3-g733a5 From ec18991492849393a8b3ae4e0c70a22319e8ea60 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Sat, 11 Aug 2018 14:09:59 -0400 Subject: Add links to std::char::REPLACEMENT_CHARACTER from docs. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are a few places where we mention the replacement character in the docs, and it could be helpful for users to utilize the constant which is available in the standard library, so let’s link to it! --- src/liballoc/string.rs | 6 ++++-- src/libcore/str/mod.rs | 5 ++++- src/libstd/ffi/c_str.rs | 7 ++++--- src/libstd/ffi/os_str.rs | 4 +++- src/libstd/path.rs | 4 +++- src/libstd/sys/windows/ext/ffi.rs | 3 ++- 6 files changed, 20 insertions(+), 9 deletions(-) (limited to 'src/libstd/sys/windows') diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index 631779a17a1..dd559df08cc 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -519,10 +519,11 @@ impl String { /// between the two. Not all byte slices are valid strings, however: strings /// are required to be valid UTF-8. During this conversion, /// `from_utf8_lossy()` will replace any invalid UTF-8 sequences with - /// `U+FFFD REPLACEMENT CHARACTER`, which looks like this: � + /// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD], which looks like this: � /// /// [`u8`]: ../../std/primitive.u8.html /// [byteslice]: ../../std/primitive.slice.html + /// [U+FFFD]: ../char/constant.REPLACEMENT_CHARACTER.html /// /// If you are sure that the byte slice is valid UTF-8, and you don't want /// to incur the overhead of the conversion, there is an unsafe version @@ -621,7 +622,7 @@ impl String { } /// Decode a UTF-16 encoded slice `v` into a `String`, replacing - /// invalid data with the replacement character (U+FFFD). + /// invalid data with [the replacement character (`U+FFFD`)][U+FFFD]. /// /// Unlike [`from_utf8_lossy`] which returns a [`Cow<'a, str>`], /// `from_utf16_lossy` returns a `String` since the UTF-16 to UTF-8 @@ -629,6 +630,7 @@ impl String { /// /// [`from_utf8_lossy`]: #method.from_utf8_lossy /// [`Cow<'a, str>`]: ../borrow/enum.Cow.html + /// [U+FFFD]: ../char/constant.REPLACEMENT_CHARACTER.html /// /// # Examples /// diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 356534a9187..54b17b0fbb3 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -244,7 +244,10 @@ impl Utf8Error { /// The length provided is that of the invalid byte sequence /// that starts at the index given by `valid_up_to()`. /// Decoding should resume after that sequence - /// (after inserting a U+FFFD REPLACEMENT CHARACTER) in case of lossy decoding. + /// (after inserting a [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD]) in case of + /// lossy decoding. + /// + /// [U+FFFD]: ../../std/char/constant.REPLACEMENT_CHARACTER.html #[stable(feature = "utf8_error_error_len", since = "1.20.0")] pub fn error_len(&self) -> Option { self.error_len.map(|len| len as usize) diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index b2777f5c485..2b87094926c 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -1175,9 +1175,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 @@ -1189,6 +1189,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 /// diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs index 9e501a84e05..6bcd62dbd59 100644 --- a/src/libstd/ffi/os_str.rs +++ b/src/libstd/ffi/os_str.rs @@ -520,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 /// diff --git a/src/libstd/path.rs b/src/libstd/path.rs index 688a7e99f10..ca8be75fab5 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -1737,9 +1737,11 @@ impl Path { /// Converts a `Path` to a [`Cow`]. /// - /// 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`]: ../borrow/enum.Cow.html + /// [U+FFFD]: ../char/constant.REPLACEMENT_CHARACTER.html /// /// # Examples /// diff --git a/src/libstd/sys/windows/ext/ffi.rs b/src/libstd/sys/windows/ext/ffi.rs index 98d43552489..bae0d02786a 100644 --- a/src/libstd/sys/windows/ext/ffi.rs +++ b/src/libstd/sys/windows/ext/ffi.rs @@ -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 @@ //! [`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")] -- cgit 1.4.1-3-g733a5 From fccc04d3e72bb462cba1b492ba0e2cd4ab2aebec Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 16 Jul 2018 16:38:56 -0700 Subject: Start adding an `aarch64-pc-windows-msvc` target This commit adds the necessary definitions for target specs and such as well as the necessary support in libstd to compile basic `aarch64-pc-windows-msvc` binaries. The target is not currently built on CI, but it can be built locally with: ./configure --target=aarch64-pc-windows-msvc --set rust.lld ./x.py build src/libstd --target aarch64-pc-windows-msvc Currently this fails to build `libtest` due to a linker bug (seemingly in LLD?) which hasn't been investigate yet. Otherwise though with libstd you can build a hello world program (linked with LLD). I've not tried to execute it yet, but it at least links! Full support for this target is still a long road ahead, but this is hopefully a good stepping stone to get started. Points of note about this target are: * Currently defaults to `panic=abort` as support is still landing in LLVM for SEH on AArch64. * Currently defaults to LLD as a linker as I was able to get farther with it than I was with `link.exe` --- src/libpanic_unwind/dummy.rs | 29 ++++++++++ src/libpanic_unwind/lib.rs | 55 +++++++++---------- src/libpanic_unwind/macros.rs | 45 +++++++++++++++ src/libpanic_unwind/wasm32.rs | 29 ---------- .../spec/aarch64_pc_windows_msvc.rs | 35 ++++++++++++ src/librustc_target/spec/mod.rs | 1 + src/libstd/sys/windows/backtrace/mod.rs | 24 ++++++++ src/libstd/sys/windows/c.rs | 64 +++++++++++++++++++++- src/libstd/sys/windows/mod.rs | 10 +++- 9 files changed, 230 insertions(+), 62 deletions(-) create mode 100644 src/libpanic_unwind/dummy.rs create mode 100644 src/libpanic_unwind/macros.rs delete mode 100644 src/libpanic_unwind/wasm32.rs create mode 100644 src/librustc_target/spec/aarch64_pc_windows_msvc.rs (limited to 'src/libstd/sys/windows') diff --git a/src/libpanic_unwind/dummy.rs b/src/libpanic_unwind/dummy.rs new file mode 100644 index 00000000000..7150560b4a1 --- /dev/null +++ b/src/libpanic_unwind/dummy.rs @@ -0,0 +1,29 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Unwinding for wasm32 +//! +//! Right now we don't support this, so this is just stubs + +use alloc::boxed::Box; +use core::any::Any; +use core::intrinsics; + +pub fn payload() -> *mut u8 { + 0 as *mut u8 +} + +pub unsafe fn cleanup(_ptr: *mut u8) -> Box { + intrinsics::abort() +} + +pub unsafe fn panic(_data: Box) -> u32 { + intrinsics::abort() +} diff --git a/src/libpanic_unwind/lib.rs b/src/libpanic_unwind/lib.rs index a61b2c1f063..9c3fc76c307 100644 --- a/src/libpanic_unwind/lib.rs +++ b/src/libpanic_unwind/lib.rs @@ -55,36 +55,33 @@ use core::mem; use core::raw; use core::panic::BoxMeUp; -// Rust runtime's startup objects depend on these symbols, so make them public. -#[cfg(all(target_os="windows", target_arch = "x86", target_env="gnu"))] -pub use imp::eh_frame_registry::*; +#[macro_use] +mod macros; -// *-pc-windows-msvc -#[cfg(target_env = "msvc")] -#[path = "seh.rs"] -mod imp; - -// x86_64-pc-windows-gnu -#[cfg(all(windows, target_arch = "x86_64", target_env = "gnu"))] -#[path = "seh64_gnu.rs"] -mod imp; - -// i686-pc-windows-gnu and all others -#[cfg(any(all(unix, not(target_os = "emscripten")), - target_os = "cloudabi", - target_os = "redox", - all(windows, target_arch = "x86", target_env = "gnu")))] -#[path = "gcc.rs"] -mod imp; - -// emscripten -#[cfg(target_os = "emscripten")] -#[path = "emcc.rs"] -mod imp; - -#[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))] -#[path = "wasm32.rs"] -mod imp; +cfg_if! { + if #[cfg(target_os = "emscripten")] { + #[path = "emcc.rs"] + mod imp; + } else if #[cfg(target_arch = "wasm32")] { + #[path = "dummy.rs"] + mod imp; + } else if #[cfg(all(target_env = "msvc", target_arch = "aarch64"))] { + #[path = "dummy.rs"] + mod imp; + } else if #[cfg(target_env = "msvc")] { + #[path = "seh.rs"] + mod imp; + } else if #[cfg(all(windows, target_arch = "x86_64", target_env = "gnu"))] { + #[path = "seh64_gnu.rs"] + mod imp; + } else { + // Rust runtime's startup objects depend on these symbols, so make them public. + #[cfg(all(target_os="windows", target_arch = "x86", target_env="gnu"))] + pub use imp::eh_frame_registry::*; + #[path = "gcc.rs"] + mod imp; + } +} mod dwarf; mod windows; diff --git a/src/libpanic_unwind/macros.rs b/src/libpanic_unwind/macros.rs new file mode 100644 index 00000000000..6ea79dc862b --- /dev/null +++ b/src/libpanic_unwind/macros.rs @@ -0,0 +1,45 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/// A macro for defining `#[cfg]` if-else statements. +/// +/// This is similar to the `if/elif` C preprocessor macro by allowing definition +/// of a cascade of `#[cfg]` cases, emitting the implementation which matches +/// first. +/// +/// This allows you to conveniently provide a long list `#[cfg]`'d blocks of code +/// without having to rewrite each clause multiple times. +macro_rules! cfg_if { + ($( + if #[cfg($($meta:meta),*)] { $($it:item)* } + ) else * else { + $($it2:item)* + }) => { + __cfg_if_items! { + () ; + $( ( ($($meta),*) ($($it)*) ), )* + ( () ($($it2)*) ), + } + } +} + +macro_rules! __cfg_if_items { + (($($not:meta,)*) ; ) => {}; + (($($not:meta,)*) ; ( ($($m:meta),*) ($($it:item)*) ), $($rest:tt)*) => { + __cfg_if_apply! { cfg(all(not(any($($not),*)), $($m,)*)), $($it)* } + __cfg_if_items! { ($($not,)* $($m,)*) ; $($rest)* } + } +} + +macro_rules! __cfg_if_apply { + ($m:meta, $($it:item)*) => { + $(#[$m] $it)* + } +} diff --git a/src/libpanic_unwind/wasm32.rs b/src/libpanic_unwind/wasm32.rs deleted file mode 100644 index 7150560b4a1..00000000000 --- a/src/libpanic_unwind/wasm32.rs +++ /dev/null @@ -1,29 +0,0 @@ -// 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Unwinding for wasm32 -//! -//! Right now we don't support this, so this is just stubs - -use alloc::boxed::Box; -use core::any::Any; -use core::intrinsics; - -pub fn payload() -> *mut u8 { - 0 as *mut u8 -} - -pub unsafe fn cleanup(_ptr: *mut u8) -> Box { - intrinsics::abort() -} - -pub unsafe fn panic(_data: Box) -> u32 { - intrinsics::abort() -} diff --git a/src/librustc_target/spec/aarch64_pc_windows_msvc.rs b/src/librustc_target/spec/aarch64_pc_windows_msvc.rs new file mode 100644 index 00000000000..8747f239d34 --- /dev/null +++ b/src/librustc_target/spec/aarch64_pc_windows_msvc.rs @@ -0,0 +1,35 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use spec::{LinkerFlavor, Target, TargetResult, PanicStrategy, LldFlavor}; + +pub fn target() -> TargetResult { + let mut base = super::windows_msvc_base::opts(); + base.max_atomic_width = Some(64); + base.has_elf_tls = true; + + // FIXME: this shouldn't be panic=abort, it should be panic=unwind + base.panic_strategy = PanicStrategy::Abort; + base.linker = Some("rust-lld".to_owned()); + + Ok(Target { + llvm_target: "aarch64-pc-windows-msvc".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "64".to_string(), + target_c_int_width: "32".to_string(), + data_layout: "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128".to_string(), + arch: "aarch64".to_string(), + target_os: "windows".to_string(), + target_env: "msvc".to_string(), + target_vendor: "pc".to_string(), + linker_flavor: LinkerFlavor::Lld(LldFlavor::Link), + options: base, + }) +} diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index d55762e03ee..3a18c56f4fc 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -355,6 +355,7 @@ supported_targets! { ("x86_64-pc-windows-gnu", x86_64_pc_windows_gnu), ("i686-pc-windows-gnu", i686_pc_windows_gnu), + ("aarch64-pc-windows-msvc", aarch64_pc_windows_msvc), ("x86_64-pc-windows-msvc", x86_64_pc_windows_msvc), ("i686-pc-windows-msvc", i686_pc_windows_msvc), ("i586-pc-windows-msvc", i586_pc_windows_msvc), diff --git a/src/libstd/sys/windows/backtrace/mod.rs b/src/libstd/sys/windows/backtrace/mod.rs index 7ef4e203571..f64cae810b9 100644 --- a/src/libstd/sys/windows/backtrace/mod.rs +++ b/src/libstd/sys/windows/backtrace/mod.rs @@ -229,6 +229,7 @@ impl StackFrame for c::STACKFRAME_EX { 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; @@ -240,6 +241,17 @@ impl StackFrame for c::STACKFRAME_EX { 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 } @@ -260,6 +272,7 @@ impl StackFrame for c::STACKFRAME64 { 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; @@ -271,6 +284,17 @@ impl StackFrame for c::STACKFRAME64 { 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 } diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs index 6f81afe66f9..e514a56dcc4 100644 --- a/src/libstd/sys/windows/c.rs +++ b/src/libstd/sys/windows/c.rs @@ -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; @@ -791,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, diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs index 0d12ecf8fe3..ccf79de909f 100644 --- a/src/libstd/sys/windows/mod.rs +++ b/src/libstd/sys/windows/mod.rs @@ -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(); } -- cgit 1.4.1-3-g733a5