diff --git a/src/bootstrap/format.rs b/src/bootstrap/format.rs index 1616ae15d31d..6653c505bf53 100644 --- a/src/bootstrap/format.rs +++ b/src/bootstrap/format.rs @@ -4,7 +4,7 @@ use crate::Build; use build_helper::{output, t}; use ignore::WalkBuilder; use std::path::Path; -use std::process::Command; +use std::process::{Command, Stdio}; fn rustfmt(src: &Path, rustfmt: &Path, path: &Path, check: bool) { let mut cmd = Command::new(&rustfmt); @@ -56,16 +56,48 @@ pub fn format(build: &Build, check: bool) { for ignore in rustfmt_config.ignore { ignore_fmt.add(&format!("!{}", ignore)).expect(&ignore); } - let untracked_paths_output = output( - Command::new("git").arg("status").arg("--porcelain").arg("--untracked-files=normal"), - ); - let untracked_paths = untracked_paths_output - .lines() - .filter(|entry| entry.starts_with("??")) - .map(|entry| entry.split(" ").nth(1).expect("every git status entry should list a path")); - for untracked_path in untracked_paths { - eprintln!("skip untracked path {} during rustfmt invocations", untracked_path); - ignore_fmt.add(&format!("!{}", untracked_path)).expect(&untracked_path); + let git_available = match Command::new("git") + .arg("--version") + .stdout(Stdio::null()) + .stderr(Stdio::null()) + .status() + { + Ok(status) => status.success(), + Err(_) => false, + }; + if git_available { + let in_working_tree = match Command::new("git") + .arg("rev-parse") + .arg("--is-inside-work-tree") + .stdout(Stdio::null()) + .stderr(Stdio::null()) + .status() + { + Ok(status) => status.success(), + Err(_) => false, + }; + if in_working_tree { + let untracked_paths_output = output( + Command::new("git") + .arg("status") + .arg("--porcelain") + .arg("--untracked-files=normal"), + ); + let untracked_paths = untracked_paths_output + .lines() + .filter(|entry| entry.starts_with("??")) + .map(|entry| { + entry.split(" ").nth(1).expect("every git status entry should list a path") + }); + for untracked_path in untracked_paths { + eprintln!("skip untracked path {} during rustfmt invocations", untracked_path); + ignore_fmt.add(&format!("!{}", untracked_path)).expect(&untracked_path); + } + } else { + eprintln!("Not in git tree. Skipping git-aware format checks"); + } + } else { + eprintln!("Could not find usable git. Skipping git-aware format checks"); } let ignore_fmt = ignore_fmt.build().unwrap(); diff --git a/src/librustc/mir/interpret/pointer.rs b/src/librustc/mir/interpret/pointer.rs index 3f841cfb3300..d22207bd8165 100644 --- a/src/librustc/mir/interpret/pointer.rs +++ b/src/librustc/mir/interpret/pointer.rs @@ -46,13 +46,13 @@ pub trait PointerArithmetic: layout::HasDataLayout { } #[inline] - fn usize_max(&self) -> u64 { + fn machine_usize_max(&self) -> u64 { let max_usize_plus_1 = 1u128 << self.pointer_size().bits(); u64::try_from(max_usize_plus_1 - 1).unwrap() } #[inline] - fn isize_max(&self) -> i64 { + fn machine_isize_max(&self) -> i64 { let max_isize_plus_1 = 1u128 << (self.pointer_size().bits() - 1); i64::try_from(max_isize_plus_1 - 1).unwrap() } diff --git a/src/librustc/mir/interpret/value.rs b/src/librustc/mir/interpret/value.rs index 706cf1cd09a7..bf4ee8488238 100644 --- a/src/librustc/mir/interpret/value.rs +++ b/src/librustc/mir/interpret/value.rs @@ -192,7 +192,7 @@ impl<'tcx, Tag> Scalar { } #[inline] - pub fn ptr_null(cx: &impl HasDataLayout) -> Self { + pub fn null_ptr(cx: &impl HasDataLayout) -> Self { Scalar::Raw { data: 0, size: cx.data_layout().pointer_size.bytes() as u8 } } diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs index 24176427ba52..6fe97bcb1183 100644 --- a/src/librustc_mir/interpret/cast.rs +++ b/src/librustc_mir/interpret/cast.rs @@ -208,7 +208,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Char => { // `u8` to `char` cast - Ok(Scalar::from_uint(u8::try_from(v).unwrap(), Size::from_bytes(4))) + Ok(Scalar::from_u32(u8::try_from(v).unwrap().into())) } // Casts to bool are not permitted by rustc, no need to handle them here. diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index e5f89b10e76e..46f8e98ef34a 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -2,6 +2,8 @@ //! looking at their MIR. Intrinsics/functions supported here are shared by CTFE //! and miri. +use std::convert::TryFrom; + use rustc::mir::{ self, interpret::{ConstValue, GlobalId, InterpResult, Scalar}, @@ -220,7 +222,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { sym::discriminant_value => { let place = self.deref_operand(args[0])?; let discr_val = self.read_discriminant(place.into())?.0; - self.write_scalar(Scalar::from_uint(discr_val, dest.layout.size), dest)?; + self.write_scalar(Scalar::from_u64(u64::try_from(discr_val).unwrap()), dest)?; } sym::unchecked_shl | sym::unchecked_shr @@ -275,7 +277,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } sym::ptr_offset_from => { - let isize_layout = self.layout_of(self.tcx.types.isize)?; let a = self.read_immediate(args[0])?.to_scalar()?; let b = self.read_immediate(args[1])?.to_scalar()?; @@ -292,7 +293,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let a = a.to_machine_usize(self)?; let b = b.to_machine_usize(self)?; if a == b && a != 0 { - self.write_scalar(Scalar::from_int(0, isize_layout.size), dest)?; + self.write_scalar(Scalar::from_machine_isize(0, self), dest)?; true } else { false @@ -312,6 +313,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ); } let usize_layout = self.layout_of(self.tcx.types.usize)?; + let isize_layout = self.layout_of(self.tcx.types.isize)?; let a_offset = ImmTy::from_uint(a.offset.bytes(), usize_layout); let b_offset = ImmTy::from_uint(b.offset.bytes(), usize_layout); let (val, _overflowed, _ty) = diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 8e2a0ca9b021..1ffe6a873023 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -54,10 +54,7 @@ impl From> for Immediate { impl<'tcx, Tag> Immediate { pub fn new_slice(val: Scalar, len: u64, cx: &impl HasDataLayout) -> Self { - Immediate::ScalarPair( - val.into(), - Scalar::from_uint(len, cx.data_layout().pointer_size).into(), - ) + Immediate::ScalarPair(val.into(), Scalar::from_machine_usize(len, cx).into()) } pub fn new_dyn_trait(val: Scalar, vtable: Pointer) -> Self { @@ -621,7 +618,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let real_discr = if discr_val.layout.abi.is_signed() { // going from layout tag type to typeck discriminant type // requires first sign extending with the discriminant layout - let sexted = sign_extend(bits_discr, discr_val.layout.size) as i128; + let sexted = sign_extend(bits_discr, discr_val.layout.size); // and then zeroing with the typeck discriminant type let discr_ty = rval .layout @@ -631,8 +628,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { .repr .discr_type(); let size = layout::Integer::from_attr(self, discr_ty).size(); - let truncatee = sexted as u128; - truncate(truncatee, size) + truncate(sexted, size) } else { bits_discr }; diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index 94c9a8b2a6d5..915cffa33214 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -139,7 +139,7 @@ impl MemPlace { /// Produces a Place that will error if attempted to be read from or written to #[inline(always)] fn null(cx: &impl HasDataLayout) -> Self { - Self::from_scalar_ptr(Scalar::ptr_null(cx), Align::from_bytes(1).unwrap()) + Self::from_scalar_ptr(Scalar::null_ptr(cx), Align::from_bytes(1).unwrap()) } #[inline(always)] @@ -180,7 +180,7 @@ impl<'tcx, Tag> MPlaceTy<'tcx, Tag> { #[inline] pub fn dangling(layout: TyLayout<'tcx>, cx: &impl HasDataLayout) -> Self { let align = layout.align.abi; - let ptr = Scalar::from_uint(align.bytes(), cx.pointer_size()); + let ptr = Scalar::from_machine_usize(align.bytes(), cx); // `Poison` this to make sure that the pointer value `ptr` is never observable by the program. MPlaceTy { mplace: MemPlace { ptr, align, meta: MemPlaceMeta::Poison }, layout } } @@ -504,7 +504,7 @@ where // implement this. ty::Array(inner, _) => (MemPlaceMeta::None, self.tcx.mk_array(inner, inner_len)), ty::Slice(..) => { - let len = Scalar::from_uint(inner_len, self.pointer_size()); + let len = Scalar::from_machine_usize(inner_len, self); (MemPlaceMeta::Meta(len), base.layout.ty) } _ => bug!("cannot subslice non-array type: `{:?}`", base.layout.ty), @@ -1044,7 +1044,7 @@ where kind: MemoryKind, ) -> MPlaceTy<'tcx, M::PointerTag> { let ptr = self.memory.allocate_bytes(str.as_bytes(), kind); - let meta = Scalar::from_uint(u128::try_from(str.len()).unwrap(), self.pointer_size()); + let meta = Scalar::from_machine_usize(u64::try_from(str.len()).unwrap(), self); let mplace = MemPlace { ptr: ptr.into(), align: Align::from_bytes(1).unwrap(), diff --git a/src/librustc_mir/interpret/step.rs b/src/librustc_mir/interpret/step.rs index 01446c15ff69..764edea2fc5c 100644 --- a/src/librustc_mir/interpret/step.rs +++ b/src/librustc_mir/interpret/step.rs @@ -3,7 +3,7 @@ //! The main entry point is the `step` method. use rustc::mir; -use rustc::mir::interpret::{InterpResult, PointerArithmetic, Scalar}; +use rustc::mir::interpret::{InterpResult, Scalar}; use rustc::ty::layout::LayoutOf; use super::{InterpCx, Machine}; @@ -229,8 +229,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let src = self.eval_place(place)?; let mplace = self.force_allocation(src)?; let len = mplace.len(self)?; - let size = self.pointer_size(); - self.write_scalar(Scalar::from_uint(len, size), dest)?; + self.write_scalar(Scalar::from_machine_usize(len, self), dest)?; } AddressOf(_, ref place) | Ref(_, _, ref place) => { @@ -254,8 +253,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { !layout.is_unsized(), "SizeOf nullary MIR operator called for unsized type" ); - let size = self.pointer_size(); - self.write_scalar(Scalar::from_uint(layout.size.bytes(), size), dest)?; + self.write_scalar(Scalar::from_machine_usize(layout.size.bytes(), self), dest)?; } Cast(kind, ref operand, _) => { diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs index 0fbe8e5dd83e..5e686946f8e9 100644 --- a/src/libstd/ffi/os_str.rs +++ b/src/libstd/ffi/os_str.rs @@ -698,6 +698,147 @@ impl OsStr { fn bytes(&self) -> &[u8] { unsafe { &*(&self.inner as *const _ as *const [u8]) } } + + /// Converts this string to its ASCII lower case equivalent in-place. + /// + /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z', + /// but non-ASCII letters are unchanged. + /// + /// To return a new lowercased value without modifying the existing one, use + /// [`to_ascii_lowercase`]. + /// + /// [`to_ascii_lowercase`]: #method.to_ascii_lowercase + /// + /// # Examples + /// + /// ``` + /// #![feature(osstring_ascii)] + /// use std::ffi::OsString; + /// + /// let mut s = OsString::from("GRÜßE, JÜRGEN ❤"); + /// + /// s.make_ascii_lowercase(); + /// + /// assert_eq!("grÜße, jÜrgen ❤", s); + /// ``` + #[unstable(feature = "osstring_ascii", issue = "70516")] + pub fn make_ascii_lowercase(&mut self) { + self.inner.make_ascii_lowercase() + } + + /// Converts this string to its ASCII upper case equivalent in-place. + /// + /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z', + /// but non-ASCII letters are unchanged. + /// + /// To return a new uppercased value without modifying the existing one, use + /// [`to_ascii_uppercase`]. + /// + /// [`to_ascii_uppercase`]: #method.to_ascii_uppercase + /// + /// # Examples + /// + /// ``` + /// #![feature(osstring_ascii)] + /// use std::ffi::OsString; + /// + /// let mut s = OsString::from("Grüße, Jürgen ❤"); + /// + /// s.make_ascii_uppercase(); + /// + /// assert_eq!("GRüßE, JüRGEN ❤", s); + /// ``` + #[unstable(feature = "osstring_ascii", issue = "70516")] + pub fn make_ascii_uppercase(&mut self) { + self.inner.make_ascii_uppercase() + } + + /// Returns a copy of this string where each character is mapped to its + /// ASCII lower case equivalent. + /// + /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z', + /// but non-ASCII letters are unchanged. + /// + /// To lowercase the value in-place, use [`make_ascii_lowercase`]. + /// + /// [`make_ascii_lowercase`]: #method.make_ascii_lowercase + /// + /// # Examples + /// + /// ``` + /// #![feature(osstring_ascii)] + /// use std::ffi::OsString; + /// let s = OsString::from("Grüße, Jürgen ❤"); + /// + /// assert_eq!("grüße, jürgen ❤", s.to_ascii_lowercase()); + /// ``` + #[unstable(feature = "osstring_ascii", issue = "70516")] + pub fn to_ascii_lowercase(&self) -> OsString { + OsString::from_inner(self.inner.to_ascii_lowercase()) + } + + /// Returns a copy of this string where each character is mapped to its + /// ASCII upper case equivalent. + /// + /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z', + /// but non-ASCII letters are unchanged. + /// + /// To uppercase the value in-place, use [`make_ascii_uppercase`]. + /// + /// [`make_ascii_uppercase`]: #method.make_ascii_uppercase + /// + /// # Examples + /// + /// ``` + /// #![feature(osstring_ascii)] + /// use std::ffi::OsString; + /// let s = OsString::from("Grüße, Jürgen ❤"); + /// + /// assert_eq!("GRüßE, JüRGEN ❤", s.to_ascii_uppercase()); + /// ``` + #[unstable(feature = "osstring_ascii", issue = "70516")] + pub fn to_ascii_uppercase(&self) -> OsString { + OsString::from_inner(self.inner.to_ascii_uppercase()) + } + + /// Checks if all characters in this string are within the ASCII range. + /// + /// # Examples + /// + /// ``` + /// #![feature(osstring_ascii)] + /// use std::ffi::OsString; + /// + /// let ascii = OsString::from("hello!\n"); + /// let non_ascii = OsString::from("Grüße, Jürgen ❤"); + /// + /// assert!(ascii.is_ascii()); + /// assert!(!non_ascii.is_ascii()); + /// ``` + #[unstable(feature = "osstring_ascii", issue = "70516")] + pub fn is_ascii(&self) -> bool { + self.inner.is_ascii() + } + + /// Checks that two strings are an ASCII case-insensitive match. + /// + /// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`, + /// but without allocating and copying temporaries. + /// + /// # Examples + /// + /// ``` + /// #![feature(osstring_ascii)] + /// use std::ffi::OsString; + /// + /// assert!(OsString::from("Ferris").eq_ignore_ascii_case("FERRIS")); + /// assert!(OsString::from("Ferrös").eq_ignore_ascii_case("FERRöS")); + /// assert!(!OsString::from("Ferrös").eq_ignore_ascii_case("FERRÖS")); + /// ``` + #[unstable(feature = "osstring_ascii", issue = "70516")] + pub fn eq_ignore_ascii_case>(&self, other: &S) -> bool { + self.inner.eq_ignore_ascii_case(&other.as_ref().inner) + } } #[stable(feature = "box_from_os_str", since = "1.17.0")] diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs index 7f93ef879530..134f508dfab0 100644 --- a/src/libstd/sys/windows/c.rs +++ b/src/libstd/sys/windows/c.rs @@ -778,7 +778,7 @@ extern "system" { pub fn ioctlsocket(s: SOCKET, cmd: c_long, argp: *mut c_ulong) -> c_int; pub fn InitializeCriticalSection(CriticalSection: *mut CRITICAL_SECTION); pub fn EnterCriticalSection(CriticalSection: *mut CRITICAL_SECTION); - pub fn TryEnterCriticalSection(CriticalSection: *mut CRITICAL_SECTION) -> BOOLEAN; + pub fn TryEnterCriticalSection(CriticalSection: *mut CRITICAL_SECTION) -> BOOL; pub fn LeaveCriticalSection(CriticalSection: *mut CRITICAL_SECTION); pub fn DeleteCriticalSection(CriticalSection: *mut CRITICAL_SECTION); diff --git a/src/libstd/sys/windows/os_str.rs b/src/libstd/sys/windows/os_str.rs index ff6885cb2747..6aab028873e0 100644 --- a/src/libstd/sys/windows/os_str.rs +++ b/src/libstd/sys/windows/os_str.rs @@ -179,4 +179,34 @@ impl Slice { let rc = self.inner.into_rc(); unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Slice) } } + + #[inline] + pub fn make_ascii_lowercase(&mut self) { + self.inner.make_ascii_lowercase() + } + + #[inline] + pub fn make_ascii_uppercase(&mut self) { + self.inner.make_ascii_uppercase() + } + + #[inline] + pub fn to_ascii_lowercase(&self) -> Buf { + Buf { inner: self.inner.to_ascii_lowercase() } + } + + #[inline] + pub fn to_ascii_uppercase(&self) -> Buf { + Buf { inner: self.inner.to_ascii_uppercase() } + } + + #[inline] + pub fn is_ascii(&self) -> bool { + self.inner.is_ascii() + } + + #[inline] + pub fn eq_ignore_ascii_case(&self, other: &Self) -> bool { + self.inner.eq_ignore_ascii_case(&other.inner) + } } diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs index a62a637393ea..77f9a5c9dc7b 100644 --- a/src/libstd/sys/windows/process.rs +++ b/src/libstd/sys/windows/process.rs @@ -20,7 +20,7 @@ use crate::sys::mutex::Mutex; use crate::sys::pipe::{self, AnonPipe}; use crate::sys::stdio; use crate::sys_common::process::CommandEnv; -use crate::sys_common::{AsInner, FromInner, IntoInner}; +use crate::sys_common::AsInner; use libc::{c_void, EXIT_FAILURE, EXIT_SUCCESS}; @@ -33,10 +33,9 @@ use libc::{c_void, EXIT_FAILURE, EXIT_SUCCESS}; pub struct EnvKey(OsString); impl From for EnvKey { - fn from(k: OsString) -> Self { - let mut buf = k.into_inner().into_inner(); - buf.make_ascii_uppercase(); - EnvKey(FromInner::from_inner(FromInner::from_inner(buf))) + fn from(mut k: OsString) -> Self { + k.make_ascii_uppercase(); + EnvKey(k) } } diff --git a/src/libstd/sys_common/os_str_bytes.rs b/src/libstd/sys_common/os_str_bytes.rs index c5d02fb17722..aa6cc33d831e 100644 --- a/src/libstd/sys_common/os_str_bytes.rs +++ b/src/libstd/sys_common/os_str_bytes.rs @@ -195,6 +195,36 @@ impl Slice { let rc: Rc<[u8]> = Rc::from(&self.inner); unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Slice) } } + + #[inline] + pub fn make_ascii_lowercase(&mut self) { + self.inner.make_ascii_lowercase() + } + + #[inline] + pub fn make_ascii_uppercase(&mut self) { + self.inner.make_ascii_uppercase() + } + + #[inline] + pub fn to_ascii_lowercase(&self) -> Buf { + Buf { inner: self.inner.to_ascii_lowercase() } + } + + #[inline] + pub fn to_ascii_uppercase(&self) -> Buf { + Buf { inner: self.inner.to_ascii_uppercase() } + } + + #[inline] + pub fn is_ascii(&self) -> bool { + self.inner.is_ascii() + } + + #[inline] + pub fn eq_ignore_ascii_case(&self, other: &Self) -> bool { + self.inner.eq_ignore_ascii_case(&other.inner) + } } /// Platform-specific extensions to [`OsString`]. diff --git a/src/libstd/sys_common/wtf8.rs b/src/libstd/sys_common/wtf8.rs index 498950e68210..fc6614552a92 100644 --- a/src/libstd/sys_common/wtf8.rs +++ b/src/libstd/sys_common/wtf8.rs @@ -637,6 +637,36 @@ impl Wtf8 { let rc: Rc<[u8]> = Rc::from(&self.bytes); unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Wtf8) } } + + #[inline] + pub fn make_ascii_lowercase(&mut self) { + self.bytes.make_ascii_lowercase() + } + + #[inline] + pub fn make_ascii_uppercase(&mut self) { + self.bytes.make_ascii_uppercase() + } + + #[inline] + pub fn to_ascii_lowercase(&self) -> Wtf8Buf { + Wtf8Buf { bytes: self.bytes.to_ascii_lowercase() } + } + + #[inline] + pub fn to_ascii_uppercase(&self) -> Wtf8Buf { + Wtf8Buf { bytes: self.bytes.to_ascii_uppercase() } + } + + #[inline] + pub fn is_ascii(&self) -> bool { + self.bytes.is_ascii() + } + + #[inline] + pub fn eq_ignore_ascii_case(&self, other: &Self) -> bool { + self.bytes.eq_ignore_ascii_case(&other.bytes) + } } /// Returns a slice of the given string for the byte range [`begin`..`end`). @@ -837,12 +867,6 @@ impl Hash for Wtf8 { } } -impl Wtf8 { - pub fn make_ascii_uppercase(&mut self) { - self.bytes.make_ascii_uppercase() - } -} - #[cfg(test)] mod tests { use super::*;