diff --git a/.mailmap b/.mailmap index ee5b6f257b5..40e9c003313 100644 --- a/.mailmap +++ b/.mailmap @@ -6,6 +6,7 @@ # Aaron Todd +Aaron Power Abhishek Chanda Abhishek Chanda Adolfo Ochagavía Adrien Tétar @@ -56,6 +57,7 @@ Corey Richardson Elaine "See More" Nemo Cyryl Płotnicki Damien Schoof Daniel Ramos +Daniel J Rollins David Klein David Manescu David Ross @@ -63,11 +65,12 @@ Derek Chiang Derek Chiang (Enchi Jiang) Diggory Hardy Dylan Braithwaite Dzmitry Malyshau +E. Dunham edunham Eduardo Bautista <=> Eduardo Bautista +Eduard-Mihai Burtescu Elliott Slaughter Elly Fong-Jones -Emily Dunham edunham Eric Holk Eric Holk Eric Holmes @@ -83,6 +86,8 @@ Gareth Daniel Smith Gareth Smith Graham Fawcett Graham Fawcett Graydon Hoare Graydon Hoare +Guillaume Gomez +Guillaume Gomez ggomez Guillaume Gomez Guillaume Gomez Heather Heather @@ -114,6 +119,7 @@ John Kåre Alsaker John Talling Jonathan Bailey Jonathan S Jonathan S +Jonathan Turner Jorge Aparicio Joseph Martin João Oliveira joaoxsouls @@ -136,6 +142,7 @@ NAKASHIMA, Makoto NAKASHIMA, Makoto Marcell Pardavi Margaret Meyerhofer +Mark Simulacrum Mark Sinclair Mark Sinclair =Mark Sinclair <=125axel125@gmail.com> Markus Westerlind Markus @@ -171,6 +178,7 @@ Peter Zotov Phil Dawes Phil Dawes Philipp Brüschweiler Philipp Brüschweiler +Philipp Matthias Schäfer Przemysław Wesołek Przemek Wesołek Rafael Ávila de Espíndola Rafael Avila de Espindola Ralph Giles Ralph Giles @@ -189,11 +197,13 @@ S Pradeep Kumar Scott Olson Scott Olson Sean Gillespie swgillespie Seonghyun Kim +Shyam Sundar B Simon Barber-Dueck Simon BD Simon Sapin Simonas Kazlauskas Simonas Kazlauskas startling Stepan Koltsov Stepan Koltsov +Steve Klabnik Steven Fackler Steven Stewart-Gallus Stuart Pernsteiner Stuart Pernsteiner diff --git a/.travis.yml b/.travis.yml index 3d3c1ca4082..d351bea4777 100644 --- a/.travis.yml +++ b/.travis.yml @@ -122,7 +122,7 @@ matrix: - env: IMAGE=dist-x86_64-linux DEPLOY_ALT=1 - env: > RUST_CHECK_TARGET=dist - RUST_CONFIGURE_ARGS="--enable-extended" + RUST_CONFIGURE_ARGS="--enable-extended --enable-profiler" SRC=. DEPLOY_ALT=1 RUSTC_RETRY_LINKER_ON_SEGFAULT=1 diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 00000000000..6bec9330186 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,38 @@ +# The Rust Code of Conduct + +A version of this document [can be found online](https://www.rust-lang.org/conduct.html). + +## Conduct + +**Contact**: [rust-mods@rust-lang.org](mailto:rust-mods@rust-lang.org) + +* We are committed to providing a friendly, safe and welcoming environment for all, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, nationality, or other similar characteristic. +* On IRC, please avoid using overtly sexual nicknames or other nicknames that might detract from a friendly, safe and welcoming environment for all. +* Please be kind and courteous. There's no need to be mean or rude. +* Respect that people have differences of opinion and that every design or implementation choice carries a trade-off and numerous costs. There is seldom a right answer. +* Please keep unstructured critique to a minimum. If you have solid ideas you want to experiment with, make a fork and see how it works. +* We will exclude you from interaction if you insult, demean or harass anyone. That is not welcome behaviour. We interpret the term "harassment" as including the definition in the Citizen Code of Conduct; if you have any lack of clarity about what might be included in that concept, please read their definition. In particular, we don't tolerate behavior that excludes people in socially marginalized groups. +* Private harassment is also unacceptable. No matter who you are, if you feel you have been or are being harassed or made uncomfortable by a community member, please contact one of the channel ops or any of the [Rust moderation team](/team.html#Moderation) immediately. Whether you're a regular contributor or a newcomer, we care about making this community a safe place for you and we've got your back. +* Likewise any spamming, trolling, flaming, baiting or other attention-stealing behaviour is not welcome. + +## Moderation + + +These are the policies for upholding our community's standards of conduct. If you feel that a thread needs moderation, please contact the [Rust moderation team](/team.html#Moderation). + +1. Remarks that violate the Rust standards of conduct, including hateful, hurtful, oppressive, or exclusionary remarks, are not allowed. (Cursing is allowed, but never targeting another user, and never in a hateful manner.) +2. Remarks that moderators find inappropriate, whether listed in the code of conduct or not, are also not allowed. +3. Moderators will first respond to such remarks with a warning. +4. If the warning is unheeded, the user will be "kicked," i.e., kicked out of the communication channel to cool off. +5. If the user comes back and continues to make trouble, they will be banned, i.e., indefinitely excluded. +6. Moderators may choose at their discretion to un-ban the user if it was a first offense and they offer the offended party a genuine apology. +7. If a moderator bans someone and you think it was unjustified, please take it up with that moderator, or with a different moderator, **in private**. Complaints about bans in-channel are not allowed. +8. Moderators are held to a higher standard than other community members. If a moderator creates an inappropriate situation, they should expect less leeway than others. + +In the Rust community we strive to go the extra step to look out for each other. Don't just aim to be technically unimpeachable, try to be your best self. In particular, avoid flirting with offensive or sensitive issues, particularly if they're off-topic; this all too often leads to unnecessary fights, hurt feelings, and damaged trust; worse, it can drive people away from the community entirely. + +And if someone takes issue with something you said or did, resist the urge to be defensive. Just stop doing what it was they complained about and apologize. Even if you feel you were misinterpreted or unfairly accused, chances are good there was something you could've communicated better — remember that it's your responsibility to make your fellow Rustaceans comfortable. Everyone wants to get along and we are all here first and foremost because we want to talk about cool technology. You will find that people will be eager to assume good intent and forgive as long as you earn their trust. + +The enforcement policies listed above apply to all official Rust venues; including official IRC channels (#rust, #rust-internals, #rust-tools, #rust-libs, #rustc, #rust-beginners, #rust-docs, #rust-community, #rust-lang, and #cargo); GitHub repositories under rust-lang, rust-lang-nursery, and rust-lang-deprecated; and all forums under rust-lang.org (users.rust-lang.org, internals.rust-lang.org). For other projects adopting the Rust Code of Conduct, please contact the maintainers of those projects for enforcement. If you wish to use this code of conduct for your own project, consider explicitly mentioning your moderation policy or making a copy with your own moderation policy so as to avoid confusion. + +*Adapted from the [Node.js Policy on Trolling](http://blog.izs.me/post/30036893703/policy-on-trolling) as well as the [Contributor Covenant v1.3.0](http://contributor-covenant.org/version/1/3/0/).* diff --git a/appveyor.yml b/appveyor.yml index 4711f34f830..582ca5d0f9d 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -75,7 +75,7 @@ environment: # "alternate" deployment, see .travis.yml for more info - MSYS_BITS: 64 - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-extended + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-extended --enable-profiler SCRIPT: python x.py dist DEPLOY_ALT: 1 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 or the MIT license +// , 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>>, + val: u32 +} + +impl PushOnDrop { + fn new(val: u32, vec: Rc>>) -> 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(); +}