about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2017-06-20 21:08:28 +0000
committerbors <bors@rust-lang.org>2017-06-20 21:08:28 +0000
commit445077963c55297ef1e196a3525723090fe80b22 (patch)
tree19b62bba2839c59b1e36f3998dff94997a2df797
parent29bce6e220f6fd2292d13d65fe503af7bf4852b7 (diff)
parent58425ef71dd80c9e91adb359085473d66cd7e155 (diff)
downloadrust-445077963c55297ef1e196a3525723090fe80b22.tar.gz
rust-445077963c55297ef1e196a3525723090fe80b22.zip
Auto merge of #42780 - frewsxcv:rollup, r=frewsxcv
Rollup of 6 pull requests

- Successful merges: #42271, #42717, #42728, #42749, #42756, #42772
- Failed merges:
-rw-r--r--src/doc/unstable-book/src/library-features/char-error-internals.md5
-rw-r--r--src/liballoc/vec.rs10
-rw-r--r--src/libcore/char.rs59
-rw-r--r--src/libcore/tests/char.rs11
m---------src/liblibc0
-rw-r--r--src/librustc_lint/unused.rs13
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs5
-rw-r--r--src/libstd/env.rs29
-rw-r--r--src/libstd/error.rs8
-rw-r--r--src/libstd/ffi/c_str.rs143
-rw-r--r--src/libstd/lib.rs1
-rw-r--r--src/libstd_unicode/char.rs2
-rw-r--r--src/test/compile-fail/unused-result.rs8
13 files changed, 277 insertions, 17 deletions
diff --git a/src/doc/unstable-book/src/library-features/char-error-internals.md b/src/doc/unstable-book/src/library-features/char-error-internals.md
new file mode 100644
index 00000000000..8013b4988e1
--- /dev/null
+++ b/src/doc/unstable-book/src/library-features/char-error-internals.md
@@ -0,0 +1,5 @@
+# `char_error_internals`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs
index 8bb16febb04..c9c7a27c614 100644
--- a/src/liballoc/vec.rs
+++ b/src/liballoc/vec.rs
@@ -2124,10 +2124,12 @@ impl<T> From<Box<[T]>> for 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()
     }
 }
 
diff --git a/src/libcore/char.rs b/src/libcore/char.rs
index 98268e3813f..44f5fdbf431 100644
--- a/src/libcore/char.rs
+++ b/src/libcore/char.rs
@@ -19,7 +19,7 @@ use char_private::is_printable;
 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 @@ impl From<u8> for char {
     }
 }
 
+
+/// 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;
diff --git a/src/libcore/tests/char.rs b/src/libcore/tests/char.rs
index e4012ec91e2..7c3b90c8153 100644
--- a/src/libcore/tests/char.rs
+++ b/src/libcore/tests/char.rs
@@ -10,6 +10,7 @@
 
 use std::{char,str};
 use std::convert::TryFrom;
+use std::str::FromStr;
 
 #[test]
 fn test_convert() {
@@ -29,6 +30,16 @@ fn test_convert() {
 }
 
 #[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());
     assert!('ö'.is_lowercase());
diff --git a/src/liblibc b/src/liblibc
-Subproject 03562b0cb26a00f49d4eaf18ca3e49608110b0c
+Subproject 2015cf17a6a2a2280e93d9c57214ba92dbbaf42
diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs
index 0c82679c307..473c0f3ffda 100644
--- a/src/librustc_lint/unused.rs
+++ b/src/librustc_lint/unused.rs
@@ -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 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults {
             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(": ");
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index 49fb44f9d37..b97c08b5bde 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -523,7 +523,10 @@ impl<'a> Resolver<'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> {
diff --git a/src/libstd/env.rs b/src/libstd/env.rs
index 889ba81e778..770bca7524c 100644
--- a/src/libstd/env.rs
+++ b/src/libstd/env.rs
@@ -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;
diff --git a/src/libstd/error.rs b/src/libstd/error.rs
index 3d203429e7b..4b340f70fbc 100644
--- a/src/libstd/error.rs
+++ b/src/libstd/error.rs
@@ -340,6 +340,14 @@ impl Error for char::CharTryFromError {
     }
 }
 
+#[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`
diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs
index 74ac9d528bb..1a91417ca0e 100644
--- a/src/libstd/ffi/c_str.rs
+++ b/src/libstd/ffi/c_str.rs
@@ -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 NulError(usize, Vec<u8>);
 /// 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 @@ impl 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 @@ impl CString {
     /// 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 @@ impl CString {
     /// 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 @@ impl 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 @@ impl CStr {
     /// > **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 @@ impl CStr {
     /// > 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 @@ impl CStr {
     /// > 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 @@ impl CStr {
     ///
     /// [`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 �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 @@ impl CStr {
     ///
     /// [`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) }
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index 7c843711dbe..bafe23e80a0 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -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)]
diff --git a/src/libstd_unicode/char.rs b/src/libstd_unicode/char.rs
index eb36cbe3b1f..d4d8993efb3 100644
--- a/src/libstd_unicode/char.rs
+++ b/src/libstd_unicode/char.rs
@@ -38,6 +38,8 @@ use tables::{conversions, derived_property, general_category, property};
 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")]
diff --git a/src/test/compile-fail/unused-result.rs b/src/test/compile-fail/unused-result.rs
index 6ed3b081c97..0c6c7fc5a0d 100644
--- a/src/test/compile-fail/unused-result.rs
+++ b/src/test/compile-fail/unused-result.rs
@@ -26,8 +26,8 @@ fn qux() -> MustUseMsg { return foo::<MustUseMsg>(); }
 #[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>();