From 56147219a552b8383e66f9e3e8f0c92ea332aaf4 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Fri, 27 Mar 2020 19:18:52 -0400 Subject: [PATCH 01/13] Stabilize float::to_int_unchecked This renames and stabilizes unsafe floating point to integer casts, which are intended to be the substitute for the currently unsound `as` behavior, once that changes to safe-but-slower saturating casts. --- src/libcore/convert/num.rs | 15 +++++++++++---- src/libcore/intrinsics.rs | 8 ++++++++ src/libcore/num/f32.rs | 12 +++++------- src/libcore/num/f64.rs | 12 +++++------- src/librustc_codegen_llvm/intrinsic.rs | 6 +++--- src/librustc_typeck/check/intrinsic.rs | 2 +- 6 files changed, 33 insertions(+), 22 deletions(-) diff --git a/src/libcore/convert/num.rs b/src/libcore/convert/num.rs index 752199c94b8ae..66ae760fc1f79 100644 --- a/src/libcore/convert/num.rs +++ b/src/libcore/convert/num.rs @@ -13,9 +13,9 @@ mod private { /// Typically doesn’t need to be used directly. #[unstable(feature = "convert_float_to_int", issue = "67057")] pub trait FloatToInt: private::Sealed + Sized { - #[unstable(feature = "float_approx_unchecked_to", issue = "67058")] + #[unstable(feature = "convert_float_to_int", issue = "67057")] #[doc(hidden)] - unsafe fn approx_unchecked(self) -> Int; + unsafe fn to_int_unchecked(self) -> Int; } macro_rules! impl_float_to_int { @@ -27,8 +27,15 @@ macro_rules! impl_float_to_int { impl FloatToInt<$Int> for $Float { #[doc(hidden)] #[inline] - unsafe fn approx_unchecked(self) -> $Int { - crate::intrinsics::float_to_int_approx_unchecked(self) + unsafe fn to_int_unchecked(self) -> $Int { + #[cfg(bootstrap)] + { + crate::intrinsics::float_to_int_approx_unchecked(self) + } + #[cfg(not(bootstrap))] + { + crate::intrinsics::float_to_int_unchecked(self) + } } } )+ diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 0c956104221eb..7e9140faa6411 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -1582,8 +1582,16 @@ extern "rust-intrinsic" { /// Convert with LLVM’s fptoui/fptosi, which may return undef for values out of range /// () /// This is under stabilization at + #[cfg(bootstrap)] pub fn float_to_int_approx_unchecked(value: Float) -> Int; + /// Convert with LLVM’s fptoui/fptosi, which may return undef for values out of range + /// () + /// + /// Stabilized as `f32::to_int_unchecked` and `f64::to_int_unchecked`. + #[cfg(not(bootstrap))] + pub fn float_to_int_unchecked(value: Float) -> Int; + /// Returns the number of bits set in an integer type `T` /// /// The stabilized versions of this intrinsic are available on the integer diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index 3fdc2bae33876..09f1eab2d4b9d 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -464,14 +464,12 @@ impl f32 { /// assuming that the value is finite and fits in that type. /// /// ``` - /// #![feature(float_approx_unchecked_to)] - /// /// let value = 4.6_f32; - /// let rounded = unsafe { value.approx_unchecked_to::() }; + /// let rounded = unsafe { value.to_int_unchecked::() }; /// assert_eq!(rounded, 4); /// /// let value = -128.9_f32; - /// let rounded = unsafe { value.approx_unchecked_to::() }; + /// let rounded = unsafe { value.to_int_unchecked::() }; /// assert_eq!(rounded, std::i8::MIN); /// ``` /// @@ -482,13 +480,13 @@ impl f32 { /// * Not be `NaN` /// * Not be infinite /// * Be representable in the return type `Int`, after truncating off its fractional part - #[unstable(feature = "float_approx_unchecked_to", issue = "67058")] + #[stable(feature = "float_approx_unchecked_to", since = "1.44.0")] #[inline] - pub unsafe fn approx_unchecked_to(self) -> Int + pub unsafe fn to_int_unchecked(self) -> Int where Self: FloatToInt, { - FloatToInt::::approx_unchecked(self) + FloatToInt::::to_int_unchecked(self) } /// Raw transmutation to `u32`. diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index 129df937c0bb8..65ef7ba9ac768 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -478,14 +478,12 @@ impl f64 { /// assuming that the value is finite and fits in that type. /// /// ``` - /// #![feature(float_approx_unchecked_to)] - /// /// let value = 4.6_f32; - /// let rounded = unsafe { value.approx_unchecked_to::() }; + /// let rounded = unsafe { value.to_int_unchecked::() }; /// assert_eq!(rounded, 4); /// /// let value = -128.9_f32; - /// let rounded = unsafe { value.approx_unchecked_to::() }; + /// let rounded = unsafe { value.to_int_unchecked::() }; /// assert_eq!(rounded, std::i8::MIN); /// ``` /// @@ -496,13 +494,13 @@ impl f64 { /// * Not be `NaN` /// * Not be infinite /// * Be representable in the return type `Int`, after truncating off its fractional part - #[unstable(feature = "float_approx_unchecked_to", issue = "67058")] + #[stable(feature = "float_approx_unchecked_to", since = "1.44.0")] #[inline] - pub unsafe fn approx_unchecked_to(self) -> Int + pub unsafe fn to_int_unchecked(self) -> Int where Self: FloatToInt, { - FloatToInt::::approx_unchecked(self) + FloatToInt::::to_int_unchecked(self) } /// Raw transmutation to `u64`. diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index bc25b9496d9b5..a3aa73e6217e8 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -544,13 +544,13 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { } } - "float_to_int_approx_unchecked" => { + "float_to_int_unchecked" => { if float_type_width(arg_tys[0]).is_none() { span_invalid_monomorphization_error( tcx.sess, span, &format!( - "invalid monomorphization of `float_to_int_approx_unchecked` \ + "invalid monomorphization of `float_to_int_unchecked` \ intrinsic: expected basic float type, \ found `{}`", arg_tys[0] @@ -571,7 +571,7 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { tcx.sess, span, &format!( - "invalid monomorphization of `float_to_int_approx_unchecked` \ + "invalid monomorphization of `float_to_int_unchecked` \ intrinsic: expected basic integer type, \ found `{}`", ret_ty diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index 6f9d8a8e58fa5..d506d3445f62e 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -275,7 +275,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { "fadd_fast" | "fsub_fast" | "fmul_fast" | "fdiv_fast" | "frem_fast" => { (1, vec![param(0), param(0)], param(0)) } - "float_to_int_approx_unchecked" => (2, vec![param(0)], param(1)), + "float_to_int_unchecked" => (2, vec![param(0)], param(1)), "assume" => (0, vec![tcx.types.bool], tcx.mk_unit()), "likely" => (0, vec![tcx.types.bool], tcx.types.bool), From 64e5327b6e7ad79f4a3ca7de17ac105c8c59277e Mon Sep 17 00:00:00 2001 From: Vytautas Astrauskas Date: Mon, 30 Mar 2020 20:55:17 -0700 Subject: [PATCH 02/13] Fix double-free and undefined behaviour in libstd::syn::unix::Thread::new. --- src/libstd/sys/cloudabi/thread.rs | 13 ++++++++++--- src/libstd/sys/hermit/thread.rs | 14 ++++++++------ src/libstd/sys/unix/thread.rs | 13 ++++++++++--- src/libstd/sys/vxworks/thread.rs | 13 ++++++++++--- src/libstd/sys/windows/thread.rs | 8 +++++--- 5 files changed, 43 insertions(+), 18 deletions(-) diff --git a/src/libstd/sys/cloudabi/thread.rs b/src/libstd/sys/cloudabi/thread.rs index 3afcae7ae7516..a3595debaf591 100644 --- a/src/libstd/sys/cloudabi/thread.rs +++ b/src/libstd/sys/cloudabi/thread.rs @@ -22,7 +22,7 @@ unsafe impl Sync for Thread {} impl Thread { // unsafe: see thread::Builder::spawn_unchecked for safety requirements pub unsafe fn new(stack: usize, p: Box) -> io::Result { - let p = box p; + let mut p = mem::ManuallyDrop::new(box p); let mut native: libc::pthread_t = mem::zeroed(); let mut attr: libc::pthread_attr_t = mem::zeroed(); assert_eq!(libc::pthread_attr_init(&mut attr), 0); @@ -30,13 +30,20 @@ impl Thread { let stack_size = cmp::max(stack, min_stack_size(&attr)); assert_eq!(libc::pthread_attr_setstacksize(&mut attr, stack_size), 0); - let ret = libc::pthread_create(&mut native, &attr, thread_start, &*p as *const _ as *mut _); + let ret = libc::pthread_create( + &mut native, + &attr, + thread_start, + &mut *p as &mut Box as *mut _ as *mut _, + ); assert_eq!(libc::pthread_attr_destroy(&mut attr), 0); return if ret != 0 { + // The thread failed to start and as a result p was not consumed. Therefore, it is + // safe to manually drop it. + mem::ManuallyDrop::drop(&mut p); Err(io::Error::from_raw_os_error(ret)) } else { - mem::forget(p); // ownership passed to pthread_create Ok(Thread { id: native }) }; diff --git a/src/libstd/sys/hermit/thread.rs b/src/libstd/sys/hermit/thread.rs index c3c29c93826de..8e15208abc246 100644 --- a/src/libstd/sys/hermit/thread.rs +++ b/src/libstd/sys/hermit/thread.rs @@ -49,21 +49,23 @@ impl Thread { p: Box, core_id: isize, ) -> io::Result { - let p = box p; + let mut p = mem::ManuallyDrop::new(box p); let mut tid: Tid = u32::MAX; let ret = abi::spawn( &mut tid as *mut Tid, thread_start, - &*p as *const _ as *const u8 as usize, + &mut *p as &mut Box as *mut _ as *mut u8 as usize, Priority::into(NORMAL_PRIO), core_id, ); - return if ret == 0 { - mem::forget(p); // ownership passed to pthread_create - Ok(Thread { tid: tid }) - } else { + return if ret != 0 { + // The thread failed to start and as a result p was not consumed. Therefore, it is + // safe to manually drop it. + mem::ManuallyDrop::drop(&mut p); Err(io::Error::new(io::ErrorKind::Other, "Unable to create thread!")) + } else { + Ok(Thread { tid: tid }) }; extern "C" fn thread_start(main: usize) { diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs index 674d4c7113801..efcd614202468 100644 --- a/src/libstd/sys/unix/thread.rs +++ b/src/libstd/sys/unix/thread.rs @@ -43,7 +43,7 @@ unsafe fn pthread_attr_setstacksize( impl Thread { // unsafe: see thread::Builder::spawn_unchecked for safety requirements pub unsafe fn new(stack: usize, p: Box) -> io::Result { - let p = box p; + let mut p = mem::ManuallyDrop::new(box p); let mut native: libc::pthread_t = mem::zeroed(); let mut attr: libc::pthread_attr_t = mem::zeroed(); assert_eq!(libc::pthread_attr_init(&mut attr), 0); @@ -65,13 +65,20 @@ impl Thread { } }; - let ret = libc::pthread_create(&mut native, &attr, thread_start, &*p as *const _ as *mut _); + let ret = libc::pthread_create( + &mut native, + &attr, + thread_start, + &mut *p as &mut Box as *mut _ as *mut _, + ); assert_eq!(libc::pthread_attr_destroy(&mut attr), 0); return if ret != 0 { + // The thread failed to start and as a result p was not consumed. Therefore, it is + // safe to manually drop it. + mem::ManuallyDrop::drop(&mut p); Err(io::Error::from_raw_os_error(ret)) } else { - mem::forget(p); // ownership passed to pthread_create Ok(Thread { id: native }) }; diff --git a/src/libstd/sys/vxworks/thread.rs b/src/libstd/sys/vxworks/thread.rs index e0d104b5f3ec9..81233c1975c79 100644 --- a/src/libstd/sys/vxworks/thread.rs +++ b/src/libstd/sys/vxworks/thread.rs @@ -31,7 +31,7 @@ unsafe fn pthread_attr_setstacksize( impl Thread { // unsafe: see thread::Builder::spawn_unchecked for safety requirements pub unsafe fn new(stack: usize, p: Box) -> io::Result { - let p = box p; + let mut p = mem::ManuallyDrop::new(box p); let mut native: libc::pthread_t = mem::zeroed(); let mut attr: libc::pthread_attr_t = mem::zeroed(); assert_eq!(libc::pthread_attr_init(&mut attr), 0); @@ -53,13 +53,20 @@ impl Thread { } }; - let ret = libc::pthread_create(&mut native, &attr, thread_start, &*p as *const _ as *mut _); + let ret = libc::pthread_create( + &mut native, + &attr, + thread_start, + &mut *p as &mut Box as *mut _ as *mut _, + ); assert_eq!(libc::pthread_attr_destroy(&mut attr), 0); return if ret != 0 { + // The thread failed to start and as a result p was not consumed. Therefore, it is + // safe to manually drop it. + mem::ManuallyDrop::drop(&mut p); Err(io::Error::from_raw_os_error(ret)) } else { - mem::forget(p); // ownership passed to pthread_create Ok(Thread { id: native }) }; diff --git a/src/libstd/sys/windows/thread.rs b/src/libstd/sys/windows/thread.rs index c828243a59b11..052f51a33ceeb 100644 --- a/src/libstd/sys/windows/thread.rs +++ b/src/libstd/sys/windows/thread.rs @@ -20,7 +20,7 @@ pub struct Thread { impl Thread { // unsafe: see thread::Builder::spawn_unchecked for safety requirements pub unsafe fn new(stack: usize, p: Box) -> io::Result { - let p = box p; + let mut p = mem::ManuallyDrop::new(box p); // FIXME On UNIX, we guard against stack sizes that are too small but // that's because pthreads enforces that stacks are at least @@ -34,15 +34,17 @@ impl Thread { ptr::null_mut(), stack_size, thread_start, - &*p as *const _ as *mut _, + &mut *p as &mut Box as *mut _ as *mut _, c::STACK_SIZE_PARAM_IS_A_RESERVATION, ptr::null_mut(), ); return if ret as usize == 0 { + // The thread failed to start and as a result p was not consumed. Therefore, it is + // safe to manually drop it. + mem::ManuallyDrop::drop(&mut p); Err(io::Error::last_os_error()) } else { - mem::forget(p); // ownership passed to CreateThread Ok(Thread { handle: Handle::new(ret) }) }; From 753bc7ddf8a0f00acf039731947a12d06ad30884 Mon Sep 17 00:00:00 2001 From: Vytautas Astrauskas Date: Tue, 31 Mar 2020 12:35:07 -0700 Subject: [PATCH 03/13] Inline start_thread into its callers. --- src/libstd/sys/cloudabi/thread.rs | 8 ++++++-- src/libstd/sys/hermit/thread.rs | 9 ++++++--- src/libstd/sys/unix/thread.rs | 10 ++++++---- src/libstd/sys/vxworks/thread.rs | 10 ++++++---- src/libstd/sys/windows/thread.rs | 8 ++++++-- src/libstd/sys_common/thread.rs | 11 ----------- 6 files changed, 30 insertions(+), 26 deletions(-) diff --git a/src/libstd/sys/cloudabi/thread.rs b/src/libstd/sys/cloudabi/thread.rs index a3595debaf591..112bb1ce3af0a 100644 --- a/src/libstd/sys/cloudabi/thread.rs +++ b/src/libstd/sys/cloudabi/thread.rs @@ -4,8 +4,8 @@ use crate::io; use crate::mem; use crate::ptr; use crate::sys::cloudabi::abi; +use crate::sys::stack_overflow; use crate::sys::time::checked_dur2intervals; -use crate::sys_common::thread::*; use crate::time::Duration; pub const DEFAULT_MIN_STACK_SIZE: usize = 2 * 1024 * 1024; @@ -49,7 +49,11 @@ impl Thread { extern "C" fn thread_start(main: *mut libc::c_void) -> *mut libc::c_void { unsafe { - start_thread(main as *mut u8); + // Next, set up our stack overflow handler which may get triggered if we run + // out of stack. + let _handler = stack_overflow::Handler::new(); + // Finally, let's run some code. + Box::from_raw(main as *mut Box)(); } ptr::null_mut() } diff --git a/src/libstd/sys/hermit/thread.rs b/src/libstd/sys/hermit/thread.rs index 8e15208abc246..f92c18a3a4521 100644 --- a/src/libstd/sys/hermit/thread.rs +++ b/src/libstd/sys/hermit/thread.rs @@ -5,11 +5,10 @@ use crate::fmt; use crate::io; use crate::mem; use crate::sys::hermit::abi; +use crate::sys::stack_overflow; use crate::time::Duration; use core::u32; -use crate::sys_common::thread::*; - pub type Tid = abi::Tid; /// Priority of a task @@ -70,7 +69,11 @@ impl Thread { extern "C" fn thread_start(main: usize) { unsafe { - start_thread(main as *mut u8); + // Next, set up our stack overflow handler which may get triggered if we run + // out of stack. + let _handler = stack_overflow::Handler::new(); + // Finally, let's run some code. + Box::from_raw(main as *mut Box)(); } } } diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs index efcd614202468..513a1fde331b7 100644 --- a/src/libstd/sys/unix/thread.rs +++ b/src/libstd/sys/unix/thread.rs @@ -3,11 +3,9 @@ use crate::ffi::CStr; use crate::io; use crate::mem; use crate::ptr; -use crate::sys::os; +use crate::sys::{os, stack_overflow}; use crate::time::Duration; -use crate::sys_common::thread::*; - #[cfg(not(target_os = "l4re"))] pub const DEFAULT_MIN_STACK_SIZE: usize = 2 * 1024 * 1024; #[cfg(target_os = "l4re")] @@ -84,7 +82,11 @@ impl Thread { extern "C" fn thread_start(main: *mut libc::c_void) -> *mut libc::c_void { unsafe { - start_thread(main as *mut u8); + // Next, set up our stack overflow handler which may get triggered if we run + // out of stack. + let _handler = stack_overflow::Handler::new(); + // Finally, let's run some code. + Box::from_raw(main as *mut Box)(); } ptr::null_mut() } diff --git a/src/libstd/sys/vxworks/thread.rs b/src/libstd/sys/vxworks/thread.rs index 81233c1975c79..92163865b799a 100644 --- a/src/libstd/sys/vxworks/thread.rs +++ b/src/libstd/sys/vxworks/thread.rs @@ -3,11 +3,9 @@ use crate::ffi::CStr; use crate::io; use crate::mem; use crate::ptr; -use crate::sys::os; +use crate::sys::{os, stack_overflow}; use crate::time::Duration; -use crate::sys_common::thread::*; - pub const DEFAULT_MIN_STACK_SIZE: usize = 0x40000; // 256K pub struct Thread { @@ -72,7 +70,11 @@ impl Thread { extern "C" fn thread_start(main: *mut libc::c_void) -> *mut libc::c_void { unsafe { - start_thread(main as *mut u8); + // Next, set up our stack overflow handler which may get triggered if we run + // out of stack. + let _handler = stack_overflow::Handler::new(); + // Finally, let's run some code. + Box::from_raw(main as *mut Box)(); } ptr::null_mut() } diff --git a/src/libstd/sys/windows/thread.rs b/src/libstd/sys/windows/thread.rs index 052f51a33ceeb..a1cad19d0f57e 100644 --- a/src/libstd/sys/windows/thread.rs +++ b/src/libstd/sys/windows/thread.rs @@ -4,7 +4,7 @@ use crate::mem; use crate::ptr; use crate::sys::c; use crate::sys::handle::Handle; -use crate::sys_common::thread::*; +use crate::sys::stack_overflow; use crate::time::Duration; use libc::c_void; @@ -50,7 +50,11 @@ impl Thread { extern "system" fn thread_start(main: *mut c_void) -> c::DWORD { unsafe { - start_thread(main as *mut u8); + // Next, set up our stack overflow handler which may get triggered if we run + // out of stack. + let _handler = stack_overflow::Handler::new(); + // Finally, let's run some code. + Box::from_raw(main as *mut Box)(); } 0 } diff --git a/src/libstd/sys_common/thread.rs b/src/libstd/sys_common/thread.rs index 6ab0d5cbe9c96..f3a8bef8f718f 100644 --- a/src/libstd/sys_common/thread.rs +++ b/src/libstd/sys_common/thread.rs @@ -1,18 +1,7 @@ use crate::env; use crate::sync::atomic::{self, Ordering}; -use crate::sys::stack_overflow; use crate::sys::thread as imp; -#[allow(dead_code)] -pub unsafe fn start_thread(main: *mut u8) { - // Next, set up our stack overflow handler which may get triggered if we run - // out of stack. - let _handler = stack_overflow::Handler::new(); - - // Finally, let's run some code. - Box::from_raw(main as *mut Box)() -} - pub fn min_stack() -> usize { static MIN: atomic::AtomicUsize = atomic::AtomicUsize::new(0); match MIN.load(Ordering::SeqCst) { From 5382347064ac47a2a5ac56b57cec0d91b9b40edc Mon Sep 17 00:00:00 2001 From: Vytautas Astrauskas Date: Tue, 31 Mar 2020 17:51:51 -0700 Subject: [PATCH 04/13] Use Box::into_raw instead of ManuallyDrop in Thread::new. --- src/libstd/sys/cloudabi/thread.rs | 13 ++++--------- src/libstd/sys/hermit/thread.rs | 8 ++++---- src/libstd/sys/unix/thread.rs | 13 ++++--------- src/libstd/sys/vxworks/thread.rs | 13 ++++--------- src/libstd/sys/windows/thread.rs | 9 ++++----- 5 files changed, 20 insertions(+), 36 deletions(-) diff --git a/src/libstd/sys/cloudabi/thread.rs b/src/libstd/sys/cloudabi/thread.rs index 112bb1ce3af0a..9d95a61c3154d 100644 --- a/src/libstd/sys/cloudabi/thread.rs +++ b/src/libstd/sys/cloudabi/thread.rs @@ -22,7 +22,7 @@ unsafe impl Sync for Thread {} impl Thread { // unsafe: see thread::Builder::spawn_unchecked for safety requirements pub unsafe fn new(stack: usize, p: Box) -> io::Result { - let mut p = mem::ManuallyDrop::new(box p); + let p = Box::into_raw(box p); let mut native: libc::pthread_t = mem::zeroed(); let mut attr: libc::pthread_attr_t = mem::zeroed(); assert_eq!(libc::pthread_attr_init(&mut attr), 0); @@ -30,18 +30,13 @@ impl Thread { let stack_size = cmp::max(stack, min_stack_size(&attr)); assert_eq!(libc::pthread_attr_setstacksize(&mut attr, stack_size), 0); - let ret = libc::pthread_create( - &mut native, - &attr, - thread_start, - &mut *p as &mut Box as *mut _ as *mut _, - ); + let ret = libc::pthread_create(&mut native, &attr, thread_start, p as *mut _); assert_eq!(libc::pthread_attr_destroy(&mut attr), 0); return if ret != 0 { // The thread failed to start and as a result p was not consumed. Therefore, it is - // safe to manually drop it. - mem::ManuallyDrop::drop(&mut p); + // safe to reconstruct the box so that it gets deallocated. + let _ = Box::from_raw(p); Err(io::Error::from_raw_os_error(ret)) } else { Ok(Thread { id: native }) diff --git a/src/libstd/sys/hermit/thread.rs b/src/libstd/sys/hermit/thread.rs index f92c18a3a4521..6b00903780541 100644 --- a/src/libstd/sys/hermit/thread.rs +++ b/src/libstd/sys/hermit/thread.rs @@ -48,20 +48,20 @@ impl Thread { p: Box, core_id: isize, ) -> io::Result { - let mut p = mem::ManuallyDrop::new(box p); + let p = Box::into_raw(box p); let mut tid: Tid = u32::MAX; let ret = abi::spawn( &mut tid as *mut Tid, thread_start, - &mut *p as &mut Box as *mut _ as *mut u8 as usize, + p as *mut u8 as usize, Priority::into(NORMAL_PRIO), core_id, ); return if ret != 0 { // The thread failed to start and as a result p was not consumed. Therefore, it is - // safe to manually drop it. - mem::ManuallyDrop::drop(&mut p); + // safe to reconstruct the box so that it gets deallocated. + let _ = Box::from_raw(p); Err(io::Error::new(io::ErrorKind::Other, "Unable to create thread!")) } else { Ok(Thread { tid: tid }) diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs index 513a1fde331b7..1cad474e33e63 100644 --- a/src/libstd/sys/unix/thread.rs +++ b/src/libstd/sys/unix/thread.rs @@ -41,7 +41,7 @@ unsafe fn pthread_attr_setstacksize( impl Thread { // unsafe: see thread::Builder::spawn_unchecked for safety requirements pub unsafe fn new(stack: usize, p: Box) -> io::Result { - let mut p = mem::ManuallyDrop::new(box p); + let p = Box::into_raw(box p); let mut native: libc::pthread_t = mem::zeroed(); let mut attr: libc::pthread_attr_t = mem::zeroed(); assert_eq!(libc::pthread_attr_init(&mut attr), 0); @@ -63,18 +63,13 @@ impl Thread { } }; - let ret = libc::pthread_create( - &mut native, - &attr, - thread_start, - &mut *p as &mut Box as *mut _ as *mut _, - ); + let ret = libc::pthread_create(&mut native, &attr, thread_start, p as *mut _); assert_eq!(libc::pthread_attr_destroy(&mut attr), 0); return if ret != 0 { // The thread failed to start and as a result p was not consumed. Therefore, it is - // safe to manually drop it. - mem::ManuallyDrop::drop(&mut p); + // safe to reconstruct the box so that it gets deallocated. + let _ = Box::from_raw(p); Err(io::Error::from_raw_os_error(ret)) } else { Ok(Thread { id: native }) diff --git a/src/libstd/sys/vxworks/thread.rs b/src/libstd/sys/vxworks/thread.rs index 92163865b799a..3c9557db94ade 100644 --- a/src/libstd/sys/vxworks/thread.rs +++ b/src/libstd/sys/vxworks/thread.rs @@ -29,7 +29,7 @@ unsafe fn pthread_attr_setstacksize( impl Thread { // unsafe: see thread::Builder::spawn_unchecked for safety requirements pub unsafe fn new(stack: usize, p: Box) -> io::Result { - let mut p = mem::ManuallyDrop::new(box p); + let p = Box::into_raw(box p); let mut native: libc::pthread_t = mem::zeroed(); let mut attr: libc::pthread_attr_t = mem::zeroed(); assert_eq!(libc::pthread_attr_init(&mut attr), 0); @@ -51,18 +51,13 @@ impl Thread { } }; - let ret = libc::pthread_create( - &mut native, - &attr, - thread_start, - &mut *p as &mut Box as *mut _ as *mut _, - ); + let ret = libc::pthread_create(&mut native, &attr, thread_start, p as *mut _); assert_eq!(libc::pthread_attr_destroy(&mut attr), 0); return if ret != 0 { // The thread failed to start and as a result p was not consumed. Therefore, it is - // safe to manually drop it. - mem::ManuallyDrop::drop(&mut p); + // safe to reconstruct the box so that it gets deallocated. + let _ = Box::from_raw(p); Err(io::Error::from_raw_os_error(ret)) } else { Ok(Thread { id: native }) diff --git a/src/libstd/sys/windows/thread.rs b/src/libstd/sys/windows/thread.rs index a1cad19d0f57e..e39c1c0a13261 100644 --- a/src/libstd/sys/windows/thread.rs +++ b/src/libstd/sys/windows/thread.rs @@ -1,6 +1,5 @@ use crate::ffi::CStr; use crate::io; -use crate::mem; use crate::ptr; use crate::sys::c; use crate::sys::handle::Handle; @@ -20,7 +19,7 @@ pub struct Thread { impl Thread { // unsafe: see thread::Builder::spawn_unchecked for safety requirements pub unsafe fn new(stack: usize, p: Box) -> io::Result { - let mut p = mem::ManuallyDrop::new(box p); + let p = Box::into_raw(box p); // FIXME On UNIX, we guard against stack sizes that are too small but // that's because pthreads enforces that stacks are at least @@ -34,15 +33,15 @@ impl Thread { ptr::null_mut(), stack_size, thread_start, - &mut *p as &mut Box as *mut _ as *mut _, + p as *mut _, c::STACK_SIZE_PARAM_IS_A_RESERVATION, ptr::null_mut(), ); return if ret as usize == 0 { // The thread failed to start and as a result p was not consumed. Therefore, it is - // safe to manually drop it. - mem::ManuallyDrop::drop(&mut p); + // safe to reconstruct the box so that it gets deallocated. + let _ = Box::from_raw(p); Err(io::Error::last_os_error()) } else { Ok(Thread { handle: Handle::new(ret) }) From baa6d557a7b965ff8277f940a43e0ce3df3b8913 Mon Sep 17 00:00:00 2001 From: Vytautas Astrauskas Date: Wed, 1 Apr 2020 12:46:14 -0700 Subject: [PATCH 05/13] In Thread::new, add a comment that a panic could cause a memory leak. --- src/libstd/sys/cloudabi/thread.rs | 5 ++++- src/libstd/sys/hermit/thread.rs | 2 +- src/libstd/sys/unix/thread.rs | 5 ++++- src/libstd/sys/vxworks/thread.rs | 5 ++++- src/libstd/sys/windows/thread.rs | 2 +- 5 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/libstd/sys/cloudabi/thread.rs b/src/libstd/sys/cloudabi/thread.rs index 9d95a61c3154d..abc15b18e321a 100644 --- a/src/libstd/sys/cloudabi/thread.rs +++ b/src/libstd/sys/cloudabi/thread.rs @@ -31,12 +31,15 @@ impl Thread { assert_eq!(libc::pthread_attr_setstacksize(&mut attr, stack_size), 0); let ret = libc::pthread_create(&mut native, &attr, thread_start, p as *mut _); + // Note: if the thread creation fails and this assert fails, then p will + // be leaked. However, an alternative design could cause double-free + // which is clearly worse. assert_eq!(libc::pthread_attr_destroy(&mut attr), 0); return if ret != 0 { // The thread failed to start and as a result p was not consumed. Therefore, it is // safe to reconstruct the box so that it gets deallocated. - let _ = Box::from_raw(p); + drop(Box::from_raw(p)); Err(io::Error::from_raw_os_error(ret)) } else { Ok(Thread { id: native }) diff --git a/src/libstd/sys/hermit/thread.rs b/src/libstd/sys/hermit/thread.rs index 6b00903780541..4f20a6453fc27 100644 --- a/src/libstd/sys/hermit/thread.rs +++ b/src/libstd/sys/hermit/thread.rs @@ -61,7 +61,7 @@ impl Thread { return if ret != 0 { // The thread failed to start and as a result p was not consumed. Therefore, it is // safe to reconstruct the box so that it gets deallocated. - let _ = Box::from_raw(p); + drop(Box::from_raw(p)); Err(io::Error::new(io::ErrorKind::Other, "Unable to create thread!")) } else { Ok(Thread { tid: tid }) diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs index 1cad474e33e63..aab5a92a7ad2a 100644 --- a/src/libstd/sys/unix/thread.rs +++ b/src/libstd/sys/unix/thread.rs @@ -64,12 +64,15 @@ impl Thread { }; let ret = libc::pthread_create(&mut native, &attr, thread_start, p as *mut _); + // Note: if the thread creation fails and this assert fails, then p will + // be leaked. However, an alternative design could cause double-free + // which is clearly worse. assert_eq!(libc::pthread_attr_destroy(&mut attr), 0); return if ret != 0 { // The thread failed to start and as a result p was not consumed. Therefore, it is // safe to reconstruct the box so that it gets deallocated. - let _ = Box::from_raw(p); + drop(Box::from_raw(p)); Err(io::Error::from_raw_os_error(ret)) } else { Ok(Thread { id: native }) diff --git a/src/libstd/sys/vxworks/thread.rs b/src/libstd/sys/vxworks/thread.rs index 3c9557db94ade..4d0196e4b4de5 100644 --- a/src/libstd/sys/vxworks/thread.rs +++ b/src/libstd/sys/vxworks/thread.rs @@ -52,12 +52,15 @@ impl Thread { }; let ret = libc::pthread_create(&mut native, &attr, thread_start, p as *mut _); + // Note: if the thread creation fails and this assert fails, then p will + // be leaked. However, an alternative design could cause double-free + // which is clearly worse. assert_eq!(libc::pthread_attr_destroy(&mut attr), 0); return if ret != 0 { // The thread failed to start and as a result p was not consumed. Therefore, it is // safe to reconstruct the box so that it gets deallocated. - let _ = Box::from_raw(p); + drop(Box::from_raw(p)); Err(io::Error::from_raw_os_error(ret)) } else { Ok(Thread { id: native }) diff --git a/src/libstd/sys/windows/thread.rs b/src/libstd/sys/windows/thread.rs index e39c1c0a13261..38839ea5e90ed 100644 --- a/src/libstd/sys/windows/thread.rs +++ b/src/libstd/sys/windows/thread.rs @@ -41,7 +41,7 @@ impl Thread { return if ret as usize == 0 { // The thread failed to start and as a result p was not consumed. Therefore, it is // safe to reconstruct the box so that it gets deallocated. - let _ = Box::from_raw(p); + drop(Box::from_raw(p)); Err(io::Error::last_os_error()) } else { Ok(Thread { handle: Handle::new(ret) }) From f87afec2cec4f75e2caf9f72a7d8ee5e93b1eaab Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Thu, 2 Apr 2020 03:55:35 +0000 Subject: [PATCH 06/13] Use Self over specific type in return position --- src/libstd/fs.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index e20fcfafa229b..119bdfcb0f442 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -734,7 +734,7 @@ impl OpenOptions { /// let file = options.read(true).open("foo.txt"); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn new() -> OpenOptions { + pub fn new() -> Self { OpenOptions(fs_imp::OpenOptions::new()) } @@ -751,7 +751,7 @@ impl OpenOptions { /// let file = OpenOptions::new().read(true).open("foo.txt"); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn read(&mut self, read: bool) -> &mut OpenOptions { + pub fn read(&mut self, read: bool) -> &mut Self { self.0.read(read); self } @@ -772,7 +772,7 @@ impl OpenOptions { /// let file = OpenOptions::new().write(true).open("foo.txt"); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn write(&mut self, write: bool) -> &mut OpenOptions { + pub fn write(&mut self, write: bool) -> &mut Self { self.0.write(write); self } @@ -819,7 +819,7 @@ impl OpenOptions { /// let file = OpenOptions::new().append(true).open("foo.txt"); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn append(&mut self, append: bool) -> &mut OpenOptions { + pub fn append(&mut self, append: bool) -> &mut Self { self.0.append(append); self } @@ -839,7 +839,7 @@ impl OpenOptions { /// let file = OpenOptions::new().write(true).truncate(true).open("foo.txt"); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn truncate(&mut self, truncate: bool) -> &mut OpenOptions { + pub fn truncate(&mut self, truncate: bool) -> &mut Self { self.0.truncate(truncate); self } @@ -860,7 +860,7 @@ impl OpenOptions { /// let file = OpenOptions::new().write(true).create(true).open("foo.txt"); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn create(&mut self, create: bool) -> &mut OpenOptions { + pub fn create(&mut self, create: bool) -> &mut Self { self.0.create(create); self } @@ -893,7 +893,7 @@ impl OpenOptions { /// .open("foo.txt"); /// ``` #[stable(feature = "expand_open_options2", since = "1.9.0")] - pub fn create_new(&mut self, create_new: bool) -> &mut OpenOptions { + pub fn create_new(&mut self, create_new: bool) -> &mut Self { self.0.create_new(create_new); self } From 75e2e8c71b4988324ebed0696d0177030d26be1d Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Mon, 30 Mar 2020 09:56:52 -0400 Subject: [PATCH 07/13] Remove unused discriminant reads from MIR bodies Allow the `SimplifyLocals` pass to remove reads of discriminants if the read is never used. --- src/librustc_mir/transform/simplify.rs | 26 +++++++------ ...ocals-removes-unused-discriminant-reads.rs | 12 ++++++ .../rustc.map.SimplifyLocals.diff | 37 +++++++++++++++++++ src/test/mir-opt/simplify_try.rs | 16 ++++---- 4 files changed, 71 insertions(+), 20 deletions(-) create mode 100644 src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads.rs create mode 100644 src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads/rustc.map.SimplifyLocals.diff diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs index faee077f51e1a..c2029a223b941 100644 --- a/src/librustc_mir/transform/simplify.rs +++ b/src/librustc_mir/transform/simplify.rs @@ -368,18 +368,22 @@ impl<'a, 'tcx> Visitor<'tcx> for DeclMarker<'a, 'tcx> { if location.statement_index != block.statements.len() { let stmt = &block.statements[location.statement_index]; - if let StatementKind::Assign(box (p, Rvalue::Use(Operand::Constant(c)))) = - &stmt.kind - { - match c.literal.val { - // Keep assignments from unevaluated constants around, since the evaluation - // may report errors, even if the use of the constant is dead code. - ty::ConstKind::Unevaluated(..) => {} - _ => { - if !p.is_indirect() { - trace!("skipping store of const value {:?} to {:?}", c, p); - return; + if let StatementKind::Assign(box (dest, rvalue)) = &stmt.kind { + if !dest.is_indirect() && dest.local == *local { + if let Rvalue::Use(Operand::Constant(c)) = rvalue { + match c.literal.val { + // Keep assignments from unevaluated constants around, since the + // evaluation may report errors, even if the use of the constant + // is dead code. + ty::ConstKind::Unevaluated(..) => {} + _ => { + trace!("skipping store of const value {:?} to {:?}", c, dest); + return; + } } + } else if let Rvalue::Discriminant(d) = rvalue { + trace!("skipping store of discriminant value {:?} to {:?}", d, dest); + return; } } } diff --git a/src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads.rs b/src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads.rs new file mode 100644 index 0000000000000..067fa879b4038 --- /dev/null +++ b/src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads.rs @@ -0,0 +1,12 @@ +fn map(x: Option>) -> Option> { + match x { + None => None, + Some(x) => Some(x), + } +} + +fn main() { + map(None); +} + +// EMIT_MIR rustc.map.SimplifyLocals.diff diff --git a/src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads/rustc.map.SimplifyLocals.diff b/src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads/rustc.map.SimplifyLocals.diff new file mode 100644 index 0000000000000..bba8bc82fe7d9 --- /dev/null +++ b/src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads/rustc.map.SimplifyLocals.diff @@ -0,0 +1,37 @@ +- // MIR for `map` before SimplifyLocals ++ // MIR for `map` after SimplifyLocals + + fn map(_1: std::option::Option>) -> std::option::Option> { + debug x => _1; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:1:8: 1:9 + let mut _0: std::option::Option>; // return place in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:1:31: 1:46 + let mut _2: isize; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:3:9: 3:13 + let _3: std::boxed::Box<()>; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:4:14: 4:15 +- let mut _4: std::boxed::Box<()>; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:4:25: 4:26 +- let mut _5: isize; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:6:1: 6:2 +- let mut _6: isize; // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:6:1: 6:2 + scope 1 { + debug x => _3; // in scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:4:14: 4:15 + } + + bb0: { + _2 = discriminant(_1); // bb0[0]: scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:3:9: 3:13 + switchInt(move _2) -> [0isize: bb2, otherwise: bb1]; // bb0[1]: scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:3:9: 3:13 + } + + bb1: { + _0 = move _1; // bb1[0]: scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:4:20: 4:27 + goto -> bb3; // bb1[1]: scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:2:5: 5:6 + } + + bb2: { + discriminant(_0) = 0; // bb2[0]: scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:3:17: 3:21 + goto -> bb3; // bb2[1]: scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:2:5: 5:6 + } + + bb3: { +- _5 = discriminant(_1); // bb3[0]: scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:6:1: 6:2 +- return; // bb3[1]: scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:6:2: 6:2 ++ return; // bb3[0]: scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:6:2: 6:2 + } + } + diff --git a/src/test/mir-opt/simplify_try.rs b/src/test/mir-opt/simplify_try.rs index abac66d95c548..78a7f722538ed 100644 --- a/src/test/mir-opt/simplify_try.rs +++ b/src/test/mir-opt/simplify_try.rs @@ -183,25 +183,24 @@ fn main() { // fn try_identity(_1: std::result::Result) -> std::result::Result { // debug x => _1; // let mut _0: std::result::Result; -// let mut _2: isize; -// let _3: i32; -// let _4: u32; +// let _2: i32; +// let _3: u32; // scope 1 { -// debug y => _4; +// debug y => _3; // } // scope 2 { -// debug err => _3; +// debug err => _2; // scope 3 { // scope 7 { -// debug t => _3; +// debug t => _2; // } // scope 8 { -// debug v => _3; +// debug v => _2; // } // } // } // scope 4 { -// debug val => _4; +// debug val => _3; // scope 5 { // } // } @@ -209,7 +208,6 @@ fn main() { // debug self => _1; // } // bb0: { -// _2 = discriminant(_1); // _0 = move _1; // return; // } From 0b612399366e28b5314b5fd289f46c636d596a7b Mon Sep 17 00:00:00 2001 From: Tim Diekmann Date: Thu, 2 Apr 2020 14:20:35 +0200 Subject: [PATCH 08/13] Improve docs in `AllocRef` --- src/libcore/alloc/mod.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/libcore/alloc/mod.rs b/src/libcore/alloc/mod.rs index e8c4b68c64890..77ac93c7b7905 100644 --- a/src/libcore/alloc/mod.rs +++ b/src/libcore/alloc/mod.rs @@ -33,9 +33,7 @@ impl fmt::Display for AllocErr { #[derive(Debug, Copy, Clone, PartialEq, Eq)] #[unstable(feature = "allocator_api", issue = "32838")] pub enum AllocInit { - /// The contents of the new memory are undefined. - /// - /// Reading uninitialized memory is Undefined Behavior; it must be initialized before use. + /// The contents of the new memory are uninitialized. Uninitialized, /// The new memory is guaranteed to be zeroed. Zeroed, @@ -196,7 +194,11 @@ pub unsafe trait AllocRef { /// /// # Safety /// - /// `memory` must be a memory block returned by this allocator. + /// * `ptr` must be [*currently allocated*] via this allocator, and + /// * `layout` must [*fit*] the `ptr`. + /// + /// [*currently allocated*]: #currently-allocated-memory + /// [*fit*]: #memory-fitting unsafe fn dealloc(&mut self, ptr: NonNull, layout: Layout); /// Attempts to extend the memory block. @@ -237,7 +239,7 @@ pub unsafe trait AllocRef { // * `new_size must be strictly greater than `memory.size` or both are zero /// * `new_size` must be greater than or equal to `layout.size()` /// * `new_size`, when rounded up to the nearest multiple of `layout.align()`, must not overflow - /// (i.e., the rounded value must be less than `usize::MAX`). + /// (i.e., the rounded value must be less than or equal to `usize::MAX`). /// /// [*currently allocated*]: #currently-allocated-memory /// [*fit*]: #memory-fitting From ec8275c364493b938357a3615216e3f30c60a443 Mon Sep 17 00:00:00 2001 From: Vytautas Astrauskas Date: Thu, 2 Apr 2020 07:15:12 -0700 Subject: [PATCH 09/13] Remove stack overflow handler stub for wasm. --- src/libstd/sys/wasm/stack_overflow.rs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/libstd/sys/wasm/stack_overflow.rs b/src/libstd/sys/wasm/stack_overflow.rs index cbf62b6e5b7e3..32555394cd5a5 100644 --- a/src/libstd/sys/wasm/stack_overflow.rs +++ b/src/libstd/sys/wasm/stack_overflow.rs @@ -1,11 +1,3 @@ -pub struct Handler; - -impl Handler { - pub unsafe fn new() -> Handler { - Handler - } -} - pub unsafe fn init() {} pub unsafe fn cleanup() {} From 1c1bd957d5c9f5c478a738ae83116c1260bc4896 Mon Sep 17 00:00:00 2001 From: Vytautas Astrauskas Date: Thu, 2 Apr 2020 07:15:45 -0700 Subject: [PATCH 10/13] Remove unnecessary intermediate pointer cast in Thread::new. --- src/libstd/sys/hermit/thread.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/sys/hermit/thread.rs b/src/libstd/sys/hermit/thread.rs index 4f20a6453fc27..beb02d9c8be47 100644 --- a/src/libstd/sys/hermit/thread.rs +++ b/src/libstd/sys/hermit/thread.rs @@ -53,7 +53,7 @@ impl Thread { let ret = abi::spawn( &mut tid as *mut Tid, thread_start, - p as *mut u8 as usize, + p as usize, Priority::into(NORMAL_PRIO), core_id, ); From 65fcc3f1cdc623607a7529487a6b869b3a6c1943 Mon Sep 17 00:00:00 2001 From: Roberto Vidal Date: Thu, 2 Apr 2020 16:34:43 +0200 Subject: [PATCH 11/13] Expand on platform details of `include_xxx` macros --- src/libcore/macros/mod.rs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/libcore/macros/mod.rs b/src/libcore/macros/mod.rs index f67762cd04346..9c885ef99a980 100644 --- a/src/libcore/macros/mod.rs +++ b/src/libcore/macros/mod.rs @@ -1070,8 +1070,10 @@ pub(crate) mod builtin { /// Includes a utf8-encoded file as a string. /// - /// The file is located relative to the current file. (similarly to how - /// modules are found) + /// The file is located relative to the current file (similarly to how + /// modules are found). The provided path is interpreted in a platform-specific + /// way at compile time. So, for instance, an invocation with a Windows path + /// containing backslashes `\` would not compile correctly on Unix. /// /// This macro will yield an expression of type `&'static str` which is the /// contents of the file. @@ -1108,8 +1110,10 @@ pub(crate) mod builtin { /// Includes a file as a reference to a byte array. /// - /// The file is located relative to the current file. (similarly to how - /// modules are found) + /// The file is located relative to the current file (similarly to how + /// modules are found). The provided path is interpreted in a platform-specific + /// way at compile time. So, for instance, an invocation with a Windows path + /// containing backslashes `\` would not compile correctly on Unix. /// /// This macro will yield an expression of type `&'static [u8; N]` which is /// the contents of the file. @@ -1202,7 +1206,9 @@ pub(crate) mod builtin { /// Parses a file as an expression or an item according to the context. /// /// The file is located relative to the current file (similarly to how - /// modules are found). + /// modules are found). The provided path is interpreted in a platform-specific + /// way at compile time. So, for instance, an invocation with a Windows path + /// containing backslashes `\` would not compile correctly on Unix. /// /// Using this macro is often a bad idea, because if the file is /// parsed as an expression, it is going to be placed in the From e992565857df86b8dde9365b7fa76cbfdbf283c3 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 30 Mar 2020 21:21:35 -0400 Subject: [PATCH 12/13] bootstrap: add `--json-output` for rust-analyzer --- src/bootstrap/compile.rs | 6 +++++- src/bootstrap/config.rs | 2 ++ src/bootstrap/flags.rs | 3 +++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index ad494b88b3af2..5602c65913818 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -911,7 +911,11 @@ pub fn stream_cargo( } // Instruct Cargo to give us json messages on stdout, critically leaving // stderr as piped so we can get those pretty colors. - let mut message_format = String::from("json-render-diagnostics"); + let mut message_format = if builder.config.json_output { + String::from("json") + } else { + String::from("json-render-diagnostics") + }; if let Some(s) = &builder.config.rustc_error_format { message_format.push_str(",json-diagnostic-"); message_format.push_str(s); diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 56164b74f3088..133709421a5cd 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -48,6 +48,7 @@ pub struct Config { pub ignore_git: bool, pub exclude: Vec, pub rustc_error_format: Option, + pub json_output: bool, pub test_compare_mode: bool, pub llvm_libunwind: bool, @@ -415,6 +416,7 @@ impl Config { let mut config = Config::default_opts(); config.exclude = flags.exclude; config.rustc_error_format = flags.rustc_error_format; + config.json_output = flags.json_output; config.on_fail = flags.on_fail; config.stage = flags.stage; config.jobs = flags.jobs.map(threads_from_config); diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index eda26f7df1f1c..5d6e401d5b3fb 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -31,6 +31,7 @@ pub struct Flags { pub incremental: bool, pub exclude: Vec, pub rustc_error_format: Option, + pub json_output: bool, pub dry_run: bool, // This overrides the deny-warnings configuration option, @@ -156,6 +157,7 @@ To learn more about a subcommand, run `./x.py -h`", "VALUE", ); opts.optopt("", "error-format", "rustc error format", "FORMAT"); + opts.optflag("", "json-output", "use message-format=json"); opts.optopt( "", "llvm-skip-rebuild", @@ -503,6 +505,7 @@ Arguments: dry_run: matches.opt_present("dry-run"), on_fail: matches.opt_str("on-fail"), rustc_error_format: matches.opt_str("error-format"), + json_output: matches.opt_present("json-output"), keep_stage: matches .opt_strs("keep-stage") .into_iter() From 354ddbfb3f14f68aecb63d87fc31f87400b6f820 Mon Sep 17 00:00:00 2001 From: Pocakking <42542447+Pocakking@users.noreply.github.com> Date: Thu, 2 Apr 2020 20:01:29 +0200 Subject: [PATCH 13/13] Fix typo in u8::to_ascii_uppercase and u8::to_ascii_lowercase fith => fifth --- src/libcore/num/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 853092dd85ee9..c85064759ea03 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -4376,7 +4376,7 @@ impl u8 { #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[inline] pub fn to_ascii_uppercase(&self) -> u8 { - // Unset the fith bit if this is a lowercase letter + // Unset the fifth bit if this is a lowercase letter *self & !((self.is_ascii_lowercase() as u8) << 5) } @@ -4399,7 +4399,7 @@ impl u8 { #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[inline] pub fn to_ascii_lowercase(&self) -> u8 { - // Set the fith bit if this is an uppercase letter + // Set the fifth bit if this is an uppercase letter *self | ((self.is_ascii_uppercase() as u8) << 5) }