about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2017-07-14 00:50:33 +0000
committerbors <bors@rust-lang.org>2017-07-14 00:50:33 +0000
commitab91c70cc69450bc69b76df0fd2faa82bda42d6b (patch)
treed79dcef1bcd5099dfe9617ac181dcbbc0baba97b /src
parentb2c0707872082c890f332178f59fd02eea5b98f3 (diff)
parentda3f5b80ed8a0fb88aae2d2a462acc97b05ba911 (diff)
downloadrust-ab91c70cc69450bc69b76df0fd2faa82bda42d6b.tar.gz
rust-ab91c70cc69450bc69b76df0fd2faa82bda42d6b.zip
Auto merge of #43216 - steveklabnik:rollup, r=steveklabnik
Rollup of 7 pull requests

- Successful merges: #42926, #43125, #43157, #43167, #43187, #43203, #43204
- Failed merges:
Diffstat (limited to 'src')
-rw-r--r--src/libstd/path.rs34
-rw-r--r--src/libstd/sys/redox/fs.rs7
-rw-r--r--src/libstd/sys/redox/mod.rs20
-rw-r--r--src/test/run-pass/rfc1857-drop-order.rs231
4 files changed, 270 insertions, 22 deletions
diff --git a/src/libstd/path.rs b/src/libstd/path.rs
index e7c7be981d2..3f466d5031e 100644
--- a/src/libstd/path.rs
+++ b/src/libstd/path.rs
@@ -2216,12 +2216,22 @@ impl Path {
     /// This function will traverse symbolic links to query information about the
     /// destination file. In case of broken symbolic links this will return `false`.
     ///
+    /// If you cannot access the directory containing the file, e.g. because of a
+    /// permission error, this will return `false`.
+    ///
     /// # Examples
     ///
     /// ```no_run
     /// use std::path::Path;
     /// assert_eq!(Path::new("does_not_exist.txt").exists(), false);
     /// ```
+    ///
+    /// # See Also
+    ///
+    /// This is a convenience function that coerces errors to false. If you want to
+    /// check errors, call [fs::metadata].
+    ///
+    /// [fs::metadata]: ../../std/fs/fn.metadata.html
     #[stable(feature = "path_ext", since = "1.5.0")]
     pub fn exists(&self) -> bool {
         fs::metadata(self).is_ok()
@@ -2232,6 +2242,9 @@ impl Path {
     /// This function will traverse symbolic links to query information about the
     /// destination file. In case of broken symbolic links this will return `false`.
     ///
+    /// If you cannot access the directory containing the file, e.g. because of a
+    /// permission error, this will return `false`.
+    ///
     /// # Examples
     ///
     /// ```no_run
@@ -2239,6 +2252,15 @@ impl Path {
     /// assert_eq!(Path::new("./is_a_directory/").is_file(), false);
     /// assert_eq!(Path::new("a_file.txt").is_file(), true);
     /// ```
+    ///
+    /// # See Also
+    ///
+    /// This is a convenience function that coerces errors to false. If you want to
+    /// check errors, call [fs::metadata] and handle its Result. Then call
+    /// [fs::Metadata::is_file] if it was Ok.
+    ///
+    /// [fs::metadata]: ../../std/fs/fn.metadata.html
+    /// [fs::Metadata::is_file]: ../../std/fs/struct.Metadata.html#method.is_file
     #[stable(feature = "path_ext", since = "1.5.0")]
     pub fn is_file(&self) -> bool {
         fs::metadata(self).map(|m| m.is_file()).unwrap_or(false)
@@ -2249,6 +2271,9 @@ impl Path {
     /// This function will traverse symbolic links to query information about the
     /// destination file. In case of broken symbolic links this will return `false`.
     ///
+    /// If you cannot access the directory containing the file, e.g. because of a
+    /// permission error, this will return `false`.
+    ///
     /// # Examples
     ///
     /// ```no_run
@@ -2256,6 +2281,15 @@ impl Path {
     /// assert_eq!(Path::new("./is_a_directory/").is_dir(), true);
     /// assert_eq!(Path::new("a_file.txt").is_dir(), false);
     /// ```
+    ///
+    /// # See Also
+    ///
+    /// This is a convenience function that coerces errors to false. If you want to
+    /// check errors, call [fs::metadata] and handle its Result. Then call
+    /// [fs::Metadata::is_dir] if it was Ok.
+    ///
+    /// [fs::metadata]: ../../std/fs/fn.metadata.html
+    /// [fs::Metadata::is_dir]: ../../std/fs/struct.Metadata.html#method.is_dir
     #[stable(feature = "path_ext", since = "1.5.0")]
     pub fn is_dir(&self) -> bool {
         fs::metadata(self).map(|m| m.is_dir()).unwrap_or(false)
diff --git a/src/libstd/sys/redox/fs.rs b/src/libstd/sys/redox/fs.rs
index 87e50c40148..918893097f8 100644
--- a/src/libstd/sys/redox/fs.rs
+++ b/src/libstd/sys/redox/fs.rs
@@ -383,9 +383,10 @@ pub fn unlink(p: &Path) -> io::Result<()> {
     Ok(())
 }
 
-pub fn rename(_old: &Path, _new: &Path) -> io::Result<()> {
-    ::sys_common::util::dumb_print(format_args!("Rename\n"));
-    unimplemented!();
+pub fn rename(old: &Path, new: &Path) -> io::Result<()> {
+    copy(old, new)?;
+    unlink(old)?;
+    Ok(())
 }
 
 pub fn set_perm(p: &Path, perm: FilePermissions) -> io::Result<()> {
diff --git a/src/libstd/sys/redox/mod.rs b/src/libstd/sys/redox/mod.rs
index 31c40ea58b1..7c728ebb1af 100644
--- a/src/libstd/sys/redox/mod.rs
+++ b/src/libstd/sys/redox/mod.rs
@@ -39,25 +39,7 @@ pub mod thread_local;
 pub mod time;
 
 #[cfg(not(test))]
-pub fn init() {
-    use alloc::oom;
-
-    oom::set_oom_handler(oom_handler);
-
-    // A nicer handler for out-of-memory situations than the default one. This
-    // one prints a message to stderr before aborting. It is critical that this
-    // code does not allocate any memory since we are in an OOM situation. Any
-    // errors are ignored while printing since there's nothing we can do about
-    // them and we are about to exit anyways.
-    fn oom_handler() -> ! {
-        use intrinsics;
-        let msg = "fatal runtime error: out of memory\n";
-        unsafe {
-            let _ = syscall::write(2, msg.as_bytes());
-            intrinsics::abort();
-        }
-    }
-}
+pub fn init() {}
 
 pub fn decode_error_kind(errno: i32) -> ErrorKind {
     match errno {
diff --git a/src/test/run-pass/rfc1857-drop-order.rs b/src/test/run-pass/rfc1857-drop-order.rs
new file mode 100644
index 00000000000..42f989538c8
--- /dev/null
+++ b/src/test/run-pass/rfc1857-drop-order.rs
@@ -0,0 +1,231 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![allow(dead_code, unreachable_code)]
+
+use std::cell::RefCell;
+use std::rc::Rc;
+use std::panic::{self, AssertUnwindSafe, UnwindSafe};
+
+// This struct is used to record the order in which elements are dropped
+struct PushOnDrop {
+    vec: Rc<RefCell<Vec<u32>>>,
+    val: u32
+}
+
+impl PushOnDrop {
+    fn new(val: u32, vec: Rc<RefCell<Vec<u32>>>) -> PushOnDrop {
+        PushOnDrop { vec, val }
+    }
+}
+
+impl Drop for PushOnDrop {
+    fn drop(&mut self) {
+        self.vec.borrow_mut().push(self.val)
+    }
+}
+
+impl UnwindSafe for PushOnDrop { }
+
+// Structs
+struct TestStruct {
+    x: PushOnDrop,
+    y: PushOnDrop,
+    z: PushOnDrop
+}
+
+// Tuple structs
+struct TestTupleStruct(PushOnDrop, PushOnDrop, PushOnDrop);
+
+// Enum variants
+enum TestEnum {
+    Tuple(PushOnDrop, PushOnDrop, PushOnDrop),
+    Struct { x: PushOnDrop, y: PushOnDrop, z: PushOnDrop }
+}
+
+fn test_drop_tuple() {
+    // Tuple fields are dropped in the same order they are declared
+    let dropped_fields = Rc::new(RefCell::new(Vec::new()));
+    let test_tuple = (PushOnDrop::new(1, dropped_fields.clone()),
+                      PushOnDrop::new(2, dropped_fields.clone()));
+    drop(test_tuple);
+    assert_eq!(*dropped_fields.borrow(), &[1, 2]);
+
+    // Panic during construction means that fields are treated as local variables
+    // Therefore they are dropped in reverse order of initialization
+    let dropped_fields = Rc::new(RefCell::new(Vec::new()));
+    let cloned = AssertUnwindSafe(dropped_fields.clone());
+    panic::catch_unwind(|| {
+        (PushOnDrop::new(2, cloned.clone()),
+         PushOnDrop::new(1, cloned.clone()),
+         panic!("this panic is catched :D"));
+    }).err().unwrap();
+    assert_eq!(*dropped_fields.borrow(), &[1, 2]);
+}
+
+fn test_drop_struct() {
+    // Struct fields are dropped in the same order they are declared
+    let dropped_fields = Rc::new(RefCell::new(Vec::new()));
+    let test_struct = TestStruct {
+        x: PushOnDrop::new(1, dropped_fields.clone()),
+        y: PushOnDrop::new(2, dropped_fields.clone()),
+        z: PushOnDrop::new(3, dropped_fields.clone()),
+    };
+    drop(test_struct);
+    assert_eq!(*dropped_fields.borrow(), &[1, 2, 3]);
+
+    // The same holds for tuple structs
+    let dropped_fields = Rc::new(RefCell::new(Vec::new()));
+    let test_tuple_struct = TestTupleStruct(PushOnDrop::new(1, dropped_fields.clone()),
+                                            PushOnDrop::new(2, dropped_fields.clone()),
+                                            PushOnDrop::new(3, dropped_fields.clone()));
+    drop(test_tuple_struct);
+    assert_eq!(*dropped_fields.borrow(), &[1, 2, 3]);
+
+    // Panic during struct construction means that fields are treated as local variables
+    // Therefore they are dropped in reverse order of initialization
+    let dropped_fields = Rc::new(RefCell::new(Vec::new()));
+    let cloned = AssertUnwindSafe(dropped_fields.clone());
+    panic::catch_unwind(|| {
+        TestStruct {
+            x: PushOnDrop::new(2, cloned.clone()),
+            y: PushOnDrop::new(1, cloned.clone()),
+            z: panic!("this panic is catched :D")
+        };
+    }).err().unwrap();
+    assert_eq!(*dropped_fields.borrow(), &[1, 2]);
+
+    // Test with different initialization order
+    let dropped_fields = Rc::new(RefCell::new(Vec::new()));
+    let cloned = AssertUnwindSafe(dropped_fields.clone());
+    panic::catch_unwind(|| {
+        TestStruct {
+            y: PushOnDrop::new(2, cloned.clone()),
+            x: PushOnDrop::new(1, cloned.clone()),
+            z: panic!("this panic is catched :D")
+        };
+    }).err().unwrap();
+    assert_eq!(*dropped_fields.borrow(), &[1, 2]);
+
+    // The same holds for tuple structs
+    let dropped_fields = Rc::new(RefCell::new(Vec::new()));
+    let cloned = AssertUnwindSafe(dropped_fields.clone());
+    panic::catch_unwind(|| {
+        TestTupleStruct(PushOnDrop::new(2, cloned.clone()),
+                        PushOnDrop::new(1, cloned.clone()),
+                        panic!("this panic is catched :D"));
+    }).err().unwrap();
+    assert_eq!(*dropped_fields.borrow(), &[1, 2]);
+}
+
+fn test_drop_enum() {
+    // Enum variants are dropped in the same order they are declared
+    let dropped_fields = Rc::new(RefCell::new(Vec::new()));
+    let test_struct_enum = TestEnum::Struct {
+        x: PushOnDrop::new(1, dropped_fields.clone()),
+        y: PushOnDrop::new(2, dropped_fields.clone()),
+        z: PushOnDrop::new(3, dropped_fields.clone())
+    };
+    drop(test_struct_enum);
+    assert_eq!(*dropped_fields.borrow(), &[1, 2, 3]);
+
+    // The same holds for tuple enum variants
+    let dropped_fields = Rc::new(RefCell::new(Vec::new()));
+    let test_tuple_enum = TestEnum::Tuple(PushOnDrop::new(1, dropped_fields.clone()),
+                                          PushOnDrop::new(2, dropped_fields.clone()),
+                                          PushOnDrop::new(3, dropped_fields.clone()));
+    drop(test_tuple_enum);
+    assert_eq!(*dropped_fields.borrow(), &[1, 2, 3]);
+
+    // Panic during enum construction means that fields are treated as local variables
+    // Therefore they are dropped in reverse order of initialization
+    let dropped_fields = Rc::new(RefCell::new(Vec::new()));
+    let cloned = AssertUnwindSafe(dropped_fields.clone());
+    panic::catch_unwind(|| {
+        TestEnum::Struct {
+            x: PushOnDrop::new(2, cloned.clone()),
+            y: PushOnDrop::new(1, cloned.clone()),
+            z: panic!("this panic is catched :D")
+        };
+    }).err().unwrap();
+    assert_eq!(*dropped_fields.borrow(), &[1, 2]);
+
+    // Test with different initialization order
+    let dropped_fields = Rc::new(RefCell::new(Vec::new()));
+    let cloned = AssertUnwindSafe(dropped_fields.clone());
+    panic::catch_unwind(|| {
+        TestEnum::Struct {
+            y: PushOnDrop::new(2, cloned.clone()),
+            x: PushOnDrop::new(1, cloned.clone()),
+            z: panic!("this panic is catched :D")
+        };
+    }).err().unwrap();
+    assert_eq!(*dropped_fields.borrow(), &[1, 2]);
+
+    // The same holds for tuple enum variants
+    let dropped_fields = Rc::new(RefCell::new(Vec::new()));
+    let cloned = AssertUnwindSafe(dropped_fields.clone());
+    panic::catch_unwind(|| {
+        TestEnum::Tuple(PushOnDrop::new(2, cloned.clone()),
+                        PushOnDrop::new(1, cloned.clone()),
+                        panic!("this panic is catched :D"));
+    }).err().unwrap();
+    assert_eq!(*dropped_fields.borrow(), &[1, 2]);
+}
+
+fn test_drop_list() {
+    // Elements in a Vec are dropped in the same order they are pushed
+    let dropped_fields = Rc::new(RefCell::new(Vec::new()));
+    let xs = vec![PushOnDrop::new(1, dropped_fields.clone()),
+                  PushOnDrop::new(2, dropped_fields.clone()),
+                  PushOnDrop::new(3, dropped_fields.clone())];
+    drop(xs);
+    assert_eq!(*dropped_fields.borrow(), &[1, 2, 3]);
+
+    // The same holds for arrays
+    let dropped_fields = Rc::new(RefCell::new(Vec::new()));
+    let xs = [PushOnDrop::new(1, dropped_fields.clone()),
+              PushOnDrop::new(2, dropped_fields.clone()),
+              PushOnDrop::new(3, dropped_fields.clone())];
+    drop(xs);
+    assert_eq!(*dropped_fields.borrow(), &[1, 2, 3]);
+
+    // Panic during vec construction means that fields are treated as local variables
+    // Therefore they are dropped in reverse order of initialization
+    let dropped_fields = Rc::new(RefCell::new(Vec::new()));
+    let cloned = AssertUnwindSafe(dropped_fields.clone());
+    panic::catch_unwind(|| {
+        vec![
+            PushOnDrop::new(2, cloned.clone()),
+            PushOnDrop::new(1, cloned.clone()),
+            panic!("this panic is catched :D")
+        ];
+    }).err().unwrap();
+    assert_eq!(*dropped_fields.borrow(), &[1, 2]);
+
+    // The same holds for arrays
+    let dropped_fields = Rc::new(RefCell::new(Vec::new()));
+    let cloned = AssertUnwindSafe(dropped_fields.clone());
+    panic::catch_unwind(|| {
+        [
+            PushOnDrop::new(2, cloned.clone()),
+            PushOnDrop::new(1, cloned.clone()),
+            panic!("this panic is catched :D")
+        ];
+    }).err().unwrap();
+    assert_eq!(*dropped_fields.borrow(), &[1, 2]);
+}
+
+fn main() {
+    test_drop_tuple();
+    test_drop_struct();
+    test_drop_enum();
+    test_drop_list();
+}