about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--man/rustc.19
-rw-r--r--man/rustdoc.110
-rw-r--r--src/libcore/ptr.rs12
-rw-r--r--src/librustc/middle/infer/region_inference/mod.rs13
-rw-r--r--src/librustc_back/target/windows_base.rs1
-rw-r--r--src/librustc_back/target/x86_64_rumprun_netbsd.rs1
-rw-r--r--src/librustc_mir/build/expr/into.rs2
-rw-r--r--src/libstd/fs.rs34
-rw-r--r--src/libstd/sys/unix/fs.rs11
-rw-r--r--src/libstd/sys/windows/fs.rs13
-rw-r--r--src/test/compile-fail/issue-30438-a.rs33
-rw-r--r--src/test/compile-fail/issue-30438-b.rs34
-rw-r--r--src/test/compile-fail/issue-30438-c.rs30
13 files changed, 180 insertions, 23 deletions
diff --git a/man/rustc.1 b/man/rustc.1
index 3d7fc7f6bf4..0b8b1559d90 100644
--- a/man/rustc.1
+++ b/man/rustc.1
@@ -6,9 +6,7 @@ rustc \- The Rust compiler
 [\fIOPTIONS\fR] \fIINPUT\fR
 
 .SH DESCRIPTION
-This program is a compiler for the Rust language, available at
-.UR https://www.rust\-lang.org
-.UE .
+This program is a compiler for the Rust language, available at https://www.rust\-lang.org.
 
 .SH OPTIONS
 
@@ -298,10 +296,7 @@ To build an executable with debug info:
 .BR rustdoc (1)
 
 .SH "BUGS"
-See
-.UR https://github.com/rust\-lang/rust/issues
-.UE
-for issues.
+See https://github.com/rust\-lang/rust/issues for issues.
 
 .SH "AUTHOR"
 See \fIAUTHORS.txt\fR in the Rust source distribution.
diff --git a/man/rustdoc.1 b/man/rustdoc.1
index b710c2c3a25..ae14c9d7828 100644
--- a/man/rustdoc.1
+++ b/man/rustdoc.1
@@ -8,10 +8,8 @@ rustdoc \- generate documentation from Rust source code
 .SH DESCRIPTION
 This tool generates API reference documentation by extracting comments from
 source code written in the Rust language, available at
-.UR https://www.rust\-lang.org
-.UE .
-It accepts several input formats and provides several output formats
-for the generated documentation.
+<\fBhttps://www.rust-lang.org\fR>. It accepts several input formats and
+provides several output formats for the generated documentation.
 
 .SH OPTIONS
 
@@ -131,9 +129,7 @@ The generated HTML can be viewed with any standard web browser.
 .BR rustc (1)
 
 .SH "BUGS"
-See
-.UR https://github.com/rust\-lang/rust/issues
-.UE
+See <\fBhttps://github.com/rust\-lang/rust/issues\fR>
 for issues.
 
 .SH "AUTHOR"
diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs
index e1e7869d548..a826f2bb444 100644
--- a/src/libcore/ptr.rs
+++ b/src/libcore/ptr.rs
@@ -465,7 +465,7 @@ impl<T: ?Sized> PartialOrd for *mut T {
     fn ge(&self, other: &*mut T) -> bool { *self >= *other }
 }
 
-/// A wrapper around a raw `*mut T` that indicates that the possessor
+/// A wrapper around a raw non-null `*mut T` that indicates that the possessor
 /// of this wrapper owns the referent. This in turn implies that the
 /// `Unique<T>` is `Send`/`Sync` if `T` is `Send`/`Sync`, unlike a raw
 /// `*mut T` (which conveys no particular ownership semantics).  It
@@ -502,6 +502,10 @@ unsafe impl<T: Sync + ?Sized> Sync for Unique<T> { }
 #[unstable(feature = "unique", issue = "27730")]
 impl<T: ?Sized> Unique<T> {
     /// Creates a new `Unique`.
+    ///
+    /// # Safety
+    ///
+    /// `ptr` must be non-null.
     pub const unsafe fn new(ptr: *mut T) -> Unique<T> {
         Unique { pointer: NonZero::new(ptr), _marker: PhantomData }
     }
@@ -537,7 +541,7 @@ impl<T> fmt::Pointer for Unique<T> {
     }
 }
 
-/// A wrapper around a raw `*mut T` that indicates that the possessor
+/// A wrapper around a raw non-null `*mut T` that indicates that the possessor
 /// of this wrapper has shared ownership of the referent. Useful for
 /// building abstractions like `Rc<T>` or `Arc<T>`, which internally
 /// use raw pointers to manage the memory that they own.
@@ -566,6 +570,10 @@ impl<T: ?Sized> !Sync for Shared<T> { }
 #[unstable(feature = "shared", issue = "27730")]
 impl<T: ?Sized> Shared<T> {
     /// Creates a new `Shared`.
+    ///
+    /// # Safety
+    ///
+    /// `ptr` must be non-null.
     pub unsafe fn new(ptr: *mut T) -> Self {
         Shared { pointer: NonZero::new(ptr), _marker: PhantomData }
     }
diff --git a/src/librustc/middle/infer/region_inference/mod.rs b/src/librustc/middle/infer/region_inference/mod.rs
index 2c2b69ff85b..bfc770d53aa 100644
--- a/src/librustc/middle/infer/region_inference/mod.rs
+++ b/src/librustc/middle/infer/region_inference/mod.rs
@@ -1105,7 +1105,14 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
         for _ in 0..num_vars {
             graph.add_node(());
         }
-        let dummy_idx = graph.add_node(());
+
+        // Issue #30438: two distinct dummy nodes, one for incoming
+        // edges (dummy_source) and another for outgoing edges
+        // (dummy_sink). In `dummy -> a -> b -> dummy`, using one
+        // dummy node leads one to think (erroneously) there exists a
+        // path from `b` to `a`. Two dummy nodes sidesteps the issue.
+        let dummy_source = graph.add_node(());
+        let dummy_sink = graph.add_node(());
 
         for (constraint, _) in constraints.iter() {
             match *constraint {
@@ -1115,10 +1122,10 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
                                    *constraint);
                 }
                 ConstrainRegSubVar(_, b_id) => {
-                    graph.add_edge(dummy_idx, NodeIndex(b_id.index as usize), *constraint);
+                    graph.add_edge(dummy_source, NodeIndex(b_id.index as usize), *constraint);
                 }
                 ConstrainVarSubReg(a_id, _) => {
-                    graph.add_edge(NodeIndex(a_id.index as usize), dummy_idx, *constraint);
+                    graph.add_edge(NodeIndex(a_id.index as usize), dummy_sink, *constraint);
                 }
             }
         }
diff --git a/src/librustc_back/target/windows_base.rs b/src/librustc_back/target/windows_base.rs
index 634a63cf0bb..4eacea3fcd9 100644
--- a/src/librustc_back/target/windows_base.rs
+++ b/src/librustc_back/target/windows_base.rs
@@ -84,7 +84,6 @@ pub fn opts() -> TargetOptions {
             "rsend.o".to_string()
         ),
         custom_unwind_resume: true,
-        exe_allocation_crate: super::maybe_jemalloc(),
 
         .. Default::default()
     }
diff --git a/src/librustc_back/target/x86_64_rumprun_netbsd.rs b/src/librustc_back/target/x86_64_rumprun_netbsd.rs
index d63ad53cc2b..c97b434b9e0 100644
--- a/src/librustc_back/target/x86_64_rumprun_netbsd.rs
+++ b/src/librustc_back/target/x86_64_rumprun_netbsd.rs
@@ -21,6 +21,7 @@ pub fn target() -> Target {
     base.position_independent_executables = false;
     base.disable_redzone = true;
     base.no_default_libraries = false;
+    base.exe_allocation_crate = "alloc_system".to_string();
 
     Target {
         llvm_target: "x86_64-rumprun-netbsd".to_string(),
diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs
index f50e5689df0..ca00b99b108 100644
--- a/src/librustc_mir/build/expr/into.rs
+++ b/src/librustc_mir/build/expr/into.rs
@@ -63,7 +63,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
                 } else {
                     // Body of the `if` expression without an `else` clause must return `()`, thus
                     // we implicitly generate a `else {}` if it is not specified.
-                    this.cfg.push_assign_unit(else_block, expr_span, &Lvalue::ReturnPointer);
+                    this.cfg.push_assign_unit(else_block, expr_span, destination);
                     else_block
                 };
 
diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs
index 343d71abb64..2087148d844 100644
--- a/src/libstd/fs.rs
+++ b/src/libstd/fs.rs
@@ -1940,6 +1940,7 @@ mod tests {
         check!(fs::create_dir_all(&d2));
         check!(check!(File::create(&canary)).write(b"foo"));
         check!(symlink_junction(&d2, &dt.join("d2")));
+        let _ = symlink_file(&canary, &d1.join("canary"));
         check!(fs::remove_dir_all(&d1));
 
         assert!(!d1.is_dir());
@@ -1947,6 +1948,39 @@ mod tests {
     }
 
     #[test]
+    fn recursive_rmdir_of_symlink() {
+        // test we do not recursively delete a symlink but only dirs.
+        let tmpdir = tmpdir();
+        let link = tmpdir.join("d1");
+        let dir = tmpdir.join("d2");
+        let canary = dir.join("do_not_delete");
+        check!(fs::create_dir_all(&dir));
+        check!(check!(File::create(&canary)).write(b"foo"));
+        check!(symlink_junction(&dir, &link));
+        check!(fs::remove_dir_all(&link));
+
+        assert!(!link.is_dir());
+        assert!(canary.exists());
+    }
+
+    #[test]
+    // only Windows makes a distinction between file and directory symlinks.
+    #[cfg(windows)]
+    fn recursive_rmdir_of_file_symlink() {
+        let tmpdir = tmpdir();
+        if !got_symlink_permission(&tmpdir) { return };
+
+        let f1 = tmpdir.join("f1");
+        let f2 = tmpdir.join("f2");
+        check!(check!(File::create(&f1)).write(b"foo"));
+        check!(symlink_file(&f1, &f2));
+        match fs::remove_dir_all(&f2) {
+            Ok(..) => panic!("wanted a failure"),
+            Err(..) => {}
+        }
+    }
+
+    #[test]
     fn unicode_path_is_dir() {
         assert!(Path::new(".").is_dir());
         assert!(!Path::new("test/stdtest/fs.rs").is_dir());
diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs
index 727624dad7c..ee81c516e33 100644
--- a/src/libstd/sys/unix/fs.rs
+++ b/src/libstd/sys/unix/fs.rs
@@ -627,10 +627,19 @@ pub fn rmdir(p: &Path) -> io::Result<()> {
 }
 
 pub fn remove_dir_all(path: &Path) -> io::Result<()> {
+    let filetype = try!(lstat(path)).file_type();
+    if filetype.is_symlink() {
+        unlink(path)
+    } else {
+        remove_dir_all_recursive(path)
+    }
+}
+
+fn remove_dir_all_recursive(path: &Path) -> io::Result<()> {
     for child in try!(readdir(path)) {
         let child = try!(child);
         if try!(child.file_type()).is_dir() {
-            try!(remove_dir_all(&child.path()));
+            try!(remove_dir_all_recursive(&child.path()));
         } else {
             try!(unlink(&child.path()));
         }
diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs
index 16d337fcc70..3062d38f8c2 100644
--- a/src/libstd/sys/windows/fs.rs
+++ b/src/libstd/sys/windows/fs.rs
@@ -552,11 +552,22 @@ pub fn rmdir(p: &Path) -> io::Result<()> {
 }
 
 pub fn remove_dir_all(path: &Path) -> io::Result<()> {
+    let filetype = try!(lstat(path)).file_type();
+    if filetype.is_symlink() {
+        // On Windows symlinks to files and directories are removed differently.
+        // rmdir only deletes dir symlinks and junctions, not file symlinks.
+        rmdir(path)
+    } else {
+        remove_dir_all_recursive(path)
+    }
+}
+
+fn remove_dir_all_recursive(path: &Path) -> io::Result<()> {
     for child in try!(readdir(path)) {
         let child = try!(child);
         let child_type = try!(child.file_type());
         if child_type.is_dir() {
-            try!(remove_dir_all(&child.path()));
+            try!(remove_dir_all_recursive(&child.path()));
         } else if child_type.is_symlink_dir() {
             try!(rmdir(&child.path()));
         } else {
diff --git a/src/test/compile-fail/issue-30438-a.rs b/src/test/compile-fail/issue-30438-a.rs
new file mode 100644
index 00000000000..441815de81d
--- /dev/null
+++ b/src/test/compile-fail/issue-30438-a.rs
@@ -0,0 +1,33 @@
+// Copyright 2016 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.
+
+// Original regression test for Issue #30438.
+
+use std::ops::Index;
+
+struct Test<'a> {
+    s: &'a String
+}
+
+impl <'a> Index<usize> for Test<'a> {
+    type Output = Test<'a>;
+    fn index(&self, _: usize) -> &Self::Output {
+        return &Test { s: &self.s};
+        //~^ ERROR: borrowed value does not live long enough
+    }
+}
+
+fn main() {
+    let s = "Hello World".to_string();
+    let test = Test{s: &s};
+    let r = &test[0];
+    println!("{}", test.s); // OK since test is valid
+    println!("{}", r.s); // Segfault since value pointed by r has already been dropped
+}
diff --git a/src/test/compile-fail/issue-30438-b.rs b/src/test/compile-fail/issue-30438-b.rs
new file mode 100644
index 00000000000..981b196c4ae
--- /dev/null
+++ b/src/test/compile-fail/issue-30438-b.rs
@@ -0,0 +1,34 @@
+// Copyright 2016 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.
+
+// Modified regression test for Issue #30438 that exposed an
+// independent issue (see discussion on ticket).
+
+use std::ops::Index;
+
+struct Test<'a> {
+    s: &'a String
+}
+
+impl <'a> Index<usize> for Test<'a> {
+    type Output = Test<'a>;
+    fn index(&self, _: usize) -> &Self::Output {
+        &Test { s: &self.s}
+        //~^ ERROR: borrowed value does not live long enough
+    }
+}
+
+fn main() {
+    let s = "Hello World".to_string();
+    let test = Test{s: &s};
+    let r = &test[0];
+    println!("{}", test.s); // OK since test is valid
+    println!("{}", r.s); // Segfault since value pointed by r has already been dropped
+}
diff --git a/src/test/compile-fail/issue-30438-c.rs b/src/test/compile-fail/issue-30438-c.rs
new file mode 100644
index 00000000000..06d391af559
--- /dev/null
+++ b/src/test/compile-fail/issue-30438-c.rs
@@ -0,0 +1,30 @@
+// Copyright 2016 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.
+
+// Simplfied regression test for #30438, inspired by arielb1.
+
+trait Trait { type Out; }
+
+struct Test<'a> { s: &'a str }
+
+fn silly<'y, 'z>(_s: &'y Test<'z>) -> &'y <Test<'z> as Trait>::Out where 'z: 'static {
+    let x = Test { s: "this cannot last" };
+    &x
+    //~^ ERROR: `x` does not live long enough
+}
+
+impl<'b> Trait for Test<'b> { type Out = Test<'b>; }
+
+fn main() {
+    let orig = Test { s: "Hello World" };
+    let r = silly(&orig);
+    println!("{}", orig.s); // OK since `orig` is valid
+    println!("{}", r.s); // Segfault (method does not return a sane value)
+}