diff options
| -rw-r--r-- | man/rustc.1 | 9 | ||||
| -rw-r--r-- | man/rustdoc.1 | 10 | ||||
| -rw-r--r-- | src/libcore/ptr.rs | 12 | ||||
| -rw-r--r-- | src/librustc/middle/infer/region_inference/mod.rs | 13 | ||||
| -rw-r--r-- | src/librustc_back/target/windows_base.rs | 1 | ||||
| -rw-r--r-- | src/librustc_back/target/x86_64_rumprun_netbsd.rs | 1 | ||||
| -rw-r--r-- | src/librustc_mir/build/expr/into.rs | 2 | ||||
| -rw-r--r-- | src/libstd/fs.rs | 34 | ||||
| -rw-r--r-- | src/libstd/sys/unix/fs.rs | 11 | ||||
| -rw-r--r-- | src/libstd/sys/windows/fs.rs | 13 | ||||
| -rw-r--r-- | src/test/compile-fail/issue-30438-a.rs | 33 | ||||
| -rw-r--r-- | src/test/compile-fail/issue-30438-b.rs | 34 | ||||
| -rw-r--r-- | src/test/compile-fail/issue-30438-c.rs | 30 |
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) +} |
