Auto merge of #42780 - frewsxcv:rollup, r=frewsxcv

Rollup of 6 pull requests

- Successful merges: #42271, #42717, #42728, #42749, #42756, #42772
- Failed merges:
This commit is contained in:
bors 2017-06-20 21:08:28 +00:00
commit 445077963c
13 changed files with 278 additions and 18 deletions

View File

@ -0,0 +1,5 @@
# `char_error_internals`
This feature is internal to the Rust compiler and is not intended for general use.
------------------------

View File

@ -2124,10 +2124,12 @@ fn from(s: Box<[T]>) -> Vec<T> {
}
}
#[stable(feature = "box_from_vec", since = "1.18.0")]
impl<T> Into<Box<[T]>> for Vec<T> {
fn into(self) -> Box<[T]> {
self.into_boxed_slice()
// note: test pulls in libstd, which causes errors here
#[cfg(not(test))]
#[stable(feature = "box_from_vec", since = "1.20.0")]
impl<T> From<Vec<T>> for Box<[T]> {
fn from(v: Vec<T>) -> Box<[T]> {
v.into_boxed_slice()
}
}

View File

@ -19,7 +19,7 @@
use convert::TryFrom;
use fmt::{self, Write};
use slice;
use str::from_utf8_unchecked_mut;
use str::{from_utf8_unchecked_mut, FromStr};
use iter::FusedIterator;
use mem::transmute;
@ -208,6 +208,63 @@ fn from(i: u8) -> Self {
}
}
/// An error which can be returned when parsing a char.
#[stable(feature = "char_from_str", since = "1.19.0")]
#[derive(Clone, Debug)]
pub struct ParseCharError {
kind: CharErrorKind,
}
impl ParseCharError {
#[unstable(feature = "char_error_internals",
reason = "this method should not be available publicly",
issue = "0")]
#[doc(hidden)]
pub fn __description(&self) -> &str {
match self.kind {
CharErrorKind::EmptyString => {
"cannot parse char from empty string"
},
CharErrorKind::TooManyChars => "too many characters in string"
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
enum CharErrorKind {
EmptyString,
TooManyChars,
}
#[stable(feature = "char_from_str", since = "1.19.0")]
impl fmt::Display for ParseCharError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.__description().fmt(f)
}
}
#[stable(feature = "char_from_str", since = "1.19.0")]
impl FromStr for char {
type Err = ParseCharError;
#[inline]
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut chars = s.chars();
match (chars.next(), chars.next()) {
(None, _) => {
Err(ParseCharError { kind: CharErrorKind::EmptyString })
},
(Some(c), None) => Ok(c),
_ => {
Err(ParseCharError { kind: CharErrorKind::TooManyChars })
}
}
}
}
#[unstable(feature = "try_from", issue = "33417")]
impl TryFrom<u32> for char {
type Error = CharTryFromError;

View File

@ -10,6 +10,7 @@
use std::{char,str};
use std::convert::TryFrom;
use std::str::FromStr;
#[test]
fn test_convert() {
@ -28,6 +29,16 @@ fn test_convert() {
assert!(char::try_from(0xFFFF_FFFF_u32).is_err());
}
#[test]
fn test_from_str() {
assert_eq!(char::from_str("a").unwrap(), 'a');
assert_eq!(char::try_from("a").unwrap(), 'a');
assert_eq!(char::from_str("\0").unwrap(), '\0');
assert_eq!(char::from_str("\u{D7FF}").unwrap(), '\u{d7FF}');
assert!(char::from_str("").is_err());
assert!(char::from_str("abc").is_err());
}
#[test]
fn test_is_lowercase() {
assert!('a'.is_lowercase());

@ -1 +1 @@
Subproject commit 03562b0cb26a00f49d4eaf18ca3e49608110b0c8
Subproject commit 2015cf17a6a2a2280e93d9c57214ba92dbbaf42f

View File

@ -8,6 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use rustc::hir::def_id::DefId;
use rustc::ty;
use rustc::ty::adjustment;
use util::nodemap::FxHashMap;
@ -144,20 +145,18 @@ fn check_stmt(&mut self, cx: &LateContext, s: &hir::Stmt) {
ty::TyTuple(ref tys, _) if tys.is_empty() => return,
ty::TyNever => return,
ty::TyBool => return,
ty::TyAdt(def, _) => {
let attrs = cx.tcx.get_attrs(def.did);
check_must_use(cx, &attrs, s.span)
}
ty::TyAdt(def, _) => check_must_use(cx, def.did, s.span),
_ => false,
};
if !warned {
cx.span_lint(UNUSED_RESULTS, s.span, "unused result");
}
fn check_must_use(cx: &LateContext, attrs: &[ast::Attribute], sp: Span) -> bool {
for attr in attrs {
fn check_must_use(cx: &LateContext, def_id: DefId, sp: Span) -> bool {
for attr in cx.tcx.get_attrs(def_id).iter() {
if attr.check_name("must_use") {
let mut msg = "unused result which must be used".to_string();
let mut msg = format!("unused `{}` which must be used",
cx.tcx.item_path_str(def_id));
// check for #[must_use="..."]
if let Some(s) = attr.value_str() {
msg.push_str(": ");

View File

@ -523,7 +523,10 @@ pub fn get_module(&mut self, def_id: DefId) -> Module<'a> {
};
let kind = ModuleKind::Def(Def::Mod(def_id), name);
self.arenas.alloc_module(ModuleData::new(parent, kind, def_id, Mark::root(), DUMMY_SP))
let module =
self.arenas.alloc_module(ModuleData::new(parent, kind, def_id, Mark::root(), DUMMY_SP));
self.extern_module_map.insert((def_id, macros_only), module);
module
}
pub fn macro_def_scope(&mut self, expansion: Mark) -> Module<'a> {

View File

@ -438,6 +438,35 @@ pub struct JoinPathsError {
///
/// # Examples
///
/// Joining paths on a Unix-like platform:
///
/// ```
/// # if cfg!(unix) {
/// use std::env;
/// use std::ffi::OsString;
/// use std::path::Path;
///
/// let paths = [Path::new("/bin"), Path::new("/usr/bin")];
/// let path_os_string = env::join_paths(paths.iter()).unwrap();
/// assert_eq!(path_os_string, OsString::from("/bin:/usr/bin"));
/// # }
/// ```
///
/// Joining a path containing a colon on a Unix-like platform results in an error:
///
/// ```
/// # if cfg!(unix) {
/// use std::env;
/// use std::path::Path;
///
/// let paths = [Path::new("/bin"), Path::new("/usr/bi:n")];
/// assert!(env::join_paths(paths.iter()).is_err());
/// # }
/// ```
///
/// Using `env::join_paths` with `env::spit_paths` to append an item to the `PATH` environment
/// variable:
///
/// ```
/// use std::env;
/// use std::path::PathBuf;

View File

@ -340,6 +340,14 @@ fn description(&self) -> &str {
}
}
#[stable(feature = "char_from_str", since = "1.19.0")]
impl Error for char::ParseCharError {
fn description(&self) -> &str {
self.__description()
}
}
// copied from any.rs
impl Error + 'static {
/// Returns true if the boxed type is the same as `T`

View File

@ -152,6 +152,14 @@ pub struct CStr {
/// in the vector provided.
///
/// [`CString::new`]: struct.CString.html#method.new
///
/// # Examples
///
/// ```
/// use std::ffi::{CString, NulError};
///
/// let _: NulError = CString::new(b"f\0oo".to_vec()).unwrap_err();
/// ```
#[derive(Clone, PartialEq, Eq, Debug)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct NulError(usize, Vec<u8>);
@ -160,6 +168,14 @@ pub struct CStr {
/// byte was found too early in the slice provided or one wasn't found at all.
///
/// [`CStr::from_bytes_with_nul`]: struct.CStr.html#method.from_bytes_with_nul
///
/// # Examples
///
/// ```
/// use std::ffi::{CStr, FromBytesWithNulError};
///
/// let _: FromBytesWithNulError = CStr::from_bytes_with_nul(b"f\0oo").unwrap_err();
/// ```
#[derive(Clone, PartialEq, Eq, Debug)]
#[stable(feature = "cstr_from_bytes", since = "1.10.0")]
pub struct FromBytesWithNulError {
@ -271,6 +287,27 @@ pub unsafe fn from_vec_unchecked(mut v: Vec<u8>) -> CString {
/// to undefined behavior or allocator corruption.
///
/// [`into_raw`]: #method.into_raw
///
/// # Examples
///
/// Create a `CString`, pass ownership to an `extern` function (via raw pointer), then retake
/// ownership with `from_raw`:
///
/// ```no_run
/// use std::ffi::CString;
/// use std::os::raw::c_char;
///
/// extern {
/// fn some_extern_function(s: *mut c_char);
/// }
///
/// let c_string = CString::new("Hello!").unwrap();
/// let raw = c_string.into_raw();
/// unsafe {
/// some_extern_function(raw);
/// let c_string = CString::from_raw(raw);
/// }
/// ```
#[stable(feature = "cstr_memory", since = "1.4.0")]
pub unsafe fn from_raw(ptr: *mut c_char) -> CString {
let len = libc::strlen(ptr) + 1; // Including the NUL byte
@ -412,6 +449,18 @@ pub fn as_bytes_with_nul(&self) -> &[u8] {
/// Extracts a [`CStr`] slice containing the entire string.
///
/// [`CStr`]: struct.CStr.html
///
/// # Examples
///
/// ```
/// #![feature(as_c_str)]
///
/// use std::ffi::{CString, CStr};
///
/// let c_string = CString::new(b"foo".to_vec()).unwrap();
/// let c_str = c_string.as_c_str();
/// assert_eq!(c_str, CStr::from_bytes_with_nul(b"foo\0").unwrap());
/// ```
#[inline]
#[unstable(feature = "as_c_str", issue = "40380")]
pub fn as_c_str(&self) -> &CStr {
@ -421,6 +470,18 @@ pub fn as_c_str(&self) -> &CStr {
/// Converts this `CString` into a boxed [`CStr`].
///
/// [`CStr`]: struct.CStr.html
///
/// # Examples
///
/// ```
/// #![feature(into_boxed_c_str)]
///
/// use std::ffi::{CString, CStr};
///
/// let c_string = CString::new(b"foo".to_vec()).unwrap();
/// let boxed = c_string.into_boxed_c_str();
/// assert_eq!(&*boxed, CStr::from_bytes_with_nul(b"foo\0").unwrap());
/// ```
#[unstable(feature = "into_boxed_c_str", issue = "40380")]
pub fn into_boxed_c_str(self) -> Box<CStr> {
unsafe { mem::transmute(self.into_inner()) }
@ -708,6 +769,24 @@ pub unsafe fn from_ptr<'a>(ptr: *const c_char) -> &'a CStr {
/// let cstr = CStr::from_bytes_with_nul(b"hello\0");
/// assert!(cstr.is_ok());
/// ```
///
/// Creating a `CStr` without a trailing nul byte is an error:
///
/// ```
/// use std::ffi::CStr;
///
/// let c_str = CStr::from_bytes_with_nul(b"hello");
/// assert!(c_str.is_err());
/// ```
///
/// Creating a `CStr` with an interior nul byte is an error:
///
/// ```
/// use std::ffi::CStr;
///
/// let c_str = CStr::from_bytes_with_nul(b"he\0llo\0");
/// assert!(c_str.is_err());
/// ```
#[stable(feature = "cstr_from_bytes", since = "1.10.0")]
pub fn from_bytes_with_nul(bytes: &[u8])
-> Result<&CStr, FromBytesWithNulError> {
@ -800,6 +879,15 @@ pub fn as_ptr(&self) -> *const c_char {
/// > **Note**: This method is currently implemented as a 0-cost cast, but
/// > it is planned to alter its definition in the future to perform the
/// > length calculation whenever this method is called.
///
/// # Examples
///
/// ```
/// use std::ffi::CStr;
///
/// let c_str = CStr::from_bytes_with_nul(b"foo\0").unwrap();
/// assert_eq!(c_str.to_bytes(), b"foo");
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn to_bytes(&self) -> &[u8] {
@ -817,6 +905,15 @@ pub fn to_bytes(&self) -> &[u8] {
/// > length calculation whenever this method is called.
///
/// [`to_bytes`]: #method.to_bytes
///
/// # Examples
///
/// ```
/// use std::ffi::CStr;
///
/// let c_str = CStr::from_bytes_with_nul(b"foo\0").unwrap();
/// assert_eq!(c_str.to_bytes_with_nul(), b"foo\0");
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn to_bytes_with_nul(&self) -> &[u8] {
@ -834,6 +931,15 @@ pub fn to_bytes_with_nul(&self) -> &[u8] {
/// > check whenever this method is called.
///
/// [`&str`]: ../primitive.str.html
///
/// # Examples
///
/// ```
/// use std::ffi::CStr;
///
/// let c_str = CStr::from_bytes_with_nul(b"foo\0").unwrap();
/// assert_eq!(c_str.to_str(), Ok("foo"));
/// ```
#[stable(feature = "cstr_to_str", since = "1.4.0")]
pub fn to_str(&self) -> Result<&str, str::Utf8Error> {
// NB: When CStr is changed to perform the length check in .to_bytes()
@ -857,6 +963,31 @@ pub fn to_str(&self) -> Result<&str, str::Utf8Error> {
///
/// [`Cow`]: ../borrow/enum.Cow.html
/// [`str`]: ../primitive.str.html
///
/// # Examples
///
/// Calling `to_string_lossy` on a `CStr` containing valid UTF-8:
///
/// ```
/// use std::borrow::Cow;
/// use std::ffi::CStr;
///
/// let c_str = CStr::from_bytes_with_nul(b"Hello World\0").unwrap();
/// assert_eq!(c_str.to_string_lossy(), Cow::Borrowed("Hello World"));
/// ```
///
/// Calling `to_string_lossy` on a `CStr` containing invalid UTF-8:
///
/// ```
/// use std::borrow::Cow;
/// use std::ffi::CStr;
///
/// let c_str = CStr::from_bytes_with_nul(b"Hello \xF0\x90\x80World\0").unwrap();
/// assert_eq!(
/// c_str.to_string_lossy(),
/// Cow::Owned(String::from("Hello <20>World")) as Cow<str>
/// );
/// ```
#[stable(feature = "cstr_to_str", since = "1.4.0")]
pub fn to_string_lossy(&self) -> Cow<str> {
String::from_utf8_lossy(self.to_bytes())
@ -866,6 +997,18 @@ pub fn to_string_lossy(&self) -> Cow<str> {
///
/// [`Box`]: ../boxed/struct.Box.html
/// [`CString`]: struct.CString.html
///
/// # Examples
///
/// ```
/// #![feature(into_boxed_c_str)]
///
/// use std::ffi::CString;
///
/// let c_string = CString::new(b"foo".to_vec()).unwrap();
/// let boxed = c_string.into_boxed_c_str();
/// assert_eq!(boxed.into_c_string(), CString::new("foo").unwrap());
/// ```
#[unstable(feature = "into_boxed_c_str", issue = "40380")]
pub fn into_c_string(self: Box<CStr>) -> CString {
unsafe { mem::transmute(self) }

View File

@ -254,6 +254,7 @@
#![feature(cfg_target_thread_local)]
#![feature(cfg_target_vendor)]
#![feature(char_escape_debug)]
#![feature(char_error_internals)]
#![feature(char_internals)]
#![feature(collections_range)]
#![feature(compiler_builtins_lib)]

View File

@ -38,6 +38,8 @@
pub use core::char::{MAX, from_digit, from_u32, from_u32_unchecked};
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::char::{EscapeDebug, EscapeDefault, EscapeUnicode};
#[stable(feature = "char_from_str", since = "1.19.0")]
pub use core::char::ParseCharError;
// unstable reexports
#[unstable(feature = "try_from", issue = "33417")]

View File

@ -26,8 +26,8 @@ fn foo<T>() -> T { panic!() }
#[allow(unused_results)]
fn test() {
foo::<isize>();
foo::<MustUse>(); //~ ERROR: unused result which must be used
foo::<MustUseMsg>(); //~ ERROR: unused result which must be used: some message
foo::<MustUse>(); //~ ERROR: unused `MustUse` which must be used
foo::<MustUseMsg>(); //~ ERROR: unused `MustUseMsg` which must be used: some message
}
#[allow(unused_results, unused_must_use)]
@ -39,8 +39,8 @@ fn test2() {
fn main() {
foo::<isize>(); //~ ERROR: unused result
foo::<MustUse>(); //~ ERROR: unused result which must be used
foo::<MustUseMsg>(); //~ ERROR: unused result which must be used: some message
foo::<MustUse>(); //~ ERROR: unused `MustUse` which must be used
foo::<MustUseMsg>(); //~ ERROR: unused `MustUseMsg` which must be used: some message
let _ = foo::<isize>();
let _ = foo::<MustUse>();