From ec356bb1a7654f38bd784028b6c0aa69518dafee Mon Sep 17 00:00:00 2001 From: Alex Burka Date: Sun, 4 Dec 2016 19:07:27 +0000 Subject: [PATCH 001/137] rustdoc: fix doctests with non-feature crate attrs --- src/doc/book/documentation.md | 4 +- ...using-rust-without-the-standard-library.md | 4 +- src/librustc/diagnostics.rs | 2 +- src/librustdoc/test.rs | 3 +- src/test/rustdoc/issue-38129.rs | 110 ++++++++++++++++++ 5 files changed, 117 insertions(+), 6 deletions(-) create mode 100644 src/test/rustdoc/issue-38129.rs diff --git a/src/doc/book/documentation.md b/src/doc/book/documentation.md index f30a95b4e7890..dad0cccd65563 100644 --- a/src/doc/book/documentation.md +++ b/src/doc/book/documentation.md @@ -600,7 +600,7 @@ is documented, especially when you are working on a library. Rust allows you to to generate warnings or errors, when an item is missing documentation. To generate warnings you use `warn`: -```rust +```rust,ignore #![warn(missing_docs)] ``` @@ -630,7 +630,7 @@ struct Hidden; You can control a few aspects of the HTML that `rustdoc` generates through the `#![doc]` version of the attribute: -```rust +```rust,ignore #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://www.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/")] diff --git a/src/doc/book/using-rust-without-the-standard-library.md b/src/doc/book/using-rust-without-the-standard-library.md index 69958dd3e68a4..e66e1d05fff73 100644 --- a/src/doc/book/using-rust-without-the-standard-library.md +++ b/src/doc/book/using-rust-without-the-standard-library.md @@ -13,7 +13,7 @@ don’t want to use the standard library via an attribute: `#![no_std]`. To use `#![no_std]`, add it to your crate root: -```rust +```rust,ignore #![no_std] fn plus_one(x: i32) -> i32 { @@ -29,7 +29,7 @@ use its features without an explicit import. By the same token, when using prelude](../core/prelude/v1/index.html). This means that a lot of code will Just Work: -```rust +```rust,ignore #![no_std] fn may_fail(failure: bool) -> Result<(), &'static str> { diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index ec09877ae121c..554af61286885 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -557,7 +557,7 @@ them yourself. You can build a free-standing crate by adding `#![no_std]` to the crate attributes: -``` +```ignore #![no_std] ``` diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 009330065f3c2..ae466d504ac1f 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -344,6 +344,7 @@ pub fn maketest(s: &str, cratename: Option<&str>, dont_insert_main: bool, prog } +// FIXME(aburka): use a real parser to deal with multiline attributes fn partition_source(s: &str) -> (String, String) { use rustc_unicode::str::UnicodeStr; @@ -354,7 +355,7 @@ fn partition_source(s: &str) -> (String, String) { for line in s.lines() { let trimline = line.trim(); let header = trimline.is_whitespace() || - trimline.starts_with("#![feature"); + trimline.starts_with("#!["); if !header || after_header { after_header = true; after.push_str(line); diff --git a/src/test/rustdoc/issue-38129.rs b/src/test/rustdoc/issue-38129.rs new file mode 100644 index 0000000000000..00ccc74d8874d --- /dev/null +++ b/src/test/rustdoc/issue-38129.rs @@ -0,0 +1,110 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags:--test + +// This file tests the source-partitioning behavior of rustdoc. +// Each test contains some code that should be put into the generated +// `fn main` and some attributes should be left outside (except the first +// one, which has no attributes). +// If the #![recursion_limit] attribute is incorrectly left inside, +// then the tests will fail because the macro recurses 128 times. + +/// ``` +/// assert_eq!(1 + 1, 2); +/// ``` +pub fn simple() {} + +/// ``` +/// #![recursion_limit = "1024"] +/// macro_rules! recurse { +/// (()) => {}; +/// (() $($rest:tt)*) => { recurse!($($rest)*); } +/// } +/// recurse!(() () () () () () () () +/// () () () () () () () () +/// () () () () () () () () +/// () () () () () () () () +/// () () () () () () () () +/// () () () () () () () () +/// () () () () () () () () +/// () () () () () () () () +/// () () () () () () () () +/// () () () () () () () () +/// () () () () () () () () +/// () () () () () () () () +/// () () () () () () () () +/// () () () () () () () () +/// () () () () () () () () +/// () () () () () () () ()); +/// assert_eq!(1 + 1, 2); +/// ``` +pub fn non_feature_attr() {} + +/// ``` +/// #![feature(core_intrinsics)] +/// assert_eq!(1 + 1, 2); +/// ``` +pub fn feature_attr() {} + +/// ``` +/// #![feature(core_intrinsics)] +/// #![recursion_limit = "1024"] +/// macro_rules! recurse { +/// (()) => {}; +/// (() $($rest:tt)*) => { recurse!($($rest)*); } +/// } +/// recurse!(() () () () () () () () +/// () () () () () () () () +/// () () () () () () () () +/// () () () () () () () () +/// () () () () () () () () +/// () () () () () () () () +/// () () () () () () () () +/// () () () () () () () () +/// () () () () () () () () +/// () () () () () () () () +/// () () () () () () () () +/// () () () () () () () () +/// () () () () () () () () +/// () () () () () () () () +/// () () () () () () () () +/// () () () () () () () ()); +/// assert_eq!(1 + 1, 2); +/// ``` +pub fn both_attrs() {} + +/// ``` +/// #![recursion_limit = "1024"] +/// #![feature(core_intrinsics)] +/// macro_rules! recurse { +/// (()) => {}; +/// (() $($rest:tt)*) => { recurse!($($rest)*); } +/// } +/// recurse!(() () () () () () () () +/// () () () () () () () () +/// () () () () () () () () +/// () () () () () () () () +/// () () () () () () () () +/// () () () () () () () () +/// () () () () () () () () +/// () () () () () () () () +/// () () () () () () () () +/// () () () () () () () () +/// () () () () () () () () +/// () () () () () () () () +/// () () () () () () () () +/// () () () () () () () () +/// () () () () () () () () +/// () () () () () () () ()); +/// assert_eq!(1 + 1, 2); +/// ``` +pub fn both_attrs_reverse() {} + From 02ae1e10605dccf29c77f94dbbf916b28d2b7c54 Mon Sep 17 00:00:00 2001 From: Chris Morgan Date: Sun, 8 Jan 2017 16:35:13 +0530 Subject: [PATCH 002/137] Support unprivileged symlink creation in Windows MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Symlink creation on Windows has in the past basically required admin; it’s being opened up a bit in the Creators Update, so that at least people who have put their computers into Developer Mode will be able to create symlinks without special privileges. (Microsoft are being cautious about it all; the Developer Mode requirement makes it so that it this won’t be as helpful as I’d like, but it’s still an improvement over requiring admin.) Because of compatibility concerns, they’ve hidden this new functionality behind a new flag in the CreateSymbolicLink dwFlags: SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE. So we add this flag in order to join the party. Older Windows doesn’t like this new flag, though, so if we encounter ERROR_INVALID_PARAMETER we try again without the new flag. Sources: - https://blogs.windows.com/buildingapps/2016/12/02/symlinks-windows-10/ is the official announcement (search for CreateSymbolicLink) - https://news.ycombinator.com/item?id=13096354 on why the new flag. - https://twitter.com/richturn_ms/status/818167548269051905 confirming that Developer Mode will still be required. --- src/libstd/sys/windows/c.rs | 1 + src/libstd/sys/windows/fs.rs | 22 +++++++++++++++++++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs index 910d802f05902..7b8575f9ec4c7 100644 --- a/src/libstd/sys/windows/c.rs +++ b/src/libstd/sys/windows/c.rs @@ -166,6 +166,7 @@ pub const SYMLINK_FLAG_RELATIVE: DWORD = 0x00000001; pub const FSCTL_SET_REPARSE_POINT: DWORD = 0x900a4; pub const SYMBOLIC_LINK_FLAG_DIRECTORY: DWORD = 0x1; +pub const SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE: DWORD = 0x2; // Note that these are not actually HANDLEs, just values to pass to GetStdHandle pub const STD_INPUT_HANDLE: DWORD = -10i32 as DWORD; diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs index c410fcd1ee0ed..4efc68afdc4c7 100644 --- a/src/libstd/sys/windows/fs.rs +++ b/src/libstd/sys/windows/fs.rs @@ -646,9 +646,25 @@ pub fn symlink_inner(src: &Path, dst: &Path, dir: bool) -> io::Result<()> { let src = to_u16s(src)?; let dst = to_u16s(dst)?; let flags = if dir { c::SYMBOLIC_LINK_FLAG_DIRECTORY } else { 0 }; - cvt(unsafe { - c::CreateSymbolicLinkW(dst.as_ptr(), src.as_ptr(), flags) as c::BOOL - })?; + // Formerly, symlink creation required the SeCreateSymbolicLink privilege. For the Windows 10 + // Creators Update, Microsoft loosened this to allow unprivileged symlink creation if the + // computer is in Developer Mode, but SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE must be + // added to dwFlags to opt into this behaviour. + let result = cvt(unsafe { + c::CreateSymbolicLinkW(dst.as_ptr(), src.as_ptr(), + flags | c::SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE) as c::BOOL + }); + if let Err(err) = result { + if err.raw_os_error() == Some(c::ERROR_INVALID_PARAMETER as i32) { + // Older Windows objects to SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE, + // so if we encounter ERROR_INVALID_PARAMETER, retry without that flag. + cvt(unsafe { + c::CreateSymbolicLinkW(dst.as_ptr(), src.as_ptr(), flags) as c::BOOL + })?; + } else { + return Err(err); + } + } Ok(()) } From 9903975003276cc42a1ed5f21eee292b7c62c331 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Tue, 10 Jan 2017 13:20:38 +0100 Subject: [PATCH 003/137] Add 128-bit atomics --- src/libcore/sync/atomic.rs | 18 ++++++++++++++++++ .../atomic-lock-free/atomic_lock_free.rs | 10 +++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs index 7520579447152..7534473b49221 100644 --- a/src/libcore/sync/atomic.rs +++ b/src/libcore/sync/atomic.rs @@ -1314,6 +1314,24 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), u64 AtomicU64 ATOMIC_U64_INIT } +#[cfg(not(stage0))] +#[cfg(target_has_atomic = "128")] +atomic_int! { + unstable(feature = "i128", issue = "35118"), + unstable(feature = "i128", issue = "35118"), + unstable(feature = "i128", issue = "35118"), + unstable(feature = "i128", issue = "35118"), + i128 AtomicI128 ATOMIC_I128_INIT +} +#[cfg(not(stage0))] +#[cfg(target_has_atomic = "128")] +atomic_int! { + unstable(feature = "i128", issue = "35118"), + unstable(feature = "i128", issue = "35118"), + unstable(feature = "i128", issue = "35118"), + unstable(feature = "i128", issue = "35118"), + u128 AtomicU128 ATOMIC_U128_INIT +} #[cfg(target_has_atomic = "ptr")] atomic_int!{ stable(feature = "rust1", since = "1.0.0"), diff --git a/src/test/run-make/atomic-lock-free/atomic_lock_free.rs b/src/test/run-make/atomic-lock-free/atomic_lock_free.rs index 023f2218b87ae..5ac50e04b8d2f 100644 --- a/src/test/run-make/atomic-lock-free/atomic_lock_free.rs +++ b/src/test/run-make/atomic-lock-free/atomic_lock_free.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(cfg_target_has_atomic, no_core, intrinsics, lang_items)] +#![feature(cfg_target_has_atomic, no_core, intrinsics, lang_items, i128_type)] #![crate_type="rlib"] #![no_core] @@ -54,6 +54,14 @@ pub unsafe fn atomic_u64(x: *mut u64) { pub unsafe fn atomic_i64(x: *mut i64) { atomic_xadd(x, 1); } +#[cfg(target_has_atomic = "128")] +pub unsafe fn atomic_u128(x: *mut u128) { + atomic_xadd(x, 1); +} +#[cfg(target_has_atomic = "128")] +pub unsafe fn atomic_i128(x: *mut i128) { + atomic_xadd(x, 1); +} #[cfg(target_has_atomic = "ptr")] pub unsafe fn atomic_usize(x: *mut usize) { atomic_xadd(x, 1); From 6c940893e58ad141ec8e3eaf2c65741d15d9eb93 Mon Sep 17 00:00:00 2001 From: Andre Bogus Date: Mon, 16 Jan 2017 22:28:58 +0100 Subject: [PATCH 004/137] branchless .filter(_).count() --- src/libcore/iter/mod.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index 3999db0d63c99..5dce60b79c99f 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -1099,6 +1099,16 @@ impl Iterator for Filter where P: FnMut(&I::Item) -> bool let (_, upper) = self.iter.size_hint(); (0, upper) // can't know a lower bound, due to the predicate } + + #[inline] + fn count(self) -> usize { + let (mut c, mut predicate, mut iter) = (0, self.predicate, self.iter); + for x in iter.by_ref() { + // branchless count + c += (&mut predicate)(&x) as usize; + } + c + } } #[stable(feature = "rust1", since = "1.0.0")] From 27f76157aafbac691e625b5d1b8b37330ec04552 Mon Sep 17 00:00:00 2001 From: Andre Bogus Date: Tue, 17 Jan 2017 13:18:16 +0100 Subject: [PATCH 005/137] fix style nits --- src/libcore/iter/mod.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index 5dce60b79c99f..ea98265ef8de0 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -1086,7 +1086,7 @@ impl Iterator for Filter where P: FnMut(&I::Item) -> bool #[inline] fn next(&mut self) -> Option { - for x in self.iter.by_ref() { + for x in &mut self.iter { if (self.predicate)(&x) { return Some(x); } @@ -1101,13 +1101,12 @@ impl Iterator for Filter where P: FnMut(&I::Item) -> bool } #[inline] - fn count(self) -> usize { - let (mut c, mut predicate, mut iter) = (0, self.predicate, self.iter); - for x in iter.by_ref() { - // branchless count - c += (&mut predicate)(&x) as usize; + fn count(mut self) -> usize { + let mut count = 0; + for x in &mut self.iter { + count += (self.predicate)(&x) as usize; } - c + count } } From b40432c94924f1fd7fef7df403348742ee17af4d Mon Sep 17 00:00:00 2001 From: Andre Bogus Date: Wed, 18 Jan 2017 13:55:47 +0100 Subject: [PATCH 006/137] add test case for filter+count --- src/libcoretest/iter.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/libcoretest/iter.rs b/src/libcoretest/iter.rs index 99d312930533f..05a674e05d5be 100644 --- a/src/libcoretest/iter.rs +++ b/src/libcoretest/iter.rs @@ -191,6 +191,12 @@ fn test_iterator_enumerate_count() { assert_eq!(xs.iter().count(), 6); } +#[test] +fn test_iterator_filter_count() { + let xs = [0, 1, 2, 3, 4, 5, 6, 7, 8]; + assert_eq!(xs.iter().filter(|x| x % 2 == 0).count(), 5); +} + #[test] fn test_iterator_peekable() { let xs = vec![0, 1, 2, 3, 4, 5]; From c2eab73788a066384f3d1facca1ca7b9fc214962 Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Wed, 21 Dec 2016 21:42:07 +0200 Subject: [PATCH 007/137] Expand documentation of process::exit and exec Show a conventional way to use process::exit when destructors are considered important and also mention that the same caveats wrt destructors apply to exec as well. --- src/libstd/process.rs | 21 +++++++++++++++++++-- src/libstd/sys/unix/ext/process.rs | 10 ++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/libstd/process.rs b/src/libstd/process.rs index aa76b79253582..011d4d81b8912 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -924,10 +924,27 @@ impl Child { /// /// # Examples /// +/// Due to this function’s behavior regarding destructors, a conventional way +/// to use the function is to extract the actual computation to another +/// function and compute the exit code from its return value: +/// /// ``` -/// use std::process; +/// use std::io::{self, Write}; +/// +/// fn run_app() -> Result<(), ()> { +/// // Application logic here +/// Ok(()) +/// } /// -/// process::exit(0); +/// fn main() { +/// ::std::process::exit(match run_app() { +/// Ok(_) => 0, +/// Err(err) => { +/// writeln!(io::stderr(), "error: {:?}", err).unwrap(); +/// 1 +/// } +/// }); +/// } /// ``` /// /// Due to [platform-specific behavior], the exit code for this example will be diff --git a/src/libstd/sys/unix/ext/process.rs b/src/libstd/sys/unix/ext/process.rs index 585dcbb9a34a1..2961c4ec58245 100644 --- a/src/libstd/sys/unix/ext/process.rs +++ b/src/libstd/sys/unix/ext/process.rs @@ -67,10 +67,20 @@ pub trait CommandExt { /// an error indicating why the exec (or another part of the setup of the /// `Command`) failed. /// + /// `exec` not returning has the same implications as calling + /// [`process::exit`] – no destructors on the current stack or any other + /// thread’s stack will be run. Therefore, it is recommended to only call + /// `exec` at a point where it is fine to not run any destructors. Note, + /// that the `execvp` syscall independently guarantees that all memory is + /// freed and all file descriptors with the `CLOEXEC` option (set by default + /// on all file descriptors opened by the standard library) are closed. + /// /// This function, unlike `spawn`, will **not** `fork` the process to create /// a new child. Like spawn, however, the default behavior for the stdio /// descriptors will be to inherited from the current process. /// + /// [`process::exit`]: ../../../process/fn.exit.html + /// /// # Notes /// /// The process may be in a "broken state" if this function returns in From 2bafbba655888c288e43ce107cc4bfdf6e758ca3 Mon Sep 17 00:00:00 2001 From: Sergey Pepyakin Date: Thu, 19 Jan 2017 22:31:57 +0300 Subject: [PATCH 008/137] tell emcc stip exception handling if panic rt used --- src/librustc_back/target/asmjs_unknown_emscripten.rs | 1 + src/librustc_back/target/mod.rs | 5 +++++ src/librustc_back/target/wasm32_unknown_emscripten.rs | 1 + src/librustc_trans/back/link.rs | 6 ++++++ 4 files changed, 13 insertions(+) diff --git a/src/librustc_back/target/asmjs_unknown_emscripten.rs b/src/librustc_back/target/asmjs_unknown_emscripten.rs index 2dbaeaf26e970..4d38b0d170596 100644 --- a/src/librustc_back/target/asmjs_unknown_emscripten.rs +++ b/src/librustc_back/target/asmjs_unknown_emscripten.rs @@ -22,6 +22,7 @@ pub fn target() -> Result { linker_is_gnu: true, allow_asm: false, obj_is_bitcode: true, + is_like_emscripten: true, max_atomic_width: Some(32), post_link_args: vec!["-s".to_string(), "ERROR_ON_UNDEFINED_SYMBOLS=1".to_string()], target_family: Some("unix".to_string()), diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs index 5afa85d155279..9c30057d4189c 100644 --- a/src/librustc_back/target/mod.rs +++ b/src/librustc_back/target/mod.rs @@ -330,6 +330,10 @@ pub struct TargetOptions { /// Whether the target toolchain is like Android's. Only useful for compiling against Android. /// Defaults to false. pub is_like_android: bool, + /// Whether the target toolchain is like Emscripten's. Only useful for compiling with + /// Emscripten toolchain. + /// Defaults to false. + pub is_like_emscripten: bool, /// Whether the linker support GNU-like arguments such as -O. Defaults to false. pub linker_is_gnu: bool, /// The MinGW toolchain has a known issue that prevents it from correctly @@ -428,6 +432,7 @@ impl Default for TargetOptions { is_like_solaris: false, is_like_windows: false, is_like_android: false, + is_like_emscripten: false, is_like_msvc: false, linker_is_gnu: false, allows_weak_linkage: true, diff --git a/src/librustc_back/target/wasm32_unknown_emscripten.rs b/src/librustc_back/target/wasm32_unknown_emscripten.rs index a06980767fd75..b1967fa8f37a7 100644 --- a/src/librustc_back/target/wasm32_unknown_emscripten.rs +++ b/src/librustc_back/target/wasm32_unknown_emscripten.rs @@ -24,6 +24,7 @@ pub fn target() -> Result { linker_is_gnu: true, allow_asm: false, obj_is_bitcode: true, + is_like_emscripten: true, max_atomic_width: Some(32), post_link_args: vec!["-s".to_string(), "BINARYEN=1".to_string(), "-s".to_string(), "ERROR_ON_UNDEFINED_SYMBOLS=1".to_string()], diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index defbb44448a9f..2da042da8aa50 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -29,6 +29,7 @@ use rustc::dep_graph::DepNode; use rustc::hir::def_id::CrateNum; use rustc::hir::svh::Svh; use rustc_back::tempdir::TempDir; +use rustc_back::PanicStrategy; use rustc_incremental::IncrementalHashesMap; use std::ascii; @@ -712,6 +713,11 @@ fn link_natively(sess: &Session, cmd.arg(root.join(obj)); } + if sess.target.target.options.is_like_emscripten && + sess.panic_strategy() == PanicStrategy::Abort { + cmd.arg("-s DISABLE_EXCEPTION_CATCHING=1"); + } + { let mut linker = trans.linker_info.to_linker(&mut cmd, &sess); link_args(&mut *linker, sess, crate_type, tmpdir, From 91f8144906137335c3683b99d9c5c4ccaaebcde6 Mon Sep 17 00:00:00 2001 From: Vadim Chugunov Date: Tue, 13 Dec 2016 09:50:30 -0800 Subject: [PATCH 009/137] Implement the "static-nobundle" library kind (RFC 1717). These are static libraries that are not bundled (as the name implies) into rlibs and staticlibs that rustc generates, and must be present when the final binary artifact is being linked. --- src/librustc/middle/cstore.rs | 3 ++- src/librustc/session/config.rs | 1 + src/librustc_metadata/creader.rs | 1 + src/librustc_metadata/cstore.rs | 2 +- src/librustc_trans/back/link.rs | 4 ++++ src/test/run-make/static-nobundle/Makefile | 13 +++++++++++++ src/test/run-make/static-nobundle/bar.rs | 22 ++++++++++++++++++++++ src/test/run-make/static-nobundle/foo.c | 11 +++++++++++ src/test/run-make/static-nobundle/main.rs | 16 ++++++++++++++++ 9 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 src/test/run-make/static-nobundle/Makefile create mode 100644 src/test/run-make/static-nobundle/bar.rs create mode 100644 src/test/run-make/static-nobundle/foo.c create mode 100644 src/test/run-make/static-nobundle/main.rs diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 496a3d4a49847..e674b6ea8363e 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -46,7 +46,7 @@ use rustc_back::target::Target; use hir; use rustc_back::PanicStrategy; -pub use self::NativeLibraryKind::{NativeStatic, NativeFramework, NativeUnknown}; +pub use self::NativeLibraryKind::*; // lonely orphan structs and enums looking for a better home @@ -122,6 +122,7 @@ pub enum LinkagePreference { #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] pub enum NativeLibraryKind { NativeStatic, // native static library (.a archive) + NativeStaticNobundle, // native static library, which doesn't get bundled into .rlibs NativeFramework, // OSX-specific NativeUnknown, // default way to specify a dynamic library } diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 104c851e057e6..ef68b2f76b07f 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1473,6 +1473,7 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches) (Some(name), "dylib") => (name, cstore::NativeUnknown), (Some(name), "framework") => (name, cstore::NativeFramework), (Some(name), "static") => (name, cstore::NativeStatic), + (Some(name), "static-nobundle") => (name, cstore::NativeStaticNobundle), (_, s) => { early_error(error_format, &format!("unknown library kind `{}`, expected \ one of dylib, framework, or static", diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 8f7b9c24cbf8a..d9c64d3e7b343 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -917,6 +917,7 @@ impl<'a> CrateLoader<'a> { }).and_then(|a| a.value_str()).map(Symbol::as_str); let kind = match kind.as_ref().map(|s| &s[..]) { Some("static") => cstore::NativeStatic, + Some("static-nobundle") => cstore::NativeStaticNobundle, Some("dylib") => cstore::NativeUnknown, Some("framework") => cstore::NativeFramework, Some(k) => { diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs index 761041ad7198a..beba5faf3d034 100644 --- a/src/librustc_metadata/cstore.rs +++ b/src/librustc_metadata/cstore.rs @@ -32,7 +32,7 @@ use syntax::symbol::Symbol; use syntax_pos; pub use rustc::middle::cstore::{NativeLibrary, NativeLibraryKind, LinkagePreference}; -pub use rustc::middle::cstore::{NativeStatic, NativeFramework, NativeUnknown}; +pub use rustc::middle::cstore::NativeLibraryKind::*; pub use rustc::middle::cstore::{CrateSource, LinkMeta, LibSource}; // A map from external crate numbers (as decoded from some crate file) to diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index defbb44448a9f..aa42364f951c7 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -476,6 +476,7 @@ fn link_rlib<'a>(sess: &'a Session, for lib in sess.cstore.used_libraries() { match lib.kind { NativeLibraryKind::NativeStatic => {} + NativeLibraryKind::NativeStaticNobundle | NativeLibraryKind::NativeFramework | NativeLibraryKind::NativeUnknown => continue, } @@ -674,6 +675,7 @@ fn link_staticlib(sess: &Session, objects: &[PathBuf], out_filename: &Path, for lib in all_native_libs.iter().filter(|l| relevant_lib(sess, l)) { let name = match lib.kind { + NativeLibraryKind::NativeStaticNobundle | NativeLibraryKind::NativeUnknown => "library", NativeLibraryKind::NativeFramework => "framework", // These are included, no need to print them @@ -985,6 +987,7 @@ fn add_local_native_libraries(cmd: &mut Linker, sess: &Session) { match lib.kind { NativeLibraryKind::NativeUnknown => cmd.link_dylib(&lib.name.as_str()), NativeLibraryKind::NativeFramework => cmd.link_framework(&lib.name.as_str()), + NativeLibraryKind::NativeStaticNobundle => cmd.link_staticlib(&lib.name.as_str()), NativeLibraryKind::NativeStatic => bug!(), } } @@ -1229,6 +1232,7 @@ fn add_upstream_native_libraries(cmd: &mut Linker, sess: &Session) { match lib.kind { NativeLibraryKind::NativeUnknown => cmd.link_dylib(&lib.name.as_str()), NativeLibraryKind::NativeFramework => cmd.link_framework(&lib.name.as_str()), + NativeLibraryKind::NativeStaticNobundle => cmd.link_staticlib(&lib.name.as_str()), // ignore statically included native libraries here as we've // already included them when we included the rust library diff --git a/src/test/run-make/static-nobundle/Makefile b/src/test/run-make/static-nobundle/Makefile new file mode 100644 index 0000000000000..b184d54ff9c6f --- /dev/null +++ b/src/test/run-make/static-nobundle/Makefile @@ -0,0 +1,13 @@ +-include ../tools.mk + +all: $(call NATIVE_STATICLIB,foo) + $(RUSTC) bar.rs + + # Check that libbar.rlib does not contain the definition of `func` + nm $(TMPDIR)/libbar.rlib | (! grep "T _*func") + nm $(TMPDIR)/libbar.rlib | grep "U _*func" + + # Check that foo gets passed to the linker (as either `-l foo` or `foo.lib`) + $(RUSTC) main.rs -Z print-link-args | grep -e "-l[\" ]*foo" -e "foo.lib" + + $(call RUN,main) diff --git a/src/test/run-make/static-nobundle/bar.rs b/src/test/run-make/static-nobundle/bar.rs new file mode 100644 index 0000000000000..e14b5a669f440 --- /dev/null +++ b/src/test/run-make/static-nobundle/bar.rs @@ -0,0 +1,22 @@ +// Copyright 2015 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. + +#![crate_type = "rlib"] + +#[link(name = "foo", kind = "static-nobundle")] +extern { + pub fn func(); +} + +pub fn wrapped_func() { + unsafe { + func(); + } +} diff --git a/src/test/run-make/static-nobundle/foo.c b/src/test/run-make/static-nobundle/foo.c new file mode 100644 index 0000000000000..5ccf713f79c61 --- /dev/null +++ b/src/test/run-make/static-nobundle/foo.c @@ -0,0 +1,11 @@ +// Copyright 2015 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. + +void func() {} diff --git a/src/test/run-make/static-nobundle/main.rs b/src/test/run-make/static-nobundle/main.rs new file mode 100644 index 0000000000000..7aa730f1dd26b --- /dev/null +++ b/src/test/run-make/static-nobundle/main.rs @@ -0,0 +1,16 @@ +// Copyright 2015 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. + +extern crate bar; + +fn main() { + unsafe { bar::func(); } + bar::wrapped_func(); +} From 3ae2174fc5bfef0b2220a44d5e371220f3dca532 Mon Sep 17 00:00:00 2001 From: Vadim Chugunov Date: Thu, 15 Dec 2016 23:46:21 -0800 Subject: [PATCH 010/137] Feature gate --- src/librustc/session/config.rs | 4 ++++ src/librustc_metadata/creader.rs | 7 +++++++ src/libsyntax/feature_gate.rs | 3 +++ .../compile-fail/feature-gate-static-nobundle.rs | 13 +++++++++++++ src/test/run-make/static-nobundle/bar.rs | 1 + 5 files changed, 28 insertions(+) create mode 100644 src/test/compile-fail/feature-gate-static-nobundle.rs diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index ef68b2f76b07f..550f6eb12a7bd 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1480,6 +1480,10 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches) s)); } }; + if kind == cstore::NativeStaticNobundle && !nightly_options::is_nightly_build() { + early_error(error_format, &format!("the library kind 'static-nobundle' is only \ + accepted on the nightly compiler")); + } let mut name_parts = name.splitn(2, ':'); let name = name_parts.next().unwrap(); let new_name = name_parts.next(); diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index d9c64d3e7b343..87ba2edbfda7d 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -111,6 +111,13 @@ fn register_native_lib(sess: &Session, GateIssue::Language, "is feature gated"); } + if lib.kind == cstore::NativeStaticNobundle && !sess.features.borrow().static_nobundle { + feature_gate::emit_feature_err(&sess.parse_sess, + "static_nobundle", + span.unwrap(), + GateIssue::Language, + "kind=\"static-nobundle\" is feature gated"); + } cstore.add_used_library(lib); } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 924f51fd95251..cf2905e913108 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -322,6 +322,9 @@ declare_features! ( // Allows attributes on struct literal fields. (active, struct_field_attributes, "1.16.0", Some(38814)), + // Allows #[link(kind="static-nobundle"...] + (active, static_nobundle, "1.16.0", Some(37403)), + // `extern "msp430-interrupt" fn()` (active, abi_msp430_interrupt, "1.16.0", Some(38487)), ); diff --git a/src/test/compile-fail/feature-gate-static-nobundle.rs b/src/test/compile-fail/feature-gate-static-nobundle.rs new file mode 100644 index 0000000000000..bc0025c7c9581 --- /dev/null +++ b/src/test/compile-fail/feature-gate-static-nobundle.rs @@ -0,0 +1,13 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[link(name="foo", kind="static-nobundle")] +//~^ ERROR: kind="static-nobundle" is feature gated +extern {} diff --git a/src/test/run-make/static-nobundle/bar.rs b/src/test/run-make/static-nobundle/bar.rs index e14b5a669f440..c5d6237c9d594 100644 --- a/src/test/run-make/static-nobundle/bar.rs +++ b/src/test/run-make/static-nobundle/bar.rs @@ -9,6 +9,7 @@ // except according to those terms. #![crate_type = "rlib"] +#![feature(static_nobundle)] #[link(name = "foo", kind = "static-nobundle")] extern { From 65147b673bcf8cc740d40209321f0716864a0ab3 Mon Sep 17 00:00:00 2001 From: Andrew Paseltiner Date: Thu, 19 Jan 2017 18:09:23 -0500 Subject: [PATCH 011/137] Update nomicon to describe `#[may_dangle]` --- src/doc/nomicon/dropck.md | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/src/doc/nomicon/dropck.md b/src/doc/nomicon/dropck.md index f54933827b330..6114006cbb341 100644 --- a/src/doc/nomicon/dropck.md +++ b/src/doc/nomicon/dropck.md @@ -199,24 +199,42 @@ assert (unsafely) that a generic type's destructor is *guaranteed* to not access any expired data, even if its type gives it the capability to do so. -That attribute is called `unsafe_destructor_blind_to_params`. +That attribute is called `may_dangle` and was introduced in [RFC 1327] +(https://github.com/rust-lang/rfcs/blob/master/text/1327-dropck-param-eyepatch.md). To deploy it on the Inspector example from above, we would write: ```rust,ignore struct Inspector<'a>(&'a u8, &'static str); -impl<'a> Drop for Inspector<'a> { - #[unsafe_destructor_blind_to_params] +unsafe impl<#[may_dangle] 'a> Drop for Inspector<'a> { fn drop(&mut self) { println!("Inspector(_, {}) knows when *not* to inspect.", self.1); } } ``` -This attribute has the word `unsafe` in it because the compiler is not -checking the implicit assertion that no potentially expired data +Use of this attribute requires the `Drop` impl to be marked `unsafe` because the +compiler is not checking the implicit assertion that no potentially expired data (e.g. `self.0` above) is accessed. +The attribute can be applied to any number of lifetime and type parameters. In +the following example, we assert that we access no data behind a reference of +lifetime `'b` and that the only uses of `T` will be moves or drops, but omit +the attribute from `'a` and `U`, because we do access data with that lifetime +and that type: + +```rust,ignore +use std::fmt::Display; + +struct Inspector<'a, 'b, T, U: Display>(&'a u8, &'b u8, T, U); + +unsafe impl<'a, #[may_dangle] 'b, #[may_dangle] T, U: Display> Drop for Inspector<'a, 'b, T, U> { + fn drop(&mut self) { + println!("Inspector({}, _, _, {})", self.0, self.3); + } +} +``` + It is sometimes obvious that no such access can occur, like the case above. However, when dealing with a generic type parameter, such access can occur indirectly. Examples of such indirect access are: @@ -263,7 +281,7 @@ some other method invoked by the destructor, rather than being written directly within it. In all of the above cases where the `&'a u8` is accessed in the -destructor, adding the `#[unsafe_destructor_blind_to_params]` +destructor, adding the `#[may_dangle]` attribute makes the type vulnerable to misuse that the borrower checker will not catch, inviting havoc. It is better to avoid adding the attribute. From 62c088c047f4a510bb2f65b550decb5bebff0f7c Mon Sep 17 00:00:00 2001 From: Sergey Pepyakin Date: Fri, 20 Jan 2017 21:18:17 +0300 Subject: [PATCH 012/137] Separate emscripten args --- src/librustc_trans/back/link.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index 2da042da8aa50..f34c19a8380f4 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -715,7 +715,7 @@ fn link_natively(sess: &Session, if sess.target.target.options.is_like_emscripten && sess.panic_strategy() == PanicStrategy::Abort { - cmd.arg("-s DISABLE_EXCEPTION_CATCHING=1"); + cmd.args(&["-s", "DISABLE_EXCEPTION_CATCHING=1"]); } { From 24cb5b7bae251b4d7d0f20e1a76728eb087d53d4 Mon Sep 17 00:00:00 2001 From: Sergey Pepyakin Date: Fri, 20 Jan 2017 21:18:51 +0300 Subject: [PATCH 013/137] Json encoding/decoding for is_like_emscripten --- src/librustc_back/target/mod.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs index 9c30057d4189c..d2b76b1d55a98 100644 --- a/src/librustc_back/target/mod.rs +++ b/src/librustc_back/target/mod.rs @@ -608,6 +608,7 @@ impl Target { key!(is_like_solaris, bool); key!(is_like_windows, bool); key!(is_like_msvc, bool); + key!(is_like_emscripten, bool); key!(is_like_android, bool); key!(linker_is_gnu, bool); key!(allows_weak_linkage, bool); @@ -772,6 +773,7 @@ impl ToJson for Target { target_option_val!(is_like_solaris); target_option_val!(is_like_windows); target_option_val!(is_like_msvc); + target_option_val!(is_like_emscripten); target_option_val!(is_like_android); target_option_val!(linker_is_gnu); target_option_val!(allows_weak_linkage); From bfabe817de438c63777aa8c01d6998b5158f7fdb Mon Sep 17 00:00:00 2001 From: Andre Bogus Date: Tue, 24 Jan 2017 09:46:01 +0100 Subject: [PATCH 014/137] add explanation, fix test --- src/libcore/iter/mod.rs | 11 +++++++++++ src/libcoretest/iter.rs | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index ea98265ef8de0..d9b8c5ea589fd 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -1100,6 +1100,17 @@ impl Iterator for Filter where P: FnMut(&I::Item) -> bool (0, upper) // can't know a lower bound, due to the predicate } + // this special case allows the compiler to make `.filter(_).count()` + // branchless. Barring perfect branch prediction (which is unattainable in + // the general case), this will be much faster in >90% of cases (containing + // virtually all real workloads) and only a tiny bit slower in the rest. + // + // Having this specialization thus allows us to write `.filter(p).count()` + // where we would otherwise write `.map(|x| p(x) as usize).sum()`, which is + // less readable and also less backwards-compatible to Rust before 1.10. + // + // Using the branchless version will also simplify the LLVM byte code, thus + // leaving more budget for LLVM optimizations. #[inline] fn count(mut self) -> usize { let mut count = 0; diff --git a/src/libcoretest/iter.rs b/src/libcoretest/iter.rs index 05a674e05d5be..e6d2494f5fda8 100644 --- a/src/libcoretest/iter.rs +++ b/src/libcoretest/iter.rs @@ -194,7 +194,7 @@ fn test_iterator_enumerate_count() { #[test] fn test_iterator_filter_count() { let xs = [0, 1, 2, 3, 4, 5, 6, 7, 8]; - assert_eq!(xs.iter().filter(|x| x % 2 == 0).count(), 5); + assert_eq!(xs.iter().filter(|&&x| x % 2 == 0).count(), 5); } #[test] From b996a7ecec4bb22a28bce3b86f68fe51b4409287 Mon Sep 17 00:00:00 2001 From: Freyskeyd Date: Wed, 4 Jan 2017 16:02:34 +0100 Subject: [PATCH 015/137] Fix doc cfg(test) and tests directory Signed-off-by: Freyskeyd --- src/doc/book/testing.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/doc/book/testing.md b/src/doc/book/testing.md index 96cec7295aa9d..6fefa1c9f1e1c 100644 --- a/src/doc/book/testing.md +++ b/src/doc/book/testing.md @@ -499,6 +499,10 @@ be imported in every test with `mod common;` That's all there is to the `tests` directory. The `tests` module isn't needed here, since the whole thing is focused on tests. +Note, when building integration tests, cargo will not pass the `test` attribute +to the compiler. It means that all parts in `cfg(test)` won't be included in +the build used in your integration tests. + Let's finally check out that third section: documentation tests. # Documentation tests From c6cfa3c4899e46addfe6d04d6aaa2d247056748f Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Tue, 24 Jan 2017 22:44:33 -0500 Subject: [PATCH 016/137] Extend Cell to work with non-Copy types Part of #39264 --- src/libcore/cell.rs | 130 +++++++++++++++++++++++++++++----------- src/libcoretest/cell.rs | 31 ++++++++++ src/libcoretest/lib.rs | 1 + 3 files changed, 126 insertions(+), 36 deletions(-) diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index c3f862e7c5418..cafa19afcb648 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -176,6 +176,7 @@ use cmp::Ordering; use fmt::{self, Debug, Display}; use marker::Unsize; +use mem; use ops::{Deref, DerefMut, CoerceUnsized}; /// A mutable memory location that admits only `Copy` data. @@ -187,23 +188,6 @@ pub struct Cell { } impl Cell { - /// Creates a new `Cell` containing the given value. - /// - /// # Examples - /// - /// ``` - /// use std::cell::Cell; - /// - /// let c = Cell::new(5); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub const fn new(value: T) -> Cell { - Cell { - value: UnsafeCell::new(value), - } - } - /// Returns a copy of the contained value. /// /// # Examples @@ -221,25 +205,6 @@ impl Cell { unsafe{ *self.value.get() } } - /// Sets the contained value. - /// - /// # Examples - /// - /// ``` - /// use std::cell::Cell; - /// - /// let c = Cell::new(5); - /// - /// c.set(10); - /// ``` - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn set(&self, value: T) { - unsafe { - *self.value.get() = value; - } - } - /// Returns a reference to the underlying `UnsafeCell`. /// /// # Examples @@ -378,6 +343,99 @@ impl From for Cell { } } +#[unstable(feature = "move_cell", issue = "39264")] +impl Cell { + /// Creates a new `Cell` containing the given value. + /// + /// # Examples + /// + /// ``` + /// use std::cell::Cell; + /// + /// let c = Cell::new(5); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub const fn new(value: T) -> Cell { + Cell { + value: UnsafeCell::new(value), + } + } + + /// Sets the contained value. + /// + /// # Examples + /// + /// ``` + /// use std::cell::Cell; + /// + /// let c = Cell::new(5); + /// + /// c.set(10); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn set(&self, val: T) { + let old = self.replace(val); + drop(old); + } + + /// Replaces the contained value. + /// + /// # Examples + /// + /// ``` + /// #![feature(move_cell)] + /// use std::cell::Cell; + /// + /// let c = Cell::new(5); + /// let old = c.replace(10); + /// + /// assert_eq!(5, old); + /// ``` + pub fn replace(&self, val: T) -> T { + mem::replace(unsafe { &mut *self.value.get() }, val) + } + + /// Unwraps the value. + /// + /// # Examples + /// + /// ``` + /// #![feature(move_cell)] + /// use std::cell::Cell; + /// + /// let c = Cell::new(5); + /// let five = c.into_inner(); + /// + /// assert_eq!(five, 5); + /// ``` + pub fn into_inner(self) -> T { + unsafe { self.value.into_inner() } + } +} + +#[unstable(feature = "move_cell", issue = "39264")] +impl Cell { + /// Takes the value of the cell, leaving `Default::default()` in its place. + /// + /// # Examples + /// + /// ``` + /// #![feature(move_cell)] + /// use std::cell::Cell; + /// + /// let c = Cell::new(5); + /// let five = c.take(); + /// + /// assert_eq!(five, 5); + /// assert_eq!(c.into_inner(), 0); + /// ``` + pub fn take(&self) -> T { + self.replace(Default::default()) + } +} + #[unstable(feature = "coerce_unsized", issue = "27732")] impl, U> CoerceUnsized> for Cell {} diff --git a/src/libcoretest/cell.rs b/src/libcoretest/cell.rs index 724a312ea79e0..8585f2f087113 100644 --- a/src/libcoretest/cell.rs +++ b/src/libcoretest/cell.rs @@ -209,6 +209,37 @@ fn cell_default() { assert_eq!(0, cell.get()); } +#[test] +fn cell_set() { + let cell = Cell::new(10); + cell.set(20); + assert_eq!(20, cell.get()); + + let cell = Cell::new("Hello".to_owned()); + cell.set("World".to_owned()); + assert_eq!("World".to_owned(), cell.into_inner()); +} + +#[test] +fn cell_replace() { + let cell = Cell::new(10); + assert_eq!(10, cell.replace(20)); + assert_eq!(20, cell.get()); + + let cell = Cell::new("Hello".to_owned()); + assert_eq!("Hello".to_owned(), cell.replace("World".to_owned())); + assert_eq!("World".to_owned(), cell.into_inner()); +} + +#[test] +fn cell_into_inner() { + let cell = Cell::new(10); + assert_eq!(10, cell.into_inner()); + + let cell = Cell::new("Hello world".to_owned()); + assert_eq!("Hello world".to_owned(), cell.into_inner()); +} + #[test] fn refcell_default() { let cell: RefCell = Default::default(); diff --git a/src/libcoretest/lib.rs b/src/libcoretest/lib.rs index ee47b510ee074..ea88d45630c46 100644 --- a/src/libcoretest/lib.rs +++ b/src/libcoretest/lib.rs @@ -34,6 +34,7 @@ #![feature(ordering_chaining)] #![feature(result_unwrap_or_default)] #![feature(ptr_unaligned)] +#![feature(move_cell)] extern crate core; extern crate test; From bb34856e9d0e480758bdc3afaad60654435d12b3 Mon Sep 17 00:00:00 2001 From: Michael Gattozzi Date: Thu, 26 Jan 2017 01:35:00 -0500 Subject: [PATCH 017/137] Fix full path being output with `rustdoc -h` rustdoc would output the full path to the binary when calling it with the `-h` or `--help` flags. This is undesired behavior. It has been replaced with a hardcoded string `rustdoc` to fix the issue. Fixes #39310 --- src/librustdoc/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 503ef4c3183d2..84f69cd35045c 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -193,7 +193,7 @@ pub fn main_args(args: &[String]) -> isize { nightly_options::check_nightly_options(&matches, &opts()); if matches.opt_present("h") || matches.opt_present("help") { - usage(&args[0]); + usage("rustdoc"); return 0; } else if matches.opt_present("version") { rustc_driver::version("rustdoc", &matches); From 1363cdaec9984269fc421cbc910f1f520b669f21 Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Thu, 26 Jan 2017 17:51:10 +0200 Subject: [PATCH 018/137] Remove unnecessary LLVMRustPersonalityFn binding LLVM Core C bindings provide this function for all the versions back to what we support (3.7), and helps to avoid this unnecessary builder->function transition every time. Also a negative diff. --- src/librustc_llvm/ffi.rs | 2 +- src/librustc_trans/builder.rs | 2 +- src/librustc_trans/mir/mod.rs | 4 +++- src/rustllvm/RustWrapper.cpp | 8 -------- 4 files changed, 5 insertions(+), 11 deletions(-) diff --git a/src/librustc_llvm/ffi.rs b/src/librustc_llvm/ffi.rs index caa27404086b9..58b2017ceb66e 100644 --- a/src/librustc_llvm/ffi.rs +++ b/src/librustc_llvm/ffi.rs @@ -804,7 +804,7 @@ extern "C" { Name: *const c_char) -> ValueRef; pub fn LLVMRustAddHandler(CatchSwitch: ValueRef, Handler: BasicBlockRef); - pub fn LLVMRustSetPersonalityFn(B: BuilderRef, Pers: ValueRef); + pub fn LLVMSetPersonalityFn(Func: ValueRef, Pers: ValueRef); // Add a case to the switch instruction pub fn LLVMAddCase(Switch: ValueRef, OnVal: ValueRef, Dest: BasicBlockRef); diff --git a/src/librustc_trans/builder.rs b/src/librustc_trans/builder.rs index cf7f3e9501d1a..c113716ca5c74 100644 --- a/src/librustc_trans/builder.rs +++ b/src/librustc_trans/builder.rs @@ -1107,7 +1107,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { pub fn set_personality_fn(&self, personality: ValueRef) { unsafe { - llvm::LLVMRustSetPersonalityFn(self.llbuilder, personality); + llvm::LLVMSetPersonalityFn(self.llfn(), personality); } } diff --git a/src/librustc_trans/mir/mod.rs b/src/librustc_trans/mir/mod.rs index eedd7956805b6..30c138310da9c 100644 --- a/src/librustc_trans/mir/mod.rs +++ b/src/librustc_trans/mir/mod.rs @@ -319,7 +319,9 @@ pub fn trans_mir<'a, 'tcx: 'a>( mircx.cleanup_kinds.iter_enumerated().map(|(bb, cleanup_kind)| { if let CleanupKind::Funclet = *cleanup_kind { let bcx = mircx.get_builder(bb); - bcx.set_personality_fn(mircx.ccx.eh_personality()); + unsafe { + llvm::LLVMSetPersonalityFn(mircx.llfn, mircx.ccx.eh_personality()); + } if base::wants_msvc_seh(ccx.sess()) { return Some(Funclet::new(bcx.cleanup_pad(None, &[]))); } diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index bd0ff9e8d83cc..34ee7d552f346 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -1082,14 +1082,6 @@ extern "C" void LLVMRustAddHandler(LLVMValueRef CatchSwitchRef, #endif } -extern "C" void LLVMRustSetPersonalityFn(LLVMBuilderRef B, - LLVMValueRef Personality) { -#if LLVM_VERSION_GE(3, 8) - unwrap(B)->GetInsertBlock()->getParent()->setPersonalityFn( - cast(unwrap(Personality))); -#endif -} - #if LLVM_VERSION_GE(3, 8) extern "C" OperandBundleDef *LLVMRustBuildOperandBundleDef(const char *Name, LLVMValueRef *Inputs, From afac3ecacc92ccf7a3f693702c9582f930fb91f3 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Thu, 26 Jan 2017 21:28:22 -0500 Subject: [PATCH 019/137] Move stability attributes per feedback --- src/libcore/cell.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index cafa19afcb648..f889ff9a6ae2f 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -343,7 +343,6 @@ impl From for Cell { } } -#[unstable(feature = "move_cell", issue = "39264")] impl Cell { /// Creates a new `Cell` containing the given value. /// @@ -393,6 +392,7 @@ impl Cell { /// /// assert_eq!(5, old); /// ``` + #[unstable(feature = "move_cell", issue = "39264")] pub fn replace(&self, val: T) -> T { mem::replace(unsafe { &mut *self.value.get() }, val) } @@ -410,12 +410,12 @@ impl Cell { /// /// assert_eq!(five, 5); /// ``` + #[unstable(feature = "move_cell", issue = "39264")] pub fn into_inner(self) -> T { unsafe { self.value.into_inner() } } } -#[unstable(feature = "move_cell", issue = "39264")] impl Cell { /// Takes the value of the cell, leaving `Default::default()` in its place. /// @@ -431,6 +431,7 @@ impl Cell { /// assert_eq!(five, 5); /// assert_eq!(c.into_inner(), 0); /// ``` + #[unstable(feature = "move_cell", issue = "39264")] pub fn take(&self) -> T { self.replace(Default::default()) } From c31d5b504144c4c542c3042b850cfc3b1066aa38 Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Fri, 27 Jan 2017 19:45:18 +0100 Subject: [PATCH 020/137] Use less syscalls in `anon_pipe()` Save a `ENOSYS` failure from `pipe2` and don't try again. Use `cvt` instead of `cvt_r` for `pipe2` - `EINTR` is not an error `pipe2` can return. --- src/libstd/sys/unix/pipe.rs | 38 ++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/libstd/sys/unix/pipe.rs b/src/libstd/sys/unix/pipe.rs index a8ed415b7f47f..a5d60c257ed63 100644 --- a/src/libstd/sys/unix/pipe.rs +++ b/src/libstd/sys/unix/pipe.rs @@ -13,7 +13,8 @@ use io; use libc::{self, c_int}; use mem; use ptr; -use sys::cvt_r; +use sync::atomic::{AtomicBool, Ordering}; +use sys::{cvt, cvt_r}; use sys::fd::FileDesc; //////////////////////////////////////////////////////////////////////////////// @@ -29,34 +30,33 @@ pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> { // CLOEXEC flag is to use the `pipe2` syscall on Linux. This was added in // 2.6.27, however, and because we support 2.6.18 we must detect this // support dynamically. - if cfg!(target_os = "linux") { + static TRY_PIPE2: AtomicBool = AtomicBool::new(cfg!(target_os = "linux")); + if TRY_PIPE2.load(Ordering::Relaxed) { weak! { fn pipe2(*mut c_int, c_int) -> c_int } if let Some(pipe) = pipe2.get() { - match cvt_r(|| unsafe { pipe(fds.as_mut_ptr(), libc::O_CLOEXEC) }) { - Ok(_) => { + match cvt(unsafe { pipe(fds.as_mut_ptr(), libc::O_CLOEXEC) }) { + Err(ref e) if e.raw_os_error() == Some(libc::ENOSYS) => { + TRY_PIPE2.store(false, Ordering::Relaxed); + // Fall through + }, + res => { + res?; return Ok((AnonPipe(FileDesc::new(fds[0])), - AnonPipe(FileDesc::new(fds[1])))) + AnonPipe(FileDesc::new(fds[1])))); } - Err(ref e) if e.raw_os_error() == Some(libc::ENOSYS) => {} - Err(e) => return Err(e), } } } - if unsafe { libc::pipe(fds.as_mut_ptr()) == 0 } { - let fd0 = FileDesc::new(fds[0]); - let fd1 = FileDesc::new(fds[1]); - Ok((AnonPipe::from_fd(fd0)?, AnonPipe::from_fd(fd1)?)) - } else { - Err(io::Error::last_os_error()) - } + cvt(unsafe { libc::pipe(fds.as_mut_ptr()) })?; + + let fd0 = FileDesc::new(fds[0]); + let fd1 = FileDesc::new(fds[1]); + fd0.set_cloexec()?; + fd1.set_cloexec()?; + Ok((AnonPipe(fd0), AnonPipe(fd1))) } impl AnonPipe { - pub fn from_fd(fd: FileDesc) -> io::Result { - fd.set_cloexec()?; - Ok(AnonPipe(fd)) - } - pub fn read(&self, buf: &mut [u8]) -> io::Result { self.0.read(buf) } From e74b55b9da5a163e02bbcbf97e7ea24d48742943 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Krasnoborski?= Date: Fri, 27 Jan 2017 04:51:24 +0100 Subject: [PATCH 021/137] use `String::with_capacity` in `format!` --- src/libcollections/fmt.rs | 3 ++- src/libcore/fmt/mod.rs | 28 ++++++++++++++++++++++++++++ src/libcoretest/fmt/mod.rs | 8 ++++++++ src/libcoretest/lib.rs | 1 + 4 files changed, 39 insertions(+), 1 deletion(-) diff --git a/src/libcollections/fmt.rs b/src/libcollections/fmt.rs index 883417e9f4ec7..bd74848a01d83 100644 --- a/src/libcollections/fmt.rs +++ b/src/libcollections/fmt.rs @@ -539,7 +539,8 @@ use string; /// [format!]: ../macro.format.html #[stable(feature = "rust1", since = "1.0.0")] pub fn format(args: Arguments) -> string::String { - let mut output = string::String::new(); + let capacity = args.estimated_capacity(); + let mut output = string::String::with_capacity(capacity); let _ = output.write_fmt(args); output } diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 2ba7d6e8bd1ac..ed9c5d3337f04 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -265,6 +265,34 @@ impl<'a> Arguments<'a> { args: args } } + + /// Estimates the length of the formatted text. + /// + /// This is intended to be used for setting initial `String` capacity + /// when using `format!`. Note: this is neither the lower nor upper bound. + #[doc(hidden)] #[inline] + #[unstable(feature = "fmt_internals", reason = "internal to format_args!", + issue = "0")] + pub fn estimated_capacity(&self) -> usize { + // Using wrapping arithmetics in this function, because + // wrong result is highly unlikely and doesn't cause unsafety. + use ::num::Wrapping as W; + + let pieces_length: W = self.pieces.iter() + .map(|x| W(x.len())).sum(); + + // If they are any arguments to format, the string will most likely + // double in size. So we're pre-doubling it here. + let multiplier = if self.args.is_empty() { W(1) } else { W(2) }; + + let capacity = multiplier * pieces_length; + if multiplier == W(2) && (W(1)..W(8)).contains(capacity) { + // Allocations smaller than 8 don't really make sense for String. + 8 + } else { + capacity.0 + } + } } /// This structure represents a safely precompiled version of a format string diff --git a/src/libcoretest/fmt/mod.rs b/src/libcoretest/fmt/mod.rs index ed33596e1c264..71b3a440f7bea 100644 --- a/src/libcoretest/fmt/mod.rs +++ b/src/libcoretest/fmt/mod.rs @@ -28,3 +28,11 @@ fn test_pointer_formats_data_pointer() { assert_eq!(format!("{:p}", s), format!("{:p}", s.as_ptr())); assert_eq!(format!("{:p}", b), format!("{:p}", b.as_ptr())); } + +#[test] +fn test_estimated_capacity() { + assert_eq!(format_args!("{}", "").estimated_capacity(), 0); + assert_eq!(format_args!("Hello").estimated_capacity(), 5); + assert_eq!(format_args!("Hello, {}!", "").estimated_capacity(), 16); + assert_eq!(format_args!("{}, hello!", "World").estimated_capacity(), 16); +} diff --git a/src/libcoretest/lib.rs b/src/libcoretest/lib.rs index ee47b510ee074..fed5b86c369e8 100644 --- a/src/libcoretest/lib.rs +++ b/src/libcoretest/lib.rs @@ -34,6 +34,7 @@ #![feature(ordering_chaining)] #![feature(result_unwrap_or_default)] #![feature(ptr_unaligned)] +#![feature(fmt_internals)] extern crate core; extern crate test; From b081872d5bf19a063fbf7f2f315560a59592308d Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Wed, 28 Dec 2016 12:16:19 -0800 Subject: [PATCH 022/137] Implement `PartialEq<&[A]>` for `VecDeque`. Fixes https://github.com/rust-lang/rust/issues/38625. --- src/libcollections/vec_deque.rs | 110 +++++++++++++++++++--------- src/libcollectionstest/vec_deque.rs | 19 +++++ 2 files changed, 93 insertions(+), 36 deletions(-) diff --git a/src/libcollections/vec_deque.rs b/src/libcollections/vec_deque.rs index 5b1bc3a3ae4f1..5e1adb3d808ce 100644 --- a/src/libcollections/vec_deque.rs +++ b/src/libcollections/vec_deque.rs @@ -469,9 +469,9 @@ impl VecDeque { /// buf.push_back(3); /// buf.push_back(4); /// buf.push_back(5); + /// assert_eq!(buf, [3, 4, 5]); /// buf.swap(0, 2); - /// assert_eq!(buf[0], 5); - /// assert_eq!(buf[2], 3); + /// assert_eq!(buf, [5, 4, 3]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn swap(&mut self, i: usize, j: usize) { @@ -649,9 +649,9 @@ impl VecDeque { /// buf.push_back(5); /// buf.push_back(10); /// buf.push_back(15); + /// assert_eq!(buf, [5, 10, 15]); /// buf.truncate(1); - /// assert_eq!(buf.len(), 1); - /// assert_eq!(Some(&5), buf.get(0)); + /// assert_eq!(buf, [5]); /// ``` #[stable(feature = "deque_extras", since = "1.16.0")] pub fn truncate(&mut self, len: usize) { @@ -826,8 +826,9 @@ impl VecDeque { /// use std::collections::VecDeque; /// /// let mut v: VecDeque<_> = vec![1, 2, 3].into_iter().collect(); - /// assert_eq!(vec![3].into_iter().collect::>(), v.drain(2..).collect()); - /// assert_eq!(vec![1, 2].into_iter().collect::>(), v); + /// let drained = v.drain(2..).collect::>(); + /// assert_eq!(drained, [3]); + /// assert_eq!(v, [1, 2]); /// /// // A full range clears all contents /// v.drain(..); @@ -1179,11 +1180,10 @@ impl VecDeque { /// buf.push_back(1); /// buf.push_back(2); /// buf.push_back(3); + /// assert_eq!(buf, [1, 2, 3]); /// /// assert_eq!(buf.swap_remove_back(0), Some(1)); - /// assert_eq!(buf.len(), 2); - /// assert_eq!(buf[0], 3); - /// assert_eq!(buf[1], 2); + /// assert_eq!(buf, [3, 2]); /// ``` #[stable(feature = "deque_extras_15", since = "1.5.0")] pub fn swap_remove_back(&mut self, index: usize) -> Option { @@ -1215,11 +1215,10 @@ impl VecDeque { /// buf.push_back(1); /// buf.push_back(2); /// buf.push_back(3); + /// assert_eq!(buf, [1, 2, 3]); /// /// assert_eq!(buf.swap_remove_front(2), Some(3)); - /// assert_eq!(buf.len(), 2); - /// assert_eq!(buf[0], 2); - /// assert_eq!(buf[1], 1); + /// assert_eq!(buf, [2, 1]); /// ``` #[stable(feature = "deque_extras_15", since = "1.5.0")] pub fn swap_remove_front(&mut self, index: usize) -> Option { @@ -1250,11 +1249,10 @@ impl VecDeque { /// vec_deque.push_back('a'); /// vec_deque.push_back('b'); /// vec_deque.push_back('c'); + /// assert_eq!(vec_deque, &['a', 'b', 'c']); /// /// vec_deque.insert(1, 'd'); - /// - /// let vec = vec_deque.into_iter().collect::>(); - /// assert_eq!(vec, ['a', 'd', 'b', 'c']); + /// assert_eq!(vec_deque, &['a', 'd', 'b', 'c']); /// ``` #[stable(feature = "deque_extras_15", since = "1.5.0")] pub fn insert(&mut self, index: usize, value: T) { @@ -1478,9 +1476,10 @@ impl VecDeque { /// buf.push_back(1); /// buf.push_back(2); /// buf.push_back(3); + /// assert_eq!(buf, [1, 2, 3]); /// /// assert_eq!(buf.remove(1), Some(2)); - /// assert_eq!(buf.get(1), Some(&3)); + /// assert_eq!(buf, [1, 3]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn remove(&mut self, index: usize) -> Option { @@ -1659,9 +1658,8 @@ impl VecDeque { /// /// let mut buf: VecDeque<_> = vec![1,2,3].into_iter().collect(); /// let buf2 = buf.split_off(1); - /// // buf = [1], buf2 = [2, 3] - /// assert_eq!(buf.len(), 1); - /// assert_eq!(buf2.len(), 2); + /// assert_eq!(buf, [1]); + /// assert_eq!(buf2, [2, 3]); /// ``` #[inline] #[stable(feature = "split_off", since = "1.4.0")] @@ -1718,11 +1716,11 @@ impl VecDeque { /// ``` /// use std::collections::VecDeque; /// - /// let mut buf: VecDeque<_> = vec![1, 2, 3].into_iter().collect(); - /// let mut buf2: VecDeque<_> = vec![4, 5, 6].into_iter().collect(); + /// let mut buf: VecDeque<_> = vec![1, 2].into_iter().collect(); + /// let mut buf2: VecDeque<_> = vec![3, 4].into_iter().collect(); /// buf.append(&mut buf2); - /// assert_eq!(buf.len(), 6); - /// assert_eq!(buf2.len(), 0); + /// assert_eq!(buf, [1, 2, 3, 4]); + /// assert_eq!(buf2, []); /// ``` #[inline] #[stable(feature = "append", since = "1.4.0")] @@ -1745,9 +1743,7 @@ impl VecDeque { /// let mut buf = VecDeque::new(); /// buf.extend(1..5); /// buf.retain(|&x| x%2 == 0); - /// - /// let v: Vec<_> = buf.into_iter().collect(); - /// assert_eq!(&v[..], &[2, 4]); + /// assert_eq!(buf, [2, 4]); /// ``` #[stable(feature = "vec_deque_retain", since = "1.4.0")] pub fn retain(&mut self, mut f: F) @@ -1781,11 +1777,13 @@ impl VecDeque { /// buf.push_back(5); /// buf.push_back(10); /// buf.push_back(15); + /// assert_eq!(buf, [5, 10, 15]); + /// /// buf.resize(2, 0); - /// buf.resize(6, 20); - /// for (a, b) in [5, 10, 20, 20, 20, 20].iter().zip(&buf) { - /// assert_eq!(a, b); - /// } + /// assert_eq!(buf, [5, 10]); + /// + /// buf.resize(5, 20); + /// assert_eq!(buf, [5, 10, 20, 20, 20]); /// ``` #[stable(feature = "deque_extras", since = "1.16.0")] pub fn resize(&mut self, new_len: usize, value: T) { @@ -2162,6 +2160,46 @@ impl PartialEq for VecDeque { #[stable(feature = "rust1", since = "1.0.0")] impl Eq for VecDeque {} +macro_rules! __impl_slice_eq1 { + ($Lhs: ty, $Rhs: ty) => { + __impl_slice_eq1! { $Lhs, $Rhs, Sized } + }; + ($Lhs: ty, $Rhs: ty, $Bound: ident) => { + #[stable(feature = "vec-deque-partial-eq-slice", since = "1.16.0")] + impl<'a, 'b, A: $Bound, B> PartialEq<$Rhs> for $Lhs where A: PartialEq { + fn eq(&self, other: &$Rhs) -> bool { + if self.len() != other.len() { + return false; + } + let (sa, sb) = self.as_slices(); + let (oa, ob) = other[..].split_at(sa.len()); + sa == oa && sb == ob + } + } + } +} + +__impl_slice_eq1! { VecDeque, Vec } +__impl_slice_eq1! { VecDeque, &'b [B] } +__impl_slice_eq1! { VecDeque, &'b mut [B] } + +macro_rules! array_impls { + ($($N: expr)+) => { + $( + __impl_slice_eq1! { VecDeque, [B; $N] } + __impl_slice_eq1! { VecDeque, &'b [B; $N] } + __impl_slice_eq1! { VecDeque, &'b mut [B; $N] } + )+ + } +} + +array_impls! { + 0 1 2 3 4 5 6 7 8 9 + 10 11 12 13 14 15 16 17 18 19 + 20 21 22 23 24 25 26 27 28 29 + 30 31 32 +} + #[stable(feature = "rust1", since = "1.0.0")] impl PartialOrd for VecDeque { fn partial_cmp(&self, other: &VecDeque) -> Option { @@ -2434,7 +2472,7 @@ mod tests { let final_len = usable_cap / 2; for len in 0..final_len { - let expected = if back { + let expected: VecDeque<_> = if back { (0..len).collect() } else { (0..len).rev().collect() @@ -2483,7 +2521,7 @@ mod tests { // len is the length *after* insertion for len in 1..cap { // 0, 1, 2, .., len - 1 - let expected = (0..).take(len).collect(); + let expected = (0..).take(len).collect::>(); for tail_pos in 0..cap { for to_insert in 0..len { tester.tail = tail_pos; @@ -2516,7 +2554,7 @@ mod tests { // len is the length *after* removal for len in 0..cap - 1 { // 0, 1, 2, .., len - 1 - let expected = (0..).take(len).collect(); + let expected = (0..).take(len).collect::>(); for tail_pos in 0..cap { for to_remove in 0..len + 1 { tester.tail = tail_pos; @@ -2591,7 +2629,7 @@ mod tests { for len in 0..cap + 1 { // 0, 1, 2, .., len - 1 - let expected = (0..).take(len).collect(); + let expected = (0..).take(len).collect::>(); for tail_pos in 0..max_cap + 1 { tester.tail = tail_pos; tester.head = tail_pos; @@ -2624,9 +2662,9 @@ mod tests { // index to split at for at in 0..len + 1 { // 0, 1, 2, .., at - 1 (may be empty) - let expected_self = (0..).take(at).collect(); + let expected_self = (0..).take(at).collect::>(); // at, at + 1, .., len - 1 (may be empty) - let expected_other = (at..).take(len - at).collect(); + let expected_other = (at..).take(len - at).collect::>(); for tail_pos in 0..cap { tester.tail = tail_pos; diff --git a/src/libcollectionstest/vec_deque.rs b/src/libcollectionstest/vec_deque.rs index cdf022e4f02f3..bb60f888f8be6 100644 --- a/src/libcollectionstest/vec_deque.rs +++ b/src/libcollectionstest/vec_deque.rs @@ -603,6 +603,25 @@ fn test_eq() { assert!(e == VecDeque::new()); } +#[test] +fn test_partial_eq_array() { + let d = VecDeque::::new(); + assert!(d == []); + + let mut d = VecDeque::new(); + d.push_front('a'); + assert!(d == ['a']); + + let mut d = VecDeque::new(); + d.push_back('a'); + assert!(d == ['a']); + + let mut d = VecDeque::new(); + d.push_back('a'); + d.push_back('b'); + assert!(d == ['a', 'b']); +} + #[test] fn test_hash() { let mut x = VecDeque::new(); From 95227a4dc16b90994e6b39271a75363ff0f05bb3 Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Sat, 28 Jan 2017 14:37:50 -0700 Subject: [PATCH 023/137] Remove ToPrimitive trait. It is no longer used. --- src/librustc/lib.rs | 1 - src/librustc/util/num.rs | 98 ---------------------------------------- 2 files changed, 99 deletions(-) delete mode 100644 src/librustc/util/num.rs diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 0ff9626ae11a8..855f4a8197e35 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -109,7 +109,6 @@ pub mod util { pub mod common; pub mod ppaux; pub mod nodemap; - pub mod num; pub mod fs; } diff --git a/src/librustc/util/num.rs b/src/librustc/util/num.rs deleted file mode 100644 index da04976a96a37..0000000000000 --- a/src/librustc/util/num.rs +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright 2015 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. - -pub trait ToPrimitive { - fn to_i8(&self) -> Option; - fn to_i16(&self) -> Option; - fn to_i32(&self) -> Option; - fn to_i64(&self) -> Option; - fn to_u8(&self) -> Option; - fn to_u16(&self) -> Option; - fn to_u32(&self) -> Option; - fn to_u64(&self) -> Option; -} - -impl ToPrimitive for i64 { - fn to_i8(&self) -> Option { - if *self < i8::min_value() as i64 || *self > i8::max_value() as i64 { - None - } else { - Some(*self as i8) - } - } - fn to_i16(&self) -> Option { - if *self < i16::min_value() as i64 || *self > i16::max_value() as i64 { - None - } else { - Some(*self as i16) - } - } - fn to_i32(&self) -> Option { - if *self < i32::min_value() as i64 || *self > i32::max_value() as i64 { - None - } else { - Some(*self as i32) - } - } - fn to_i64(&self) -> Option { - Some(*self) - } - fn to_u8(&self) -> Option { - if *self < 0 || *self > u8::max_value() as i64 { - None - } else { - Some(*self as u8) - } - } - fn to_u16(&self) -> Option { - if *self < 0 || *self > u16::max_value() as i64 { - None - } else { - Some(*self as u16) - } - } - fn to_u32(&self) -> Option { - if *self < 0 || *self > u32::max_value() as i64 { - None - } else { - Some(*self as u32) - } - } - fn to_u64(&self) -> Option { - if *self < 0 {None} else {Some(*self as u64)} - } -} - -impl ToPrimitive for u64 { - fn to_i8(&self) -> Option { - if *self > i8::max_value() as u64 {None} else {Some(*self as i8)} - } - fn to_i16(&self) -> Option { - if *self > i16::max_value() as u64 {None} else {Some(*self as i16)} - } - fn to_i32(&self) -> Option { - if *self > i32::max_value() as u64 {None} else {Some(*self as i32)} - } - fn to_i64(&self) -> Option { - if *self > i64::max_value() as u64 {None} else {Some(*self as i64)} - } - fn to_u8(&self) -> Option { - if *self > u8::max_value() as u64 {None} else {Some(*self as u8)} - } - fn to_u16(&self) -> Option { - if *self > u16::max_value() as u64 {None} else {Some(*self as u16)} - } - fn to_u32(&self) -> Option { - if *self > u32::max_value() as u64 {None} else {Some(*self as u32)} - } - fn to_u64(&self) -> Option { - Some(*self) - } -} From b54f593cffc40e9d07650b36629e60c48da6b11d Mon Sep 17 00:00:00 2001 From: Michael Gattozzi Date: Sat, 14 Jan 2017 15:25:33 -0500 Subject: [PATCH 024/137] Add clearer error message using `&str + &str` This is the first part of #39018. One of the common things for new users coming from more dynamic languages like JavaScript, Python or Ruby is to use `+` to concatenate strings. However, this doesn't work that way in Rust unless the first type is a `String`. This commit adds a check for this use case and outputs a new error as well as a suggestion to guide the user towards the desired behavior. It also adds a new test case to test the output of the error. --- src/librustc_typeck/check/op.rs | 57 ++++++++++++++++++++++++-- src/test/parse-fail/issue-39018.stderr | 28 +++++++++++++ src/test/ui/span/issue-39018.rs | 23 +++++++++++ src/test/ui/span/issue-39018.stderr | 28 +++++++++++++ 4 files changed, 133 insertions(+), 3 deletions(-) create mode 100644 src/test/parse-fail/issue-39018.stderr create mode 100644 src/test/ui/span/issue-39018.rs create mode 100644 src/test/ui/span/issue-39018.stderr diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs index 925d28247b610..0dcdab07e6fc8 100644 --- a/src/librustc_typeck/check/op.rs +++ b/src/librustc_typeck/check/op.rs @@ -13,7 +13,9 @@ use super::FnCtxt; use hir::def_id::DefId; use rustc::ty::{Ty, TypeFoldable, PreferMutLvalue, TypeVariants}; +use rustc::ty::TypeVariants::{TyStr, TyRef}; use rustc::infer::type_variable::TypeVariableOrigin; +use errors; use syntax::ast; use syntax::symbol::Symbol; use rustc::hir; @@ -237,9 +239,17 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }; if let Some(missing_trait) = missing_trait { - span_note!(&mut err, lhs_expr.span, - "an implementation of `{}` might be missing for `{}`", - missing_trait, lhs_ty); + if missing_trait == "std::ops::Add" && + self.check_str_addition(expr, lhs_expr, lhs_ty, + rhs_expr, rhs_ty_var, &mut err) { + // This has nothing here because it means we did string + // concatenation (e.g. "Hello " + "World!"). This means + // we don't want the span in the else clause to be emmitted + } else { + span_note!(&mut err, lhs_expr.span, + "an implementation of `{}` might be missing for `{}`", + missing_trait, lhs_ty); + } } err.emit(); } @@ -254,6 +264,47 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { (rhs_ty_var, return_ty) } + fn check_str_addition(&self, + expr: &'gcx hir::Expr, + lhs_expr: &'gcx hir::Expr, + lhs_ty: Ty<'tcx>, + rhs_expr: &'gcx hir::Expr, + rhs_ty_var: Ty<'tcx>, + mut err: &mut errors::DiagnosticBuilder) -> bool { + // If this function returns false it means we use it to make sure we print + // out the an "implementation of span_note!" above where this function is + // called and if true we don't. + let mut is_string_addition = false; + let rhs_ty = self.check_expr_coercable_to_type(rhs_expr, rhs_ty_var); + if let TyRef(_, l_ty) = lhs_ty.sty { + if let TyRef(_, r_ty) = rhs_ty.sty { + if l_ty.ty.sty == TyStr && r_ty.ty.sty == TyStr { + span_note!(&mut err, lhs_expr.span, + "`+` can't be used to concatenate two `&str` strings"); + let codemap = self.tcx.sess.codemap(); + let suggestion = + match (codemap.span_to_snippet(lhs_expr.span), + codemap.span_to_snippet(rhs_expr.span)) { + (Ok(lstring), Ok(rstring)) => + format!("{}.to_owned() + {}", lstring, rstring), + _ => format!("") + }; + err.span_suggestion(expr.span, + &format!("to_owned() can be used to create an owned `String` \ + from a string reference. String concatenation \ + appends the string on the right to the string \ + on the left and may require reallocation. This \ + requires ownership of the string on the left."), suggestion); + is_string_addition = true; + } + + } + + } + + is_string_addition + } + pub fn check_user_unop(&self, op_str: &str, mname: &str, diff --git a/src/test/parse-fail/issue-39018.stderr b/src/test/parse-fail/issue-39018.stderr new file mode 100644 index 0000000000000..ee1a32c4c16cf --- /dev/null +++ b/src/test/parse-fail/issue-39018.stderr @@ -0,0 +1,28 @@ +error[E0369]: binary operation `+` cannot be applied to type `&'static str` + --> src/test/ui/span/issue-39018.rs:2:13 + | +2 | let x = "Hello " + "World!"; + | ^^^^^^^^ + | +note: `+` can't be used to concatenate two `&str` strings + --> src/test/ui/span/issue-39018.rs:2:13 + | +2 | let x = "Hello " + "World!"; + | ^^^^^^^^ +help: to_owned() can be used to create an owned `String` from a string reference. This allows concatenation since the `String` is owned. + | let x = "Hello ".to_owned() + "World!"; + +error[E0369]: binary operation `+` cannot be applied to type `World` + --> src/test/ui/span/issue-39018.rs:7:13 + | +7 | let y = World::Hello + World::Goodbye; + | ^^^^^^^^^^^^ + | +note: an implementation of `std::ops::Add` might be missing for `World` + --> src/test/ui/span/issue-39018.rs:7:13 + | +7 | let y = World::Hello + World::Goodbye; + | ^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/span/issue-39018.rs b/src/test/ui/span/issue-39018.rs new file mode 100644 index 0000000000000..1cbc5ff1d2ab5 --- /dev/null +++ b/src/test/ui/span/issue-39018.rs @@ -0,0 +1,23 @@ +// 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. + +pub fn main() { + let x = "Hello " + "World!"; + + // Make sure that the span outputs a warning + // for not having an implementation for std::ops::Add + // that won't output for the above string concatenation + let y = World::Hello + World::Goodbye; +} + +enum World { + Hello, + Goodbye, +} diff --git a/src/test/ui/span/issue-39018.stderr b/src/test/ui/span/issue-39018.stderr new file mode 100644 index 0000000000000..a8cc74056ca2c --- /dev/null +++ b/src/test/ui/span/issue-39018.stderr @@ -0,0 +1,28 @@ +error[E0369]: binary operation `+` cannot be applied to type `&'static str` + --> $DIR/issue-39018.rs:12:13 + | +12 | let x = "Hello " + "World!"; + | ^^^^^^^^ + | +note: `+` can't be used to concatenate two `&str` strings + --> $DIR/issue-39018.rs:12:13 + | +12 | let x = "Hello " + "World!"; + | ^^^^^^^^ +help: to_owned() can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left. + | let x = "Hello ".to_owned() + "World!"; + +error[E0369]: binary operation `+` cannot be applied to type `World` + --> $DIR/issue-39018.rs:17:13 + | +17 | let y = World::Hello + World::Goodbye; + | ^^^^^^^^^^^^ + | +note: an implementation of `std::ops::Add` might be missing for `World` + --> $DIR/issue-39018.rs:17:13 + | +17 | let y = World::Hello + World::Goodbye; + | ^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + From 18b96cf286e99ba61ff52fb916463466b2a63a67 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 9 Jan 2017 00:21:35 +0300 Subject: [PATCH 025/137] Privatize constructors of tuple structs with private fields --- src/librustc_metadata/encoder.rs | 8 +++- src/librustc_resolve/build_reduced_graph.rs | 22 ++++++---- .../auxiliary/privacy-struct-ctor.rs | 21 ++++++++++ src/test/compile-fail/privacy-struct-ctor.rs | 42 +++++++++++++++++++ 4 files changed, 83 insertions(+), 10 deletions(-) create mode 100644 src/test/compile-fail/auxiliary/privacy-struct-ctor.rs create mode 100644 src/test/compile-fail/privacy-struct-ctor.rs diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 028555d1df848..b9c2f0622b698 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -396,10 +396,16 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let struct_id = tcx.hir.as_local_node_id(adt_def_id).unwrap(); let struct_vis = &tcx.hir.expect_item(struct_id).vis; + let mut ctor_vis = ty::Visibility::from_hir(struct_vis, struct_id, tcx); + for field in &variant.fields { + if ctor_vis.is_at_least(field.vis, tcx) { + ctor_vis = field.vis; + } + } Entry { kind: EntryKind::Struct(self.lazy(&data)), - visibility: self.lazy(&ty::Visibility::from_hir(struct_vis, struct_id, tcx)), + visibility: self.lazy(&ctor_vis), span: self.lazy(&tcx.def_span(def_id)), attributes: LazySeq::empty(), children: LazySeq::empty(), diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index f74af416cde09..f144be7996aec 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -327,21 +327,25 @@ impl<'a> Resolver<'a> { let def = Def::Struct(self.definitions.local_def_id(item.id)); self.define(parent, ident, TypeNS, (def, vis, sp, expansion)); - // If this is a tuple or unit struct, define a name - // in the value namespace as well. - if !struct_def.is_struct() { - let ctor_def = Def::StructCtor(self.definitions.local_def_id(struct_def.id()), - CtorKind::from_ast(struct_def)); - self.define(parent, ident, ValueNS, (ctor_def, vis, sp, expansion)); - } - // Record field names for error reporting. + let mut ctor_vis = vis; let field_names = struct_def.fields().iter().filter_map(|field| { - self.resolve_visibility(&field.vis); + let field_vis = self.resolve_visibility(&field.vis); + if ctor_vis.is_at_least(field_vis, &*self) { + ctor_vis = field_vis; + } field.ident.map(|ident| ident.name) }).collect(); let item_def_id = self.definitions.local_def_id(item.id); self.insert_field_names(item_def_id, field_names); + + // If this is a tuple or unit struct, define a name + // in the value namespace as well. + if !struct_def.is_struct() { + let ctor_def = Def::StructCtor(self.definitions.local_def_id(struct_def.id()), + CtorKind::from_ast(struct_def)); + self.define(parent, ident, ValueNS, (ctor_def, ctor_vis, sp, expansion)); + } } ItemKind::Union(ref vdata, _) => { diff --git a/src/test/compile-fail/auxiliary/privacy-struct-ctor.rs b/src/test/compile-fail/auxiliary/privacy-struct-ctor.rs new file mode 100644 index 0000000000000..f190f5dd0534d --- /dev/null +++ b/src/test/compile-fail/auxiliary/privacy-struct-ctor.rs @@ -0,0 +1,21 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(pub_restricted)] + +pub mod m { + pub struct S(u8); + + pub mod n { + pub(m) struct Z(pub(m::n) u8); + } +} + +pub use m::S; diff --git a/src/test/compile-fail/privacy-struct-ctor.rs b/src/test/compile-fail/privacy-struct-ctor.rs new file mode 100644 index 0000000000000..13a04f490141f --- /dev/null +++ b/src/test/compile-fail/privacy-struct-ctor.rs @@ -0,0 +1,42 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:privacy-struct-ctor.rs + +#![feature(pub_restricted)] + +extern crate privacy_struct_ctor as xcrate; + +mod m { + pub struct S(u8); + + pub mod n { + pub(m) struct Z(pub(m::n) u8); + } + + use m::n::Z; // OK, only the type is imported + + fn f() { + n::Z; //~ ERROR tuple struct `Z` is private + Z; //~ ERROR expected value, found struct `Z` + } +} + +use m::S; // OK, only the type is imported + +fn main() { + m::S; //~ ERROR tuple struct `S` is private + S; //~ ERROR expected value, found struct `S` + m::n::Z; //~ ERROR tuple struct `Z` is private + + xcrate::m::S; //~ ERROR tuple struct `S` is private + xcrate::S; //~ ERROR expected value, found struct `xcrate::S` + xcrate::m::n::Z; //~ ERROR tuple struct `Z` is private +} From 962d88b5eeeb602b2a6c9a2f96f9476152279a42 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 9 Jan 2017 00:34:52 +0300 Subject: [PATCH 026/137] Fix the fallout --- src/librustc_privacy/diagnostics.rs | 2 +- src/libsyntax/symbol.rs | 19 ++-- .../explore-issue-38412.rs | 7 -- src/test/compile-fail/E0450.rs | 21 ---- src/test/compile-fail/E0451.rs | 5 - src/test/compile-fail/issue-38412.rs | 2 +- src/test/compile-fail/privacy5.rs | 107 +++++++++--------- 7 files changed, 63 insertions(+), 100 deletions(-) delete mode 100644 src/test/compile-fail/E0450.rs diff --git a/src/librustc_privacy/diagnostics.rs b/src/librustc_privacy/diagnostics.rs index 66afe5835bf6f..8506b1d75c5b9 100644 --- a/src/librustc_privacy/diagnostics.rs +++ b/src/librustc_privacy/diagnostics.rs @@ -119,7 +119,7 @@ E0450: r##" A tuple constructor was invoked while some of its fields are private. Erroneous code example: -```compile_fail,E0450 +```compile_fail mod Bar { pub struct Foo(isize); } diff --git a/src/libsyntax/symbol.rs b/src/libsyntax/symbol.rs index c2123ea5a0798..c278171aa109a 100644 --- a/src/libsyntax/symbol.rs +++ b/src/libsyntax/symbol.rs @@ -140,7 +140,7 @@ macro_rules! declare_keywords {( $( #[allow(non_upper_case_globals)] pub const $konst: Keyword = Keyword { - ident: ast::Ident::with_empty_ctxt(ast::Name($index)) + ident: ast::Ident::with_empty_ctxt(super::Symbol($index)) }; )* } @@ -282,25 +282,24 @@ impl Encodable for InternedString { #[cfg(test)] mod tests { use super::*; - use ast::Name; #[test] fn interner_tests() { let mut i: Interner = Interner::new(); // first one is zero: - assert_eq!(i.intern("dog"), Name(0)); + assert_eq!(i.intern("dog"), Symbol(0)); // re-use gets the same entry: - assert_eq!(i.intern ("dog"), Name(0)); + assert_eq!(i.intern ("dog"), Symbol(0)); // different string gets a different #: - assert_eq!(i.intern("cat"), Name(1)); - assert_eq!(i.intern("cat"), Name(1)); + assert_eq!(i.intern("cat"), Symbol(1)); + assert_eq!(i.intern("cat"), Symbol(1)); // dog is still at zero - assert_eq!(i.intern("dog"), Name(0)); + assert_eq!(i.intern("dog"), Symbol(0)); // gensym gets 3 - assert_eq!(i.gensym("zebra"), Name(2)); + assert_eq!(i.gensym("zebra"), Symbol(2)); // gensym of same string gets new number : - assert_eq!(i.gensym("zebra"), Name(3)); + assert_eq!(i.gensym("zebra"), Symbol(3)); // gensym of *existing* string gets new number: - assert_eq!(i.gensym("dog"), Name(4)); + assert_eq!(i.gensym("dog"), Symbol(4)); } } diff --git a/src/test/compile-fail-fulldeps/explore-issue-38412.rs b/src/test/compile-fail-fulldeps/explore-issue-38412.rs index aab92575321e3..b9839edea2dc4 100644 --- a/src/test/compile-fail-fulldeps/explore-issue-38412.rs +++ b/src/test/compile-fail-fulldeps/explore-issue-38412.rs @@ -25,21 +25,14 @@ use pub_and_stability::{Record, Trait, Tuple}; fn main() { // Okay let Record { .. } = Record::new(); - // Okay (for now; see RFC Issue #902) - let Tuple(..) = Tuple::new(); // Okay let Record { a_stable_pub: _, a_unstable_declared_pub: _, .. } = Record::new(); - // Okay (for now; see RFC Issue #902) - let Tuple(_, _, ..) = Tuple::new(); // analogous to above let Record { a_stable_pub: _, a_unstable_declared_pub: _, a_unstable_undeclared_pub: _, .. } = Record::new(); //~^^ ERROR use of unstable library feature 'unstable_undeclared' - let Tuple(_, _, _, ..) = Tuple::new(); // analogous to previous - //~^ ERROR use of unstable library feature 'unstable_undeclared' - let r = Record::new(); let t = Tuple::new(); diff --git a/src/test/compile-fail/E0450.rs b/src/test/compile-fail/E0450.rs deleted file mode 100644 index 200b58a329344..0000000000000 --- a/src/test/compile-fail/E0450.rs +++ /dev/null @@ -1,21 +0,0 @@ -// 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -mod Bar { - pub struct Foo( bool, pub i32, f32, bool); - //~^ NOTE private field declared here - //~| NOTE private field declared here - //~| NOTE private field declared here -} - -fn main() { - let f = Bar::Foo(false,1,0.1, true); //~ ERROR E0450 - //~^ NOTE cannot construct with a private field -} diff --git a/src/test/compile-fail/E0451.rs b/src/test/compile-fail/E0451.rs index f7b106d160dae..ace96c9983e66 100644 --- a/src/test/compile-fail/E0451.rs +++ b/src/test/compile-fail/E0451.rs @@ -25,11 +25,6 @@ fn pat_match(foo: Bar::Foo) { //~^ NOTE field `b` is private } -fn pat_match_tuple(foo: Bar::FooTuple) { - let Bar::FooTuple(a,b) = foo; //~ ERROR E0451 - //~^ NOTE field `1` is private -} - fn main() { let f = Bar::Foo{ a: 0, b: 0 }; //~ ERROR E0451 //~^ NOTE field `b` is private diff --git a/src/test/compile-fail/issue-38412.rs b/src/test/compile-fail/issue-38412.rs index 00305eb2bc04b..b4feadbacf740 100644 --- a/src/test/compile-fail/issue-38412.rs +++ b/src/test/compile-fail/issue-38412.rs @@ -10,7 +10,7 @@ fn main() { let Box(a) = loop { }; - //~^ ERROR field `0` of struct `std::boxed::Box` is private + //~^ ERROR expected tuple struct/variant, found struct `Box` // (The below is a trick to allow compiler to infer a type for // variable `a` without attempting to ascribe a type to the diff --git a/src/test/compile-fail/privacy5.rs b/src/test/compile-fail/privacy5.rs index 9d6ae187cd381..599c1f8716044 100644 --- a/src/test/compile-fail/privacy5.rs +++ b/src/test/compile-fail/privacy5.rs @@ -58,30 +58,31 @@ mod a { } fn this_crate() { - let a = a::A(()); //~ ERROR: cannot invoke tuple struct constructor - let b = a::B(2); //~ ERROR: cannot invoke tuple struct constructor - let c = a::C(2, 3); //~ ERROR: cannot invoke tuple struct constructor + let a = a::A(()); //~ ERROR tuple struct `A` is private + let b = a::B(2); //~ ERROR tuple struct `B` is private + let c = a::C(2, 3); //~ ERROR tuple struct `C` is private let d = a::D(4); - let a::A(()) = a; //~ ERROR: field `0` of struct `a::A` is private - let a::A(_) = a; - match a { a::A(()) => {} } //~ ERROR: field `0` of struct `a::A` is private - match a { a::A(_) => {} } - - let a::B(_) = b; - let a::B(_b) = b; //~ ERROR: field `0` of struct `a::B` is private - match b { a::B(_) => {} } - match b { a::B(_b) => {} } //~ ERROR: field `0` of struct `a::B` is private - match b { a::B(1) => {} a::B(_) => {} } //~ ERROR: field `0` of struct `a::B` is private - - let a::C(_, _) = c; - let a::C(_a, _) = c; - let a::C(_, _b) = c; //~ ERROR: field `1` of struct `a::C` is private - let a::C(_a, _b) = c; //~ ERROR: field `1` of struct `a::C` is private - match c { a::C(_, _) => {} } - match c { a::C(_a, _) => {} } - match c { a::C(_, _b) => {} } //~ ERROR: field `1` of struct `a::C` is private - match c { a::C(_a, _b) => {} } //~ ERROR: field `1` of struct `a::C` is private + let a::A(()) = a; //~ ERROR tuple struct `A` is private + let a::A(_) = a; //~ ERROR tuple struct `A` is private + match a { a::A(()) => {} } //~ ERROR tuple struct `A` is private + match a { a::A(_) => {} } //~ ERROR tuple struct `A` is private + + let a::B(_) = b; //~ ERROR tuple struct `B` is private + let a::B(_b) = b; //~ ERROR tuple struct `B` is private + match b { a::B(_) => {} } //~ ERROR tuple struct `B` is private + match b { a::B(_b) => {} } //~ ERROR tuple struct `B` is private + match b { a::B(1) => {} a::B(_) => {} } //~ ERROR tuple struct `B` is private + //~^ ERROR tuple struct `B` is private + + let a::C(_, _) = c; //~ ERROR tuple struct `C` is private + let a::C(_a, _) = c; //~ ERROR tuple struct `C` is private + let a::C(_, _b) = c; //~ ERROR tuple struct `C` is private + let a::C(_a, _b) = c; //~ ERROR tuple struct `C` is private + match c { a::C(_, _) => {} } //~ ERROR tuple struct `C` is private + match c { a::C(_a, _) => {} } //~ ERROR tuple struct `C` is private + match c { a::C(_, _b) => {} } //~ ERROR tuple struct `C` is private + match c { a::C(_a, _b) => {} } //~ ERROR tuple struct `C` is private let a::D(_) = d; let a::D(_d) = d; @@ -89,42 +90,38 @@ fn this_crate() { match d { a::D(_d) => {} } match d { a::D(1) => {} a::D(_) => {} } - let a2 = a::A; //~ ERROR: cannot invoke tuple struct constructor - let b2 = a::B; //~ ERROR: cannot invoke tuple struct constructor - let c2 = a::C; //~ ERROR: cannot invoke tuple struct constructor + let a2 = a::A; //~ ERROR tuple struct `A` is private + let b2 = a::B; //~ ERROR tuple struct `B` is private + let c2 = a::C; //~ ERROR tuple struct `C` is private let d2 = a::D; } fn xcrate() { - let a = other::A(()); //~ ERROR: cannot invoke tuple struct constructor - let b = other::B(2); //~ ERROR: cannot invoke tuple struct constructor - let c = other::C(2, 3); //~ ERROR: cannot invoke tuple struct constructor + let a = other::A(()); //~ ERROR tuple struct `A` is private + let b = other::B(2); //~ ERROR tuple struct `B` is private + let c = other::C(2, 3); //~ ERROR tuple struct `C` is private let d = other::D(4); - let other::A(()) = a; //~ ERROR: field `0` of struct `other::A` is private - let other::A(_) = a; - match a { other::A(()) => {} } - //~^ ERROR: field `0` of struct `other::A` is private - match a { other::A(_) => {} } - - let other::B(_) = b; - let other::B(_b) = b; //~ ERROR: field `0` of struct `other::B` is private - match b { other::B(_) => {} } - match b { other::B(_b) => {} } - //~^ ERROR: field `0` of struct `other::B` is private - match b { other::B(1) => {} other::B(_) => {} } - //~^ ERROR: field `0` of struct `other::B` is private - - let other::C(_, _) = c; - let other::C(_a, _) = c; - let other::C(_, _b) = c; //~ ERROR: field `1` of struct `other::C` is private - let other::C(_a, _b) = c; //~ ERROR: field `1` of struct `other::C` is private - match c { other::C(_, _) => {} } - match c { other::C(_a, _) => {} } - match c { other::C(_, _b) => {} } - //~^ ERROR: field `1` of struct `other::C` is private - match c { other::C(_a, _b) => {} } - //~^ ERROR: field `1` of struct `other::C` is private + let other::A(()) = a; //~ ERROR tuple struct `A` is private + let other::A(_) = a; //~ ERROR tuple struct `A` is private + match a { other::A(()) => {} } //~ ERROR tuple struct `A` is private + match a { other::A(_) => {} } //~ ERROR tuple struct `A` is private + + let other::B(_) = b; //~ ERROR tuple struct `B` is private + let other::B(_b) = b; //~ ERROR tuple struct `B` is private + match b { other::B(_) => {} } //~ ERROR tuple struct `B` is private + match b { other::B(_b) => {} } //~ ERROR tuple struct `B` is private + match b { other::B(1) => {} other::B(_) => {} } //~ ERROR tuple struct `B` is private + //~^ ERROR tuple struct `B` is private + + let other::C(_, _) = c; //~ ERROR tuple struct `C` is private + let other::C(_a, _) = c; //~ ERROR tuple struct `C` is private + let other::C(_, _b) = c; //~ ERROR tuple struct `C` is private + let other::C(_a, _b) = c; //~ ERROR tuple struct `C` is private + match c { other::C(_, _) => {} } //~ ERROR tuple struct `C` is private + match c { other::C(_a, _) => {} } //~ ERROR tuple struct `C` is private + match c { other::C(_, _b) => {} } //~ ERROR tuple struct `C` is private + match c { other::C(_a, _b) => {} } //~ ERROR tuple struct `C` is private let other::D(_) = d; let other::D(_d) = d; @@ -132,9 +129,9 @@ fn xcrate() { match d { other::D(_d) => {} } match d { other::D(1) => {} other::D(_) => {} } - let a2 = other::A; //~ ERROR: cannot invoke tuple struct constructor - let b2 = other::B; //~ ERROR: cannot invoke tuple struct constructor - let c2 = other::C; //~ ERROR: cannot invoke tuple struct constructor + let a2 = other::A; //~ ERROR tuple struct `A` is private + let b2 = other::B; //~ ERROR tuple struct `B` is private + let c2 = other::C; //~ ERROR tuple struct `C` is private let d2 = other::D; } From 8b060e25ba80eb2866839335302b31359c18421a Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 20 Jan 2017 18:53:49 +0300 Subject: [PATCH 027/137] Implement compatibility lint for legacy constructor visibilities --- src/librustc/lint/builtin.rs | 7 +++++ src/librustc_lint/lib.rs | 4 +++ src/librustc_resolve/build_reduced_graph.rs | 3 ++ src/librustc_resolve/lib.rs | 24 ++++++++++++++-- .../privacy/legacy-ctor-visibility.rs | 28 +++++++++++++++++++ 5 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 src/test/compile-fail/privacy/legacy-ctor-visibility.rs diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index b0db3b75029fb..e1605959922c0 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -223,6 +223,12 @@ declare_lint! { "detects names that resolve to ambiguous glob imports with RFC 1560" } +declare_lint! { + pub LEGACY_CONSTRUCTOR_VISIBILITY, + Deny, + "detects use of struct constructors that would be invisible with new visibility rules" +} + declare_lint! { pub DEPRECATED, Warn, @@ -271,6 +277,7 @@ impl LintPass for HardwiredLints { EXTRA_REQUIREMENT_IN_IMPL, LEGACY_DIRECTORY_OWNERSHIP, LEGACY_IMPORTS, + LEGACY_CONSTRUCTOR_VISIBILITY, DEPRECATED ) } diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 34bc57884ecbb..18067cb86739b 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -240,6 +240,10 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { id: LintId::of(LEGACY_IMPORTS), reference: "issue #38260 ", }, + FutureIncompatibleInfo { + id: LintId::of(LEGACY_CONSTRUCTOR_VISIBILITY), + reference: "issue #39207 ", + }, ]); // Register renamed and removed lints diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index f144be7996aec..144ec8c680ee8 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -345,6 +345,9 @@ impl<'a> Resolver<'a> { let ctor_def = Def::StructCtor(self.definitions.local_def_id(struct_def.id()), CtorKind::from_ast(struct_def)); self.define(parent, ident, ValueNS, (ctor_def, ctor_vis, sp, expansion)); + if !ctor_vis.is_at_least(vis, &*self) { + self.legacy_ctor_visibilities.insert(def.def_id(), (ctor_def, ctor_vis)); + } } } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index b5e2715ab4f0b..4ade64ee19850 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -45,7 +45,7 @@ use rustc::hir::def::*; use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, LOCAL_CRATE, DefId}; use rustc::ty; use rustc::hir::{Freevar, FreevarMap, TraitCandidate, TraitMap, GlobMap}; -use rustc::util::nodemap::{NodeMap, NodeSet, FxHashMap, FxHashSet}; +use rustc::util::nodemap::{NodeMap, NodeSet, FxHashMap, FxHashSet, DefIdMap}; use syntax::ext::hygiene::{Mark, SyntaxContext}; use syntax::ast::{self, Name, NodeId, Ident, SpannedIdent, FloatTy, IntTy, UintTy}; @@ -1131,6 +1131,9 @@ pub struct Resolver<'a> { warned_proc_macros: FxHashSet, potentially_unused_imports: Vec<&'a ImportDirective<'a>>, + + // Auxiliary map used only for reporting `legacy_constructor_visibility` lint. + legacy_ctor_visibilities: DefIdMap<(Def, ty::Visibility)>, } pub struct ResolverArenas<'a> { @@ -1310,6 +1313,7 @@ impl<'a> Resolver<'a> { proc_macro_enabled: features.proc_macro, warned_proc_macros: FxHashSet(), potentially_unused_imports: Vec::new(), + legacy_ctor_visibilities: DefIdMap(), } } @@ -2235,7 +2239,23 @@ impl<'a> Resolver<'a> { if is_expected(resolution.base_def) || resolution.base_def == Def::Err { resolution } else { - report_errors(self, Some(resolution.base_def)) + // Add a temporary hack to smooth the transition to new struct ctor + // visibility rules. See #38932 for more details. + let mut res = None; + if let Def::Struct(def_id) = resolution.base_def { + if let Some((ctor_def, ctor_vis)) + = self.legacy_ctor_visibilities.get(&def_id).cloned() { + if is_expected(ctor_def) && self.is_accessible(ctor_vis) { + let lint = lint::builtin::LEGACY_CONSTRUCTOR_VISIBILITY; + self.session.add_lint(lint, id, span, + "private struct constructors are not usable through \ + reexports in outer modules".to_string()); + res = Some(PathResolution::new(ctor_def)); + } + } + } + + res.unwrap_or_else(|| report_errors(self, Some(resolution.base_def))) } } Some(resolution) if source.defer_to_typeck() => { diff --git a/src/test/compile-fail/privacy/legacy-ctor-visibility.rs b/src/test/compile-fail/privacy/legacy-ctor-visibility.rs new file mode 100644 index 0000000000000..fb65af230ace5 --- /dev/null +++ b/src/test/compile-fail/privacy/legacy-ctor-visibility.rs @@ -0,0 +1,28 @@ +// 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(unused)] + +use m::S; + +mod m { + pub struct S(u8); + + mod n { + use S; + fn f() { + S(10); + //~^ ERROR private struct constructors are not usable through reexports in outer modules + //~| WARN this was previously accepted + } + } +} + +fn main() {} From c9788fdd5b8d136b1c32e0130f8e2fdbc8f8073b Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 20 Jan 2017 20:11:42 +0300 Subject: [PATCH 028/137] Remove no longer necessary ctor checks in rustc_privacy --- src/librustc_privacy/diagnostics.rs | 43 +++-------------------------- src/librustc_privacy/lib.rs | 29 +------------------ src/librustdoc/html/markdown.rs | 2 -- 3 files changed, 5 insertions(+), 69 deletions(-) diff --git a/src/librustc_privacy/diagnostics.rs b/src/librustc_privacy/diagnostics.rs index 8506b1d75c5b9..49f2ccb7c57f5 100644 --- a/src/librustc_privacy/diagnostics.rs +++ b/src/librustc_privacy/diagnostics.rs @@ -115,45 +115,6 @@ pub enum Foo { ``` "##, -E0450: r##" -A tuple constructor was invoked while some of its fields are private. Erroneous -code example: - -```compile_fail -mod Bar { - pub struct Foo(isize); -} - -let f = Bar::Foo(0); // error: cannot invoke tuple struct constructor with - // private fields -``` - -To solve this issue, please ensure that all of the fields of the tuple struct -are public. Alternatively, provide a `new()` method to the tuple struct to -construct it from a given inner value. Example: - -``` -mod Bar { - pub struct Foo(pub isize); // we set its field to public -} - -let f = Bar::Foo(0); // ok! - -// or: -mod bar { - pub struct Foo(isize); - - impl Foo { - pub fn new(x: isize) -> Foo { - Foo(x) - } - } -} - -let f = bar::Foo::new(1); -``` -"##, - E0451: r##" A struct constructor with private fields was invoked. Erroneous code example: @@ -204,3 +165,7 @@ let f = Bar::Foo::new(); // ok! "##, } + +register_diagnostics! { +// E0450, moved into resolve +} diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 7357d6f38b651..9dc94745cff7b 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -27,7 +27,7 @@ extern crate syntax_pos; use rustc::dep_graph::DepNode; use rustc::hir::{self, PatKind}; -use rustc::hir::def::{self, Def, CtorKind}; +use rustc::hir::def::{self, Def}; use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId}; use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; use rustc::hir::itemlikevisit::DeepVisitor; @@ -478,33 +478,6 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivacyVisitor<'a, 'tcx> { } } } - hir::ExprPath(hir::QPath::Resolved(_, ref path)) => { - if let Def::StructCtor(_, CtorKind::Fn) = path.def { - let adt_def = self.tcx.expect_variant_def(path.def); - let private_indexes = adt_def.fields.iter().enumerate().filter(|&(_, field)| { - !field.vis.is_accessible_from(self.curitem, self.tcx) - }).map(|(i, _)| i).collect::>(); - - if !private_indexes.is_empty() { - let mut error = struct_span_err!(self.tcx.sess, expr.span, E0450, - "cannot invoke tuple struct constructor \ - with private fields"); - error.span_label(expr.span, - &format!("cannot construct with a private field")); - - if let Some(node_id) = self.tcx.hir.as_local_node_id(adt_def.did) { - let node = self.tcx.hir.find(node_id); - if let Some(hir::map::NodeStructCtor(vdata)) = node { - for i in private_indexes { - error.span_label(vdata.fields()[i].span, - &format!("private field declared here")); - } - } - } - error.emit(); - } - } - } _ => {} } diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 8cc3b60a18406..442a2f4074215 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -660,8 +660,6 @@ mod tests { t("no_run", false, true, false, true, false, false, Vec::new()); t("test_harness", false, false, false, true, true, false, Vec::new()); t("compile_fail", false, true, false, true, false, true, Vec::new()); - t("E0450", false, false, false, true, false, false, - vec!["E0450".to_owned()]); t("{.no_run .example}", false, true, false, true, false, false, Vec::new()); t("{.sh .should_panic}", true, false, false, true, false, false, Vec::new()); t("{.example .rust}", false, false, false, true, false, false, Vec::new()); From d38a8ad488047b8acdeed44bb7c67dc776324624 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 29 Jan 2017 02:56:52 +0300 Subject: [PATCH 029/137] Improve diagnostics for inaccessible constructors --- src/librustc_resolve/build_reduced_graph.rs | 16 +++-- src/librustc_resolve/lib.rs | 18 +++-- src/test/compile-fail/issue-38412.rs | 1 + .../resolve}/auxiliary/privacy-struct-ctor.rs | 0 .../resolve}/privacy-struct-ctor.rs | 12 +++- .../ui/resolve/privacy-struct-ctor.stderr | 68 +++++++++++++++++++ 6 files changed, 103 insertions(+), 12 deletions(-) rename src/test/{compile-fail => ui/resolve}/auxiliary/privacy-struct-ctor.rs (100%) rename src/test/{compile-fail => ui/resolve}/privacy-struct-ctor.rs (71%) create mode 100644 src/test/ui/resolve/privacy-struct-ctor.stderr diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 144ec8c680ee8..eb6c7f4bed5de 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -345,9 +345,7 @@ impl<'a> Resolver<'a> { let ctor_def = Def::StructCtor(self.definitions.local_def_id(struct_def.id()), CtorKind::from_ast(struct_def)); self.define(parent, ident, ValueNS, (ctor_def, ctor_vis, sp, expansion)); - if !ctor_vis.is_at_least(vis, &*self) { - self.legacy_ctor_visibilities.insert(def.def_id(), (ctor_def, ctor_vis)); - } + self.struct_constructors.insert(def.def_id(), (ctor_def, ctor_vis)); } } @@ -441,9 +439,17 @@ impl<'a> Resolver<'a> { Def::Variant(..) | Def::TyAlias(..) => { self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, Mark::root())); } - Def::Fn(..) | Def::Static(..) | Def::Const(..) | - Def::VariantCtor(..) | Def::StructCtor(..) => { + Def::Fn(..) | Def::Static(..) | Def::Const(..) | Def::VariantCtor(..) => { + self.define(parent, ident, ValueNS, (def, vis, DUMMY_SP, Mark::root())); + } + Def::StructCtor(..) => { self.define(parent, ident, ValueNS, (def, vis, DUMMY_SP, Mark::root())); + + if let Some(struct_def_id) = + self.session.cstore.def_key(def_id).parent + .map(|index| DefId { krate: def_id.krate, index: index }) { + self.struct_constructors.insert(struct_def_id, (def, vis)); + } } Def::Trait(..) => { let module_kind = ModuleKind::Def(def, ident.name); diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 4ade64ee19850..676ff98e602d6 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1132,8 +1132,9 @@ pub struct Resolver<'a> { potentially_unused_imports: Vec<&'a ImportDirective<'a>>, - // Auxiliary map used only for reporting `legacy_constructor_visibility` lint. - legacy_ctor_visibilities: DefIdMap<(Def, ty::Visibility)>, + // This table maps struct IDs into struct constructor IDs, + // it's not used during normal resolution, only for better error reporting. + struct_constructors: DefIdMap<(Def, ty::Visibility)>, } pub struct ResolverArenas<'a> { @@ -1313,7 +1314,7 @@ impl<'a> Resolver<'a> { proc_macro_enabled: features.proc_macro, warned_proc_macros: FxHashSet(), potentially_unused_imports: Vec::new(), - legacy_ctor_visibilities: DefIdMap(), + struct_constructors: DefIdMap(), } } @@ -2209,6 +2210,15 @@ impl<'a> Resolver<'a> { _ => {} }, _ if ns == ValueNS && is_struct_like(def) => { + if let Def::Struct(def_id) = def { + if let Some((ctor_def, ctor_vis)) + = this.struct_constructors.get(&def_id).cloned() { + if is_expected(ctor_def) && !this.is_accessible(ctor_vis) { + err.span_label(span, &format!("constructor is not visible \ + here due to private fields")); + } + } + } err.span_label(span, &format!("did you mean `{} {{ /* fields */ }}`?", path_str)); return err; @@ -2244,7 +2254,7 @@ impl<'a> Resolver<'a> { let mut res = None; if let Def::Struct(def_id) = resolution.base_def { if let Some((ctor_def, ctor_vis)) - = self.legacy_ctor_visibilities.get(&def_id).cloned() { + = self.struct_constructors.get(&def_id).cloned() { if is_expected(ctor_def) && self.is_accessible(ctor_vis) { let lint = lint::builtin::LEGACY_CONSTRUCTOR_VISIBILITY; self.session.add_lint(lint, id, span, diff --git a/src/test/compile-fail/issue-38412.rs b/src/test/compile-fail/issue-38412.rs index b4feadbacf740..3b62aaf2ab8e9 100644 --- a/src/test/compile-fail/issue-38412.rs +++ b/src/test/compile-fail/issue-38412.rs @@ -11,6 +11,7 @@ fn main() { let Box(a) = loop { }; //~^ ERROR expected tuple struct/variant, found struct `Box` + //~| ERROR expected tuple struct/variant, found struct `Box` // (The below is a trick to allow compiler to infer a type for // variable `a` without attempting to ascribe a type to the diff --git a/src/test/compile-fail/auxiliary/privacy-struct-ctor.rs b/src/test/ui/resolve/auxiliary/privacy-struct-ctor.rs similarity index 100% rename from src/test/compile-fail/auxiliary/privacy-struct-ctor.rs rename to src/test/ui/resolve/auxiliary/privacy-struct-ctor.rs diff --git a/src/test/compile-fail/privacy-struct-ctor.rs b/src/test/ui/resolve/privacy-struct-ctor.rs similarity index 71% rename from src/test/compile-fail/privacy-struct-ctor.rs rename to src/test/ui/resolve/privacy-struct-ctor.rs index 13a04f490141f..3d0c76c740ad6 100644 --- a/src/test/compile-fail/privacy-struct-ctor.rs +++ b/src/test/ui/resolve/privacy-struct-ctor.rs @@ -25,7 +25,9 @@ mod m { fn f() { n::Z; //~ ERROR tuple struct `Z` is private - Z; //~ ERROR expected value, found struct `Z` + Z; + //~^ ERROR expected value, found struct `Z` + //~| NOTE tuple struct constructors with private fields are invisible outside of their mod } } @@ -33,10 +35,14 @@ use m::S; // OK, only the type is imported fn main() { m::S; //~ ERROR tuple struct `S` is private - S; //~ ERROR expected value, found struct `S` + S; + //~^ ERROR expected value, found struct `S` + //~| NOTE constructor is not visible here due to private fields m::n::Z; //~ ERROR tuple struct `Z` is private xcrate::m::S; //~ ERROR tuple struct `S` is private - xcrate::S; //~ ERROR expected value, found struct `xcrate::S` + xcrate::S; + //~^ ERROR expected value, found struct `xcrate::S` + //~| NOTE constructor is not visible here due to private fields xcrate::m::n::Z; //~ ERROR tuple struct `Z` is private } diff --git a/src/test/ui/resolve/privacy-struct-ctor.stderr b/src/test/ui/resolve/privacy-struct-ctor.stderr new file mode 100644 index 0000000000000..30fdbb02cc715 --- /dev/null +++ b/src/test/ui/resolve/privacy-struct-ctor.stderr @@ -0,0 +1,68 @@ +error[E0423]: expected value, found struct `Z` + --> $DIR/privacy-struct-ctor.rs:28:9 + | +28 | Z; + | ^ + | | + | did you mean `Z { /* fields */ }`? + | constructor is not visible here due to private fields + | + = help: possible better candidate is found in another module, you can import it into scope: + `use m::n::Z;` + +error[E0423]: expected value, found struct `S` + --> $DIR/privacy-struct-ctor.rs:38:5 + | +38 | S; + | ^ + | | + | did you mean `S { /* fields */ }`? + | constructor is not visible here due to private fields + | + = help: possible better candidate is found in another module, you can import it into scope: + `use m::S;` + +error[E0423]: expected value, found struct `xcrate::S` + --> $DIR/privacy-struct-ctor.rs:44:5 + | +44 | xcrate::S; + | ^^^^^^^^^ + | | + | did you mean `xcrate::S { /* fields */ }`? + | constructor is not visible here due to private fields + | + = help: possible better candidate is found in another module, you can import it into scope: + `use m::S;` + +error: tuple struct `Z` is private + --> $DIR/privacy-struct-ctor.rs:27:9 + | +27 | n::Z; //~ ERROR tuple struct `Z` is private + | ^^^^ + +error: tuple struct `S` is private + --> $DIR/privacy-struct-ctor.rs:37:5 + | +37 | m::S; //~ ERROR tuple struct `S` is private + | ^^^^ + +error: tuple struct `Z` is private + --> $DIR/privacy-struct-ctor.rs:41:5 + | +41 | m::n::Z; //~ ERROR tuple struct `Z` is private + | ^^^^^^^ + +error: tuple struct `S` is private + --> $DIR/privacy-struct-ctor.rs:43:5 + | +43 | xcrate::m::S; //~ ERROR tuple struct `S` is private + | ^^^^^^^^^^^^ + +error: tuple struct `Z` is private + --> $DIR/privacy-struct-ctor.rs:47:5 + | +47 | xcrate::m::n::Z; //~ ERROR tuple struct `Z` is private + | ^^^^^^^^^^^^^^^ + +error: aborting due to 8 previous errors + From d880bbb35ff19a6e7c257eae6ef7c48df5eda9e6 Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Sun, 29 Jan 2017 08:17:34 +0200 Subject: [PATCH 030/137] Remove the workaround for gh32959 This workaround is no longer necessary as Rust, and by extension MIR, now support uninhabited type properly. This removes the workaround for the gh32959 that was introduced in gh33267. Fixes #32959 --- src/librustc_mir/build/block.rs | 5 +---- src/librustc_mir/build/expr/into.rs | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/librustc_mir/build/block.rs b/src/librustc_mir/build/block.rs index 73d3875ba2384..121d592da0316 100644 --- a/src/librustc_mir/build/block.rs +++ b/src/librustc_mir/build/block.rs @@ -16,8 +16,6 @@ use rustc::hir; impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { pub fn ast_block(&mut self, destination: &Lvalue<'tcx>, - // FIXME(#32959): temporary measure for the issue - dest_is_unit: bool, mut block: BasicBlock, ast_block: &'tcx hir::Block) -> BlockAnd<()> { @@ -83,8 +81,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // of the block. if let Some(expr) = expr { unpack!(block = this.into(destination, block, expr)); - } else if dest_is_unit { - // FIXME(#31472) + } else { let source_info = this.source_info(span); this.cfg.push_assign_unit(block, source_info, destination); } diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index 24b9c955658fd..3d4af259ec9f7 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -40,7 +40,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { this.in_scope(extent, block, |this| this.into(destination, block, value)) } ExprKind::Block { body: ast_block } => { - this.ast_block(destination, expr.ty.is_nil(), block, ast_block) + this.ast_block(destination, block, ast_block) } ExprKind::Match { discriminant, arms } => { this.match_expr(destination, expr_span, block, discriminant, arms) From 9128f6100c9bfe2c2c22d85ccec92f01166f5d25 Mon Sep 17 00:00:00 2001 From: Oliver Middleton Date: Sun, 29 Jan 2017 13:31:47 +0000 Subject: [PATCH 031/137] Fix a few impl stability attributes The versions show up in rustdoc. --- src/libcollections/binary_heap.rs | 4 ++-- src/libcore/char.rs | 6 +++--- src/libcore/internal_macros.rs | 16 ++++++++++++---- src/libcore/iter/traits.rs | 18 +++++++++++------- src/libcore/num/int_macros.rs | 6 +++--- src/libcore/num/uint_macros.rs | 6 +++--- src/libcore/num/wrapping.rs | 30 ++++++++++++++++++++---------- src/libcore/slice.rs | 14 +++++++------- src/libstd/ascii.rs | 2 +- src/libstd/collections/hash/map.rs | 16 ++++++++-------- src/libstd/collections/hash/set.rs | 14 +++++++------- src/libstd/env.rs | 10 +++++----- src/libstd/fs.rs | 2 +- src/libstd/io/mod.rs | 2 +- src/libstd/io/stdio.rs | 12 ++++++------ src/libstd/io/util.rs | 6 +++--- src/libstd/net/mod.rs | 5 ++++- src/libstd/os/raw.rs | 2 +- src/libstd/panic.rs | 2 +- src/libstd/process.rs | 10 +++++----- src/libstd/sync/barrier.rs | 4 ++-- src/libstd/sync/condvar.rs | 2 +- src/libstd/sync/mutex.rs | 2 +- src/libstd/sync/once.rs | 2 +- src/libstd/sync/rwlock.rs | 4 ++-- src/libstd/thread/local.rs | 3 +-- src/libstd/thread/mod.rs | 4 ++-- src/libstd_unicode/char.rs | 5 ++--- 28 files changed, 116 insertions(+), 93 deletions(-) diff --git a/src/libcollections/binary_heap.rs b/src/libcollections/binary_heap.rs index b7c2a708baf49..23e0295ba5401 100644 --- a/src/libcollections/binary_heap.rs +++ b/src/libcollections/binary_heap.rs @@ -1088,7 +1088,7 @@ impl<'a, T: 'a> ExactSizeIterator for Drain<'a, T> { #[unstable(feature = "fused", issue = "35602")] impl<'a, T: 'a> FusedIterator for Drain<'a, T> {} -#[stable(feature = "rust1", since = "1.0.0")] +#[stable(feature = "binary_heap_extras_15", since = "1.5.0")] impl From> for BinaryHeap { fn from(vec: Vec) -> BinaryHeap { let mut heap = BinaryHeap { data: vec }; @@ -1097,7 +1097,7 @@ impl From> for BinaryHeap { } } -#[stable(feature = "rust1", since = "1.0.0")] +#[stable(feature = "binary_heap_extras_15", since = "1.5.0")] impl From> for Vec { fn from(heap: BinaryHeap) -> Vec { heap.data diff --git a/src/libcore/char.rs b/src/libcore/char.rs index 367422f55364a..78764091cf032 100644 --- a/src/libcore/char.rs +++ b/src/libcore/char.rs @@ -588,7 +588,7 @@ impl ExactSizeIterator for EscapeUnicode { #[unstable(feature = "fused", issue = "35602")] impl FusedIterator for EscapeUnicode {} -#[stable(feature = "char_struct_display", since = "1.17.0")] +#[stable(feature = "char_struct_display", since = "1.16.0")] impl fmt::Display for EscapeUnicode { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { for c in self.clone() { @@ -701,7 +701,7 @@ impl ExactSizeIterator for EscapeDefault { #[unstable(feature = "fused", issue = "35602")] impl FusedIterator for EscapeDefault {} -#[stable(feature = "char_struct_display", since = "1.17.0")] +#[stable(feature = "char_struct_display", since = "1.16.0")] impl fmt::Display for EscapeDefault { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { for c in self.clone() { @@ -735,7 +735,7 @@ impl ExactSizeIterator for EscapeDebug { } #[unstable(feature = "fused", issue = "35602")] impl FusedIterator for EscapeDebug {} -#[stable(feature = "char_struct_display", since = "1.17.0")] +#[unstable(feature = "char_escape_debug", issue = "35068")] impl fmt::Display for EscapeDebug { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) diff --git a/src/libcore/internal_macros.rs b/src/libcore/internal_macros.rs index f2cdc9d6a98c5..9a7914064fdd5 100644 --- a/src/libcore/internal_macros.rs +++ b/src/libcore/internal_macros.rs @@ -13,7 +13,11 @@ // based on "op T" where T is expected to be `Copy`able macro_rules! forward_ref_unop { (impl $imp:ident, $method:ident for $t:ty) => { - #[stable(feature = "rust1", since = "1.0.0")] + forward_ref_unop!(impl $imp, $method for $t, + #[stable(feature = "rust1", since = "1.0.0")]); + }; + (impl $imp:ident, $method:ident for $t:ty, #[$attr:meta]) => { + #[$attr] impl<'a> $imp for &'a $t { type Output = <$t as $imp>::Output; @@ -29,7 +33,11 @@ macro_rules! forward_ref_unop { // based on "T op U" where T and U are expected to be `Copy`able macro_rules! forward_ref_binop { (impl $imp:ident, $method:ident for $t:ty, $u:ty) => { - #[stable(feature = "rust1", since = "1.0.0")] + forward_ref_binop!(impl $imp, $method for $t, $u, + #[stable(feature = "rust1", since = "1.0.0")]); + }; + (impl $imp:ident, $method:ident for $t:ty, $u:ty, #[$attr:meta]) => { + #[$attr] impl<'a> $imp<$u> for &'a $t { type Output = <$t as $imp<$u>>::Output; @@ -39,7 +47,7 @@ macro_rules! forward_ref_binop { } } - #[stable(feature = "rust1", since = "1.0.0")] + #[$attr] impl<'a> $imp<&'a $u> for $t { type Output = <$t as $imp<$u>>::Output; @@ -49,7 +57,7 @@ macro_rules! forward_ref_binop { } } - #[stable(feature = "rust1", since = "1.0.0")] + #[$attr] impl<'a, 'b> $imp<&'a $u> for &'b $t { type Output = <$t as $imp<$u>>::Output; diff --git a/src/libcore/iter/traits.rs b/src/libcore/iter/traits.rs index 1e12714830067..3e8d0600e1971 100644 --- a/src/libcore/iter/traits.rs +++ b/src/libcore/iter/traits.rs @@ -603,29 +603,29 @@ pub trait Product: Sized { // NB: explicitly use Add and Mul here to inherit overflow checks macro_rules! integer_sum_product { - (@impls $zero:expr, $one:expr, $($a:ty)*) => ($( - #[stable(feature = "iter_arith_traits", since = "1.12.0")] + (@impls $zero:expr, $one:expr, #[$attr:meta], $($a:ty)*) => ($( + #[$attr] impl Sum for $a { fn sum>(iter: I) -> $a { iter.fold($zero, Add::add) } } - #[stable(feature = "iter_arith_traits", since = "1.12.0")] + #[$attr] impl Product for $a { fn product>(iter: I) -> $a { iter.fold($one, Mul::mul) } } - #[stable(feature = "iter_arith_traits", since = "1.12.0")] + #[$attr] impl<'a> Sum<&'a $a> for $a { fn sum>(iter: I) -> $a { iter.fold($zero, Add::add) } } - #[stable(feature = "iter_arith_traits", since = "1.12.0")] + #[$attr] impl<'a> Product<&'a $a> for $a { fn product>(iter: I) -> $a { iter.fold($one, Mul::mul) @@ -633,8 +633,12 @@ macro_rules! integer_sum_product { } )*); ($($a:ty)*) => ( - integer_sum_product!(@impls 0, 1, $($a)+); - integer_sum_product!(@impls Wrapping(0), Wrapping(1), $(Wrapping<$a>)+); + integer_sum_product!(@impls 0, 1, + #[stable(feature = "iter_arith_traits", since = "1.12.0")], + $($a)+); + integer_sum_product!(@impls Wrapping(0), Wrapping(1), + #[stable(feature = "wrapping_iter_arith", since = "1.14.0")], + $(Wrapping<$a>)+); ); } diff --git a/src/libcore/num/int_macros.rs b/src/libcore/num/int_macros.rs index 04311d687ea92..3b1612a4ee29f 100644 --- a/src/libcore/num/int_macros.rs +++ b/src/libcore/num/int_macros.rs @@ -12,12 +12,12 @@ macro_rules! int_module { ($T:ident) => (int_module!($T, #[stable(feature = "rust1", since = "1.0.0")]);); - ($T:ident, $($attr: tt)*) => ( + ($T:ident, #[$attr:meta]) => ( /// The smallest value that can be represented by this integer type. - $($attr)* + #[$attr] pub const MIN: $T = $T::min_value(); /// The largest value that can be represented by this integer type. - $($attr)* + #[$attr] pub const MAX: $T = $T::max_value(); ) } diff --git a/src/libcore/num/uint_macros.rs b/src/libcore/num/uint_macros.rs index 2e59b39278ab6..f7e1f78d69ebf 100644 --- a/src/libcore/num/uint_macros.rs +++ b/src/libcore/num/uint_macros.rs @@ -12,12 +12,12 @@ macro_rules! uint_module { ($T:ident) => (uint_module!($T, #[stable(feature = "rust1", since = "1.0.0")]);); - ($T:ident, $($attr: tt)*) => ( + ($T:ident, #[$attr:meta]) => ( /// The smallest value that can be represented by this integer type. - $($attr)* + #[$attr] pub const MIN: $T = $T::min_value(); /// The largest value that can be represented by this integer type. - $($attr)* + #[$attr] pub const MAX: $T = $T::max_value(); ) } diff --git a/src/libcore/num/wrapping.rs b/src/libcore/num/wrapping.rs index b3c2c25551e0d..5d9e6ab129468 100644 --- a/src/libcore/num/wrapping.rs +++ b/src/libcore/num/wrapping.rs @@ -131,7 +131,8 @@ macro_rules! wrapping_impl { Wrapping(self.0.wrapping_add(other.0)) } } - forward_ref_binop! { impl Add, add for Wrapping<$t>, Wrapping<$t> } + forward_ref_binop! { impl Add, add for Wrapping<$t>, Wrapping<$t>, + #[stable(feature = "wrapping_ref", since = "1.14.0")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] impl AddAssign for Wrapping<$t> { @@ -150,7 +151,8 @@ macro_rules! wrapping_impl { Wrapping(self.0.wrapping_sub(other.0)) } } - forward_ref_binop! { impl Sub, sub for Wrapping<$t>, Wrapping<$t> } + forward_ref_binop! { impl Sub, sub for Wrapping<$t>, Wrapping<$t>, + #[stable(feature = "wrapping_ref", since = "1.14.0")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] impl SubAssign for Wrapping<$t> { @@ -169,7 +171,8 @@ macro_rules! wrapping_impl { Wrapping(self.0.wrapping_mul(other.0)) } } - forward_ref_binop! { impl Mul, mul for Wrapping<$t>, Wrapping<$t> } + forward_ref_binop! { impl Mul, mul for Wrapping<$t>, Wrapping<$t>, + #[stable(feature = "wrapping_ref", since = "1.14.0")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] impl MulAssign for Wrapping<$t> { @@ -188,7 +191,8 @@ macro_rules! wrapping_impl { Wrapping(self.0.wrapping_div(other.0)) } } - forward_ref_binop! { impl Div, div for Wrapping<$t>, Wrapping<$t> } + forward_ref_binop! { impl Div, div for Wrapping<$t>, Wrapping<$t>, + #[stable(feature = "wrapping_ref", since = "1.14.0")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] impl DivAssign for Wrapping<$t> { @@ -207,7 +211,8 @@ macro_rules! wrapping_impl { Wrapping(self.0.wrapping_rem(other.0)) } } - forward_ref_binop! { impl Rem, rem for Wrapping<$t>, Wrapping<$t> } + forward_ref_binop! { impl Rem, rem for Wrapping<$t>, Wrapping<$t>, + #[stable(feature = "wrapping_ref", since = "1.14.0")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] impl RemAssign for Wrapping<$t> { @@ -226,7 +231,8 @@ macro_rules! wrapping_impl { Wrapping(!self.0) } } - forward_ref_unop! { impl Not, not for Wrapping<$t> } + forward_ref_unop! { impl Not, not for Wrapping<$t>, + #[stable(feature = "wrapping_ref", since = "1.14.0")] } #[stable(feature = "rust1", since = "1.0.0")] impl BitXor for Wrapping<$t> { @@ -237,7 +243,8 @@ macro_rules! wrapping_impl { Wrapping(self.0 ^ other.0) } } - forward_ref_binop! { impl BitXor, bitxor for Wrapping<$t>, Wrapping<$t> } + forward_ref_binop! { impl BitXor, bitxor for Wrapping<$t>, Wrapping<$t>, + #[stable(feature = "wrapping_ref", since = "1.14.0")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] impl BitXorAssign for Wrapping<$t> { @@ -256,7 +263,8 @@ macro_rules! wrapping_impl { Wrapping(self.0 | other.0) } } - forward_ref_binop! { impl BitOr, bitor for Wrapping<$t>, Wrapping<$t> } + forward_ref_binop! { impl BitOr, bitor for Wrapping<$t>, Wrapping<$t>, + #[stable(feature = "wrapping_ref", since = "1.14.0")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] impl BitOrAssign for Wrapping<$t> { @@ -275,7 +283,8 @@ macro_rules! wrapping_impl { Wrapping(self.0 & other.0) } } - forward_ref_binop! { impl BitAnd, bitand for Wrapping<$t>, Wrapping<$t> } + forward_ref_binop! { impl BitAnd, bitand for Wrapping<$t>, Wrapping<$t>, + #[stable(feature = "wrapping_ref", since = "1.14.0")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] impl BitAndAssign for Wrapping<$t> { @@ -293,7 +302,8 @@ macro_rules! wrapping_impl { Wrapping(0) - self } } - forward_ref_unop! { impl Neg, neg for Wrapping<$t> } + forward_ref_unop! { impl Neg, neg for Wrapping<$t>, + #[stable(feature = "wrapping_ref", since = "1.14.0")] } )*) } diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index b942d85f9808b..1a482b75731c1 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -616,7 +616,7 @@ pub trait SliceIndex { fn index_mut(self, slice: &mut [T]) -> &mut Self::Output; } -#[stable(feature = "slice-get-slice-impls", since = "1.13.0")] +#[stable(feature = "slice-get-slice-impls", since = "1.15.0")] impl SliceIndex for usize { type Output = T; @@ -665,7 +665,7 @@ impl SliceIndex for usize { } } -#[stable(feature = "slice-get-slice-impls", since = "1.13.0")] +#[stable(feature = "slice-get-slice-impls", since = "1.15.0")] impl SliceIndex for ops::Range { type Output = [T]; @@ -726,7 +726,7 @@ impl SliceIndex for ops::Range { } } -#[stable(feature = "slice-get-slice-impls", since = "1.13.0")] +#[stable(feature = "slice-get-slice-impls", since = "1.15.0")] impl SliceIndex for ops::RangeTo { type Output = [T]; @@ -761,7 +761,7 @@ impl SliceIndex for ops::RangeTo { } } -#[stable(feature = "slice-get-slice-impls", since = "1.13.0")] +#[stable(feature = "slice-get-slice-impls", since = "1.15.0")] impl SliceIndex for ops::RangeFrom { type Output = [T]; @@ -796,7 +796,7 @@ impl SliceIndex for ops::RangeFrom { } } -#[stable(feature = "slice-get-slice-impls", since = "1.13.0")] +#[stable(feature = "slice-get-slice-impls", since = "1.15.0")] impl SliceIndex for ops::RangeFull { type Output = [T]; @@ -832,7 +832,7 @@ impl SliceIndex for ops::RangeFull { } -#[stable(feature = "slice-get-slice-impls", since = "1.13.0")] +#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] impl SliceIndex for ops::RangeInclusive { type Output = [T]; @@ -895,7 +895,7 @@ impl SliceIndex for ops::RangeInclusive { } } -#[stable(feature = "slice-get-slice-impls", since = "1.13.0")] +#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] impl SliceIndex for ops::RangeToInclusive { type Output = [T]; diff --git a/src/libstd/ascii.rs b/src/libstd/ascii.rs index b220504d2b4f5..35c388ba076ce 100644 --- a/src/libstd/ascii.rs +++ b/src/libstd/ascii.rs @@ -399,7 +399,7 @@ impl ExactSizeIterator for EscapeDefault {} #[unstable(feature = "fused", issue = "35602")] impl FusedIterator for EscapeDefault {} -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for EscapeDefault { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("EscapeDefault { .. }") diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index a314717a8772b..2a4826f804581 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -1276,7 +1276,7 @@ impl<'a, K, V> Clone for Iter<'a, K, V> { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<'a, K: Debug, V: Debug> fmt::Debug for Iter<'a, K, V> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_list() @@ -1311,7 +1311,7 @@ impl<'a, K, V> Clone for Keys<'a, K, V> { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<'a, K: Debug, V: Debug> fmt::Debug for Keys<'a, K, V> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_list() @@ -1334,7 +1334,7 @@ impl<'a, K, V> Clone for Values<'a, K, V> { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<'a, K: Debug, V: Debug> fmt::Debug for Values<'a, K, V> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_list() @@ -1584,7 +1584,7 @@ impl<'a, K, V> ExactSizeIterator for IterMut<'a, K, V> { #[unstable(feature = "fused", issue = "35602")] impl<'a, K, V> FusedIterator for IterMut<'a, K, V> {} -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<'a, K, V> fmt::Debug for IterMut<'a, K, V> where K: fmt::Debug, V: fmt::Debug, @@ -1619,7 +1619,7 @@ impl ExactSizeIterator for IntoIter { #[unstable(feature = "fused", issue = "35602")] impl FusedIterator for IntoIter {} -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for IntoIter { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_list() @@ -1697,7 +1697,7 @@ impl<'a, K, V> ExactSizeIterator for ValuesMut<'a, K, V> { #[unstable(feature = "fused", issue = "35602")] impl<'a, K, V> FusedIterator for ValuesMut<'a, K, V> {} -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<'a, K, V> fmt::Debug for ValuesMut<'a, K, V> where K: fmt::Debug, V: fmt::Debug, @@ -1732,7 +1732,7 @@ impl<'a, K, V> ExactSizeIterator for Drain<'a, K, V> { #[unstable(feature = "fused", issue = "35602")] impl<'a, K, V> FusedIterator for Drain<'a, K, V> {} -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<'a, K, V> fmt::Debug for Drain<'a, K, V> where K: fmt::Debug, V: fmt::Debug, @@ -2220,7 +2220,7 @@ impl Default for RandomState { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for RandomState { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("RandomState { .. }") diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index 341b050862f5c..a3f7e13bbf913 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -948,7 +948,7 @@ impl<'a, K> ExactSizeIterator for Iter<'a, K> { #[unstable(feature = "fused", issue = "35602")] impl<'a, K> FusedIterator for Iter<'a, K> {} -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<'a, K: fmt::Debug> fmt::Debug for Iter<'a, K> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_list() @@ -977,7 +977,7 @@ impl ExactSizeIterator for IntoIter { #[unstable(feature = "fused", issue = "35602")] impl FusedIterator for IntoIter {} -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for IntoIter { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let entries_iter = self.iter.inner.iter().map(|(k, _)| k); @@ -1007,7 +1007,7 @@ impl<'a, K> ExactSizeIterator for Drain<'a, K> { #[unstable(feature = "fused", issue = "35602")] impl<'a, K> FusedIterator for Drain<'a, K> {} -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<'a, K: fmt::Debug> fmt::Debug for Drain<'a, K> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let entries_iter = self.iter.inner.iter().map(|(k, _)| k); @@ -1050,7 +1050,7 @@ impl<'a, T, S> Iterator for Intersection<'a, T, S> } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<'a, T, S> fmt::Debug for Intersection<'a, T, S> where T: fmt::Debug + Eq + Hash, S: BuildHasher, @@ -1109,7 +1109,7 @@ impl<'a, T, S> FusedIterator for Difference<'a, T, S> { } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<'a, T, S> fmt::Debug for Difference<'a, T, S> where T: fmt::Debug + Eq + Hash, S: BuildHasher, @@ -1150,7 +1150,7 @@ impl<'a, T, S> FusedIterator for SymmetricDifference<'a, T, S> { } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<'a, T, S> fmt::Debug for SymmetricDifference<'a, T, S> where T: fmt::Debug + Eq + Hash, S: BuildHasher, @@ -1176,7 +1176,7 @@ impl<'a, T, S> FusedIterator for Union<'a, T, S> { } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<'a, T, S> fmt::Debug for Union<'a, T, S> where T: fmt::Debug + Eq + Hash, S: BuildHasher, diff --git a/src/libstd/env.rs b/src/libstd/env.rs index c3a6b2433ed88..29f2ac6ab444c 100644 --- a/src/libstd/env.rs +++ b/src/libstd/env.rs @@ -145,7 +145,7 @@ impl Iterator for Vars { fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Vars { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("Vars { .. }") @@ -159,7 +159,7 @@ impl Iterator for VarsOs { fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for VarsOs { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("VarsOs { .. }") @@ -382,7 +382,7 @@ impl<'a> Iterator for SplitPaths<'a> { fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<'a> fmt::Debug for SplitPaths<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("SplitPaths { .. }") @@ -665,7 +665,7 @@ impl DoubleEndedIterator for Args { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Args { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("Args { .. }") @@ -690,7 +690,7 @@ impl DoubleEndedIterator for ArgsOs { fn next_back(&mut self) -> Option { self.inner.next_back() } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for ArgsOs { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("ArgsOs { .. }") diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index 249627c430cb7..e5562d05f10ae 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -869,7 +869,7 @@ impl Metadata { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Metadata { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("Metadata") diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index de5fc5bfad137..8cb7b2bda7554 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -1450,7 +1450,7 @@ pub struct Chain { done_first: bool, } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Chain { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("Chain") diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs index 83a675eb512e5..e16e8019b5f73 100644 --- a/src/libstd/io/stdio.rs +++ b/src/libstd/io/stdio.rs @@ -282,7 +282,7 @@ impl Stdin { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Stdin { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("Stdin { .. }") @@ -321,7 +321,7 @@ impl<'a> BufRead for StdinLock<'a> { fn consume(&mut self, n: usize) { self.inner.consume(n) } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<'a> fmt::Debug for StdinLock<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("StdinLock { .. }") @@ -438,7 +438,7 @@ impl Stdout { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Stdout { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("Stdout { .. }") @@ -470,7 +470,7 @@ impl<'a> Write for StdoutLock<'a> { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<'a> fmt::Debug for StdoutLock<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("StdoutLock { .. }") @@ -573,7 +573,7 @@ impl Stderr { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Stderr { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("Stderr { .. }") @@ -605,7 +605,7 @@ impl<'a> Write for StderrLock<'a> { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<'a> fmt::Debug for StderrLock<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("StderrLock { .. }") diff --git a/src/libstd/io/util.rs b/src/libstd/io/util.rs index e50665120eb47..4163187488e65 100644 --- a/src/libstd/io/util.rs +++ b/src/libstd/io/util.rs @@ -98,7 +98,7 @@ impl BufRead for Empty { fn consume(&mut self, _n: usize) {} } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Empty { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("Empty { .. }") @@ -141,7 +141,7 @@ impl Read for Repeat { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Repeat { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("Repeat { .. }") @@ -180,7 +180,7 @@ impl Write for Sink { fn flush(&mut self) -> io::Result<()> { Ok(()) } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Sink { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("Sink { .. }") diff --git a/src/libstd/net/mod.rs b/src/libstd/net/mod.rs index 2b60fc38198ec..b0d2e3e4687b4 100644 --- a/src/libstd/net/mod.rs +++ b/src/libstd/net/mod.rs @@ -106,7 +106,10 @@ impl Iterator for LookupHost { fn next(&mut self) -> Option { self.0.next() } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[unstable(feature = "lookup_host", reason = "unsure about the returned \ + iterator and returning socket \ + addresses", + issue = "27705")] impl fmt::Debug for LookupHost { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("LookupHost { .. }") diff --git a/src/libstd/os/raw.rs b/src/libstd/os/raw.rs index cc154f7ab413b..68d4ca900195c 100644 --- a/src/libstd/os/raw.rs +++ b/src/libstd/os/raw.rs @@ -73,7 +73,7 @@ pub enum c_void { #[doc(hidden)] __variant2, } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for c_void { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("c_void") diff --git a/src/libstd/panic.rs b/src/libstd/panic.rs index faf4949e86192..ac0d0d2afb803 100644 --- a/src/libstd/panic.rs +++ b/src/libstd/panic.rs @@ -297,7 +297,7 @@ impl R> FnOnce<()> for AssertUnwindSafe { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for AssertUnwindSafe { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_tuple("AssertUnwindSafe") diff --git a/src/libstd/process.rs b/src/libstd/process.rs index 5af4ba53bf9a5..e44c01e32a128 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -114,7 +114,7 @@ impl IntoInner for Child { fn into_inner(self) -> imp::Process { self.handle } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Child { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("Child") @@ -160,7 +160,7 @@ impl FromInner for ChildStdin { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for ChildStdin { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("ChildStdin { .. }") @@ -201,7 +201,7 @@ impl FromInner for ChildStdout { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for ChildStdout { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("ChildStdout { .. }") @@ -242,7 +242,7 @@ impl FromInner for ChildStderr { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for ChildStderr { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("ChildStderr { .. }") @@ -696,7 +696,7 @@ impl FromInner for Stdio { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Stdio { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("Stdio { .. }") diff --git a/src/libstd/sync/barrier.rs b/src/libstd/sync/barrier.rs index b8e83dced8d4b..fc4fd4ce92b1b 100644 --- a/src/libstd/sync/barrier.rs +++ b/src/libstd/sync/barrier.rs @@ -55,7 +55,7 @@ struct BarrierState { #[stable(feature = "rust1", since = "1.0.0")] pub struct BarrierWaitResult(bool); -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Barrier { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("Barrier { .. }") @@ -110,7 +110,7 @@ impl Barrier { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for BarrierWaitResult { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("BarrierWaitResult") diff --git a/src/libstd/sync/condvar.rs b/src/libstd/sync/condvar.rs index 8ab30c51b282e..d5bfc331c4ef1 100644 --- a/src/libstd/sync/condvar.rs +++ b/src/libstd/sync/condvar.rs @@ -240,7 +240,7 @@ impl Condvar { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Condvar { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("Condvar { .. }") diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs index 2efddeb4610dd..0d6ad5e38e98b 100644 --- a/src/libstd/sync/mutex.rs +++ b/src/libstd/sync/mutex.rs @@ -428,7 +428,7 @@ impl<'a, T: ?Sized> Drop for MutexGuard<'a, T> { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<'a, T: ?Sized + fmt::Debug> fmt::Debug for MutexGuard<'a, T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("MutexGuard") diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs index a9747639aacd7..ba99375139139 100644 --- a/src/libstd/sync/once.rs +++ b/src/libstd/sync/once.rs @@ -330,7 +330,7 @@ impl Once { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Once { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("Once { .. }") diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs index adbb98e4b1f4f..a3db0adeda00d 100644 --- a/src/libstd/sync/rwlock.rs +++ b/src/libstd/sync/rwlock.rs @@ -361,7 +361,7 @@ impl<'rwlock, T: ?Sized> RwLockWriteGuard<'rwlock, T> { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<'a, T: fmt::Debug> fmt::Debug for RwLockReadGuard<'a, T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("RwLockReadGuard") @@ -370,7 +370,7 @@ impl<'a, T: fmt::Debug> fmt::Debug for RwLockReadGuard<'a, T> { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl<'a, T: fmt::Debug> fmt::Debug for RwLockWriteGuard<'a, T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("RwLockWriteGuard") diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs index 01584979aabaa..5166ddf8a21b6 100644 --- a/src/libstd/thread/local.rs +++ b/src/libstd/thread/local.rs @@ -99,7 +99,7 @@ pub struct LocalKey { init: fn() -> T, } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for LocalKey { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("LocalKey { .. }") @@ -332,7 +332,6 @@ pub mod os { marker: marker::PhantomData>, } - #[stable(feature = "std_debug", since = "1.15.0")] impl fmt::Debug for Key { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("Key { .. }") diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 8789006436c0c..93e320c45223c 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -698,7 +698,7 @@ impl ThreadId { } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[unstable(feature = "thread_id", issue = "21507")] impl fmt::Debug for ThreadId { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("ThreadId { .. }") @@ -1002,7 +1002,7 @@ impl IntoInner for JoinHandle { fn into_inner(self) -> imp::Thread { self.0.native.unwrap() } } -#[stable(feature = "std_debug", since = "1.15.0")] +#[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for JoinHandle { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("JoinHandle { .. }") diff --git a/src/libstd_unicode/char.rs b/src/libstd_unicode/char.rs index f2c53efda1737..4269ce8534bd0 100644 --- a/src/libstd_unicode/char.rs +++ b/src/libstd_unicode/char.rs @@ -131,7 +131,6 @@ impl Iterator for CaseMappingIter { } } -#[stable(feature = "char_struct_display", since = "1.17.0")] impl fmt::Display for CaseMappingIter { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { @@ -152,14 +151,14 @@ impl fmt::Display for CaseMappingIter { } } -#[stable(feature = "char_struct_display", since = "1.17.0")] +#[stable(feature = "char_struct_display", since = "1.16.0")] impl fmt::Display for ToLowercase { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) } } -#[stable(feature = "char_struct_display", since = "1.17.0")] +#[stable(feature = "char_struct_display", since = "1.16.0")] impl fmt::Display for ToUppercase { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) From 4af76e88f3e40d44b06e58d14ba35c0f1114bcdd Mon Sep 17 00:00:00 2001 From: Clar Charr Date: Sun, 29 Jan 2017 13:35:40 -0500 Subject: [PATCH 032/137] Add Iterator::rfind. --- src/libcore/iter/iterator.rs | 58 ++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs index 3b406873d4b19..0d34e06193c8f 100644 --- a/src/libcore/iter/iterator.rs +++ b/src/libcore/iter/iterator.rs @@ -1488,6 +1488,64 @@ pub trait Iterator { None } + /// Searches for an element of an iterator from the right that satisfies a predicate. + /// + /// `rfind()` takes a closure that returns `true` or `false`. It applies + /// this closure to each element of the iterator, starting at the end, and if any + /// of them return `true`, then `rfind()` returns [`Some(element)`]. If they all return + /// `false`, it returns [`None`]. + /// + /// `rfind()` is short-circuiting; in other words, it will stop processing + /// as soon as the closure returns `true`. + /// + /// Because `rfind()` takes a reference, and many iterators iterate over + /// references, this leads to a possibly confusing situation where the + /// argument is a double reference. You can see this effect in the + /// examples below, with `&&x`. + /// + /// [`Some(element)`]: ../../std/option/enum.Option.html#variant.Some + /// [`None`]: ../../std/option/enum.Option.html#variant.None + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(iter_rfind)] + /// + /// let a = [1, 2, 3]; + /// + /// assert_eq!(a.iter().rfind(|&&x| x == 2), Some(&2)); + /// + /// assert_eq!(a.iter().rfind(|&&x| x == 5), None); + /// ``` + /// + /// Stopping at the first `true`: + /// + /// ``` + /// #![feature(iter_rfind)] + /// + /// let a = [1, 2, 3]; + /// + /// let mut iter = a.iter(); + /// + /// assert_eq!(iter.rfind(|&&x| x == 2), Some(&2)); + /// + /// // we can still use `iter`, as there are more elements. + /// assert_eq!(iter.next_back(), Some(&1)); + /// ``` + #[inline] + #[unstable(feature = "iter_rfind", issue = "0")] + fn rfind

(&mut self, mut predicate: P) -> Option where + Self: Sized + DoubleEndedIterator, + P: FnMut(&Self::Item) -> bool + { + for x in self.by_ref().rev() { + if predicate(&x) { return Some(x) } + } + None + } + /// Searches for an element in an iterator, returning its index. /// /// `position()` takes a closure that returns `true` or `false`. It applies From 986dd077eabd5b4bb313ed2e3b864106f8076fc0 Mon Sep 17 00:00:00 2001 From: king6cong Date: Mon, 30 Jan 2017 10:12:10 +0800 Subject: [PATCH 033/137] doc comment reword --- src/librustc_driver/driver.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index a7188f6da1ff9..5603ecb1c0419 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -780,7 +780,7 @@ pub fn phase_2_configure_and_expand(sess: &Session, hir_map::Forest::new(hir_crate, &sess.dep_graph) }); - // Discard hygiene data, which isn't required past lowering to HIR. + // Discard hygiene data, which isn't required after lowering to HIR. if !keep_hygiene_data(sess) { syntax::ext::hygiene::reset_hygiene_data(); } From 701c32ed4ab5014671f7237ab115817b9130d3bb Mon Sep 17 00:00:00 2001 From: king6cong Date: Mon, 30 Jan 2017 10:22:26 +0800 Subject: [PATCH 034/137] unify time_passes argument passing --- src/librustc_driver/driver.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 5603ecb1c0419..a04a5b106b8f1 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -741,15 +741,15 @@ pub fn phase_2_configure_and_expand(sess: &Session, "checking for inline asm in case the target doesn't support it", || no_asm::check_crate(sess, &krate)); - time(sess.time_passes(), + time(time_passes, "early lint checks", || lint::check_ast_crate(sess, &krate)); - time(sess.time_passes(), + time(time_passes, "AST validation", || ast_validation::check_crate(sess, &krate)); - time(sess.time_passes(), "name resolution", || -> CompileResult { + time(time_passes, "name resolution", || -> CompileResult { // Since import resolution will eventually happen in expansion, // don't perform `after_expand` until after import resolution. after_expand(&krate)?; @@ -770,7 +770,7 @@ pub fn phase_2_configure_and_expand(sess: &Session, })?; // Lower ast -> hir. - let hir_forest = time(sess.time_passes(), "lowering ast -> hir", || { + let hir_forest = time(time_passes, "lowering ast -> hir", || { let hir_crate = lower_crate(sess, &krate, &mut resolver); if sess.opts.debugging_opts.hir_stats { From 4b46d2a3a222f090b07b019df0e9346b08c40ae1 Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Mon, 30 Jan 2017 17:37:49 +0100 Subject: [PATCH 035/137] Don't handle ENOSYS in `anon_pipe()` We're not calling the raw syscall but a libc function, the libc will have a compatibility layer. --- src/libstd/sys/unix/pipe.rs | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/src/libstd/sys/unix/pipe.rs b/src/libstd/sys/unix/pipe.rs index a5d60c257ed63..51e00fc1ab96a 100644 --- a/src/libstd/sys/unix/pipe.rs +++ b/src/libstd/sys/unix/pipe.rs @@ -13,7 +13,6 @@ use io; use libc::{self, c_int}; use mem; use ptr; -use sync::atomic::{AtomicBool, Ordering}; use sys::{cvt, cvt_r}; use sys::fd::FileDesc; @@ -30,21 +29,17 @@ pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> { // CLOEXEC flag is to use the `pipe2` syscall on Linux. This was added in // 2.6.27, however, and because we support 2.6.18 we must detect this // support dynamically. - static TRY_PIPE2: AtomicBool = AtomicBool::new(cfg!(target_os = "linux")); - if TRY_PIPE2.load(Ordering::Relaxed) { + if cfg!(any(target_os = "dragonfly", + target_os = "freebsd", + target_os = "linux", + target_os = "netbsd", + target_os = "openbsd")) + { weak! { fn pipe2(*mut c_int, c_int) -> c_int } if let Some(pipe) = pipe2.get() { - match cvt(unsafe { pipe(fds.as_mut_ptr(), libc::O_CLOEXEC) }) { - Err(ref e) if e.raw_os_error() == Some(libc::ENOSYS) => { - TRY_PIPE2.store(false, Ordering::Relaxed); - // Fall through - }, - res => { - res?; - return Ok((AnonPipe(FileDesc::new(fds[0])), - AnonPipe(FileDesc::new(fds[1])))); - } - } + cvt(unsafe { pipe(fds.as_mut_ptr(), libc::O_CLOEXEC) })?; + return Ok((AnonPipe(FileDesc::new(fds[0])), + AnonPipe(FileDesc::new(fds[1])))); } } cvt(unsafe { libc::pipe(fds.as_mut_ptr()) })?; From bcca5e64544d55ae090b05048496c478bac22d59 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Tue, 10 Nov 2015 12:42:37 -0500 Subject: [PATCH 036/137] trans::debuginfo: simplify --- src/librustc_trans/debuginfo/utils.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/librustc_trans/debuginfo/utils.rs b/src/librustc_trans/debuginfo/utils.rs index 3ee2497009f65..8d634c0e292ad 100644 --- a/src/librustc_trans/debuginfo/utils.rs +++ b/src/librustc_trans/debuginfo/utils.rs @@ -60,8 +60,7 @@ pub fn bytes_to_bits(bytes: u64) -> u64 { #[inline] pub fn debug_context<'a, 'tcx>(cx: &'a CrateContext<'a, 'tcx>) -> &'a CrateDebugContext<'tcx> { - let debug_context: &'a CrateDebugContext<'tcx> = cx.dbg_cx().as_ref().unwrap(); - debug_context + cx.dbg_cx().as_ref().unwrap() } #[inline] From 83fe5325d23fc77ff326db168c854cbc28e19258 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Sun, 8 Nov 2015 13:39:27 -0500 Subject: [PATCH 037/137] statics in match arm: compile with -g Closes #24956. --- src/test/run-pass/match-arm-statics.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/run-pass/match-arm-statics.rs b/src/test/run-pass/match-arm-statics.rs index 9700ed247959b..78a37f5183786 100644 --- a/src/test/run-pass/match-arm-statics.rs +++ b/src/test/run-pass/match-arm-statics.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// compile-flags: -g #[derive(PartialEq, Eq)] struct NewBool(bool); From 775b32305f8ec9ed18d6cc8ff13bd8af8f4be14a Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 30 Jan 2017 15:21:32 -0800 Subject: [PATCH 038/137] travis: Really delete the `doc` folder Got two location to look at, be sure to delete them both. --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 5abbdbc599bd8..7afa97260f5a3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -108,11 +108,12 @@ cache: before_deploy: - mkdir -p deploy/$TRAVIS_COMMIT - - rm -rf build/dist/doc - > if [ "$TRAVIS_OS_NAME" == "osx" ]; then + rm -rf build/dist/doc && cp -r build/dist/* deploy/$TRAVIS_COMMIT; else + rm -rf obj/build/dist/doc && cp -r obj/build/dist/* deploy/$TRAVIS_COMMIT; fi From fe324cea6490fc6e7ce16fb5209fde57cfa1b94f Mon Sep 17 00:00:00 2001 From: Trevor Spiteri Date: Tue, 31 Jan 2017 00:57:52 +0100 Subject: [PATCH 039/137] rustdoc: mark ffi functions with unsafety icon --- src/librustdoc/html/render.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 52257653405e0..40eb7e5ab78c3 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1806,12 +1806,13 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context, String::new() }; - let mut unsafety_flag = ""; - if let clean::FunctionItem(ref func) = myitem.inner { - if func.unsafety == hir::Unsafety::Unsafe { - unsafety_flag = ""; + let unsafety_flag = match myitem.inner { + clean::FunctionItem(ref func) | clean::ForeignFunctionItem(ref func) + if func.unsafety == hir::Unsafety::Unsafe => { + "" } - } + _ => "", + }; let doc_value = myitem.doc_value().unwrap_or(""); write!(w, " From b13d9ce2220a9769b526fb65e7d411ada8db34c9 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 30 Jan 2017 20:19:00 -0700 Subject: [PATCH 040/137] Add dev and ino to MetadataExt --- src/libstd/sys/redox/ext/fs.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/libstd/sys/redox/ext/fs.rs b/src/libstd/sys/redox/ext/fs.rs index 7ad8d27b48330..fc81cc737d9f0 100644 --- a/src/libstd/sys/redox/ext/fs.rs +++ b/src/libstd/sys/redox/ext/fs.rs @@ -160,6 +160,10 @@ impl OpenOptionsExt for OpenOptions { // casts and rely on manual lowering to `stat` if the raw type is desired. #[stable(feature = "metadata_ext", since = "1.1.0")] pub trait MetadataExt { + #[stable(feature = "metadata_ext", since = "1.1.0")] + fn dev(&self) -> u64; + #[stable(feature = "metadata_ext", since = "1.1.0")] + fn ino(&self) -> u64; #[stable(feature = "metadata_ext", since = "1.1.0")] fn mode(&self) -> u32; #[stable(feature = "metadata_ext", since = "1.1.0")] @@ -184,6 +188,12 @@ pub trait MetadataExt { #[stable(feature = "metadata_ext", since = "1.1.0")] impl MetadataExt for fs::Metadata { + fn dev(&self) -> u64 { + self.as_inner().as_inner().st_dev as u64 + } + fn ino(&self) -> u64 { + self.as_inner().as_inner().st_ino as u64 + } fn mode(&self) -> u32 { self.as_inner().as_inner().st_mode as u32 } From d73e84d2e7a7733d507ed7a3a44af4ab7941ce88 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 31 Jan 2017 14:45:08 +0100 Subject: [PATCH 041/137] use suggestions instead of helps with code in them --- src/librustc_const_eval/eval.rs | 2 -- src/libsyntax/parse/parser.rs | 27 ++++++++++++++++++--- src/test/compile-fail/missing-block-hint.rs | 3 ++- src/test/parse-fail/tuple-float-index.rs | 3 ++- 4 files changed, 27 insertions(+), 8 deletions(-) diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index a9dcb1ed89613..47a98155fc4b0 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//#![allow(non_camel_case_types)] - use rustc::middle::const_val::ConstVal::*; use rustc::middle::const_val::ConstVal; use self::ErrKind::*; diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 3480db8ec3b7d..2532a1def7dda 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2456,9 +2456,21 @@ impl<'a> Parser<'a> { Some(f) => f, None => continue, }; - err.help(&format!("try parenthesizing the first index; e.g., `(foo.{}){}`", - float.trunc() as usize, - format!(".{}", fstr.splitn(2, ".").last().unwrap()))); + let sugg = pprust::to_string(|s| { + use print::pprust::PrintState; + use print::pp::word; + s.popen()?; + s.print_expr(&e)?; + word(&mut s.s, ".")?; + s.print_usize(float.trunc() as usize)?; + s.pclose()?; + word(&mut s.s, ".")?; + word(&mut s.s, fstr.splitn(2, ".").last().unwrap()) + }); + err.span_suggestion( + prev_span, + "try parenthesizing the first index", + sugg); } return Err(err); @@ -3900,7 +3912,14 @@ impl<'a> Parser<'a> { if self.eat(&token::Semi) { stmt_span.hi = self.prev_span.hi; } - e.span_help(stmt_span, "try placing this code inside a block"); + let sugg = pprust::to_string(|s| { + use print::pprust::{PrintState, INDENT_UNIT}; + s.ibox(INDENT_UNIT)?; + s.bopen()?; + s.print_stmt(&stmt)?; + s.bclose_maybe_open(stmt.span, INDENT_UNIT, false) + }); + e.span_suggestion(stmt_span, "try placing this code inside a block", sugg); } Err(mut e) => { self.recover_stmt_(SemiColonMode::Break); diff --git a/src/test/compile-fail/missing-block-hint.rs b/src/test/compile-fail/missing-block-hint.rs index 1f29ff4e05c09..6a140e6f21c19 100644 --- a/src/test/compile-fail/missing-block-hint.rs +++ b/src/test/compile-fail/missing-block-hint.rs @@ -15,6 +15,7 @@ fn main() { { if (foo) bar; //~ ERROR expected `{`, found `bar` - //^ HELP try placing this code inside a block + //~^ HELP try placing this code inside a block + //~| SUGGESTION { bar; } } } diff --git a/src/test/parse-fail/tuple-float-index.rs b/src/test/parse-fail/tuple-float-index.rs index f3f5e35634682..57ad89ad37404 100644 --- a/src/test/parse-fail/tuple-float-index.rs +++ b/src/test/parse-fail/tuple-float-index.rs @@ -12,5 +12,6 @@ fn main () { (1, (2, 3)).1.1; //~ ERROR unexpected token - //~^ HELP try parenthesizing the first index; e.g., `(foo.1).1` + //~^ HELP try parenthesizing the first index + //~| SUGGESTION ((1, (2, 3)).1).1 } From d848f1d7821a22ec2462e08401f966074041c324 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 31 Jan 2017 04:35:17 -0500 Subject: [PATCH 042/137] rewrite the predecessors code to create a reduced graph The old code created a flat listing of "HIR -> WorkProduct" edges. While perfectly general, this could lead to a lot of repetition if the same HIR nodes affect many work-products. This is set to be a problem when we start to skip typeck, since we will be adding a lot more "work-product"-like nodes. The newer code uses an alternative strategy: it "reduces" the graph instead. Basically we walk the dep-graph and convert it to a DAG, where we only keep intermediate nodes if they are used by multiple work-products. This DAG does not contain the same set of nodes as the original graph, but it is guaranteed that (a) every output node is included in the graph and (b) the set of input nodes that can reach each output node is unchanged. (Input nodes are basically HIR nodes and foreign metadata; output nodes are nodes that have assocaited state which we will persist to disk in some way. These are assumed to be disjoint sets.) --- src/librustc_incremental/lib.rs | 3 + .../persist/dirty_clean.rs | 6 +- src/librustc_incremental/persist/load.rs | 155 ++++---- src/librustc_incremental/persist/preds.rs | 366 ------------------ .../persist/preds/compress/README.md | 48 +++ .../persist/preds/compress/classify/mod.rs | 139 +++++++ .../persist/preds/compress/classify/test.rs | 79 ++++ .../persist/preds/compress/construct.rs | 201 ++++++++++ .../persist/preds/compress/dag_id.rs | 33 ++ .../persist/preds/compress/mod.rs | 125 ++++++ .../persist/preds/compress/test.rs | 243 ++++++++++++ .../persist/preds/compress/test_macro.rs | 40 ++ src/librustc_incremental/persist/preds/mod.rs | 75 ++++ src/librustc_incremental/persist/save.rs | 49 ++- 14 files changed, 1095 insertions(+), 467 deletions(-) delete mode 100644 src/librustc_incremental/persist/preds.rs create mode 100644 src/librustc_incremental/persist/preds/compress/README.md create mode 100644 src/librustc_incremental/persist/preds/compress/classify/mod.rs create mode 100644 src/librustc_incremental/persist/preds/compress/classify/test.rs create mode 100644 src/librustc_incremental/persist/preds/compress/construct.rs create mode 100644 src/librustc_incremental/persist/preds/compress/dag_id.rs create mode 100644 src/librustc_incremental/persist/preds/compress/mod.rs create mode 100644 src/librustc_incremental/persist/preds/compress/test.rs create mode 100644 src/librustc_incremental/persist/preds/compress/test_macro.rs create mode 100644 src/librustc_incremental/persist/preds/mod.rs diff --git a/src/librustc_incremental/lib.rs b/src/librustc_incremental/lib.rs index a866a15c4d280..e3c339829f6a4 100644 --- a/src/librustc_incremental/lib.rs +++ b/src/librustc_incremental/lib.rs @@ -23,6 +23,9 @@ #![feature(staged_api)] #![feature(rand)] #![feature(core_intrinsics)] +#![feature(conservative_impl_trait)] +#![feature(field_init_shorthand)] +#![feature(pub_restricted)] extern crate graphviz; #[macro_use] extern crate rustc; diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs index 6e66dac6470f0..798bc6e9f9856 100644 --- a/src/librustc_incremental/persist/dirty_clean.rs +++ b/src/librustc_incremental/persist/dirty_clean.rs @@ -67,9 +67,9 @@ pub fn check_dirty_clean_annotations<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let _ignore = tcx.dep_graph.in_ignore(); let dirty_inputs: FxHashSet> = - dirty_inputs.iter() - .filter_map(|d| retraced.map(d)) - .collect(); + dirty_inputs.keys() + .filter_map(|d| retraced.map(d)) + .collect(); let query = tcx.dep_graph.query(); debug!("query-nodes: {:?}", query.nodes()); let krate = tcx.hir.krate(); diff --git a/src/librustc_incremental/persist/load.rs b/src/librustc_incremental/persist/load.rs index 433110a2a6de0..e9a59fd762972 100644 --- a/src/librustc_incremental/persist/load.rs +++ b/src/librustc_incremental/persist/load.rs @@ -10,7 +10,7 @@ //! Code to save/load the dep-graph from files. -use rustc::dep_graph::DepNode; +use rustc::dep_graph::{DepNode, WorkProductId}; use rustc::hir::def_id::DefId; use rustc::hir::svh::Svh; use rustc::session::Session; @@ -19,6 +19,7 @@ use rustc_data_structures::fx::{FxHashSet, FxHashMap}; use rustc_serialize::Decodable as RustcDecodable; use rustc_serialize::opaque::Decoder; use std::path::{Path}; +use std::sync::Arc; use IncrementalHashesMap; use ich::Fingerprint; @@ -30,7 +31,9 @@ use super::fs::*; use super::file_format; use super::work_product; -pub type DirtyNodes = FxHashSet>; +// The key is a dirty node. The value is **some** base-input that we +// can blame it on. +pub type DirtyNodes = FxHashMap, DepNode>; /// If we are in incremental mode, and a previous dep-graph exists, /// then load up those nodes/edges that are still valid into the @@ -152,83 +155,65 @@ pub fn decode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Retrace the paths in the directory to find their current location (if any). let retraced = directory.retrace(tcx); - // Compute the set of Hir nodes whose data has changed or which - // have been removed. These are "raw" source nodes, which means - // that they still use the original `DefPathIndex` values from the - // encoding, rather than having been retraced to a `DefId`. The - // reason for this is that this way we can include nodes that have - // been removed (which no longer have a `DefId` in the current - // compilation). - let dirty_raw_source_nodes = dirty_nodes(tcx, - incremental_hashes_map, - &serialized_dep_graph.hashes, - &retraced); - - // Create a list of (raw-source-node -> - // retracted-target-node) edges. In the process of retracing the - // target nodes, we may discover some of them def-paths no longer exist, - // in which case there is no need to mark the corresopnding nodes as dirty - // (they are just not present). So this list may be smaller than the original. - // - // Note though that in the common case the target nodes are - // `DepNode::WorkProduct` instances, and those don't have a - // def-id, so they will never be considered to not exist. Instead, - // we do a secondary hashing step (later, in trans) when we know - // the set of symbols that go into a work-product: if any symbols - // have been removed (or added) the hash will be different and - // we'll ignore the work-product then. - let retraced_edges: Vec<_> = - serialized_dep_graph.edges.iter() - .filter_map(|&(ref raw_source_node, ref raw_target_node)| { - retraced.map(raw_target_node) - .map(|target_node| (raw_source_node, target_node)) - }) - .collect(); - - // Compute which work-products have an input that has changed or - // been removed. Put the dirty ones into a set. - let mut dirty_target_nodes = FxHashSet(); - for &(raw_source_node, ref target_node) in &retraced_edges { - if dirty_raw_source_nodes.contains(raw_source_node) { - if !dirty_target_nodes.contains(target_node) { - dirty_target_nodes.insert(target_node.clone()); - + // Compute the set of nodes from the old graph where some input + // has changed or been removed. These are "raw" source nodes, + // which means that they still use the original `DefPathIndex` + // values from the encoding, rather than having been retraced to a + // `DefId`. The reason for this is that this way we can include + // nodes that have been removed (which no longer have a `DefId` in + // the current compilation). + let dirty_raw_nodes = initial_dirty_nodes(tcx, + incremental_hashes_map, + &serialized_dep_graph.hashes, + &retraced); + let dirty_raw_nodes = transitive_dirty_nodes(&serialized_dep_graph.edges, dirty_raw_nodes); + + // Recreate the edges in the graph that are still clean. + let mut clean_work_products = FxHashSet(); + let mut dirty_work_products = FxHashSet(); // incomplete; just used to suppress debug output + for edge in &serialized_dep_graph.edges { + // If the target is dirty, skip the edge. If this is an edge + // that targets a work-product, we can print the blame + // information now. + if let Some(blame) = dirty_raw_nodes.get(&edge.1) { + if let DepNode::WorkProduct(ref wp) = edge.1 { if tcx.sess.opts.debugging_opts.incremental_info { - // It'd be nice to pretty-print these paths better than just - // using the `Debug` impls, but wev. - println!("incremental: module {:?} is dirty because {:?} \ - changed or was removed", - target_node, - raw_source_node.map_def(|&index| { - Some(directory.def_path_string(tcx, index)) - }).unwrap()); + if dirty_work_products.insert(wp.clone()) { + // It'd be nice to pretty-print these paths better than just + // using the `Debug` impls, but wev. + println!("incremental: module {:?} is dirty because {:?} \ + changed or was removed", + wp, + blame.map_def(|&index| { + Some(directory.def_path_string(tcx, index)) + }).unwrap()); + } } } - } - } - - // For work-products that are still clean, add their deps into the - // graph. This is needed because later we will have to save this - // back out again! - let dep_graph = tcx.dep_graph.clone(); - for (raw_source_node, target_node) in retraced_edges { - if dirty_target_nodes.contains(&target_node) { continue; } - let source_node = retraced.map(raw_source_node).unwrap(); - - debug!("decode_dep_graph: clean edge: {:?} -> {:?}", source_node, target_node); - - let _task = dep_graph.in_task(target_node); - dep_graph.read(source_node); + // If the source is dirty, the target will be dirty. + assert!(!dirty_raw_nodes.contains_key(&edge.0)); + + // Retrace the source -> target edges to def-ids and then + // create an edge in the graph. Retracing may yield none if + // some of the data happens to have been removed; this ought + // to be impossible unless it is dirty, so we can unwrap. + let source_node = retraced.map(&edge.0).unwrap(); + let target_node = retraced.map(&edge.1).unwrap(); + let _task = tcx.dep_graph.in_task(target_node); + tcx.dep_graph.read(source_node); + if let DepNode::WorkProduct(ref wp) = edge.1 { + clean_work_products.insert(wp.clone()); + } } // Add in work-products that are still clean, and delete those that are // dirty. - reconcile_work_products(tcx, work_products, &dirty_target_nodes); + reconcile_work_products(tcx, work_products, &clean_work_products); - dirty_clean::check_dirty_clean_annotations(tcx, &dirty_raw_source_nodes, &retraced); + dirty_clean::check_dirty_clean_annotations(tcx, &dirty_raw_nodes, &retraced); load_prev_metadata_hashes(tcx, &retraced, @@ -238,13 +223,13 @@ pub fn decode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, /// Computes which of the original set of def-ids are dirty. Stored in /// a bit vector where the index is the DefPathIndex. -fn dirty_nodes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - incremental_hashes_map: &IncrementalHashesMap, - serialized_hashes: &[SerializedHash], - retraced: &RetracedDefIdDirectory) - -> DirtyNodes { +fn initial_dirty_nodes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + incremental_hashes_map: &IncrementalHashesMap, + serialized_hashes: &[SerializedHash], + retraced: &RetracedDefIdDirectory) + -> DirtyNodes { let mut hcx = HashContext::new(tcx, incremental_hashes_map); - let mut dirty_nodes = FxHashSet(); + let mut dirty_nodes = FxHashMap(); for hash in serialized_hashes { if let Some(dep_node) = retraced.map(&hash.dep_node) { @@ -277,21 +262,37 @@ fn dirty_nodes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, hash.dep_node); } - dirty_nodes.insert(hash.dep_node.clone()); + dirty_nodes.insert(hash.dep_node.clone(), hash.dep_node.clone()); } dirty_nodes } +fn transitive_dirty_nodes(edges: &[SerializedEdge], + mut dirty_nodes: DirtyNodes) + -> DirtyNodes +{ + let mut len = 0; + while len != dirty_nodes.len() { + len = dirty_nodes.len(); + for edge in edges { + if let Some(n) = dirty_nodes.get(&edge.0).cloned() { + dirty_nodes.insert(edge.1.clone(), n); + } + } + } + dirty_nodes +} + /// Go through the list of work-products produced in the previous run. /// Delete any whose nodes have been found to be dirty or which are /// otherwise no longer applicable. fn reconcile_work_products<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, work_products: Vec, - dirty_target_nodes: &FxHashSet>) { + clean_work_products: &FxHashSet>) { debug!("reconcile_work_products({:?})", work_products); for swp in work_products { - if dirty_target_nodes.contains(&DepNode::WorkProduct(swp.id.clone())) { + if !clean_work_products.contains(&swp.id) { debug!("reconcile_work_products: dep-node for {:?} is dirty", swp); delete_dirty_work_product(tcx, swp); } else { diff --git a/src/librustc_incremental/persist/preds.rs b/src/librustc_incremental/persist/preds.rs deleted file mode 100644 index 3daeacfe87d82..0000000000000 --- a/src/librustc_incremental/persist/preds.rs +++ /dev/null @@ -1,366 +0,0 @@ -// Copyright 2012-2015 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. - -use rustc::dep_graph::{DepGraphQuery, DepNode}; -use rustc::hir::def_id::DefId; -use rustc_data_structures::fx::FxHashMap; -use rustc_data_structures::bitvec::BitVector; -use rustc_data_structures::graph::{NodeIndex, Graph}; - -use super::hash::*; -use ich::Fingerprint; - -/// A data-structure that makes it easy to enumerate the hashable -/// predecessors of any given dep-node. -pub struct Predecessors<'query> { - // - Keys: dep-nodes that may have work-products, output meta-data - // nodes. - // - Values: transitive predecessors of the key that are hashable - // (e.g., HIR nodes, input meta-data nodes) - pub inputs: FxHashMap<&'query DepNode, Vec<&'query DepNode>>, - - // - Keys: some hashable node - // - Values: the hash thereof - pub hashes: FxHashMap<&'query DepNode, Fingerprint>, -} - -impl<'q> Predecessors<'q> { - pub fn new(query: &'q DepGraphQuery, hcx: &mut HashContext) -> Self { - let tcx = hcx.tcx; - - let collect_for_metadata = tcx.sess.opts.debugging_opts.incremental_cc || - tcx.sess.opts.debugging_opts.query_dep_graph; - - // Find nodes for which we want to know the full set of preds - let node_count = query.graph.len_nodes(); - - // Set up some data structures the cache predecessor search needs: - let mut visit_counts: Vec = Vec::new(); - let mut node_cache: Vec>> = Vec::new(); - visit_counts.resize(node_count, 0); - node_cache.resize(node_count, None); - let mut dfs_workspace1 = DfsWorkspace::new(node_count); - let mut dfs_workspace2 = DfsWorkspace::new(node_count); - - let inputs: FxHashMap<_, _> = query - .graph - .all_nodes() - .iter() - .enumerate() - .filter(|&(_, node)| match node.data { - DepNode::WorkProduct(_) => true, - DepNode::MetaData(ref def_id) => collect_for_metadata && def_id.is_local(), - - // if -Z query-dep-graph is passed, save more extended data - // to enable better unit testing - DepNode::TypeckTables(_) | - DepNode::TransCrateItem(_) => tcx.sess.opts.debugging_opts.query_dep_graph, - - _ => false, - }) - .map(|(node_index, node)| { - find_roots(&query.graph, - node_index as u32, - &mut visit_counts, - &mut node_cache[..], - HashContext::is_hashable, - &mut dfs_workspace1, - Some(&mut dfs_workspace2)); - - let inputs: Vec<_> = dfs_workspace1.output.nodes.iter().map(|&i| { - query.graph.node_data(NodeIndex(i as usize)) - }).collect(); - - (&node.data, inputs) - }) - .collect(); - - let mut hashes = FxHashMap(); - for input in inputs.values().flat_map(|v| v.iter().cloned()) { - hashes.entry(input) - .or_insert_with(|| hcx.hash(input).unwrap()); - } - - Predecessors { - inputs: inputs, - hashes: hashes, - } - } -} - -const CACHING_THRESHOLD: u32 = 60; - -// Starting at `start_node`, this function finds this node's "roots", that is, -// anything that is hashable, in the dep-graph. It uses a simple depth-first -// search to achieve that. However, since some sub-graphs are traversed over -// and over again, the function also some caching built into it: Each time it -// visits a node it increases a counter for that node. If a node has been -// visited more often than CACHING_THRESHOLD, the function will allocate a -// cache entry in the `cache` array. This cache entry contains a flat list of -// all roots reachable from the given node. The next time the node is visited, -// the search can just add the contents of this array to the output instead of -// recursing further. -// -// The function takes two `DfsWorkspace` arguments. These contains some data -// structures that would be expensive to re-allocate all the time, so they are -// allocated once up-front. There are two of them because building a cache entry -// requires a recursive invocation of this function. Two are enough though, -// since function never recurses more than once. -fn find_roots(graph: &Graph, - start_node: u32, - visit_counts: &mut [u32], - cache: &mut [Option>], - is_root: F, - workspace: &mut DfsWorkspace, - mut sub_workspace: Option<&mut DfsWorkspace>) - where F: Copy + Fn(&T) -> bool, - T: ::std::fmt::Debug, -{ - workspace.visited.clear(); - workspace.output.clear(); - workspace.stack.clear(); - workspace.stack.push(start_node); - - loop { - let node = match workspace.stack.pop() { - Some(node) => node, - None => return, - }; - - if !workspace.visited.insert(node as usize) { - continue - } - - if is_root(graph.node_data(NodeIndex(node as usize))) { - // If this is a root, just add it to the output. - workspace.output.insert(node); - } else { - if let Some(ref cached) = cache[node as usize] { - for &n in &cached[..] { - workspace.output.insert(n); - } - // No need to recurse further from this node - continue - } - - visit_counts[node as usize] += 1; - - // If this node has been visited often enough to be cached ... - if visit_counts[node as usize] > CACHING_THRESHOLD { - // ... we are actually allowed to cache something, do so: - if let Some(ref mut sub_workspace) = sub_workspace { - // Note that the following recursive invocation does never - // write to the cache (since we pass None as sub_workspace). - // This is intentional: The graph we are working with - // contains cycles and this prevent us from simply building - // our caches recursively on-demand. - // However, we can just do a regular, non-caching DFS to - // yield the set of roots and cache that. - find_roots(graph, - node, - visit_counts, - cache, - is_root, - sub_workspace, - None); - - for &n in &sub_workspace.output.nodes { - workspace.output.insert(n); - } - - cache[node as usize] = Some(sub_workspace.output - .nodes - .clone() - .into_boxed_slice()); - // No need to recurse further from this node - continue - } - } - - for pred in graph.predecessor_nodes(NodeIndex(node as usize)) { - workspace.stack.push(pred.node_id() as u32); - } - } - } -} - -struct DfsWorkspace { - stack: Vec, - visited: BitVector, - output: NodeIndexSet, -} - -impl DfsWorkspace { - fn new(total_node_count: usize) -> DfsWorkspace { - DfsWorkspace { - stack: Vec::new(), - visited: BitVector::new(total_node_count), - output: NodeIndexSet::new(total_node_count), - } - } -} - -struct NodeIndexSet { - bitset: BitVector, - nodes: Vec, -} - -impl NodeIndexSet { - fn new(total_node_count: usize) -> NodeIndexSet { - NodeIndexSet { - bitset: BitVector::new(total_node_count), - nodes: Vec::new(), - } - } - - #[inline] - fn clear(&mut self) { - self.bitset.clear(); - self.nodes.clear(); - } - - #[inline] - fn insert(&mut self, node: u32) { - if self.bitset.insert(node as usize) { - self.nodes.push(node) - } - } -} - -#[test] -fn test_cached_dfs_acyclic() { - - // 0 1 2 - // | \ / - // 3---+ | - // | | | - // | | | - // 4 5 6 - // \ / \ / \ - // | | | - // 7 8 9 - - let mut g: Graph = Graph::new(); - g.add_node(false); - g.add_node(false); - g.add_node(false); - g.add_node(false); - g.add_node(false); - g.add_node(false); - g.add_node(false); - g.add_node(true); - g.add_node(true); - g.add_node(true); - - g.add_edge(NodeIndex(3), NodeIndex(0), ()); - g.add_edge(NodeIndex(4), NodeIndex(3), ()); - g.add_edge(NodeIndex(7), NodeIndex(4), ()); - g.add_edge(NodeIndex(5), NodeIndex(3), ()); - g.add_edge(NodeIndex(7), NodeIndex(5), ()); - g.add_edge(NodeIndex(8), NodeIndex(5), ()); - g.add_edge(NodeIndex(8), NodeIndex(6), ()); - g.add_edge(NodeIndex(9), NodeIndex(6), ()); - g.add_edge(NodeIndex(6), NodeIndex(1), ()); - g.add_edge(NodeIndex(6), NodeIndex(2), ()); - - let mut ws1 = DfsWorkspace::new(g.len_nodes()); - let mut ws2 = DfsWorkspace::new(g.len_nodes()); - let mut visit_counts: Vec<_> = g.all_nodes().iter().map(|_| 0u32).collect(); - let mut cache: Vec>> = g.all_nodes().iter().map(|_| None).collect(); - - fn is_root(x: &bool) -> bool { *x } - - for _ in 0 .. CACHING_THRESHOLD + 1 { - find_roots(&g, 5, &mut visit_counts, &mut cache[..], is_root, &mut ws1, Some(&mut ws2)); - ws1.output.nodes.sort(); - assert_eq!(ws1.output.nodes, vec![7, 8]); - - find_roots(&g, 6, &mut visit_counts, &mut cache[..], is_root, &mut ws1, Some(&mut ws2)); - ws1.output.nodes.sort(); - assert_eq!(ws1.output.nodes, vec![8, 9]); - - find_roots(&g, 0, &mut visit_counts, &mut cache[..], is_root, &mut ws1, Some(&mut ws2)); - ws1.output.nodes.sort(); - assert_eq!(ws1.output.nodes, vec![7, 8]); - - find_roots(&g, 1, &mut visit_counts, &mut cache[..], is_root, &mut ws1, Some(&mut ws2)); - ws1.output.nodes.sort(); - assert_eq!(ws1.output.nodes, vec![8, 9]); - - find_roots(&g, 2, &mut visit_counts, &mut cache[..], is_root, &mut ws1, Some(&mut ws2)); - ws1.output.nodes.sort(); - assert_eq!(ws1.output.nodes, vec![8, 9]); - - find_roots(&g, 3, &mut visit_counts, &mut cache[..], is_root, &mut ws1, Some(&mut ws2)); - ws1.output.nodes.sort(); - assert_eq!(ws1.output.nodes, vec![7, 8]); - - find_roots(&g, 4, &mut visit_counts, &mut cache[..], is_root, &mut ws1, Some(&mut ws2)); - ws1.output.nodes.sort(); - assert_eq!(ws1.output.nodes, vec![7]); - } -} - -#[test] -fn test_cached_dfs_cyclic() { - - // 0 1 <---- 2 3 - // ^ | ^ ^ - // | v | | - // 4 ----> 5 ----> 6 ----> 7 - // ^ ^ ^ ^ - // | | | | - // 8 9 10 11 - - - let mut g: Graph = Graph::new(); - g.add_node(false); - g.add_node(false); - g.add_node(false); - g.add_node(false); - g.add_node(false); - g.add_node(false); - g.add_node(false); - g.add_node(false); - g.add_node(true); - g.add_node(true); - g.add_node(true); - g.add_node(true); - - g.add_edge(NodeIndex( 4), NodeIndex(0), ()); - g.add_edge(NodeIndex( 8), NodeIndex(4), ()); - g.add_edge(NodeIndex( 4), NodeIndex(5), ()); - g.add_edge(NodeIndex( 1), NodeIndex(5), ()); - g.add_edge(NodeIndex( 9), NodeIndex(5), ()); - g.add_edge(NodeIndex( 5), NodeIndex(6), ()); - g.add_edge(NodeIndex( 6), NodeIndex(2), ()); - g.add_edge(NodeIndex( 2), NodeIndex(1), ()); - g.add_edge(NodeIndex(10), NodeIndex(6), ()); - g.add_edge(NodeIndex( 6), NodeIndex(7), ()); - g.add_edge(NodeIndex(11), NodeIndex(7), ()); - g.add_edge(NodeIndex( 7), NodeIndex(3), ()); - - let mut ws1 = DfsWorkspace::new(g.len_nodes()); - let mut ws2 = DfsWorkspace::new(g.len_nodes()); - let mut visit_counts: Vec<_> = g.all_nodes().iter().map(|_| 0u32).collect(); - let mut cache: Vec>> = g.all_nodes().iter().map(|_| None).collect(); - - fn is_root(x: &bool) -> bool { *x } - - for _ in 0 .. CACHING_THRESHOLD + 1 { - find_roots(&g, 2, &mut visit_counts, &mut cache[..], is_root, &mut ws1, Some(&mut ws2)); - ws1.output.nodes.sort(); - assert_eq!(ws1.output.nodes, vec![8, 9, 10]); - - find_roots(&g, 3, &mut visit_counts, &mut cache[..], is_root, &mut ws1, Some(&mut ws2)); - ws1.output.nodes.sort(); - assert_eq!(ws1.output.nodes, vec![8, 9, 10, 11]); - } -} diff --git a/src/librustc_incremental/persist/preds/compress/README.md b/src/librustc_incremental/persist/preds/compress/README.md new file mode 100644 index 0000000000000..d2aa245c7c942 --- /dev/null +++ b/src/librustc_incremental/persist/preds/compress/README.md @@ -0,0 +1,48 @@ +Graph compression + +The graph compression algorithm is intended to remove and minimize the +size of the dependency graph so it can be saved, while preserving +everything we care about. In particular, given a set of input/output +nodes in the graph (which must be disjoint), we ensure that the set of +input nodes that can reach a given output node does not change, +although the intermediate nodes may change in various ways. In short, +the output nodes are intended to be the ones whose existence we care +about when we start up, because they have some associated data that we +will try to re-use (and hence if they are dirty, we have to throw that +data away). The other intermediate nodes don't really matter so much. + +### Overview + +The algorithm works as follows: + +1. Do a single walk of the graph to construct a DAG + - in this walk, we identify and unify all cycles, electing a representative "head" node + - this is done using the union-find implementation + - this code is found in the `classify` module +2. The result from this walk is a `Dag`: + - the set of SCCs, represented by the union-find table + - a set of edges in the new DAG, represented by: + - a vector of parent nodes for each child node + - a vector of cross-edges + - once these are canonicalized, some of these edges may turn out to be cyclic edges + (i.e., an edge A -> A where A is the head of some SCC) +3. We pass this `Dag` into the construct code, which then creates a + new graph. This graph has a smaller set of indices which includes + *at least* the inputs/outputs from the original graph, but may have + other nodes as well, if keeping them reduces the overall size of + the graph. + - This code is found in the `construct` module. + +### Some notes + +The input graph is assumed to have *read-by* edges. i.e., `A -> B` +means that the task B reads data from A. But the DAG defined by +classify is expressed in terms of *reads-from* edges, which are the +inverse. So `A -> B` is the same as `B -rf-> A`. *reads-from* edges +are more natural since we want to walk from the outputs to the inputs, +effectively. When we construct the final graph, we reverse these edges +back into the *read-by* edges common elsewhere. + + + + diff --git a/src/librustc_incremental/persist/preds/compress/classify/mod.rs b/src/librustc_incremental/persist/preds/compress/classify/mod.rs new file mode 100644 index 0000000000000..f75063f8b9c9a --- /dev/null +++ b/src/librustc_incremental/persist/preds/compress/classify/mod.rs @@ -0,0 +1,139 @@ +//! First phase. Detect cycles and cross-edges. + +use super::*; + +#[cfg(test)] +mod test; + +pub struct Classify<'a, 'g: 'a, N: 'g, I: 'a, O: 'a> + where N: Debug + Clone + 'g, + I: Fn(&N) -> bool, + O: Fn(&N) -> bool, +{ + r: &'a mut GraphReduce<'g, N, I, O>, + stack: Vec, + colors: Vec, + dag: Dag, +} + +#[derive(Copy, Clone, Debug, PartialEq)] +enum Color { + // not yet visited + White, + + // visiting; usize is index on stack + Grey(usize), + + // finished visiting + Black, +} + +impl<'a, 'g, N, I, O> Classify<'a, 'g, N, I, O> + where N: Debug + Clone + 'g, + I: Fn(&N) -> bool, + O: Fn(&N) -> bool, +{ + pub(super) fn new(r: &'a mut GraphReduce<'g, N, I, O>) -> Self { + Classify { + r: r, + colors: vec![Color::White; r.in_graph.len_nodes()], + stack: vec![], + dag: Dag { + parents: (0..r.in_graph.len_nodes()).map(|i| NodeIndex(i)).collect(), + cross_edges: vec![], + input_nodes: vec![], + output_nodes: vec![], + }, + } + } + + pub(super) fn walk(mut self) -> Dag { + for (index, node) in self.r.in_graph.all_nodes().iter().enumerate() { + if (self.r.is_output)(&node.data) { + let index = NodeIndex(index); + self.dag.output_nodes.push(index); + match self.colors[index.0] { + Color::White => self.open(index), + Color::Grey(_) => panic!("grey node but have not yet started a walk"), + Color::Black => (), // already visited, skip + } + } + } + + // At this point we've identifed all the cycles, and we've + // constructed a spanning tree over the original graph + // (encoded in `self.parents`) as well as a list of + // cross-edges that reflect additional edges from the DAG. + // + // If we converted each node to its `cycle-head` (a + // representative choice from each SCC, basically) and then + // take the union of `self.parents` and `self.cross_edges` + // (after canonicalization), that is basically our DAG. + // + // Note that both of those may well contain trivial `X -rf-> X` + // cycle edges after canonicalization, though. e.g., if you + // have a graph `{A -rf-> B, B -rf-> A}`, we will have unioned A and + // B, but A will also be B's parent (or vice versa), and hence + // when we canonicalize the parent edge it would become `A -rf-> + // A` (or `B -rf-> B`). + self.dag + } + + fn open(&mut self, node: NodeIndex) { + let index = self.stack.len(); + self.stack.push(node); + self.colors[node.0] = Color::Grey(index); + for child in self.r.inputs(node) { + self.walk_edge(node, child); + } + self.stack.pop().unwrap(); + self.colors[node.0] = Color::Black; + + if (self.r.is_input)(&self.r.in_graph.node_data(node)) { + // base inputs should have no inputs + assert!(self.r.inputs(node).next().is_none()); + debug!("input: `{:?}`", self.r.in_graph.node_data(node)); + self.dag.input_nodes.push(node); + } + } + + fn walk_edge(&mut self, parent: NodeIndex, child: NodeIndex) { + debug!("walk_edge: {:?} -rf-> {:?}, {:?}", + self.r.in_graph.node_data(parent), + self.r.in_graph.node_data(child), + self.colors[child.0]); + + // Ignore self-edges, just in case they exist. + if child == parent { + return; + } + + match self.colors[child.0] { + Color::White => { + // Not yet visited this node; start walking it. + assert_eq!(self.dag.parents[child.0], child); + self.dag.parents[child.0] = parent; + self.open(child); + } + + Color::Grey(stack_index) => { + // Back-edge; unify everything on stack between here and `stack_index` + // since we are all participating in a cycle + assert!(self.stack[stack_index] == child); + + for &n in &self.stack[stack_index..] { + debug!("cycle `{:?}` and `{:?}`", self.r.in_graph.node_data(n), self.r.in_graph.node_data(parent)); + self.r.mark_cycle(n, parent); + } + } + + Color::Black => { + // Cross-edge, record and ignore + self.dag.cross_edges.push((parent, child)); + debug!("cross-edge `{:?} -rf-> {:?}`", + self.r.in_graph.node_data(parent), + self.r.in_graph.node_data(child)); + } + } + } +} diff --git a/src/librustc_incremental/persist/preds/compress/classify/test.rs b/src/librustc_incremental/persist/preds/compress/classify/test.rs new file mode 100644 index 0000000000000..22067a10343d3 --- /dev/null +++ b/src/librustc_incremental/persist/preds/compress/classify/test.rs @@ -0,0 +1,79 @@ +use super::*; + +#[test] +fn detect_cycles() { + let (graph, nodes) = graph! { + A -> C0, + A -> C1, + B -> C1, + C0 -> C1, + C1 -> C0, + C0 -> D, + C1 -> E, + }; + let inputs = ["A", "B"]; + let outputs = ["D", "E"]; + let mut reduce = GraphReduce::new(&graph, |n| inputs.contains(n), |n| outputs.contains(n)); + Classify::new(&mut reduce).walk(); + + assert!(!reduce.in_cycle(nodes("A"), nodes("C0"))); + assert!(!reduce.in_cycle(nodes("B"), nodes("C0"))); + assert!(reduce.in_cycle(nodes("C0"), nodes("C1"))); + assert!(!reduce.in_cycle(nodes("D"), nodes("C0"))); + assert!(!reduce.in_cycle(nodes("E"), nodes("C0"))); + assert!(!reduce.in_cycle(nodes("E"), nodes("A"))); +} + +/// Regr test for a bug where we forgot to pop nodes off of the stack +/// as we were walking. In this case, because edges are pushed to the front +/// of the list, we would visit OUT, then A, then IN, and then close IN (but forget +/// to POP. Then visit B, C, and then A, which would mark everything from A to C as +/// cycle. But since we failed to pop IN, the stack was `OUT, A, IN, B, C` so that +/// marked C and IN as being in a cycle. +#[test] +fn edge_order1() { + let (graph, nodes) = graph! { + A -> C, + C -> B, + B -> A, + IN -> B, + IN -> A, + A -> OUT, + }; + let inputs = ["IN"]; + let outputs = ["OUT"]; + let mut reduce = GraphReduce::new(&graph, |n| inputs.contains(n), |n| outputs.contains(n)); + Classify::new(&mut reduce).walk(); + + assert!(reduce.in_cycle(nodes("B"), nodes("C"))); + + assert!(!reduce.in_cycle(nodes("IN"), nodes("A"))); + assert!(!reduce.in_cycle(nodes("IN"), nodes("B"))); + assert!(!reduce.in_cycle(nodes("IN"), nodes("C"))); + assert!(!reduce.in_cycle(nodes("IN"), nodes("OUT"))); +} + +/// Same as `edge_order1` but in reverse order so as to detect a failure +/// if we were to enqueue edges onto end of list instead. +#[test] +fn edge_order2() { + let (graph, nodes) = graph! { + A -> OUT, + IN -> A, + IN -> B, + B -> A, + C -> B, + A -> C, + }; + let inputs = ["IN"]; + let outputs = ["OUT"]; + let mut reduce = GraphReduce::new(&graph, |n| inputs.contains(n), |n| outputs.contains(n)); + Classify::new(&mut reduce).walk(); + + assert!(reduce.in_cycle(nodes("B"), nodes("C"))); + + assert!(!reduce.in_cycle(nodes("IN"), nodes("A"))); + assert!(!reduce.in_cycle(nodes("IN"), nodes("B"))); + assert!(!reduce.in_cycle(nodes("IN"), nodes("C"))); + assert!(!reduce.in_cycle(nodes("IN"), nodes("OUT"))); +} diff --git a/src/librustc_incremental/persist/preds/compress/construct.rs b/src/librustc_incremental/persist/preds/compress/construct.rs new file mode 100644 index 0000000000000..b0dcb63758e8c --- /dev/null +++ b/src/librustc_incremental/persist/preds/compress/construct.rs @@ -0,0 +1,201 @@ +//! Second phase. Construct new graph. The previous phase has +//! converted the input graph into a DAG by detecting and unifying +//! cycles. It provides us with the following (which is a +//! representation of the DAG): +//! +//! - SCCs, in the form of a union-find repr that can convert each node to +//! its *cycle head* (an arbitrarly chosen representative from the cycle) +//! - a vector of *leaf nodes*, just a convenience +//! - a vector of *parents* for each node (in some cases, nodes have no parents, +//! or their parent is another member of same cycle; in that case, the vector +//! will be stored `v[i] == i`, after canonicalization) +//! - a vector of *cross edges*, meaning add'l edges between graphs nodes beyond +//! the parents. + +use rustc_data_structures::fx::FxHashMap; + +use super::*; + +pub(super) fn construct_graph<'g, N, I, O>(r: &mut GraphReduce<'g, N, I, O>, dag: Dag) + -> Reduction<'g, N> + where N: Debug + Clone, I: Fn(&N) -> bool, O: Fn(&N) -> bool, +{ + let Dag { parents: old_parents, input_nodes, output_nodes, cross_edges } = dag; + let in_graph = r.in_graph; + + debug!("construct_graph"); + + // Create a canonical list of edges; this includes both parent and + // cross-edges. We store this in `(target -> Vec)` form. + // We call the first edge to any given target its "parent". + let mut edges = FxHashMap(); + let old_parent_edges = old_parents.iter().cloned().zip((0..).map(NodeIndex)); + for (source, target) in old_parent_edges.chain(cross_edges) { + debug!("original edge `{:?} -rf-> {:?}`", + in_graph.node_data(source), + in_graph.node_data(target)); + let source = r.cycle_head(source); + let target = r.cycle_head(target); + if source != target { + let v = edges.entry(target).or_insert(vec![]); + if !v.contains(&source) { + debug!("edge `{:?} -rf-> {:?}` is edge #{} with that target", + in_graph.node_data(source), + in_graph.node_data(target), + v.len()); + v.push(source); + } + } + } + let parent = |ni: NodeIndex| -> NodeIndex { + edges[&ni][0] + }; + + // `retain_map`: a map of those nodes that we will want to + // *retain* in the ultimate graph; the key is the node index in + // the old graph, the value is the node index in the new + // graph. These are nodes in the following categories: + // + // - inputs + // - work-products + // - targets of a cross-edge + // + // The first two categories hopefully make sense. We want the + // inputs so we can compare hashes later. We want the + // work-products so we can tell precisely when a given + // work-product is invalidated. But the last one isn't strictly + // needed; we keep cross-target edges so as to minimize the total + // graph size. + // + // Consider a graph like: + // + // WP0 -rf-> Y + // WP1 -rf-> Y + // Y -rf-> INPUT0 + // Y -rf-> INPUT1 + // Y -rf-> INPUT2 + // Y -rf-> INPUT3 + // + // Now if we were to remove Y, we would have a total of 8 edges: both WP0 and WP1 + // depend on INPUT0...INPUT3. As it is, we have 6 edges. + + let mut retain_map = FxHashMap(); + let mut new_graph = Graph::new(); + + { + // Start by adding start-nodes and inputs. + let retained_nodes = output_nodes.iter().chain(&input_nodes).map(|&n| r.cycle_head(n)); + + // Next add in targets of cross-edges. Due to the canonicalization, + // some of these may be self-edges or may may duplicate the parent + // edges, so ignore those. + let retained_nodes = retained_nodes.chain( + edges.iter() + .filter(|&(_, ref sources)| sources.len() > 1) + .map(|(&target, _)| target)); + + // Now create the new graph, adding in the entries from the map. + for n in retained_nodes { + retain_map.entry(n) + .or_insert_with(|| { + let data = in_graph.node_data(n); + debug!("retaining node `{:?}`", data); + new_graph.add_node(data) + }); + } + } + + // Given a cycle-head `ni`, converts it to the closest parent that has + // been retained in the output graph. + let retained_parent = |mut ni: NodeIndex| -> NodeIndex { + loop { + debug!("retained_parent({:?})", in_graph.node_data(ni)); + match retain_map.get(&ni) { + Some(&v) => return v, + None => ni = parent(ni), + } + } + }; + + // Now add in the edges into the graph. + for (&target, sources) in &edges { + if let Some(&r_target) = retain_map.get(&target) { + debug!("adding edges that target `{:?}`", in_graph.node_data(target)); + for &source in sources { + debug!("new edge `{:?} -rf-> {:?}`", + in_graph.node_data(source), + in_graph.node_data(target)); + let r_source = retained_parent(source); + + // NB. In the input graph, we have `a -> b` if b + // **reads from** a. But in the terminology of this + // code, we would describe that edge as `b -> a`, + // because we have edges *from* outputs *to* inputs. + // Therefore, when we create our new graph, we have to + // reverse the edge. + new_graph.add_edge(r_target, r_source, ()); + } + } else { + assert_eq!(sources.len(), 1); + } + } + + // One complication. In some cases, output nodes *may* participate in + // cycles. An example: + // + // [HIR0] [HIR1] + // | | + // v v + // TypeckClosureBody(X) -> ItemSignature(X::SomeClosureInX) + // | ^ | | + // | +-------------------------+ | + // | | + // v v + // Foo Bar + // + // In these cases, the output node may not wind up as the head + // of the cycle, in which case it would be absent from the + // final graph. We don't wish this to happen, therefore we go + // over the list of output nodes again and check for any that + // are not their own cycle-head. If we find such a node, we + // add it to the graph now with an edge from the cycle head. + // So the graph above could get transformed into this: + // + // [HIR0, HIR1] + // | + // v + // TypeckClosureBody(X) ItemSignature(X::SomeClosureInX) + // ^ | | + // +-------------------------+ | + // v + // [Foo, Bar] + // + // (Note that all the edges here are "read-by" edges, not + // "reads-from" edges.) + for &output_node in &output_nodes { + let head = r.cycle_head(output_node); + if output_node == head { + assert!(retain_map.contains_key(&output_node)); + } else { + assert!(!retain_map.contains_key(&output_node)); + let output_data = in_graph.node_data(output_node); + let new_node = new_graph.add_node(output_data); + let new_head_node = retain_map[&head]; + new_graph.add_edge(new_head_node, new_node, ()); + } + } + + // Finally, prepare a list of the input node indices as found in + // the new graph. Note that since all input nodes are leaves in + // the graph, they should never participate in a cycle. + let input_nodes = + input_nodes.iter() + .map(|&n| { + assert_eq!(r.cycle_head(n), n, "input node participating in a cycle"); + retain_map[&n] + }) + .collect(); + + Reduction { graph: new_graph, input_nodes: input_nodes } +} + diff --git a/src/librustc_incremental/persist/preds/compress/dag_id.rs b/src/librustc_incremental/persist/preds/compress/dag_id.rs new file mode 100644 index 0000000000000..5ebabc98fda94 --- /dev/null +++ b/src/librustc_incremental/persist/preds/compress/dag_id.rs @@ -0,0 +1,33 @@ +use rustc_data_structures::graph::NodeIndex; +use rustc_data_structures::unify::UnifyKey; + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +pub struct DagId { + index: u32, +} + +impl DagId { + pub fn from_in_index(n: NodeIndex) -> Self { + DagId { index: n.0 as u32 } + } + + pub fn as_in_index(&self) -> NodeIndex { + NodeIndex(self.index as usize) + } +} + +impl UnifyKey for DagId { + type Value = (); + + fn index(&self) -> u32 { + self.index + } + + fn from_index(u: u32) -> Self { + DagId { index: u } + } + + fn tag(_: Option) -> &'static str { + "DagId" + } +} diff --git a/src/librustc_incremental/persist/preds/compress/mod.rs b/src/librustc_incremental/persist/preds/compress/mod.rs new file mode 100644 index 0000000000000..ecd6d72e22d50 --- /dev/null +++ b/src/librustc_incremental/persist/preds/compress/mod.rs @@ -0,0 +1,125 @@ +// Copyright 2012-2013 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. + +//! Graph compression. See `README.md`. + +use rustc_data_structures::graph::{Graph, NodeIndex}; +use rustc_data_structures::unify::UnificationTable; +use std::fmt::Debug; + +#[cfg(test)] +#[macro_use] +mod test_macro; + +mod construct; + +mod classify; +use self::classify::Classify; + +mod dag_id; +use self::dag_id::DagId; + +#[cfg(test)] +mod test; + +pub fn reduce_graph(graph: &Graph, + is_input: I, + is_output: O) -> Reduction + where N: Debug + Clone, + I: Fn(&N) -> bool, + O: Fn(&N) -> bool, +{ + GraphReduce::new(graph, is_input, is_output).compute() +} + +pub struct Reduction<'q, N> where N: 'q + Debug + Clone { + pub graph: Graph<&'q N, ()>, + pub input_nodes: Vec, +} + +struct GraphReduce<'q, N, I, O> + where N: 'q + Debug + Clone, + I: Fn(&N) -> bool, + O: Fn(&N) -> bool, +{ + in_graph: &'q Graph, + unify: UnificationTable, + is_input: I, + is_output: O, +} + +struct Dag { + // The "parent" of a node is the node which reached it during the + // initial DFS. To encode the case of "no parent" (i.e., for the + // roots of the walk), we make `parents[i] == i` to start, which + // turns out be convenient. + parents: Vec, + + // Additional edges beyond the parents. + cross_edges: Vec<(NodeIndex, NodeIndex)>, + + // Nodes which we found that are considered "outputs" + output_nodes: Vec, + + // Nodes which we found that are considered "inputs" + input_nodes: Vec, +} + +#[derive(Copy, Clone, PartialEq, Eq, Hash)] +struct DagNode { + in_index: NodeIndex +} + +impl<'q, N, I, O> GraphReduce<'q, N, I, O> + where N: Debug + Clone, + I: Fn(&N) -> bool, + O: Fn(&N) -> bool, +{ + fn new(in_graph: &'q Graph, is_input: I, is_output: O) -> Self { + let mut unify = UnificationTable::new(); + + // create a set of unification keys whose indices + // correspond to the indices from the input graph + for i in 0..in_graph.len_nodes() { + let k = unify.new_key(()); + assert!(k == DagId::from_in_index(NodeIndex(i))); + } + + GraphReduce { in_graph, unify, is_input, is_output } + } + + fn compute(mut self) -> Reduction<'q, N> { + let dag = Classify::new(&mut self).walk(); + construct::construct_graph(&mut self, dag) + } + + fn inputs(&self, in_node: NodeIndex) -> impl Iterator + 'q { + self.in_graph.predecessor_nodes(in_node) + } + + fn mark_cycle(&mut self, in_node1: NodeIndex, in_node2: NodeIndex) { + let dag_id1 = DagId::from_in_index(in_node1); + let dag_id2 = DagId::from_in_index(in_node2); + self.unify.union(dag_id1, dag_id2); + } + + /// Convert a dag-id into its cycle head representative. This will + /// be a no-op unless `in_node` participates in a cycle, in which + /// case a distinct node *may* be returned. + fn cycle_head(&mut self, in_node: NodeIndex) -> NodeIndex { + let i = DagId::from_in_index(in_node); + self.unify.find(i).as_in_index() + } + + #[cfg(test)] + fn in_cycle(&mut self, ni1: NodeIndex, ni2: NodeIndex) -> bool { + self.cycle_head(ni1) == self.cycle_head(ni2) + } +} diff --git a/src/librustc_incremental/persist/preds/compress/test.rs b/src/librustc_incremental/persist/preds/compress/test.rs new file mode 100644 index 0000000000000..6ac834ee53fbc --- /dev/null +++ b/src/librustc_incremental/persist/preds/compress/test.rs @@ -0,0 +1,243 @@ +use super::*; + +fn reduce(graph: &Graph<&'static str, ()>, + inputs: &[&'static str], + outputs: &[&'static str], + expected: &[&'static str]) +{ + let reduce = GraphReduce::new(&graph, + |n| inputs.contains(n), + |n| outputs.contains(n)); + let result = reduce.compute(); + let mut edges: Vec = + result.graph + .all_edges() + .iter() + .map(|edge| format!("{} -> {}", + result.graph.node_data(edge.source()), + result.graph.node_data(edge.target()))) + .collect(); + edges.sort(); + println!("{:#?}", edges); + assert_eq!(edges.len(), expected.len()); + for (expected, actual) in expected.iter().zip(&edges) { + assert_eq!(expected, actual); + } +} + +#[test] +fn test1() { + // +---------------+ + // | | + // | +--------|------+ + // | | v v + // [A] -> [C0] -> [C1] [D] + // [ ] <- [ ] -> [E] + // ^ + // [B] -------------+ + let (graph, _nodes) = graph! { + A -> C0, + A -> C1, + B -> C1, + C0 -> C1, + C1 -> C0, + C0 -> D, + C1 -> E, + }; + + // [A] -> [C1] -> [D] + // [B] -> [ ] -> [E] + reduce(&graph, &["A", "B"], &["D", "E"], &[ + "A -> C1", + "B -> C1", + "C1 -> D", + "C1 -> E", + ]); +} + +#[test] +fn test2() { + // +---------------+ + // | | + // | +--------|------+ + // | | v v + // [A] -> [C0] -> [C1] [D] -> [E] + // [ ] <- [ ] + // ^ + // [B] -------------+ + let (graph, _nodes) = graph! { + A -> C0, + A -> C1, + B -> C1, + C0 -> C1, + C1 -> C0, + C0 -> D, + D -> E, + }; + + // [A] -> [D] -> [E] + // [B] -> [ ] + reduce(&graph, &["A", "B"], &["D", "E"], &[ + "A -> D", + "B -> D", + "D -> E", + ]); +} + +#[test] +fn test2b() { + // Variant on test2 in which [B] is not + // considered an input. + let (graph, _nodes) = graph! { + A -> C0, + A -> C1, + B -> C1, + C0 -> C1, + C1 -> C0, + C0 -> D, + D -> E, + }; + + // [A] -> [D] -> [E] + reduce(&graph, &["A"], &["D", "E"], &[ + "A -> D", + "D -> E", + ]); +} + +#[test] +fn test3() { + + // Edges going *downwards*, so 0, 1 and 2 are inputs, + // while 7, 8, and 9 are outputs. + // + // 0 1 2 + // | \ / + // 3---+ | + // | | | + // | | | + // 4 5 6 + // \ / \ / \ + // | | | + // 7 8 9 + // + // Here the end result removes node 4, instead encoding an edge + // from n3 -> n7, but keeps nodes 5 and 6, as they are common + // inputs to nodes 8/9. + + let (graph, _nodes) = graph! { + n0 -> n3, + n3 -> n4, + n3 -> n5, + n4 -> n7, + n5 -> n7, + n5 -> n8, + n1 -> n6, + n2 -> n6, + n6 -> n8, + n6 -> n9, + }; + + reduce(&graph, &["n0", "n1", "n2"], &["n7", "n8", "n9"], &[ + "n0 -> n3", + "n1 -> n6", + "n2 -> n6", + "n3 -> n5", + "n3 -> n7", + "n5 -> n7", + "n5 -> n8", + "n6 -> n8", + "n6 -> n9" + ]); +} + +//#[test] +//fn test_cached_dfs_cyclic() { +// +// // 0 1 <---- 2 3 +// // ^ | ^ ^ +// // | v | | +// // 4 ----> 5 ----> 6 ----> 7 +// // ^ ^ ^ ^ +// // | | | | +// // 8 9 10 11 +// +// +// let mut g: Graph = Graph::new(); +// g.add_node(false); +// g.add_node(false); +// g.add_node(false); +// g.add_node(false); +// g.add_node(false); +// g.add_node(false); +// g.add_node(false); +// g.add_node(false); +// g.add_node(true); +// g.add_node(true); +// g.add_node(true); +// g.add_node(true); +// +// g.add_edge(NodeIndex( 4), NodeIndex(0), ()); +// g.add_edge(NodeIndex( 8), NodeIndex(4), ()); +// g.add_edge(NodeIndex( 4), NodeIndex(5), ()); +// g.add_edge(NodeIndex( 1), NodeIndex(5), ()); +// g.add_edge(NodeIndex( 9), NodeIndex(5), ()); +// g.add_edge(NodeIndex( 5), NodeIndex(6), ()); +// g.add_edge(NodeIndex( 6), NodeIndex(2), ()); +// g.add_edge(NodeIndex( 2), NodeIndex(1), ()); +// g.add_edge(NodeIndex(10), NodeIndex(6), ()); +// g.add_edge(NodeIndex( 6), NodeIndex(7), ()); +// g.add_edge(NodeIndex(11), NodeIndex(7), ()); +// g.add_edge(NodeIndex( 7), NodeIndex(3), ()); +// +// let mut ws1 = DfsWorkspace::new(g.len_nodes()); +// let mut ws2 = DfsWorkspace::new(g.len_nodes()); +// let mut visit_counts: Vec<_> = g.all_nodes().iter().map(|_| 0u32).collect(); +// let mut cache: Vec>> = g.all_nodes().iter().map(|_| None).collect(); +// +// fn is_root(x: &bool) -> bool { *x } +// +// for _ in 0 .. CACHING_THRESHOLD + 1 { +// find_roots(&g, 2, &mut visit_counts, &mut cache[..], is_root, &mut ws1, Some(&mut ws2)); +// ws1.output.nodes.sort(); +// assert_eq!(ws1.output.nodes, vec![8, 9, 10]); +// +// find_roots(&g, 3, &mut visit_counts, &mut cache[..], is_root, &mut ws1, Some(&mut ws2)); +// ws1.output.nodes.sort(); +// assert_eq!(ws1.output.nodes, vec![8, 9, 10, 11]); +// } +//} + +#[test] +fn test_cycle_output() { + // +---------------+ + // | | + // | +--------|------+ + // | | v v + // [A] -> [C0] <-> [C1] <- [D] + // +----> [E] + // ^ + // [B] ----------------- ---+ + let (graph, _nodes) = graph! { + A -> C0, + A -> C1, + B -> E, + C0 -> C1, + C1 -> C0, + C0 -> D, + C1 -> E, + D -> C1, + }; + + // [A] -> [C0] <-> [D] + // +----> [E] + // ^ + // [B] -------------+ + reduce(&graph, &["A", "B"], &["D", "E"], &[ + "A -> C0", + "B -> E", + "C0 -> D", + "C0 -> E", + "D -> C0" + ]); +} diff --git a/src/librustc_incremental/persist/preds/compress/test_macro.rs b/src/librustc_incremental/persist/preds/compress/test_macro.rs new file mode 100644 index 0000000000000..66712c018d06d --- /dev/null +++ b/src/librustc_incremental/persist/preds/compress/test_macro.rs @@ -0,0 +1,40 @@ +macro_rules! graph { + ($( $source:ident -> $target:ident, )*) => { + { + use $crate::rustc_data_structures::graph::{Graph, NodeIndex}; + use $crate::rustc_data_structures::fx::FxHashMap; + + let mut graph = Graph::new(); + let mut nodes: FxHashMap<&'static str, NodeIndex> = FxHashMap(); + + for &name in &[ $(stringify!($source), stringify!($target)),* ] { + let name: &'static str = name; + nodes.entry(name) + .or_insert_with(|| graph.add_node(name)); + } + + $( + { + let source = nodes[&stringify!($source)]; + let target = nodes[&stringify!($target)]; + graph.add_edge(source, target, ()); + } + )* + + let f = move |name: &'static str| -> NodeIndex { nodes[&name] }; + + (graph, f) + } + } +} + +macro_rules! set { + ($( $value:expr ),*) => { + { + use $crate::rustc_data_structures::fx::FxHashSet; + let mut set = FxHashSet(); + $(set.insert($value);)* + set + } + } +} diff --git a/src/librustc_incremental/persist/preds/mod.rs b/src/librustc_incremental/persist/preds/mod.rs new file mode 100644 index 0000000000000..a80620fbde66f --- /dev/null +++ b/src/librustc_incremental/persist/preds/mod.rs @@ -0,0 +1,75 @@ +// Copyright 2012-2015 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. + +use rustc::dep_graph::{DepGraphQuery, DepNode}; +use rustc::hir::def_id::DefId; +use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::graph::Graph; + +use super::hash::*; +use ich::Fingerprint; + +mod compress; + +/// A data-structure that makes it easy to enumerate the hashable +/// predecessors of any given dep-node. +pub struct Predecessors<'query> { + // A reduced version of the input graph that contains fewer nodes. + // This is intended to keep all of the base inputs (i.e., HIR + // nodes) and all of the "work-products" we may care about + // later. Other nodes may be retained if it keeps the overall size + // of the graph down. + pub reduced_graph: Graph<&'query DepNode, ()>, + + // For the inputs (hir/foreign-metadata), we include hashes. + pub hashes: FxHashMap<&'query DepNode, Fingerprint>, +} + +impl<'q> Predecessors<'q> { + pub fn new(query: &'q DepGraphQuery, hcx: &mut HashContext) -> Self { + let tcx = hcx.tcx; + + let collect_for_metadata = tcx.sess.opts.debugging_opts.incremental_cc || + tcx.sess.opts.debugging_opts.query_dep_graph; + + // Find the set of "start nodes". These are nodes that we will + // possibly query later. + let is_output = |node: &DepNode| -> bool { + match *node { + DepNode::WorkProduct(_) => true, + DepNode::MetaData(ref def_id) => collect_for_metadata && def_id.is_local(), + + // if -Z query-dep-graph is passed, save more extended data + // to enable better unit testing + DepNode::TypeckTables(_) | + DepNode::TransCrateItem(_) => tcx.sess.opts.debugging_opts.query_dep_graph, + + _ => false, + } + }; + + // Reduce the graph to the most important nodes. + let compress::Reduction { graph, input_nodes } = + compress::reduce_graph(&query.graph, HashContext::is_hashable, is_output); + + let mut hashes = FxHashMap(); + for input_index in input_nodes { + let input = *graph.node_data(input_index); + debug!("computing hash for input node `{:?}`", input); + hashes.entry(input) + .or_insert_with(|| hcx.hash(input).unwrap()); + } + + Predecessors { + reduced_graph: graph, + hashes: hashes, + } + } +} diff --git a/src/librustc_incremental/persist/save.rs b/src/librustc_incremental/persist/save.rs index f626905f27d4a..80f51700d60e4 100644 --- a/src/librustc_incremental/persist/save.rs +++ b/src/librustc_incremental/persist/save.rs @@ -14,6 +14,7 @@ use rustc::hir::svh::Svh; use rustc::session::Session; use rustc::ty::TyCtxt; use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::graph::{NodeIndex, INCOMING}; use rustc_serialize::Encodable as RustcEncodable; use rustc_serialize::opaque::Encoder; use std::hash::Hash; @@ -178,7 +179,9 @@ pub fn encode_dep_graph(preds: &Predecessors, // Create a flat list of (Input, WorkProduct) edges for // serialization. let mut edges = vec![]; - for (&target, sources) in &preds.inputs { + for edge in preds.reduced_graph.all_edges() { + let source = *preds.reduced_graph.node_data(edge.source()); + let target = *preds.reduced_graph.node_data(edge.target()); match *target { DepNode::MetaData(ref def_id) => { // Metadata *targets* are always local metadata nodes. We have @@ -188,11 +191,10 @@ pub fn encode_dep_graph(preds: &Predecessors, } _ => (), } + debug!("serialize edge: {:?} -> {:?}", source, target); + let source = builder.map(source); let target = builder.map(target); - for &source in sources { - let source = builder.map(source); - edges.push((source, target.clone())); - } + edges.push((source, target)); } if tcx.sess.opts.debugging_opts.incremental_dump_hash { @@ -250,12 +252,10 @@ pub fn encode_metadata_hashes(tcx: TyCtxt, let mut def_id_hashes = FxHashMap(); - for (&target, sources) in &preds.inputs { - let def_id = match *target { - DepNode::MetaData(def_id) => { - assert!(def_id.is_local()); - def_id - } + for (index, target) in preds.reduced_graph.all_nodes().iter().enumerate() { + let index = NodeIndex(index); + let def_id = match *target.data { + DepNode::MetaData(def_id) if def_id.is_local() => def_id, _ => continue, }; @@ -281,13 +281,17 @@ pub fn encode_metadata_hashes(tcx: TyCtxt, // is the det. hash of the def-path. This is convenient // because we can sort this to get a stable ordering across // compilations, even if the def-ids themselves have changed. - let mut hashes: Vec<(DepNode, Fingerprint)> = sources.iter() - .map(|dep_node| { - let hash_dep_node = dep_node.map_def(|&def_id| Some(def_id_hash(def_id))).unwrap(); - let hash = preds.hashes[dep_node]; - (hash_dep_node, hash) - }) - .collect(); + let mut hashes: Vec<(DepNode, Fingerprint)> = + preds.reduced_graph + .depth_traverse(index, INCOMING) + .map(|index| preds.reduced_graph.node_data(index)) + .filter(|dep_node| HashContext::is_hashable(dep_node)) + .map(|dep_node| { + let hash_dep_node = dep_node.map_def(|&def_id| Some(def_id_hash(def_id))).unwrap(); + let hash = preds.hashes[dep_node]; + (hash_dep_node, hash) + }) + .collect(); hashes.sort(); let mut state = IchHasher::new(); @@ -298,9 +302,12 @@ pub fn encode_metadata_hashes(tcx: TyCtxt, if tcx.sess.opts.debugging_opts.incremental_dump_hash { println!("metadata hash for {:?} is {}", def_id, hash); - for dep_node in sources { - println!("metadata hash for {:?} depends on {:?} with hash {}", - def_id, dep_node, preds.hashes[dep_node]); + for pred_index in preds.reduced_graph.depth_traverse(index, INCOMING) { + let dep_node = preds.reduced_graph.node_data(pred_index); + if HashContext::is_hashable(&dep_node) { + println!("metadata hash for {:?} depends on {:?} with hash {}", + def_id, dep_node, preds.hashes[dep_node]); + } } } From d10a509932a78dc0e3d635aa554bf084befe99f4 Mon Sep 17 00:00:00 2001 From: "Jonathan A. Kollasch" Date: Mon, 23 Jan 2017 10:14:16 -0600 Subject: [PATCH 043/137] Don't build gcc_personality_v0.c on NetBSD either --- mk/rt.mk | 2 ++ src/libcompiler_builtins/build.rs | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/mk/rt.mk b/mk/rt.mk index a67bded288e20..f5149281d5071 100644 --- a/mk/rt.mk +++ b/mk/rt.mk @@ -552,9 +552,11 @@ endif ifeq ($$(findstring msvc,$(1)),) ifeq ($$(findstring freebsd,$(1)),) +ifeq ($$(findstring netbsd,$(1)),) $(call ADD_INTRINSIC,$(1),gcc_personality_v0.o) endif endif +endif ifeq ($$(findstring aarch64,$(1)),aarch64) $(foreach intrinsic,comparetf2.o \ diff --git a/src/libcompiler_builtins/build.rs b/src/libcompiler_builtins/build.rs index b9421d779b590..5360bbdeacd6a 100644 --- a/src/libcompiler_builtins/build.rs +++ b/src/libcompiler_builtins/build.rs @@ -240,7 +240,7 @@ fn main() { sources.extend(&["x86_64/floatdidf.c", "x86_64/floatdisf.c", "x86_64/floatdixf.c"]); } } else { - if !target.contains("freebsd") { + if !target.contains("freebsd") && !target.contains("netbsd") { sources.extend(&["gcc_personality_v0.c"]); } From 4b52600b152a2220dca847046962a6f37a773378 Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Tue, 31 Jan 2017 13:19:03 -0500 Subject: [PATCH 044/137] update mailmap for @pliniker --- .mailmap | 1 + 1 file changed, 1 insertion(+) diff --git a/.mailmap b/.mailmap index c44c486831acc..1ae0aae2d01ba 100644 --- a/.mailmap +++ b/.mailmap @@ -167,6 +167,7 @@ Ožbolt Menegatti gareins Paul Faria Peer Aramillo Irizar parir Peter Elmers +Peter Liniker Peter Zotov Phil Dawes Phil Dawes Philipp Brüschweiler From 4a07e722c01962aa814f2ae0915dfa84cd4d732a Mon Sep 17 00:00:00 2001 From: Federico Mena Quintero Date: Wed, 25 Jan 2017 13:11:15 -0600 Subject: [PATCH 045/137] In std:rc, clarify the lack of mutability inside an Rc Also, point to the example in Cell's docs for how to do it. --- src/liballoc/rc.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 010e378ef2f48..6108a06634bb8 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -17,9 +17,11 @@ //! pointer to the same value in the heap. When the last [`Rc`] pointer to a //! given value is destroyed, the pointed-to value is also destroyed. //! -//! Shared references in Rust disallow mutation by default, and `Rc` is no -//! exception. If you need to mutate through an [`Rc`], use [`Cell`] or -//! [`RefCell`]. +//! Shared references in Rust disallow mutation by default, and [`Rc`] +//! is no exception: you cannot obtain a mutable reference to +//! something inside an [`Rc`]. If you need mutability, put a [`Cell`] +//! or [`RefCell`] inside the [`Rc`]; see [an example of mutability +//! inside an Rc][mutability]. //! //! [`Rc`] uses non-atomic reference counting. This means that overhead is very //! low, but an [`Rc`] cannot be sent between threads, and consequently [`Rc`] @@ -214,6 +216,7 @@ //! [upgrade]: struct.Weak.html#method.upgrade //! [`None`]: ../../std/option/enum.Option.html#variant.None //! [assoc]: ../../book/method-syntax.html#associated-functions +//! [mutability]: ../../std/cell/index.html#introducing-mutability-inside-of-something-immutable #![stable(feature = "rust1", since = "1.0.0")] From 94687aaf58c9a935ed3efb84d0f3b60e00342dcc Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Mon, 30 Jan 2017 21:38:13 -0500 Subject: [PATCH 046/137] Removes FIXMEs related to #22405 --- src/libcoretest/hash/mod.rs | 1 - src/libcoretest/iter.rs | 2 -- .../auxiliary/macro_crate_test.rs | 2 -- .../borrowck/borrowck-borrowed-uniq-rvalue.rs | 1 - src/test/compile-fail/cross-borrow-trait.rs | 1 - src/test/compile-fail/dst-bad-assign-2.rs | 1 - src/test/compile-fail/dst-bad-assign.rs | 1 - src/test/compile-fail/issue-10291.rs | 1 - src/test/compile-fail/issue-11515.rs | 1 - src/test/compile-fail/issue-17441.rs | 1 - src/test/compile-fail/issue-17651.rs | 1 - src/test/compile-fail/issue-18783.rs | 2 -- src/test/compile-fail/issue-3763.rs | 2 -- src/test/compile-fail/issue-4335.rs | 1 - src/test/compile-fail/map-types.rs | 1 - ...ased-on-type-no-recursive-stack-closure.rs | 1 - .../region-object-lifetime-in-coercion.rs | 2 -- ...gions-close-associated-type-into-object.rs | 2 -- .../regions-close-param-into-object.rs | 2 -- src/test/compile-fail/regions-nested-fns.rs | 2 -- .../regions-proc-bound-capture.rs | 2 -- .../compile-fail/regions-steal-closure.rs | 1 - .../trait-coercion-generic-bad.rs | 1 - .../trait-coercion-generic-regions.rs | 1 - .../unboxed-closure-illegal-move.rs | 2 -- src/test/compile-fail/unique-pinned-nocopy.rs | 1 - .../auxiliary/macro_crate_test.rs | 3 -- .../auxiliary/plugin_args.rs | 1 - .../deriving-encodable-decodable-box.rs | 1 - src/test/run-pass-valgrind/dst-dtor-1.rs | 1 - src/test/run-pass-valgrind/dst-dtor-2.rs | 1 - ...ciated-types-doubleendediterator-object.rs | 1 - src/test/run-pass/coerce-expect-unsized.rs | 9 ------ src/test/run-pass/deriving-default-box.rs | 1 - .../run-pass/deriving-eq-ord-boxed-slice.rs | 1 - src/test/run-pass/dst-deref-mut.rs | 1 - src/test/run-pass/dst-deref.rs | 1 - src/test/run-pass/dst-struct.rs | 1 - src/test/run-pass/dst-trait.rs | 1 - .../run-pass/empty-allocation-non-null.rs | 3 -- src/test/run-pass/hashmap-memory.rs | 1 - src/test/run-pass/hrtb-precedence-of-plus.rs | 1 - src/test/run-pass/issue-11205.rs | 2 -- src/test/run-pass/issue-11677.rs | 1 - src/test/run-pass/issue-12744.rs | 1 - src/test/run-pass/issue-13808.rs | 1 - src/test/run-pass/issue-14589.rs | 2 -- src/test/run-pass/issue-14919.rs | 1 - src/test/run-pass/issue-16668.rs | 1 - src/test/run-pass/issue-17734.rs | 2 -- src/test/run-pass/issue-20575.rs | 1 - src/test/run-pass/issue-3052.rs | 1 - src/test/run-pass/issue-3609.rs | 1 - src/test/run-pass/newlambdas-ret-infer.rs | 1 - src/test/run-pass/newlambdas-ret-infer2.rs | 1 - src/test/run-pass/regions-fn-subtyping.rs | 2 -- ...ions-on-closures-to-inference-variables.rs | 1 - src/test/run-pass/show-boxed-slice.rs | 1 - src/test/run-pass/trait-bounds-in-arc.rs | 1 - src/test/run-pass/trait-coercion-generic.rs | 1 - src/test/run-pass/trait-coercion.rs | 2 -- ...ed-closures-call-sugar-object-autoderef.rs | 1 - .../unboxed-closures-call-sugar-object.rs | 1 - .../borrowck-call-is-borrow-issue-12224.rs | 2 -- ...borrowck-call-is-borrow-issue-12224.stderr | 32 +++++++++---------- 65 files changed, 16 insertions(+), 108 deletions(-) diff --git a/src/libcoretest/hash/mod.rs b/src/libcoretest/hash/mod.rs index 0d12433813343..53ac17c052f6a 100644 --- a/src/libcoretest/hash/mod.rs +++ b/src/libcoretest/hash/mod.rs @@ -66,7 +66,6 @@ fn test_writer_hasher() { assert_eq!(hash(& s), 97 + 0xFF); let cs: &[u8] = &[1, 2, 3]; assert_eq!(hash(& cs), 9); - // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. let cs: Box<[u8]> = Box::new([1, 2, 3]); assert_eq!(hash(& cs), 9); diff --git a/src/libcoretest/iter.rs b/src/libcoretest/iter.rs index 99d312930533f..6d02f76c33d16 100644 --- a/src/libcoretest/iter.rs +++ b/src/libcoretest/iter.rs @@ -700,7 +700,6 @@ fn test_collect() { #[test] fn test_all() { - // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. let v: Box<[isize]> = Box::new([1, 2, 3, 4, 5]); assert!(v.iter().all(|&x| x < 10)); assert!(!v.iter().all(|&x| x % 2 == 0)); @@ -710,7 +709,6 @@ fn test_all() { #[test] fn test_any() { - // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. let v: Box<[isize]> = Box::new([1, 2, 3, 4, 5]); assert!(v.iter().any(|&x| x < 10)); assert!(v.iter().any(|&x| x % 2 == 0)); diff --git a/src/test/compile-fail-fulldeps/auxiliary/macro_crate_test.rs b/src/test/compile-fail-fulldeps/auxiliary/macro_crate_test.rs index dc88bfc40595f..61b1a0a0b4d25 100644 --- a/src/test/compile-fail-fulldeps/auxiliary/macro_crate_test.rs +++ b/src/test/compile-fail-fulldeps/auxiliary/macro_crate_test.rs @@ -36,11 +36,9 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_macro("identity", expand_identity); reg.register_syntax_extension( Symbol::intern("into_multi_foo"), - // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. MultiModifier(Box::new(expand_into_foo_multi))); reg.register_syntax_extension( Symbol::intern("duplicate"), - // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. MultiDecorator(Box::new(expand_duplicate))); } diff --git a/src/test/compile-fail/borrowck/borrowck-borrowed-uniq-rvalue.rs b/src/test/compile-fail/borrowck/borrowck-borrowed-uniq-rvalue.rs index e4eca7e7eceb4..f58eca7c8ae39 100644 --- a/src/test/compile-fail/borrowck/borrowck-borrowed-uniq-rvalue.rs +++ b/src/test/compile-fail/borrowck/borrowck-borrowed-uniq-rvalue.rs @@ -17,7 +17,6 @@ use std::collections::HashMap; fn main() { let tmp: Box<_>; let mut buggy_map: HashMap = HashMap::new(); - // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. buggy_map.insert(42, &*Box::new(1)); //~ ERROR borrowed value does not live long enough // but it is ok if we use a temporary diff --git a/src/test/compile-fail/cross-borrow-trait.rs b/src/test/compile-fail/cross-borrow-trait.rs index f389380584b84..e5afccb9cf394 100644 --- a/src/test/compile-fail/cross-borrow-trait.rs +++ b/src/test/compile-fail/cross-borrow-trait.rs @@ -16,7 +16,6 @@ trait Trait { fn foo(&self) {} } impl Trait for Foo {} pub fn main() { - // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. let x: Box = Box::new(Foo); let _y: &Trait = x; //~ ERROR mismatched types //~| expected type `&Trait` diff --git a/src/test/compile-fail/dst-bad-assign-2.rs b/src/test/compile-fail/dst-bad-assign-2.rs index 241fabf053c0b..10c8f1eed00b0 100644 --- a/src/test/compile-fail/dst-bad-assign-2.rs +++ b/src/test/compile-fail/dst-bad-assign-2.rs @@ -41,7 +41,6 @@ impl ToBar for Bar1 { pub fn main() { // Assignment. let f5: &mut Fat = &mut Fat { f1: 5, f2: "some str", ptr: Bar1 {f :42} }; - // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. let z: Box = Box::new(Bar1 {f: 36}); f5.ptr = *z; //~^ ERROR `ToBar: std::marker::Sized` is not satisfied diff --git a/src/test/compile-fail/dst-bad-assign.rs b/src/test/compile-fail/dst-bad-assign.rs index 9e71ad2417792..4f7d07600ad15 100644 --- a/src/test/compile-fail/dst-bad-assign.rs +++ b/src/test/compile-fail/dst-bad-assign.rs @@ -41,7 +41,6 @@ impl ToBar for Bar1 { pub fn main() { // Assignment. let f5: &mut Fat = &mut Fat { f1: 5, f2: "some str", ptr: Bar1 {f :42} }; - // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. let z: Box = Box::new(Bar1 {f: 36}); f5.ptr = Bar1 {f: 36}; //~^ ERROR mismatched types diff --git a/src/test/compile-fail/issue-10291.rs b/src/test/compile-fail/issue-10291.rs index 43255db2ff3ab..d4e7dc7e9a35d 100644 --- a/src/test/compile-fail/issue-10291.rs +++ b/src/test/compile-fail/issue-10291.rs @@ -9,7 +9,6 @@ // except according to those terms. fn test<'x>(x: &'x isize) { - // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. drop:: FnMut(&'z isize) -> &'z isize>>(Box::new(|z| { x //~ ERROR E0312 })); diff --git a/src/test/compile-fail/issue-11515.rs b/src/test/compile-fail/issue-11515.rs index f682d618ab646..7afb8314ea689 100644 --- a/src/test/compile-fail/issue-11515.rs +++ b/src/test/compile-fail/issue-11515.rs @@ -15,7 +15,6 @@ struct Test { } fn main() { - // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. let closure: Box = Box::new(|| ()); let test = box Test { func: closure }; //~ ERROR mismatched types } diff --git a/src/test/compile-fail/issue-17441.rs b/src/test/compile-fail/issue-17441.rs index 45ab9903532e7..bddc9c13815e7 100644 --- a/src/test/compile-fail/issue-17441.rs +++ b/src/test/compile-fail/issue-17441.rs @@ -13,7 +13,6 @@ fn main() { //~^ ERROR cast to unsized type: `&[usize; 2]` as `[usize]` //~^^ HELP consider using an implicit coercion to `&[usize]` instead - // FIXME (#22405): Replace `std::boxed::Box::new` with `box` here when/if possible. let _bar = Box::new(1_usize) as std::fmt::Debug; //~^ ERROR cast to unsized type: `std::boxed::Box` as `std::fmt::Debug` //~^^ HELP try casting to a `Box` instead diff --git a/src/test/compile-fail/issue-17651.rs b/src/test/compile-fail/issue-17651.rs index 3ea136aca4bec..4996da057dd8e 100644 --- a/src/test/compile-fail/issue-17651.rs +++ b/src/test/compile-fail/issue-17651.rs @@ -12,7 +12,6 @@ // and rejected. fn main() { - // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. (|| Box::new(*(&[0][..])))(); //~^ ERROR `[{integer}]: std::marker::Sized` is not satisfied } diff --git a/src/test/compile-fail/issue-18783.rs b/src/test/compile-fail/issue-18783.rs index 5eb3c439df2f3..9a7b3781f1e24 100644 --- a/src/test/compile-fail/issue-18783.rs +++ b/src/test/compile-fail/issue-18783.rs @@ -10,8 +10,6 @@ use std::cell::RefCell; -// FIXME (#22405): Replace `Box::new` with `box` here when/if possible. - fn main() { let mut y = 1; let c = RefCell::new(vec![]); diff --git a/src/test/compile-fail/issue-3763.rs b/src/test/compile-fail/issue-3763.rs index 085b4e76afbf7..851f5dfeabe8a 100644 --- a/src/test/compile-fail/issue-3763.rs +++ b/src/test/compile-fail/issue-3763.rs @@ -25,13 +25,11 @@ fn main() { let _woohoo = (&my_struct).priv_field; //~^ ERROR field `priv_field` of struct `my_mod::MyStruct` is private - // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. let _woohoo = (Box::new(my_struct)).priv_field; //~^ ERROR field `priv_field` of struct `my_mod::MyStruct` is private (&my_struct).happyfun(); //~ ERROR method `happyfun` is private - // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. (Box::new(my_struct)).happyfun(); //~ ERROR method `happyfun` is private let nope = my_struct.priv_field; //~^ ERROR field `priv_field` of struct `my_mod::MyStruct` is private diff --git a/src/test/compile-fail/issue-4335.rs b/src/test/compile-fail/issue-4335.rs index 51f5fc5ee98e1..c5aae894c3ecb 100644 --- a/src/test/compile-fail/issue-4335.rs +++ b/src/test/compile-fail/issue-4335.rs @@ -13,7 +13,6 @@ fn id(t: T) -> T { t } fn f<'r, T>(v: &'r T) -> Box T + 'r> { - // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. id(Box::new(|| *v)) //~^ ERROR E0373 //~| NOTE `v` is borrowed here diff --git a/src/test/compile-fail/map-types.rs b/src/test/compile-fail/map-types.rs index eaafc312379c2..9dcf902a69f91 100644 --- a/src/test/compile-fail/map-types.rs +++ b/src/test/compile-fail/map-types.rs @@ -24,7 +24,6 @@ impl Map for HashMap {} fn main() { let x: Box> = box HashMap::new(); let x: Box> = x; - // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. let y: Box> = Box::new(x); //~^ ERROR `std::boxed::Box>: Map` is not satisfied } diff --git a/src/test/compile-fail/moves-based-on-type-no-recursive-stack-closure.rs b/src/test/compile-fail/moves-based-on-type-no-recursive-stack-closure.rs index df9a3519d5d61..d529606599994 100644 --- a/src/test/compile-fail/moves-based-on-type-no-recursive-stack-closure.rs +++ b/src/test/compile-fail/moves-based-on-type-no-recursive-stack-closure.rs @@ -38,7 +38,6 @@ fn innocent_looking_victim() { } fn conspirator(mut f: F) where F: FnMut(&mut R, bool) { - // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. let mut r = R {c: Box::new(f)}; f(&mut r, false) //~ ERROR use of moved value } diff --git a/src/test/compile-fail/region-object-lifetime-in-coercion.rs b/src/test/compile-fail/region-object-lifetime-in-coercion.rs index f95ee405895a9..687b2c344a3b7 100644 --- a/src/test/compile-fail/region-object-lifetime-in-coercion.rs +++ b/src/test/compile-fail/region-object-lifetime-in-coercion.rs @@ -14,8 +14,6 @@ trait Foo {} impl<'a> Foo for &'a [u8] {} -// FIXME (#22405): Replace `Box::new` with `box` here when/if possible. - fn a(v: &[u8]) -> Box { let x: Box = Box::new(v); //~^ ERROR cannot infer an appropriate lifetime due to conflicting diff --git a/src/test/compile-fail/regions-close-associated-type-into-object.rs b/src/test/compile-fail/regions-close-associated-type-into-object.rs index 61897aac18769..6b88abfca6c91 100644 --- a/src/test/compile-fail/regions-close-associated-type-into-object.rs +++ b/src/test/compile-fail/regions-close-associated-type-into-object.rs @@ -10,8 +10,6 @@ #![feature(box_syntax)] -// FIXME (#22405): Replace `Box::new` with `box` here when/if possible. - trait X {} trait Iter { diff --git a/src/test/compile-fail/regions-close-param-into-object.rs b/src/test/compile-fail/regions-close-param-into-object.rs index 7324d4a4a0ed6..c9063405bd7e2 100644 --- a/src/test/compile-fail/regions-close-param-into-object.rs +++ b/src/test/compile-fail/regions-close-param-into-object.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// FIXME (#22405): Replace `Box::new` with `box` here when/if possible. - trait X { fn foo(&self) {} } fn p1(v: T) -> Box diff --git a/src/test/compile-fail/regions-nested-fns.rs b/src/test/compile-fail/regions-nested-fns.rs index 5ef2a701a6005..010b7d1768812 100644 --- a/src/test/compile-fail/regions-nested-fns.rs +++ b/src/test/compile-fail/regions-nested-fns.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// FIXME (#22405): Replace `Box::new` with `box` here when/if possible. - fn ignore(t: T) {} fn nested<'x>(x: &'x isize) { diff --git a/src/test/compile-fail/regions-proc-bound-capture.rs b/src/test/compile-fail/regions-proc-bound-capture.rs index 48b6e8b773f3b..fb726e31af586 100644 --- a/src/test/compile-fail/regions-proc-bound-capture.rs +++ b/src/test/compile-fail/regions-proc-bound-capture.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// FIXME (#22405): Replace `Box::new` with `box` here when/if possible. - fn borrowed_proc<'a>(x: &'a isize) -> Box(isize) + 'a> { // This is legal, because the region bound on `proc` // states that it captures `x`. diff --git a/src/test/compile-fail/regions-steal-closure.rs b/src/test/compile-fail/regions-steal-closure.rs index 59fe1ce3af1af..7ca63b9896fe0 100644 --- a/src/test/compile-fail/regions-steal-closure.rs +++ b/src/test/compile-fail/regions-steal-closure.rs @@ -21,7 +21,6 @@ fn box_it<'r>(x: Box) -> closure_box<'r> { fn main() { let mut cl_box = { let mut i = 3; - // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. box_it(Box::new(|| i += 1)) //~ ERROR `i` does not live long enough }; cl_box.cl.call_mut(()); diff --git a/src/test/compile-fail/trait-coercion-generic-bad.rs b/src/test/compile-fail/trait-coercion-generic-bad.rs index dd64085f6f666..3839e90ed9fe7 100644 --- a/src/test/compile-fail/trait-coercion-generic-bad.rs +++ b/src/test/compile-fail/trait-coercion-generic-bad.rs @@ -23,7 +23,6 @@ impl Trait<&'static str> for Struct { } fn main() { - // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. let s: Box> = Box::new(Struct { person: "Fred" }); //~^ ERROR `Struct: Trait` is not satisfied s.f(1); diff --git a/src/test/compile-fail/trait-coercion-generic-regions.rs b/src/test/compile-fail/trait-coercion-generic-regions.rs index 9ba017e150e61..18d3ded77f8f3 100644 --- a/src/test/compile-fail/trait-coercion-generic-regions.rs +++ b/src/test/compile-fail/trait-coercion-generic-regions.rs @@ -25,6 +25,5 @@ impl Trait<&'static str> for Struct { fn main() { let person = "Fred".to_string(); let person: &str = &person; //~ ERROR `person` does not live long enough - // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. let s: Box> = Box::new(Struct { person: person }); } diff --git a/src/test/compile-fail/unboxed-closure-illegal-move.rs b/src/test/compile-fail/unboxed-closure-illegal-move.rs index 564b1b4669f7d..427be5607600d 100644 --- a/src/test/compile-fail/unboxed-closure-illegal-move.rs +++ b/src/test/compile-fail/unboxed-closure-illegal-move.rs @@ -18,8 +18,6 @@ fn to_fn>(f: F) -> F { f } fn to_fn_mut>(f: F) -> F { f } fn to_fn_once>(f: F) -> F { f } -// FIXME (#22405): Replace `Box::new` with `box` here when/if possible. - fn main() { // By-ref cases { diff --git a/src/test/compile-fail/unique-pinned-nocopy.rs b/src/test/compile-fail/unique-pinned-nocopy.rs index d971940db38f5..c09feec1d4af2 100644 --- a/src/test/compile-fail/unique-pinned-nocopy.rs +++ b/src/test/compile-fail/unique-pinned-nocopy.rs @@ -18,7 +18,6 @@ impl Drop for r { } fn main() { - // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. let i = Box::new(r { b: true }); let _j = i.clone(); //~ ERROR no method named `clone` found println!("{:?}", i); diff --git a/src/test/run-pass-fulldeps/auxiliary/macro_crate_test.rs b/src/test/run-pass-fulldeps/auxiliary/macro_crate_test.rs index 29cc6b7db9474..aa2f1626a6a86 100644 --- a/src/test/run-pass-fulldeps/auxiliary/macro_crate_test.rs +++ b/src/test/run-pass-fulldeps/auxiliary/macro_crate_test.rs @@ -38,15 +38,12 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_macro("identity", expand_identity); reg.register_syntax_extension( Symbol::intern("into_multi_foo"), - // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. MultiModifier(Box::new(expand_into_foo_multi))); reg.register_syntax_extension( Symbol::intern("duplicate"), - // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. MultiDecorator(Box::new(expand_duplicate))); reg.register_syntax_extension( Symbol::intern("caller"), - // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. MultiDecorator(Box::new(expand_caller))); } diff --git a/src/test/run-pass-fulldeps/auxiliary/plugin_args.rs b/src/test/run-pass-fulldeps/auxiliary/plugin_args.rs index ba2af77cdb297..3c8868f1664e8 100644 --- a/src/test/run-pass-fulldeps/auxiliary/plugin_args.rs +++ b/src/test/run-pass-fulldeps/auxiliary/plugin_args.rs @@ -48,6 +48,5 @@ impl TTMacroExpander for Expander { pub fn plugin_registrar(reg: &mut Registry) { let args = reg.args().to_owned(); reg.register_syntax_extension(Symbol::intern("plugin_args"), - // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. NormalTT(Box::new(Expander { args: args, }), None, false)); } diff --git a/src/test/run-pass-fulldeps/deriving-encodable-decodable-box.rs b/src/test/run-pass-fulldeps/deriving-encodable-decodable-box.rs index 328cc134f3b1f..1573b0807173f 100644 --- a/src/test/run-pass-fulldeps/deriving-encodable-decodable-box.rs +++ b/src/test/run-pass-fulldeps/deriving-encodable-decodable-box.rs @@ -24,7 +24,6 @@ struct A { } fn main() { - // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. let obj = A { foo: Box::new([true, false]) }; let s = json::encode(&obj).unwrap(); let obj2: A = json::decode(&s).unwrap(); diff --git a/src/test/run-pass-valgrind/dst-dtor-1.rs b/src/test/run-pass-valgrind/dst-dtor-1.rs index 995da8c73fab8..4af642a106c15 100644 --- a/src/test/run-pass-valgrind/dst-dtor-1.rs +++ b/src/test/run-pass-valgrind/dst-dtor-1.rs @@ -28,7 +28,6 @@ struct Fat { pub fn main() { { - // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. let _x: Box> = Box::>::new(Fat { f: Foo }); } unsafe { diff --git a/src/test/run-pass-valgrind/dst-dtor-2.rs b/src/test/run-pass-valgrind/dst-dtor-2.rs index 471169340d793..283b8202b35d0 100644 --- a/src/test/run-pass-valgrind/dst-dtor-2.rs +++ b/src/test/run-pass-valgrind/dst-dtor-2.rs @@ -25,7 +25,6 @@ struct Fat { pub fn main() { { - // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. let _x: Box> = Box::>::new(Fat { f: [Foo, Foo, Foo] }); } unsafe { diff --git a/src/test/run-pass/associated-types-doubleendediterator-object.rs b/src/test/run-pass/associated-types-doubleendediterator-object.rs index dd194447740b7..0a6135080bb6e 100644 --- a/src/test/run-pass/associated-types-doubleendediterator-object.rs +++ b/src/test/run-pass/associated-types-doubleendediterator-object.rs @@ -26,7 +26,6 @@ fn pairwise_sub(mut t: Box>) -> isize { fn main() { let v = vec![1, 2, 3, 4, 5, 6]; - // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. let r = pairwise_sub(Box::new(v.into_iter())); assert_eq!(r, 9); } diff --git a/src/test/run-pass/coerce-expect-unsized.rs b/src/test/run-pass/coerce-expect-unsized.rs index e4792e7936bc4..a074aea9caa5c 100644 --- a/src/test/run-pass/coerce-expect-unsized.rs +++ b/src/test/run-pass/coerce-expect-unsized.rs @@ -19,15 +19,6 @@ use std::rc::Rc; // rvalue expressions to be unsized. See #20169 for more information. pub fn main() { - // FIXME #22405: We cannot infer the type `Box<[isize; k]>` for - // the r-value expression from the context `Box<[isize]>`, and - // therefore the `box EXPR` desugaring breaks down. - // - // One could reasonably claim that the `box EXPR` desugaring is - // effectively regressing half of Issue #20169. Hopefully we will - // eventually fix that, at which point the `Box::new` calls below - // should be replaced wth uses of `box`. - let _: Box<[isize]> = Box::new({ [1, 2, 3] }); let _: Box<[isize]> = Box::new(if true { [1, 2, 3] } else { [1, 3, 4] }); let _: Box<[isize]> = Box::new(match true { true => [1, 2, 3], false => [1, 3, 4] }); diff --git a/src/test/run-pass/deriving-default-box.rs b/src/test/run-pass/deriving-default-box.rs index dc31e71aad873..c9e5b014da37a 100644 --- a/src/test/run-pass/deriving-default-box.rs +++ b/src/test/run-pass/deriving-default-box.rs @@ -21,7 +21,6 @@ struct A { pub fn main() { let a: A = Default::default(); - // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. let b: Box<[_]> = Box::<[bool; 0]>::new([]); assert_eq!(a.foo, b); } diff --git a/src/test/run-pass/deriving-eq-ord-boxed-slice.rs b/src/test/run-pass/deriving-eq-ord-boxed-slice.rs index f490cca6a699d..16c49065008aa 100644 --- a/src/test/run-pass/deriving-eq-ord-boxed-slice.rs +++ b/src/test/run-pass/deriving-eq-ord-boxed-slice.rs @@ -12,7 +12,6 @@ struct Foo(Box<[u8]>); pub fn main() { - // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. let a = Foo(Box::new([0, 1, 2])); let b = Foo(Box::new([0, 1, 2])); assert_eq!(a, b); diff --git a/src/test/run-pass/dst-deref-mut.rs b/src/test/run-pass/dst-deref-mut.rs index 0666e41738e3c..9fb4635765ca0 100644 --- a/src/test/run-pass/dst-deref-mut.rs +++ b/src/test/run-pass/dst-deref-mut.rs @@ -39,7 +39,6 @@ pub fn foo(arr: &mut Arr) { } fn main() { - // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. let mut a = Arr { ptr: Box::new([1, 2, 3]) }; foo(&mut a); } diff --git a/src/test/run-pass/dst-deref.rs b/src/test/run-pass/dst-deref.rs index 957ed13a3d817..4a143873e6e13 100644 --- a/src/test/run-pass/dst-deref.rs +++ b/src/test/run-pass/dst-deref.rs @@ -34,7 +34,6 @@ pub fn foo(arr: &Arr) { } fn main() { - // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. let a = Arr { ptr: Box::new([1, 2, 3]) }; foo(&a); } diff --git a/src/test/run-pass/dst-struct.rs b/src/test/run-pass/dst-struct.rs index 94efa7a256b4d..56199c1aa61fa 100644 --- a/src/test/run-pass/dst-struct.rs +++ b/src/test/run-pass/dst-struct.rs @@ -127,7 +127,6 @@ pub fn main() { let f2 : Box> = f1; foo(&*f2); - // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. let f3 : Box> = Box::>::new(Fat { f1: 5, f2: "some str", ptr: [1, 2, 3] }); foo(&*f3); diff --git a/src/test/run-pass/dst-trait.rs b/src/test/run-pass/dst-trait.rs index 9d12a4a34b7d4..d8d7d9a28bfbd 100644 --- a/src/test/run-pass/dst-trait.rs +++ b/src/test/run-pass/dst-trait.rs @@ -97,7 +97,6 @@ pub fn main() { // &* // - // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. let f7: Box = Box::new(Bar1 {f :42}); bar(&*f7); diff --git a/src/test/run-pass/empty-allocation-non-null.rs b/src/test/run-pass/empty-allocation-non-null.rs index af6e321e40aa6..3dbe7da6ac704 100644 --- a/src/test/run-pass/empty-allocation-non-null.rs +++ b/src/test/run-pass/empty-allocation-non-null.rs @@ -8,9 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// FIXME (#22405): Replace `Box::new` with `box` here when/if possible. - - pub fn main() { assert!(Some(Box::new(())).is_some()); diff --git a/src/test/run-pass/hashmap-memory.rs b/src/test/run-pass/hashmap-memory.rs index 2306fa9afa2ef..bd90ce683c452 100644 --- a/src/test/run-pass/hashmap-memory.rs +++ b/src/test/run-pass/hashmap-memory.rs @@ -62,7 +62,6 @@ mod map_reduce { } let ctrl_clone = ctrl.clone(); - // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. ::map(input, Box::new(|a,b| emit(&mut intermediates, ctrl.clone(), a, b))); ctrl_clone.send(ctrl_proto::mapper_done).unwrap(); } diff --git a/src/test/run-pass/hrtb-precedence-of-plus.rs b/src/test/run-pass/hrtb-precedence-of-plus.rs index d93e52a8f5fbb..516278df178eb 100644 --- a/src/test/run-pass/hrtb-precedence-of-plus.rs +++ b/src/test/run-pass/hrtb-precedence-of-plus.rs @@ -17,7 +17,6 @@ // cause a compilation error. Issue #18772. fn adder(y: isize) -> Box isize + 'static> { - // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. Box::new(move |x| y + x) } diff --git a/src/test/run-pass/issue-11205.rs b/src/test/run-pass/issue-11205.rs index 679d494a47302..25c66bf8d485f 100644 --- a/src/test/run-pass/issue-11205.rs +++ b/src/test/run-pass/issue-11205.rs @@ -12,8 +12,6 @@ #![allow(dead_code)] -// FIXME (#22405): Replace `Box::new` with `box` here when/if possible. - trait Foo { fn dummy(&self) { } } impl Foo for isize {} fn foo(_: [&Foo; 2]) {} diff --git a/src/test/run-pass/issue-11677.rs b/src/test/run-pass/issue-11677.rs index d4244d44439b0..62da3b1467559 100644 --- a/src/test/run-pass/issue-11677.rs +++ b/src/test/run-pass/issue-11677.rs @@ -27,6 +27,5 @@ impl X for F { } fn main() { - // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. S {f: Box::new(F), g: Box::new(F) }; } diff --git a/src/test/run-pass/issue-12744.rs b/src/test/run-pass/issue-12744.rs index 56d1d3599c7fd..aec45216b1b73 100644 --- a/src/test/run-pass/issue-12744.rs +++ b/src/test/run-pass/issue-12744.rs @@ -9,7 +9,6 @@ // except according to those terms. fn main() { - // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. fn test() -> Box { Box::new(1) } println!("{:?}", test()) } diff --git a/src/test/run-pass/issue-13808.rs b/src/test/run-pass/issue-13808.rs index c85c0117581a5..ccdfa0646c6aa 100644 --- a/src/test/run-pass/issue-13808.rs +++ b/src/test/run-pass/issue-13808.rs @@ -16,7 +16,6 @@ struct Foo<'a> { impl<'a> Foo<'a> { fn new(listener: F) -> Foo<'a> where F: FnMut() + 'a { - // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. Foo { listener: Box::new(listener) } } } diff --git a/src/test/run-pass/issue-14589.rs b/src/test/run-pass/issue-14589.rs index b0893e21af7e9..8aaa24e991ea1 100644 --- a/src/test/run-pass/issue-14589.rs +++ b/src/test/run-pass/issue-14589.rs @@ -11,8 +11,6 @@ // All 3 expressions should work in that the argument gets // coerced to a trait object -// FIXME (#22405): Replace `Box::new` with `box` here when/if possible. - // pretty-expanded FIXME #23616 fn main() { diff --git a/src/test/run-pass/issue-14919.rs b/src/test/run-pass/issue-14919.rs index d3c9fe9161ccb..df5d62e7699bb 100644 --- a/src/test/run-pass/issue-14919.rs +++ b/src/test/run-pass/issue-14919.rs @@ -31,7 +31,6 @@ trait IntoMatcher<'a, T> { impl<'a, 'b, F> IntoMatcher<'a, CharPredMatcher<'a, 'b>> for F where F: FnMut(char) -> bool + 'b { fn into_matcher(self, s: &'a str) -> CharPredMatcher<'a, 'b> { - // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. CharPredMatcher { str: s, pred: Box::new(self), diff --git a/src/test/run-pass/issue-16668.rs b/src/test/run-pass/issue-16668.rs index 18861feb1997a..5613211b31df4 100644 --- a/src/test/run-pass/issue-16668.rs +++ b/src/test/run-pass/issue-16668.rs @@ -16,7 +16,6 @@ struct Parser<'a, I, O> { impl<'a, I: 'a, O: 'a> Parser<'a, I, O> { fn compose(mut self, mut rhs: Parser<'a, O, K>) -> Parser<'a, I, K> { - // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. Parser { parse: Box::new(move |x: I| { match (self.parse)(x) { diff --git a/src/test/run-pass/issue-17734.rs b/src/test/run-pass/issue-17734.rs index 0fc8eea778da9..8178c1fd7c885 100644 --- a/src/test/run-pass/issue-17734.rs +++ b/src/test/run-pass/issue-17734.rs @@ -17,8 +17,6 @@ fn f(s: Box) -> Box { fn main() { // There is currently no safe way to construct a `Box`, so improvise - // - // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. let box_arr: Box<[u8]> = Box::new(['h' as u8, 'e' as u8, 'l' as u8, 'l' as u8, 'o' as u8]); let box_str: Box = unsafe { std::mem::transmute(box_arr) }; assert_eq!(&*box_str, "hello"); diff --git a/src/test/run-pass/issue-20575.rs b/src/test/run-pass/issue-20575.rs index e73492e7a7ee5..7db7e3b28e8e6 100644 --- a/src/test/run-pass/issue-20575.rs +++ b/src/test/run-pass/issue-20575.rs @@ -13,7 +13,6 @@ // pretty-expanded FIXME #23616 fn main() { - // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. let functions: [Box Option<()>>; 1] = [Box::new(|| None)]; let _: Option> = functions.iter().map(|f| (*f)()).collect(); diff --git a/src/test/run-pass/issue-3052.rs b/src/test/run-pass/issue-3052.rs index 8f013ee4f3a0f..3b56b2e28ff22 100644 --- a/src/test/run-pass/issue-3052.rs +++ b/src/test/run-pass/issue-3052.rs @@ -13,7 +13,6 @@ type Connection = Box) + 'static>; fn f() -> Option { - // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. let mock_connection: Connection = Box::new(|_| {}); Some(mock_connection) } diff --git a/src/test/run-pass/issue-3609.rs b/src/test/run-pass/issue-3609.rs index 61de3c6385e7b..d1bf7e066cb5a 100644 --- a/src/test/run-pass/issue-3609.rs +++ b/src/test/run-pass/issue-3609.rs @@ -26,7 +26,6 @@ fn foo(name: String, samples_chan: Sender) { thread::spawn(move|| { let mut samples_chan = samples_chan; - // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. let callback: SamplesFn = Box::new(move |buffer| { for i in 0..buffer.len() { println!("{}: {}", i, buffer[i]) diff --git a/src/test/run-pass/newlambdas-ret-infer.rs b/src/test/run-pass/newlambdas-ret-infer.rs index 543dbb36b2850..428eed0787a83 100644 --- a/src/test/run-pass/newlambdas-ret-infer.rs +++ b/src/test/run-pass/newlambdas-ret-infer.rs @@ -11,7 +11,6 @@ // Test that the lambda kind is inferred correctly as a return // expression -// FIXME (#22405): Replace `Box::new` with `box` here when/if possible. // pretty-expanded FIXME #23616 fn unique() -> Box { return Box::new(|| ()); } diff --git a/src/test/run-pass/newlambdas-ret-infer2.rs b/src/test/run-pass/newlambdas-ret-infer2.rs index e8297173a5834..439ea3f2b579c 100644 --- a/src/test/run-pass/newlambdas-ret-infer2.rs +++ b/src/test/run-pass/newlambdas-ret-infer2.rs @@ -11,7 +11,6 @@ // Test that the lambda kind is inferred correctly as a return // expression -// FIXME (#22405): Replace `Box::new` with `box` here when/if possible. // pretty-expanded FIXME #23616 fn unique() -> Box { Box::new(|| ()) } diff --git a/src/test/run-pass/regions-fn-subtyping.rs b/src/test/run-pass/regions-fn-subtyping.rs index fc42fbc714c09..c7a4accff85e1 100644 --- a/src/test/run-pass/regions-fn-subtyping.rs +++ b/src/test/run-pass/regions-fn-subtyping.rs @@ -16,8 +16,6 @@ #![allow(unused_variables)] #![allow(unknown_features)] -// FIXME (#22405): Replace `Box::new` with `box` here when/if possible. - // Should pass region checking. fn ok(f: Box) { // Here, g is a function that can accept a usize pointer with diff --git a/src/test/run-pass/regions-relate-bound-regions-on-closures-to-inference-variables.rs b/src/test/run-pass/regions-relate-bound-regions-on-closures-to-inference-variables.rs index 8eee54b3fec66..ae4adbfb1f497 100644 --- a/src/test/run-pass/regions-relate-bound-regions-on-closures-to-inference-variables.rs +++ b/src/test/run-pass/regions-relate-bound-regions-on-closures-to-inference-variables.rs @@ -31,7 +31,6 @@ struct Foo<'a,'tcx:'a> { impl<'a,'tcx> Foo<'a,'tcx> { fn bother(&mut self) -> isize { - // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. self.elaborate_bounds(Box::new(|this| { // (*) Here: type of `this` is `&'f0 Foo<&'f1, '_2>`, // where `'f0` and `'f1` are fresh, free regions that diff --git a/src/test/run-pass/show-boxed-slice.rs b/src/test/run-pass/show-boxed-slice.rs index 03971668182ac..47d0737dfc451 100644 --- a/src/test/run-pass/show-boxed-slice.rs +++ b/src/test/run-pass/show-boxed-slice.rs @@ -12,6 +12,5 @@ struct Foo(Box<[u8]>); pub fn main() { - // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. println!("{:?}", Foo(Box::new([0, 1, 2]))); } diff --git a/src/test/run-pass/trait-bounds-in-arc.rs b/src/test/run-pass/trait-bounds-in-arc.rs index 9877dffe9df02..c58442aa58f33 100644 --- a/src/test/run-pass/trait-bounds-in-arc.rs +++ b/src/test/run-pass/trait-bounds-in-arc.rs @@ -105,7 +105,6 @@ fn check_legs(arc: Arc>>) { } fn check_names(arc: Arc>>) { for pet in arc.iter() { - // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. pet.name(Box::new(|name| { assert!(name.as_bytes()[0] == 'a' as u8 && name.as_bytes()[1] == 'l' as u8); })) diff --git a/src/test/run-pass/trait-coercion-generic.rs b/src/test/run-pass/trait-coercion-generic.rs index f9a22d5ccec6d..40453262ddf3a 100644 --- a/src/test/run-pass/trait-coercion-generic.rs +++ b/src/test/run-pass/trait-coercion-generic.rs @@ -26,7 +26,6 @@ impl Trait<&'static str> for Struct { pub fn main() { let a = Struct { x: 1, y: 2 }; - // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. let b: Box> = Box::new(a); b.f("Mary"); let c: &Trait<&'static str> = &a; diff --git a/src/test/run-pass/trait-coercion.rs b/src/test/run-pass/trait-coercion.rs index d40d9c89f89df..130c6ee7521b4 100644 --- a/src/test/run-pass/trait-coercion.rs +++ b/src/test/run-pass/trait-coercion.rs @@ -30,8 +30,6 @@ impl Trait for Struct { fn foo(mut a: Box) {} -// FIXME (#22405): Replace `Box::new` with `box` here when/if possible. - pub fn main() { let a = Struct { x: 1, y: 2 }; let b: Box = Box::new(a); diff --git a/src/test/run-pass/unboxed-closures-call-sugar-object-autoderef.rs b/src/test/run-pass/unboxed-closures-call-sugar-object-autoderef.rs index a92fb05306f48..789d2237c543c 100644 --- a/src/test/run-pass/unboxed-closures-call-sugar-object-autoderef.rs +++ b/src/test/run-pass/unboxed-closures-call-sugar-object-autoderef.rs @@ -15,7 +15,6 @@ use std::ops::FnMut; fn make_adder(x: isize) -> Boxisize + 'static> { - // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. Box::new(move |y| { x + y }) } diff --git a/src/test/run-pass/unboxed-closures-call-sugar-object.rs b/src/test/run-pass/unboxed-closures-call-sugar-object.rs index 5dd2343cfd1dd..e730771547170 100644 --- a/src/test/run-pass/unboxed-closures-call-sugar-object.rs +++ b/src/test/run-pass/unboxed-closures-call-sugar-object.rs @@ -13,7 +13,6 @@ use std::ops::FnMut; fn make_adder(x: isize) -> Boxisize + 'static> { - // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. Box::new(move |y| { x + y }) } diff --git a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.rs b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.rs index ba1ae64ec330a..6264d11186452 100644 --- a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.rs +++ b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.rs @@ -18,7 +18,6 @@ struct Test<'a> { f: Box } -// FIXME (#22405): Replace `Box::new` with `box` here when/if possible. fn call(mut f: F) where F: FnMut(Fn) { f(Box::new(|| { //~^ ERROR: cannot borrow `f` as mutable more than once @@ -58,7 +57,6 @@ fn test6() { fn test7() { fn foo(_: F) where F: FnMut(Box, isize) {} let mut f = |g: Box, b: isize| {}; - // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. f(Box::new(|a| { foo(f); //~^ ERROR cannot move `f` into closure because it is borrowed diff --git a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr index f2f0e027f0161..58b3f205fe352 100644 --- a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr +++ b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr @@ -1,44 +1,44 @@ error[E0499]: cannot borrow `f` as mutable more than once at a time - --> $DIR/borrowck-call-is-borrow-issue-12224.rs:23:16 + --> $DIR/borrowck-call-is-borrow-issue-12224.rs:22:16 | -23 | f(Box::new(|| { +22 | f(Box::new(|| { | - ^^ second mutable borrow occurs here | | | first mutable borrow occurs here -24 | //~^ ERROR: cannot borrow `f` as mutable more than once -25 | f((Box::new(|| {}))) +23 | //~^ ERROR: cannot borrow `f` as mutable more than once +24 | f((Box::new(|| {}))) | - borrow occurs due to use of `f` in closure -26 | })); +25 | })); | - first borrow ends here error: cannot borrow immutable borrowed content `*f` as mutable - --> $DIR/borrowck-call-is-borrow-issue-12224.rs:36:5 + --> $DIR/borrowck-call-is-borrow-issue-12224.rs:35:5 | -35 | fn test2(f: &F) where F: FnMut() { +34 | fn test2(f: &F) where F: FnMut() { | -- use `&mut F` here to make mutable -36 | (*f)(); //~ ERROR: cannot borrow immutable borrowed content `*f` as mutable +35 | (*f)(); //~ ERROR: cannot borrow immutable borrowed content `*f` as mutable | ^^^^ cannot borrow as mutable error: cannot borrow immutable `Box` content `*f.f` as mutable - --> $DIR/borrowck-call-is-borrow-issue-12224.rs:44:5 + --> $DIR/borrowck-call-is-borrow-issue-12224.rs:43:5 | -43 | fn test4(f: &Test) { +42 | fn test4(f: &Test) { | ----- use `&mut Test` here to make mutable -44 | f.f.call_mut(()) //~ ERROR: cannot borrow immutable `Box` content `*f.f` as mutable +43 | f.f.call_mut(()) //~ ERROR: cannot borrow immutable `Box` content `*f.f` as mutable | ^^^ cannot borrow as mutable error[E0504]: cannot move `f` into closure because it is borrowed - --> $DIR/borrowck-call-is-borrow-issue-12224.rs:63:13 + --> $DIR/borrowck-call-is-borrow-issue-12224.rs:61:13 | -62 | f(Box::new(|a| { +60 | f(Box::new(|a| { | - borrow of `f` occurs here -63 | foo(f); +61 | foo(f); | ^ move into closure occurs here error[E0507]: cannot move out of captured outer variable in an `FnMut` closure - --> $DIR/borrowck-call-is-borrow-issue-12224.rs:63:13 + --> $DIR/borrowck-call-is-borrow-issue-12224.rs:61:13 | -63 | foo(f); +61 | foo(f); | ^ cannot move out of captured outer variable in an `FnMut` closure error: aborting due to 5 previous errors From dfcca546fcbdab16b2696550820b0cea5ea7a894 Mon Sep 17 00:00:00 2001 From: f001 Date: Wed, 1 Feb 2017 11:54:36 +0800 Subject: [PATCH 047/137] std: Add ToString trait specialization for Cow<'a, str> and String r? @bluss --- src/libcollections/string.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index b184a8603e6bd..9a985061ebbde 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -1866,6 +1866,22 @@ impl ToString for str { } } +#[stable(feature = "cow_str_to_string_specialization", since = "1.17.0")] +impl<'a> ToString for Cow<'a, str> { + #[inline] + fn to_string(&self) -> String { + self[..].to_owned() + } +} + +#[stable(feature = "string_to_string_specialization", since = "1.17.0")] +impl ToString for String { + #[inline] + fn to_string(&self) -> String { + self.to_owned() + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl AsRef for String { #[inline] From 7403ee9d07a1b096e9628871bd97e39f464c3aa5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Krasnoborski?= Date: Wed, 1 Feb 2017 23:47:03 +0100 Subject: [PATCH 048/137] Adjust heuristics to better handle "{}..." format strings. --- src/libcore/fmt/mod.rs | 21 ++++++++++++--------- src/libcoretest/fmt/mod.rs | 4 +++- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index ed9c5d3337f04..a870b6f88fb83 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -281,17 +281,20 @@ impl<'a> Arguments<'a> { let pieces_length: W = self.pieces.iter() .map(|x| W(x.len())).sum(); - // If they are any arguments to format, the string will most likely - // double in size. So we're pre-doubling it here. - let multiplier = if self.args.is_empty() { W(1) } else { W(2) }; - - let capacity = multiplier * pieces_length; - if multiplier == W(2) && (W(1)..W(8)).contains(capacity) { - // Allocations smaller than 8 don't really make sense for String. - 8 + if self.args.is_empty() { + pieces_length.0 + } else if self.pieces[0] == "" && pieces_length < W(16) { + // If the format string starts with an argument, + // don't preallocate anything, unless length + // of pieces is significant. + 0 } else { - capacity.0 + // There are some arguments, so any additional push + // will reallocate the string. To avoid that, + // we're "pre-doubling" the capacity here. + (pieces_length * W(2)).0 } + } } diff --git a/src/libcoretest/fmt/mod.rs b/src/libcoretest/fmt/mod.rs index 71b3a440f7bea..5d204c7d523d6 100644 --- a/src/libcoretest/fmt/mod.rs +++ b/src/libcoretest/fmt/mod.rs @@ -31,8 +31,10 @@ fn test_pointer_formats_data_pointer() { #[test] fn test_estimated_capacity() { + assert_eq!(format_args!("").estimated_capacity(), 0); assert_eq!(format_args!("{}", "").estimated_capacity(), 0); assert_eq!(format_args!("Hello").estimated_capacity(), 5); assert_eq!(format_args!("Hello, {}!", "").estimated_capacity(), 16); - assert_eq!(format_args!("{}, hello!", "World").estimated_capacity(), 16); + assert_eq!(format_args!("{}, hello!", "World").estimated_capacity(), 0); + assert_eq!(format_args!("{}. 16-bytes piece", "World").estimated_capacity(), 32); } From ecda7f314fa79bbfbf2125c99fd66288ca83c875 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Krasnoborski?= Date: Thu, 2 Feb 2017 03:38:12 +0100 Subject: [PATCH 049/137] remove the wrapping arithmetics --- src/libcore/fmt/mod.rs | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index a870b6f88fb83..a989f914db616 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -274,16 +274,12 @@ impl<'a> Arguments<'a> { #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "0")] pub fn estimated_capacity(&self) -> usize { - // Using wrapping arithmetics in this function, because - // wrong result is highly unlikely and doesn't cause unsafety. - use ::num::Wrapping as W; - - let pieces_length: W = self.pieces.iter() - .map(|x| W(x.len())).sum(); + let pieces_length: usize = self.pieces.iter() + .map(|x| x.len()).sum(); if self.args.is_empty() { - pieces_length.0 - } else if self.pieces[0] == "" && pieces_length < W(16) { + pieces_length + } else if self.pieces[0] == "" && pieces_length < 16 { // If the format string starts with an argument, // don't preallocate anything, unless length // of pieces is significant. @@ -292,9 +288,8 @@ impl<'a> Arguments<'a> { // There are some arguments, so any additional push // will reallocate the string. To avoid that, // we're "pre-doubling" the capacity here. - (pieces_length * W(2)).0 + pieces_length.checked_mul(2).unwrap_or(0) } - } } From 395f23c9f7c7e1107dce5a05e71b3a9480d4e331 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 2 Feb 2017 16:23:27 +1300 Subject: [PATCH 050/137] save-analysis: be more paranoid about generated paths fixes https://github.com/rust-lang-nursery/rls/issues/160 --- src/librustc_save_analysis/lib.rs | 3 +++ src/libsyntax/parse/parser.rs | 1 + 2 files changed, 4 insertions(+) diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 8d0cdd1678c73..ebb33a12c8703 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -430,6 +430,9 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { -> Option { self.lookup_ref_id(trait_ref.ref_id).and_then(|def_id| { let span = trait_ref.path.span; + if generated_code(span) { + return None; + } let sub_span = self.span_utils.sub_span_for_type_name(span).or(Some(span)); filter!(self.span_utils, sub_span, span, None); Some(TypeRefData { diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 3480db8ec3b7d..d2bc7bf4f4810 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1693,6 +1693,7 @@ impl<'a> Parser<'a> { } // Assemble the span. + // FIXME(#39450) This is bogus if part of the path is macro generated. let span = mk_sp(lo, self.prev_span.hi); // Assemble the result. From daa509109fb140cdbb6bb391ed361ab9ee502e68 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Thu, 26 Jan 2017 22:23:32 -0500 Subject: [PATCH 051/137] Update cell docs --- src/libcore/cell.rs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index f889ff9a6ae2f..ab44342ebf02f 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -15,10 +15,18 @@ //! references. We say that `Cell` and `RefCell` provide 'interior mutability', in contrast //! with typical Rust types that exhibit 'inherited mutability'. //! -//! Cell types come in two flavors: `Cell` and `RefCell`. `Cell` provides `get` and `set` -//! methods that change the interior value with a single method call. `Cell` though is only -//! compatible with types that implement `Copy`. For other types, one must use the `RefCell` -//! type, acquiring a write lock before mutating. +//! Cell types come in two flavors: `Cell` and `RefCell`. `Cell` implements interior +//! mutability by moving values in and out of the `Cell`. To use references instead of values, +//! one must use the `RefCell` type, acquiring a write lock before mutating. `Cell` provides +//! methods to retrieve and change the current interior value: +//! +//! - For types that implement `Copy`, the `get` method retrieves the current interior value. +//! - For types that implement `Default`, the `take` method replaces the current interior value +//! with `Default::default()` and returns the replaced value. +//! - For all types, the `replace` method replaces the current interior value and returns the +//! replaced value and the `into_inner` method consumes the `Cell` and returns the interior +//! value. Additionally, the `set` method replaces the interior value, dropping the replaced +//! value. //! //! `RefCell` uses Rust's lifetimes to implement 'dynamic borrowing', a process whereby one can //! claim temporary, exclusive, mutable access to the inner value. Borrows for `RefCell`s are @@ -179,7 +187,7 @@ use marker::Unsize; use mem; use ops::{Deref, DerefMut, CoerceUnsized}; -/// A mutable memory location that admits only `Copy` data. +/// A mutable memory location. /// /// See the [module-level documentation](index.html) for more. #[stable(feature = "rust1", since = "1.0.0")] From 8b947a37c8bf396cf80c3790f68253c97d435250 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Wed, 1 Feb 2017 22:53:39 -0500 Subject: [PATCH 052/137] Update Cell references in the book --- src/doc/book/choosing-your-guarantees.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/doc/book/choosing-your-guarantees.md b/src/doc/book/choosing-your-guarantees.md index 9dca3479d35e8..17741cac10b78 100644 --- a/src/doc/book/choosing-your-guarantees.md +++ b/src/doc/book/choosing-your-guarantees.md @@ -118,7 +118,8 @@ These types are _generally_ found in struct fields, but they may be found elsewh ## `Cell` -[`Cell`][cell] is a type that provides zero-cost interior mutability, but only for `Copy` types. +[`Cell`][cell] is a type that provides zero-cost interior mutability by moving data in and +out of the cell. Since the compiler knows that all the data owned by the contained value is on the stack, there's no worry of leaking any data behind references (or worse!) by simply replacing the data. @@ -160,7 +161,7 @@ This relaxes the “no aliasing with mutability” restriction in places unnecessary. However, this also relaxes the guarantees that the restriction provides; so if your invariants depend on data stored within `Cell`, you should be careful. -This is useful for mutating primitives and other `Copy` types when there is no easy way of +This is useful for mutating primitives and other types when there is no easy way of doing it in line with the static rules of `&` and `&mut`. `Cell` does not let you obtain interior references to the data, which makes it safe to freely @@ -168,16 +169,17 @@ mutate. #### Cost -There is no runtime cost to using `Cell`, however if you are using it to wrap larger (`Copy`) +There is no runtime cost to using `Cell`, however if you are using it to wrap larger structs, it might be worthwhile to instead wrap individual fields in `Cell` since each write is otherwise a full copy of the struct. ## `RefCell` -[`RefCell`][refcell] also provides interior mutability, but isn't restricted to `Copy` types. +[`RefCell`][refcell] also provides interior mutability, but doesn't move data in and out of the +cell. -Instead, it has a runtime cost. `RefCell` enforces the read-write lock pattern at runtime (it's +However, it has a runtime cost. `RefCell` enforces the read-write lock pattern at runtime (it's like a single-threaded mutex), unlike `&T`/`&mut T` which do so at compile time. This is done by the `borrow()` and `borrow_mut()` functions, which modify an internal reference count and return smart pointers which can be dereferenced immutably and mutably respectively. The refcount is restored when From 89f9767356b24623e6cade93dad3f59ec3288bb7 Mon Sep 17 00:00:00 2001 From: Austin Bonander Date: Wed, 1 Feb 2017 20:11:10 -0800 Subject: [PATCH 053/137] Change tracking issue for `proc_macro` feature to #38356 --- src/libsyntax/feature_gate.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 112211851ec05..8eafa5f93d8f3 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -318,7 +318,7 @@ declare_features! ( (active, abi_unadjusted, "1.16.0", None), // Macros 1.1 - (active, proc_macro, "1.16.0", Some(35900)), + (active, proc_macro, "1.16.0", Some(38356)), // Allows attributes on struct literal fields. (active, struct_field_attributes, "1.16.0", Some(38814)), From 823e185a40baf593a9e0b454a29751f0953ab2a4 Mon Sep 17 00:00:00 2001 From: Son Date: Thu, 2 Feb 2017 22:05:49 +1100 Subject: [PATCH 054/137] Suggest only if resolution was previously resolved --- src/librustc_resolve/resolve_imports.rs | 14 +++++++++++++- .../issue-38054-do-not-show-unresolved-names.rs | 15 +++++++++++++++ ...ssue-38054-do-not-show-unresolved-names.stderr | 14 ++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/did_you_mean/issue-38054-do-not-show-unresolved-names.rs create mode 100644 src/test/ui/did_you_mean/issue-38054-do-not-show-unresolved-names.stderr diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 65cdeb9253d89..dbc8bca548b76 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -639,7 +639,19 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { let names = resolutions.iter().filter_map(|(&(ref i, _), resolution)| { if *i == ident { return None; } // Never suggest the same name match *resolution.borrow() { - NameResolution { binding: Some(_), .. } => Some(&i.name), + NameResolution { binding: Some(name_binding), .. } => { + match name_binding.kind { + NameBindingKind::Import { binding, .. } => { + match binding.kind { + // Never suggest the name that has binding error + // i.e. the name that cannot be previously resolved + NameBindingKind::Def(Def::Err) => return None, + _ => Some(&i.name), + } + }, + _ => Some(&i.name), + } + }, NameResolution { single_imports: SingleImports::None, .. } => None, _ => Some(&i.name), } diff --git a/src/test/ui/did_you_mean/issue-38054-do-not-show-unresolved-names.rs b/src/test/ui/did_you_mean/issue-38054-do-not-show-unresolved-names.rs new file mode 100644 index 0000000000000..1938d33e53030 --- /dev/null +++ b/src/test/ui/did_you_mean/issue-38054-do-not-show-unresolved-names.rs @@ -0,0 +1,15 @@ +// 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. + +use Foo; + +use Foo1; + +fn main() {} diff --git a/src/test/ui/did_you_mean/issue-38054-do-not-show-unresolved-names.stderr b/src/test/ui/did_you_mean/issue-38054-do-not-show-unresolved-names.stderr new file mode 100644 index 0000000000000..325f55e686c62 --- /dev/null +++ b/src/test/ui/did_you_mean/issue-38054-do-not-show-unresolved-names.stderr @@ -0,0 +1,14 @@ +error[E0432]: unresolved import `Foo` + --> $DIR/issue-38054-do-not-show-unresolved-names.rs:11:5 + | +11 | use Foo; + | ^^^ no `Foo` in the root + +error[E0432]: unresolved import `Foo1` + --> $DIR/issue-38054-do-not-show-unresolved-names.rs:13:5 + | +13 | use Foo1; + | ^^^^ no `Foo1` in the root + +error: aborting due to 2 previous errors + From 80f7db63b6e658468f181d602767c8da412459d2 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 2 Feb 2017 11:26:44 -0800 Subject: [PATCH 055/137] std: Fix IntoIter::as_mut_slice's signature This was intended to require `&mut self`, not `&self`, otherwise it's unsound! Closes #39465 --- src/libcollections/vec.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 1f8fd32da9ab8..c45518438bd83 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -1958,7 +1958,7 @@ impl IntoIter { /// assert_eq!(into_iter.next().unwrap(), 'z'); /// ``` #[stable(feature = "vec_into_iter_as_slice", since = "1.15.0")] - pub fn as_mut_slice(&self) -> &mut [T] { + pub fn as_mut_slice(&mut self) -> &mut [T] { unsafe { slice::from_raw_parts_mut(self.ptr as *mut T, self.len()) } From 6c2ef5201abb1f9c4848088cadc89c467dbc0a46 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 27 Jan 2017 01:57:30 +0300 Subject: [PATCH 056/137] rustbuild: Build jemalloc and libbacktrace only once (take 2) --- src/bootstrap/lib.rs | 10 ++++-- src/build_helper/lib.rs | 15 ++++++++ src/liballoc_jemalloc/build.rs | 62 +++++++++++++++------------------- src/libstd/build.rs | 26 ++++++-------- 4 files changed, 60 insertions(+), 53 deletions(-) diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index db2fe2db813a6..52944f36996fb 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -482,7 +482,8 @@ impl Build { // // These variables are primarily all read by // src/bootstrap/bin/{rustc.rs,rustdoc.rs} - cargo.env("RUSTC", self.out.join("bootstrap/debug/rustc")) + cargo.env("RUSTBUILD_NATIVE_DIR", self.native_dir(target)) + .env("RUSTC", self.out.join("bootstrap/debug/rustc")) .env("RUSTC_REAL", self.compiler_path(compiler)) .env("RUSTC_STAGE", stage.to_string()) .env("RUSTC_DEBUGINFO", self.config.rust_debuginfo.to_string()) @@ -746,10 +747,15 @@ impl Build { } } + /// Directory for libraries built from C/C++ code and shared between stages. + fn native_dir(&self, target: &str) -> PathBuf { + self.out.join(target).join("native") + } + /// Root output directory for rust_test_helpers library compiled for /// `target` fn test_helpers_out(&self, target: &str) -> PathBuf { - self.out.join(target).join("rust-test-helpers") + self.native_dir(target).join("rust-test-helpers") } /// Adds the compiler's directory of dynamic libraries to `cmd`'s dynamic diff --git a/src/build_helper/lib.rs b/src/build_helper/lib.rs index d0d588f46a754..7784584baf49d 100644 --- a/src/build_helper/lib.rs +++ b/src/build_helper/lib.rs @@ -88,6 +88,21 @@ pub fn output(cmd: &mut Command) -> String { String::from_utf8(output.stdout).unwrap() } +pub fn rerun_if_changed_anything_in_dir(dir: &Path) { + let mut stack = dir.read_dir().unwrap() + .map(|e| e.unwrap()) + .filter(|e| &*e.file_name() != ".git") + .collect::>(); + while let Some(entry) = stack.pop() { + let path = entry.path(); + if entry.file_type().unwrap().is_dir() { + stack.extend(path.read_dir().unwrap().map(|e| e.unwrap())); + } else { + println!("cargo:rerun-if-changed={}", path.display()); + } + } +} + fn fail(s: &str) -> ! { println!("\n\n{}\n\n", s); std::process::exit(1); diff --git a/src/liballoc_jemalloc/build.rs b/src/liballoc_jemalloc/build.rs index 1143df0c6302d..e08fc75e9ef6a 100644 --- a/src/liballoc_jemalloc/build.rs +++ b/src/liballoc_jemalloc/build.rs @@ -13,20 +13,15 @@ extern crate build_helper; extern crate gcc; -use std::env; +use std::{env, fs}; use std::path::PathBuf; use std::process::Command; -use build_helper::run; +use build_helper::{run, rerun_if_changed_anything_in_dir}; fn main() { println!("cargo:rustc-cfg=cargobuild"); println!("cargo:rerun-if-changed=build.rs"); - let target = env::var("TARGET").expect("TARGET was not set"); - let host = env::var("HOST").expect("HOST was not set"); - let build_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap()); - let src_dir = env::current_dir().unwrap(); - // FIXME: This is a hack to support building targets that don't // support jemalloc alongside hosts that do. The jemalloc build is // controlled by a feature of the std crate, and if that feature @@ -35,6 +30,7 @@ fn main() { // that the feature set used by std is the same across all // targets, which means we have to build the alloc_jemalloc crate // for targets like emscripten, even if we don't use it. + let target = env::var("TARGET").expect("TARGET was not set"); if target.contains("rumprun") || target.contains("bitrig") || target.contains("openbsd") || target.contains("msvc") || target.contains("emscripten") || target.contains("fuchsia") || target.contains("redox") { @@ -57,6 +53,28 @@ fn main() { return; } + let build_dir = env::var_os("RUSTBUILD_NATIVE_DIR").unwrap_or(env::var_os("OUT_DIR").unwrap()); + let build_dir = PathBuf::from(build_dir).join("jemalloc"); + let _ = fs::create_dir_all(&build_dir); + + if target.contains("windows") { + println!("cargo:rustc-link-lib=static=jemalloc"); + } else { + println!("cargo:rustc-link-lib=static=jemalloc_pic"); + } + println!("cargo:rustc-link-search=native={}/lib", build_dir.display()); + if target.contains("android") { + println!("cargo:rustc-link-lib=gcc"); + } else if !target.contains("windows") && !target.contains("musl") { + println!("cargo:rustc-link-lib=pthread"); + } + if !cfg!(stage0) { + return + } + + let host = env::var("HOST").expect("HOST was not set"); + let src_dir = env::current_dir().unwrap().join("../jemalloc"); + rerun_if_changed_anything_in_dir(&src_dir); let compiler = gcc::Config::new().get_compiler(); // only msvc returns None for ar so unwrap is okay let ar = build_helper::cc2ar(compiler.path(), &target).unwrap(); @@ -66,23 +84,8 @@ fn main() { .collect::>() .join(" "); - let mut stack = src_dir.join("../jemalloc") - .read_dir() - .unwrap() - .map(|e| e.unwrap()) - .filter(|e| &*e.file_name() != ".git") - .collect::>(); - while let Some(entry) = stack.pop() { - let path = entry.path(); - if entry.file_type().unwrap().is_dir() { - stack.extend(path.read_dir().unwrap().map(|e| e.unwrap())); - } else { - println!("cargo:rerun-if-changed={}", path.display()); - } - } - let mut cmd = Command::new("sh"); - cmd.arg(src_dir.join("../jemalloc/configure") + cmd.arg(src_dir.join("configure") .to_str() .unwrap() .replace("C:\\", "/c/") @@ -158,6 +161,7 @@ fn main() { } run(&mut cmd); + let mut make = Command::new(build_helper::make(&host)); make.current_dir(&build_dir) .arg("build_lib_static"); @@ -170,18 +174,6 @@ fn main() { run(&mut make); - if target.contains("windows") { - println!("cargo:rustc-link-lib=static=jemalloc"); - } else { - println!("cargo:rustc-link-lib=static=jemalloc_pic"); - } - println!("cargo:rustc-link-search=native={}/lib", build_dir.display()); - if target.contains("android") { - println!("cargo:rustc-link-lib=gcc"); - } else if !target.contains("windows") && !target.contains("musl") { - println!("cargo:rustc-link-lib=pthread"); - } - // The pthread_atfork symbols is used by jemalloc on android but the really // old android we're building on doesn't have them defined, so just make // sure the symbols are available. diff --git a/src/libstd/build.rs b/src/libstd/build.rs index 9504194393f94..faff0d1cb47b5 100644 --- a/src/libstd/build.rs +++ b/src/libstd/build.rs @@ -13,11 +13,10 @@ extern crate gcc; extern crate build_helper; -use std::env; +use std::{env, fs}; use std::path::PathBuf; use std::process::Command; - -use build_helper::run; +use build_helper::{run, rerun_if_changed_anything_in_dir}; fn main() { println!("cargo:rustc-cfg=cargobuild"); @@ -66,24 +65,18 @@ fn main() { } fn build_libbacktrace(host: &str, target: &str) { - let src_dir = env::current_dir().unwrap().join("../libbacktrace"); - let build_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap()); + let build_dir = env::var_os("RUSTBUILD_NATIVE_DIR").unwrap_or(env::var_os("OUT_DIR").unwrap()); + let build_dir = PathBuf::from(build_dir).join("libbacktrace"); + let _ = fs::create_dir_all(&build_dir); println!("cargo:rustc-link-lib=static=backtrace"); println!("cargo:rustc-link-search=native={}/.libs", build_dir.display()); - - let mut stack = src_dir.read_dir().unwrap() - .map(|e| e.unwrap()) - .collect::>(); - while let Some(entry) = stack.pop() { - let path = entry.path(); - if entry.file_type().unwrap().is_dir() { - stack.extend(path.read_dir().unwrap().map(|e| e.unwrap())); - } else { - println!("cargo:rerun-if-changed={}", path.display()); - } + if !cfg!(stage0) { + return } + let src_dir = env::current_dir().unwrap().join("../libbacktrace"); + rerun_if_changed_anything_in_dir(&src_dir); let compiler = gcc::Config::new().get_compiler(); // only msvc returns None for ar so unwrap is okay let ar = build_helper::cc2ar(compiler.path(), target).unwrap(); @@ -105,6 +98,7 @@ fn build_libbacktrace(host: &str, target: &str) { .env("AR", &ar) .env("RANLIB", format!("{} s", ar.display())) .env("CFLAGS", cflags)); + run(Command::new(build_helper::make(host)) .current_dir(&build_dir) .arg(format!("INCDIR={}", src_dir.display())) From c0253304ea9d40103dc7d1055b7fa090b48781f8 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 28 Jan 2017 16:05:13 +0300 Subject: [PATCH 057/137] Fix build in cross-compilation scenarios --- src/liballoc_jemalloc/build.rs | 4 ++-- src/libstd/build.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/liballoc_jemalloc/build.rs b/src/liballoc_jemalloc/build.rs index e08fc75e9ef6a..c982f98e63def 100644 --- a/src/liballoc_jemalloc/build.rs +++ b/src/liballoc_jemalloc/build.rs @@ -31,6 +31,7 @@ fn main() { // targets, which means we have to build the alloc_jemalloc crate // for targets like emscripten, even if we don't use it. let target = env::var("TARGET").expect("TARGET was not set"); + let host = env::var("HOST").expect("HOST was not set"); if target.contains("rumprun") || target.contains("bitrig") || target.contains("openbsd") || target.contains("msvc") || target.contains("emscripten") || target.contains("fuchsia") || target.contains("redox") { @@ -68,11 +69,10 @@ fn main() { } else if !target.contains("windows") && !target.contains("musl") { println!("cargo:rustc-link-lib=pthread"); } - if !cfg!(stage0) { + if !cfg!(stage0) && target == host { return } - let host = env::var("HOST").expect("HOST was not set"); let src_dir = env::current_dir().unwrap().join("../jemalloc"); rerun_if_changed_anything_in_dir(&src_dir); let compiler = gcc::Config::new().get_compiler(); diff --git a/src/libstd/build.rs b/src/libstd/build.rs index faff0d1cb47b5..112e48921cb73 100644 --- a/src/libstd/build.rs +++ b/src/libstd/build.rs @@ -71,7 +71,7 @@ fn build_libbacktrace(host: &str, target: &str) { println!("cargo:rustc-link-lib=static=backtrace"); println!("cargo:rustc-link-search=native={}/.libs", build_dir.display()); - if !cfg!(stage0) { + if !cfg!(stage0) && target == host { return } From a5b603b1bf1e9d74227a8a3b2f73acd558b952ef Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 1 Feb 2017 00:27:51 +0300 Subject: [PATCH 058/137] Build libbacktrace/jemalloc only when their timestamps are older than sources --- src/Cargo.lock | 3 ++ src/bootstrap/compile.rs | 4 +-- src/bootstrap/doc.rs | 3 +- src/bootstrap/lib.rs | 20 ++---------- src/bootstrap/native.rs | 3 +- src/bootstrap/util.rs | 37 ---------------------- src/build_helper/Cargo.toml | 3 ++ src/build_helper/lib.rs | 56 ++++++++++++++++++++++++++++++++++ src/liballoc_jemalloc/build.rs | 17 +++++++---- src/libstd/build.rs | 19 +++++++----- 10 files changed, 94 insertions(+), 71 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 93bbf0f227b1b..ec45f45ccb608 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -61,6 +61,9 @@ dependencies = [ [[package]] name = "build_helper" version = "0.1.0" +dependencies = [ + "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "cargotest" diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 7c35151a6d274..776b91028a1a3 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -21,10 +21,10 @@ use std::fs::{self, File}; use std::path::{Path, PathBuf}; use std::process::Command; -use build_helper::output; +use build_helper::{output, mtime}; use filetime::FileTime; -use util::{exe, libdir, mtime, is_dylib, copy}; +use util::{exe, libdir, is_dylib, copy}; use {Build, Compiler, Mode}; /// Build the standard library. diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index d1c9918a73373..3dc9b8375550c 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -22,7 +22,8 @@ use std::io::prelude::*; use std::process::Command; use {Build, Compiler, Mode}; -use util::{up_to_date, cp_r}; +use util::cp_r; +use build_helper::up_to_date; /// Invoke `rustbook` as compiled in `stage` for `target` for the doc book /// `name` into the `out` path. diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 52944f36996fb..df1218752d1c9 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -66,6 +66,7 @@ #![deny(warnings)] +#[macro_use] extern crate build_helper; extern crate cmake; extern crate filetime; @@ -83,24 +84,9 @@ use std::fs::{self, File}; use std::path::{Component, PathBuf, Path}; use std::process::Command; -use build_helper::{run_silent, output}; +use build_helper::{run_silent, output, mtime}; -use util::{exe, mtime, libdir, add_lib_path}; - -/// A helper macro to `unwrap` a result except also print out details like: -/// -/// * The file/line of the panic -/// * The expression that failed -/// * The error itself -/// -/// This is currently used judiciously throughout the build system rather than -/// using a `Result` with `try!`, but this may change one day... -macro_rules! t { - ($e:expr) => (match $e { - Ok(e) => e, - Err(e) => panic!("{} failed with {}", stringify!($e), e), - }) -} +use util::{exe, libdir, add_lib_path}; mod cc; mod channel; diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 4b6fef8edc17f..21fc61cc81484 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -28,7 +28,8 @@ use cmake; use gcc; use Build; -use util::{self, up_to_date}; +use util; +use build_helper::up_to_date; /// Compile LLVM for `target`. pub fn llvm(build: &Build, target: &str) { diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs index 2ab3776ada096..520514f5fc95a 100644 --- a/src/bootstrap/util.rs +++ b/src/bootstrap/util.rs @@ -20,8 +20,6 @@ use std::path::{Path, PathBuf}; use std::process::Command; use std::time::Instant; -use filetime::FileTime; - /// Returns the `name` as the filename of a static library for `target`. pub fn staticlib(name: &str, target: &str) -> String { if target.contains("windows") { @@ -31,13 +29,6 @@ pub fn staticlib(name: &str, target: &str) -> String { } } -/// Returns the last-modified time for `path`, or zero if it doesn't exist. -pub fn mtime(path: &Path) -> FileTime { - fs::metadata(path).map(|f| { - FileTime::from_last_modification_time(&f) - }).unwrap_or(FileTime::zero()) -} - /// Copies a file from `src` to `dst`, attempting to use hard links and then /// falling back to an actually filesystem copy if necessary. pub fn copy(src: &Path, dst: &Path) { @@ -132,34 +123,6 @@ pub fn add_lib_path(path: Vec, cmd: &mut Command) { cmd.env(dylib_path_var(), t!(env::join_paths(list))); } -/// Returns whether `dst` is up to date given that the file or files in `src` -/// are used to generate it. -/// -/// Uses last-modified time checks to verify this. -pub fn up_to_date(src: &Path, dst: &Path) -> bool { - let threshold = mtime(dst); - let meta = match fs::metadata(src) { - Ok(meta) => meta, - Err(e) => panic!("source {:?} failed to get metadata: {}", src, e), - }; - if meta.is_dir() { - dir_up_to_date(src, &threshold) - } else { - FileTime::from_last_modification_time(&meta) <= threshold - } -} - -fn dir_up_to_date(src: &Path, threshold: &FileTime) -> bool { - t!(fs::read_dir(src)).map(|e| t!(e)).all(|e| { - let meta = t!(e.metadata()); - if meta.is_dir() { - dir_up_to_date(&e.path(), threshold) - } else { - FileTime::from_last_modification_time(&meta) < *threshold - } - }) -} - /// Returns the environment variable which the dynamic library lookup path /// resides in for this platform. pub fn dylib_path_var() -> &'static str { diff --git a/src/build_helper/Cargo.toml b/src/build_helper/Cargo.toml index 01d704f816bbc..f8ade0616a577 100644 --- a/src/build_helper/Cargo.toml +++ b/src/build_helper/Cargo.toml @@ -6,3 +6,6 @@ authors = ["The Rust Project Developers"] [lib] name = "build_helper" path = "lib.rs" + +[dependencies] +filetime = "0.1" diff --git a/src/build_helper/lib.rs b/src/build_helper/lib.rs index 7784584baf49d..3dfd293808286 100644 --- a/src/build_helper/lib.rs +++ b/src/build_helper/lib.rs @@ -10,9 +10,30 @@ #![deny(warnings)] +extern crate filetime; + +use std::fs; use std::process::{Command, Stdio}; use std::path::{Path, PathBuf}; +use filetime::FileTime; + +/// A helper macro to `unwrap` a result except also print out details like: +/// +/// * The file/line of the panic +/// * The expression that failed +/// * The error itself +/// +/// This is currently used judiciously throughout the build system rather than +/// using a `Result` with `try!`, but this may change one day... +#[macro_export] +macro_rules! t { + ($e:expr) => (match $e { + Ok(e) => e, + Err(e) => panic!("{} failed with {}", stringify!($e), e), + }) +} + pub fn run(cmd: &mut Command) { println!("running: {:?}", cmd); run_silent(cmd); @@ -103,6 +124,41 @@ pub fn rerun_if_changed_anything_in_dir(dir: &Path) { } } +/// Returns the last-modified time for `path`, or zero if it doesn't exist. +pub fn mtime(path: &Path) -> FileTime { + fs::metadata(path).map(|f| { + FileTime::from_last_modification_time(&f) + }).unwrap_or(FileTime::zero()) +} + +/// Returns whether `dst` is up to date given that the file or files in `src` +/// are used to generate it. +/// +/// Uses last-modified time checks to verify this. +pub fn up_to_date(src: &Path, dst: &Path) -> bool { + let threshold = mtime(dst); + let meta = match fs::metadata(src) { + Ok(meta) => meta, + Err(e) => panic!("source {:?} failed to get metadata: {}", src, e), + }; + if meta.is_dir() { + dir_up_to_date(src, &threshold) + } else { + FileTime::from_last_modification_time(&meta) <= threshold + } +} + +fn dir_up_to_date(src: &Path, threshold: &FileTime) -> bool { + t!(fs::read_dir(src)).map(|e| t!(e)).all(|e| { + let meta = t!(e.metadata()); + if meta.is_dir() { + dir_up_to_date(&e.path(), threshold) + } else { + FileTime::from_last_modification_time(&meta) < *threshold + } + }) +} + fn fail(s: &str) -> ! { println!("\n\n{}\n\n", s); std::process::exit(1); diff --git a/src/liballoc_jemalloc/build.rs b/src/liballoc_jemalloc/build.rs index c982f98e63def..7e616c0ff27cf 100644 --- a/src/liballoc_jemalloc/build.rs +++ b/src/liballoc_jemalloc/build.rs @@ -10,13 +10,15 @@ #![deny(warnings)] +#[macro_use] extern crate build_helper; extern crate gcc; -use std::{env, fs}; -use std::path::PathBuf; +use std::env; +use std::fs::{self, File}; +use std::path::{Path, PathBuf}; use std::process::Command; -use build_helper::{run, rerun_if_changed_anything_in_dir}; +use build_helper::{run, rerun_if_changed_anything_in_dir, up_to_date}; fn main() { println!("cargo:rustc-cfg=cargobuild"); @@ -69,12 +71,13 @@ fn main() { } else if !target.contains("windows") && !target.contains("musl") { println!("cargo:rustc-link-lib=pthread"); } - if !cfg!(stage0) && target == host { + let src_dir = env::current_dir().unwrap().join("../jemalloc"); + rerun_if_changed_anything_in_dir(&src_dir); + let timestamp = build_dir.join("rustbuild.timestamp"); + if up_to_date(&Path::new("build.rs"), ×tamp) && up_to_date(&src_dir, ×tamp) { return } - let src_dir = env::current_dir().unwrap().join("../jemalloc"); - rerun_if_changed_anything_in_dir(&src_dir); let compiler = gcc::Config::new().get_compiler(); // only msvc returns None for ar so unwrap is okay let ar = build_helper::cc2ar(compiler.path(), &target).unwrap(); @@ -184,4 +187,6 @@ fn main() { .file("pthread_atfork_dummy.c") .compile("libpthread_atfork_dummy.a"); } + + t!(File::create(×tamp)); } diff --git a/src/libstd/build.rs b/src/libstd/build.rs index 112e48921cb73..a084482170937 100644 --- a/src/libstd/build.rs +++ b/src/libstd/build.rs @@ -10,13 +10,15 @@ #![deny(warnings)] -extern crate gcc; +#[macro_use] extern crate build_helper; +extern crate gcc; -use std::{env, fs}; -use std::path::PathBuf; +use std::env; +use std::fs::{self, File}; +use std::path::{Path, PathBuf}; use std::process::Command; -use build_helper::{run, rerun_if_changed_anything_in_dir}; +use build_helper::{run, rerun_if_changed_anything_in_dir, up_to_date}; fn main() { println!("cargo:rustc-cfg=cargobuild"); @@ -71,12 +73,13 @@ fn build_libbacktrace(host: &str, target: &str) { println!("cargo:rustc-link-lib=static=backtrace"); println!("cargo:rustc-link-search=native={}/.libs", build_dir.display()); - if !cfg!(stage0) && target == host { + let src_dir = env::current_dir().unwrap().join("../libbacktrace"); + rerun_if_changed_anything_in_dir(&src_dir); + let timestamp = build_dir.join("rustbuild.timestamp"); + if up_to_date(&Path::new("build.rs"), ×tamp) && up_to_date(&src_dir, ×tamp) { return } - let src_dir = env::current_dir().unwrap().join("../libbacktrace"); - rerun_if_changed_anything_in_dir(&src_dir); let compiler = gcc::Config::new().get_compiler(); // only msvc returns None for ar so unwrap is okay let ar = build_helper::cc2ar(compiler.path(), target).unwrap(); @@ -103,4 +106,6 @@ fn build_libbacktrace(host: &str, target: &str) { .current_dir(&build_dir) .arg(format!("INCDIR={}", src_dir.display())) .arg("-j").arg(env::var("NUM_JOBS").expect("NUM_JOBS was not set"))); + + t!(File::create(×tamp)); } From b4abb72ef0bda4092ca81610d310081d78f51d2a Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 2 Feb 2017 23:55:42 +0300 Subject: [PATCH 059/137] Fixup crate versions --- src/Cargo.lock | 4 ++-- src/bootstrap/check.rs | 2 +- src/rustc/std_shim/Cargo.toml | 2 +- src/rustc/test_shim/Cargo.toml | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index ec45f45ccb608..c058586410dac 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -597,7 +597,7 @@ dependencies = [ [[package]] name = "std_shim" -version = "0.1.0" +version = "0.0.0" dependencies = [ "core 0.0.0", "std 0.0.0", @@ -656,7 +656,7 @@ dependencies = [ [[package]] name = "test_shim" -version = "0.1.0" +version = "0.0.0" dependencies = [ "test 0.0.0", ] diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 4aca843558fd0..19aac0f36bb27 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -383,7 +383,7 @@ pub fn krate(build: &Build, // helper crate, not tested. If it leaks through then it ends up // messing with various mtime calculations and such. if !name.contains("jemalloc") && name != "build_helper" { - cargo.arg("-p").arg(name); + cargo.arg("-p").arg(&format!("{}:0.0.0", name)); } for dep in build.crates[name].deps.iter() { if visited.insert(dep) { diff --git a/src/rustc/std_shim/Cargo.toml b/src/rustc/std_shim/Cargo.toml index 7260a8440734d..14c9c5544b188 100644 --- a/src/rustc/std_shim/Cargo.toml +++ b/src/rustc/std_shim/Cargo.toml @@ -21,7 +21,7 @@ [package] name = "std_shim" -version = "0.1.0" +version = "0.0.0" authors = ["The Rust Project Developers"] [lib] diff --git a/src/rustc/test_shim/Cargo.toml b/src/rustc/test_shim/Cargo.toml index ac7842770f5bb..6ef613eee0628 100644 --- a/src/rustc/test_shim/Cargo.toml +++ b/src/rustc/test_shim/Cargo.toml @@ -5,7 +5,7 @@ [package] name = "test_shim" -version = "0.1.0" +version = "0.0.0" authors = ["The Rust Project Developers"] [lib] From a0efdf34417b5564a7474e8c2175b9e643640b8f Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Thu, 2 Feb 2017 22:27:15 +0100 Subject: [PATCH 060/137] Don't check for sudo environment if vendored sources are already configured --- src/bootstrap/bootstrap.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 85e8dbce1a955..958ffd11008a3 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -438,7 +438,7 @@ def main(): rb.use_vendored_sources = '\nvendor = true' in rb.config_toml or \ 'CFG_ENABLE_VENDOR' in rb.config_mk - if 'SUDO_USER' in os.environ: + if 'SUDO_USER' in os.environ and not rb.use_vendored_sources: if os.environ['USER'] != os.environ['SUDO_USER']: rb.use_vendored_sources = True print('info: looks like you are running this command under `sudo`') From 8e793eb3c64e289d4fa5850bf28d10fe5b3e062a Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Thu, 2 Feb 2017 22:28:00 +0100 Subject: [PATCH 061/137] Guard against USER not existing in the environment --- src/bootstrap/bootstrap.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 958ffd11008a3..3869b286102c9 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -439,7 +439,7 @@ def main(): 'CFG_ENABLE_VENDOR' in rb.config_mk if 'SUDO_USER' in os.environ and not rb.use_vendored_sources: - if os.environ['USER'] != os.environ['SUDO_USER']: + if os.environ.get('USER') != os.environ['SUDO_USER']: rb.use_vendored_sources = True print('info: looks like you are running this command under `sudo`') print(' and so in order to preserve your $HOME this will now') From 51e5cb525db60435ea32c5a77c17ac75fe580f64 Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Thu, 2 Feb 2017 22:28:26 +0100 Subject: [PATCH 062/137] Fix typo in bootstrap.py info message --- src/bootstrap/bootstrap.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 3869b286102c9..bc8341102421b 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -445,7 +445,7 @@ def main(): print(' and so in order to preserve your $HOME this will now') print(' use vendored sources by default. Note that if this') print(' does not work you should run a normal build first') - print(' before running a command like `sudo make intall`') + print(' before running a command like `sudo make install`') if rb.use_vendored_sources: if not os.path.exists('.cargo'): From 5a6019429f68d2fa8b92285d7dfdcd2f30fd1303 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 27 Jan 2017 17:19:02 -0500 Subject: [PATCH 063/137] don't use a mutable field where parameter passing will do --- src/librustc_typeck/check/method/probe.rs | 37 ++++++++++++----------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 300caca30fec8..201a223c15f15 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -55,7 +55,6 @@ struct ProbeContext<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { inherent_candidates: Vec>, extension_candidates: Vec>, impl_dups: FxHashSet, - import_id: Option, /// Collects near misses when the candidate functions are missing a `self` keyword and is only /// used for error reporting @@ -351,7 +350,6 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { inherent_candidates: Vec::new(), extension_candidates: Vec::new(), impl_dups: FxHashSet(), - import_id: None, steps: Rc::new(steps), opt_simplified_steps: opt_simplified_steps, static_candidates: Vec::new(), @@ -530,7 +528,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { xform_self_ty: xform_self_ty, item: item, kind: InherentImplCandidate(impl_substs, obligations), - import_id: self.import_id, + import_id: None, }); } } @@ -559,7 +557,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { xform_self_ty: xform_self_ty, item: item, kind: ObjectCandidate, - import_id: this.import_id, + import_id: None, }); }); } @@ -609,7 +607,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { xform_self_ty: xform_self_ty, item: item, kind: WhereClauseCandidate(poly_trait_ref), - import_id: this.import_id, + import_id: None, }); }); } @@ -644,9 +642,8 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { for trait_candidate in applicable_traits { let trait_did = trait_candidate.def_id; if duplicates.insert(trait_did) { - self.import_id = trait_candidate.import_id; - let result = self.assemble_extension_candidates_for_trait(trait_did); - self.import_id = None; + let import_id = trait_candidate.import_id; + let result = self.assemble_extension_candidates_for_trait(import_id, trait_did); result?; } } @@ -658,7 +655,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { let mut duplicates = FxHashSet(); for trait_info in suggest::all_traits(self.ccx) { if duplicates.insert(trait_info.def_id) { - self.assemble_extension_candidates_for_trait(trait_info.def_id)?; + self.assemble_extension_candidates_for_trait(None, trait_info.def_id)?; } } Ok(()) @@ -682,6 +679,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { } fn assemble_extension_candidates_for_trait(&mut self, + import_id: Option, trait_def_id: DefId) -> Result<(), MethodError<'tcx>> { debug!("assemble_extension_candidates_for_trait(trait_def_id={:?})", @@ -695,19 +693,21 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { continue; } - self.assemble_extension_candidates_for_trait_impls(trait_def_id, item.clone()); + self.assemble_extension_candidates_for_trait_impls(import_id, trait_def_id, + item.clone()); - self.assemble_closure_candidates(trait_def_id, item.clone())?; + self.assemble_closure_candidates(import_id, trait_def_id, item.clone())?; - self.assemble_projection_candidates(trait_def_id, item.clone()); + self.assemble_projection_candidates(import_id, trait_def_id, item.clone()); - self.assemble_where_clause_candidates(trait_def_id, item.clone()); + self.assemble_where_clause_candidates(import_id, trait_def_id, item.clone()); } Ok(()) } fn assemble_extension_candidates_for_trait_impls(&mut self, + import_id: Option, trait_def_id: DefId, item: ty::AssociatedItem) { let trait_def = self.tcx.lookup_trait_def(trait_def_id); @@ -751,7 +751,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { xform_self_ty: xform_self_ty, item: item.clone(), kind: ExtensionImplCandidate(impl_def_id, impl_substs, obligations), - import_id: self.import_id, + import_id: import_id, }); }); } @@ -777,6 +777,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { } fn assemble_closure_candidates(&mut self, + import_id: Option, trait_def_id: DefId, item: ty::AssociatedItem) -> Result<(), MethodError<'tcx>> { @@ -840,7 +841,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { xform_self_ty: xform_self_ty, item: item.clone(), kind: TraitCandidate, - import_id: self.import_id, + import_id: import_id, }); } @@ -848,6 +849,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { } fn assemble_projection_candidates(&mut self, + import_id: Option, trait_def_id: DefId, item: ty::AssociatedItem) { debug!("assemble_projection_candidates(\ @@ -895,7 +897,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { xform_self_ty: xform_self_ty, item: item.clone(), kind: TraitCandidate, - import_id: self.import_id, + import_id: import_id, }); } } @@ -903,6 +905,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { } fn assemble_where_clause_candidates(&mut self, + import_id: Option, trait_def_id: DefId, item: ty::AssociatedItem) { debug!("assemble_where_clause_candidates(trait_def_id={:?})", @@ -923,7 +926,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { xform_self_ty: xform_self_ty, item: item.clone(), kind: WhereClauseCandidate(poly_bound), - import_id: self.import_id, + import_id: import_id, }); } } From 93e0bc6520b8d1e1ae0e886cdf7b083073e40be8 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sat, 28 Jan 2017 06:02:28 -0500 Subject: [PATCH 064/137] change the `used_trait_imports` map to be a `DefIdSet` --- src/librustc/ty/context.rs | 4 ++-- src/librustc_typeck/check/method/mod.rs | 6 ++++-- src/librustc_typeck/check_unused.rs | 4 +++- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index ce4a6a3182635..5913ed48528f7 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -494,7 +494,7 @@ pub struct GlobalCtxt<'tcx> { /// Set of trait imports actually used in the method resolution. /// This is used for warning unused imports. - pub used_trait_imports: RefCell, + pub used_trait_imports: RefCell, /// The set of external nominal types whose implementations have been read. /// This is used for lazy resolution of methods. @@ -783,7 +783,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { inherent_impls: RefCell::new(DepTrackingMap::new(dep_graph.clone())), used_unsafe: RefCell::new(NodeSet()), used_mut_nodes: RefCell::new(NodeSet()), - used_trait_imports: RefCell::new(NodeSet()), + used_trait_imports: RefCell::new(DefIdSet()), populated_external_types: RefCell::new(DefIdSet()), populated_external_primitive_impls: RefCell::new(DefIdSet()), stability: RefCell::new(stability), diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 9b8e77301e524..f8b6fbc9e816b 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -137,7 +137,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self_ty, call_expr.id)?; if let Some(import_id) = pick.import_id { - self.tcx.used_trait_imports.borrow_mut().insert(import_id); + let import_def_id = self.tcx.hir.local_def_id(import_id); + self.tcx.used_trait_imports.borrow_mut().insert(import_def_id); } self.tcx.check_stability(pick.item.def_id, call_expr.id, span); @@ -336,7 +337,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self_ty, expr_id)?; if let Some(import_id) = pick.import_id { - self.tcx.used_trait_imports.borrow_mut().insert(import_id); + let import_def_id = self.tcx.hir.local_def_id(import_id); + self.tcx.used_trait_imports.borrow_mut().insert(import_def_id); } let def = pick.item.def(); diff --git a/src/librustc_typeck/check_unused.rs b/src/librustc_typeck/check_unused.rs index bdda538db160e..c1ba53afad4e9 100644 --- a/src/librustc_typeck/check_unused.rs +++ b/src/librustc_typeck/check_unused.rs @@ -27,7 +27,9 @@ impl<'a, 'tcx> UnusedTraitImportVisitor<'a, 'tcx> { if !self.tcx.maybe_unused_trait_imports.contains(&id) { return; } - if self.tcx.used_trait_imports.borrow().contains(&id) { + + let import_def_id = self.tcx.hir.local_def_id(id); + if self.tcx.used_trait_imports.borrow().contains(&import_def_id) { return; } From 65b93ebcb8e2ff2d8747ce731108e8f5d9f7dddf Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sat, 28 Jan 2017 07:01:45 -0500 Subject: [PATCH 065/137] introduce `LintTable` --- src/librustc/lint/context.rs | 20 ++++++------- src/librustc/lint/mod.rs | 3 ++ src/librustc/lint/table.rs | 56 ++++++++++++++++++++++++++++++++++++ src/librustc/session/mod.rs | 21 +++++--------- 4 files changed, 75 insertions(+), 25 deletions(-) create mode 100644 src/librustc/lint/table.rs diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 3506a9c067ca6..edf5666a3a5f7 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -773,11 +773,10 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> { // Output any lints that were previously added to the session. fn visit_id(&mut self, id: ast::NodeId) { - if let Some(lints) = self.sess().lints.borrow_mut().remove(&id) { - debug!("LateContext::visit_id: id={:?} lints={:?}", id, lints); - for early_lint in lints { - self.early_lint(early_lint); - } + let lints = self.sess().lints.borrow_mut().take(id); + for early_lint in lints { + debug!("LateContext::visit_id: id={:?} early_lint={:?}", id, early_lint); + self.early_lint(early_lint); } } @@ -1232,7 +1231,7 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // If we missed any lints added to the session, then there's a bug somewhere // in the iteration code. - for (id, v) in tcx.sess.lints.borrow().iter() { + if let Some((id, v)) = tcx.sess.lints.borrow().get_any() { for early_lint in v { span_bug!(early_lint.diagnostic.span.clone(), "unprocessed lint {:?} at {}", @@ -1250,10 +1249,9 @@ pub fn check_ast_crate(sess: &Session, krate: &ast::Crate) { // Visit the whole crate. cx.with_lint_attrs(&krate.attrs, |cx| { // Lints may be assigned to the whole crate. - if let Some(lints) = cx.sess.lints.borrow_mut().remove(&ast::CRATE_NODE_ID) { - for early_lint in lints { - cx.early_lint(early_lint); - } + let lints = cx.sess.lints.borrow_mut().take(ast::CRATE_NODE_ID); + for early_lint in lints { + cx.early_lint(early_lint); } // since the root module isn't visited as an item (because it isn't an @@ -1270,7 +1268,7 @@ pub fn check_ast_crate(sess: &Session, krate: &ast::Crate) { // If we missed any lints added to the session, then there's a bug somewhere // in the iteration code. - for (_, v) in sess.lints.borrow().iter() { + for (_, v) in sess.lints.borrow().get_any() { for early_lint in v { span_bug!(early_lint.diagnostic.span.clone(), "unprocessed lint {:?}", early_lint); } diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index 7e0da00694c4a..704e32e2d0c1a 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -43,6 +43,8 @@ pub use lint::context::{LateContext, EarlyContext, LintContext, LintStore, raw_emit_lint, check_crate, check_ast_crate, gather_attrs, raw_struct_lint, FutureIncompatibleInfo, EarlyLint, IntoEarlyLint}; +pub use lint::table::LintTable; + /// Specification of a single lint. #[derive(Copy, Clone, Debug)] pub struct Lint { @@ -346,3 +348,4 @@ pub type LevelSource = (Level, LintSource); pub mod builtin; mod context; +mod table; diff --git a/src/librustc/lint/table.rs b/src/librustc/lint/table.rs new file mode 100644 index 0000000000000..3b6d268b08fb0 --- /dev/null +++ b/src/librustc/lint/table.rs @@ -0,0 +1,56 @@ +use syntax::ast; +use syntax_pos::MultiSpan; +use util::nodemap::NodeMap; + +use super::{Lint, LintId, EarlyLint, IntoEarlyLint}; + +pub struct LintTable { + map: NodeMap> +} + +impl LintTable { + pub fn new() -> Self { + LintTable { map: NodeMap() } + } + + pub fn add_lint>(&mut self, + lint: &'static Lint, + id: ast::NodeId, + sp: S, + msg: String) + { + self.add_lint_diagnostic(lint, id, (sp, &msg[..])) + } + + pub fn add_lint_diagnostic(&mut self, + lint: &'static Lint, + id: ast::NodeId, + msg: M) + where M: IntoEarlyLint, + { + let lint_id = LintId::of(lint); + let early_lint = msg.into_early_lint(lint_id); + let arr = self.map.entry(id).or_insert(vec![]); + if !arr.contains(&early_lint) { + arr.push(early_lint); + } + } + + pub fn get(&self, id: ast::NodeId) -> &[EarlyLint] { + self.map.get(&id).map(|v| &v[..]).unwrap_or(&[]) + } + + pub fn take(&mut self, id: ast::NodeId) -> Vec { + self.map.remove(&id).unwrap_or(vec![]) + } + + /// Returns the first (id, lint) pair that is non-empty. Used to + /// implement a sanity check in lints that all node-ids are + /// visited. + pub fn get_any(&self) -> Option<(&ast::NodeId, &Vec)> { + self.map.iter() + .filter(|&(_, v)| !v.is_empty()) + .next() + } +} + diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 36a887e062273..f10ea3544f2ca 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -20,7 +20,7 @@ use middle::dependency_format; use session::search_paths::PathKind; use session::config::DebugInfoLevel; use ty::tls; -use util::nodemap::{NodeMap, FxHashMap, FxHashSet}; +use util::nodemap::{FxHashMap, FxHashSet}; use util::common::duration_to_secs_str; use mir::transform as mir_pass; @@ -78,7 +78,7 @@ pub struct Session { pub local_crate_source_file: Option, pub working_dir: PathBuf, pub lint_store: RefCell, - pub lints: RefCell>>, + pub lints: RefCell, /// Set of (LintId, span, message) tuples tracking lint (sub)diagnostics /// that have been set once, but should not be set again, in order to avoid /// redundantly verbose output (Issue #24690). @@ -270,13 +270,14 @@ impl Session { pub fn unimpl(&self, msg: &str) -> ! { self.diagnostic().unimpl(msg) } + pub fn add_lint>(&self, lint: &'static lint::Lint, id: ast::NodeId, sp: S, msg: String) { - self.add_lint_diagnostic(lint, id, (sp, &msg[..])) + self.lints.borrow_mut().add_lint(lint, id, sp, msg); } pub fn add_lint_diagnostic(&self, @@ -285,17 +286,9 @@ impl Session { msg: M) where M: lint::IntoEarlyLint, { - let lint_id = lint::LintId::of(lint); - let mut lints = self.lints.borrow_mut(); - let early_lint = msg.into_early_lint(lint_id); - if let Some(arr) = lints.get_mut(&id) { - if !arr.contains(&early_lint) { - arr.push(early_lint); - } - return; - } - lints.insert(id, vec![early_lint]); + self.lints.borrow_mut().add_lint_diagnostic(lint, id, msg); } + pub fn reserve_node_ids(&self, count: usize) -> ast::NodeId { let id = self.next_node_id.get(); @@ -617,7 +610,7 @@ pub fn build_session_(sopts: config::Options, local_crate_source_file: local_crate_source_file, working_dir: env::current_dir().unwrap(), lint_store: RefCell::new(lint::LintStore::new()), - lints: RefCell::new(NodeMap()), + lints: RefCell::new(lint::LintTable::new()), one_time_diagnostics: RefCell::new(FxHashSet()), plugin_llvm_passes: RefCell::new(Vec::new()), mir_passes: RefCell::new(mir_pass::Passes::new()), From d9aaca71cc61a7c0792da2789b5e278cc294733f Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sat, 28 Jan 2017 18:13:21 -0500 Subject: [PATCH 066/137] store typeck lints in the `TypeckTables` Otherwise they are a "hidden output" --- src/Cargo.lock | 1 + src/librustc/lint/context.rs | 28 ++++++++++++++++++--- src/librustc/lint/mod.rs | 4 +-- src/librustc/lint/table.rs | 15 ++++++++++++ src/librustc/ty/context.rs | 5 ++++ src/librustc_errors/Cargo.toml | 1 + src/librustc_errors/diagnostic.rs | 4 +-- src/librustc_errors/lib.rs | 7 +++--- src/librustc_errors/snippet.rs | 2 +- src/librustc_typeck/check/cast.rs | 34 ++++++++++++++------------ src/librustc_typeck/check/mod.rs | 7 +++--- src/librustc_typeck/check/writeback.rs | 9 +++++++ src/libsyntax_pos/lib.rs | 2 +- 13 files changed, 87 insertions(+), 32 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 93bbf0f227b1b..f40d50dd59dc1 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -364,6 +364,7 @@ dependencies = [ name = "rustc_errors" version = "0.0.0" dependencies = [ + "serialize 0.0.0", "syntax_pos 0.0.0", ] diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index edf5666a3a5f7..362117d860a5c 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -33,6 +33,7 @@ use lint::{Level, LevelSource, Lint, LintId, LintPass, LintSource}; use lint::{EarlyLintPassObject, LateLintPassObject}; use lint::{Default, CommandLine, Node, Allow, Warn, Deny, Forbid}; use lint::builtin; +use rustc_serialize::{Decoder, Decodable, Encoder, Encodable}; use util::nodemap::FxHashMap; use std::cmp; @@ -82,7 +83,7 @@ pub struct LintStore { /// When you call `add_lint` on the session, you wind up storing one /// of these, which records a "potential lint" at a particular point. -#[derive(PartialEq)] +#[derive(PartialEq, RustcEncodable, RustcDecodable)] pub struct EarlyLint { /// what lint is this? (e.g., `dead_code`) pub id: LintId, @@ -558,7 +559,7 @@ pub trait LintContext<'tcx>: Sized { self.lookup_and_emit(lint, Some(span), msg); } - fn early_lint(&self, early_lint: EarlyLint) { + fn early_lint(&self, early_lint: &EarlyLint) { let span = early_lint.diagnostic.span.primary_span().expect("early lint w/o primary span"); let mut err = self.struct_span_lint(early_lint.id.lint, span, @@ -774,7 +775,7 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> { // Output any lints that were previously added to the session. fn visit_id(&mut self, id: ast::NodeId) { let lints = self.sess().lints.borrow_mut().take(id); - for early_lint in lints { + for early_lint in lints.iter().chain(self.tables.lints.get(id)) { debug!("LateContext::visit_id: id={:?} early_lint={:?}", id, early_lint); self.early_lint(early_lint); } @@ -1251,7 +1252,7 @@ pub fn check_ast_crate(sess: &Session, krate: &ast::Crate) { // Lints may be assigned to the whole crate. let lints = cx.sess.lints.borrow_mut().take(ast::CRATE_NODE_ID); for early_lint in lints { - cx.early_lint(early_lint); + cx.early_lint(&early_lint); } // since the root module isn't visited as an item (because it isn't an @@ -1274,3 +1275,22 @@ pub fn check_ast_crate(sess: &Session, krate: &ast::Crate) { } } } + +impl Encodable for LintId { + fn encode(&self, s: &mut S) -> Result<(), S::Error> { + s.emit_str(&self.lint.name.to_lowercase()) + } +} + +impl Decodable for LintId { + #[inline] + fn decode(d: &mut D) -> Result { + let s = d.read_str()?; + ty::tls::with(|tcx| { + match tcx.sess.lint_store.borrow().find_lint(&s, tcx.sess, None) { + Ok(id) => Ok(id), + Err(_) => panic!("invalid lint-id `{}`", s), + } + }) + } +} diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index 704e32e2d0c1a..d12065ca86e14 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -31,13 +31,13 @@ pub use self::Level::*; pub use self::LintSource::*; +use hir; +use hir::intravisit::FnKind; use std::hash; use std::ascii::AsciiExt; use syntax_pos::Span; -use hir::intravisit::FnKind; use syntax::visit as ast_visit; use syntax::ast; -use hir; pub use lint::context::{LateContext, EarlyContext, LintContext, LintStore, raw_emit_lint, check_crate, check_ast_crate, gather_attrs, diff --git a/src/librustc/lint/table.rs b/src/librustc/lint/table.rs index 3b6d268b08fb0..f2dab25229ae4 100644 --- a/src/librustc/lint/table.rs +++ b/src/librustc/lint/table.rs @@ -1,9 +1,20 @@ +// Copyright 2012-2015 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. + use syntax::ast; use syntax_pos::MultiSpan; use util::nodemap::NodeMap; use super::{Lint, LintId, EarlyLint, IntoEarlyLint}; +#[derive(RustcEncodable, RustcDecodable)] pub struct LintTable { map: NodeMap> } @@ -44,6 +55,10 @@ impl LintTable { self.map.remove(&id).unwrap_or(vec![]) } + pub fn transfer(&mut self, into: &mut LintTable) { + into.map.extend(self.map.drain()); + } + /// Returns the first (id, lint) pair that is non-empty. Used to /// implement a sanity check in lints that all node-ids are /// visited. diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 5913ed48528f7..a3b81586738b5 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -12,6 +12,7 @@ use dep_graph::{DepGraph, DepTrackingMap}; use session::Session; +use lint; use middle; use hir::TraitMap; use hir::def::Def; @@ -237,6 +238,9 @@ pub struct TypeckTables<'tcx> { /// Maps a cast expression to its kind. This is keyed on the /// *from* expression of the cast, not the cast itself. pub cast_kinds: NodeMap, + + /// Lints for the body of this fn generated by typeck. + pub lints: lint::LintTable, } impl<'tcx> TypeckTables<'tcx> { @@ -253,6 +257,7 @@ impl<'tcx> TypeckTables<'tcx> { liberated_fn_sigs: NodeMap(), fru_field_types: NodeMap(), cast_kinds: NodeMap(), + lints: lint::LintTable::new(), } } diff --git a/src/librustc_errors/Cargo.toml b/src/librustc_errors/Cargo.toml index 2ba1f501a63d8..78ff52b4b2371 100644 --- a/src/librustc_errors/Cargo.toml +++ b/src/librustc_errors/Cargo.toml @@ -9,4 +9,5 @@ path = "lib.rs" crate-type = ["dylib"] [dependencies] +serialize = { path = "../libserialize" } syntax_pos = { path = "../libsyntax_pos" } diff --git a/src/librustc_errors/diagnostic.rs b/src/librustc_errors/diagnostic.rs index ac39af2018998..1b77ead92deb6 100644 --- a/src/librustc_errors/diagnostic.rs +++ b/src/librustc_errors/diagnostic.rs @@ -17,7 +17,7 @@ use syntax_pos::{MultiSpan, Span}; use snippet::Style; #[must_use] -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)] pub struct Diagnostic { pub level: Level, pub message: Vec<(String, Style)>, @@ -27,7 +27,7 @@ pub struct Diagnostic { } /// For example a note attached to an error. -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)] pub struct SubDiagnostic { pub level: Level, pub message: Vec<(String, Style)>, diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index bf5f7cde7eb06..d7bd5ed23c2b0 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -26,6 +26,7 @@ extern crate term; extern crate libc; +extern crate serialize as rustc_serialize; extern crate syntax_pos; pub use emitter::ColorConfig; @@ -49,7 +50,7 @@ mod lock; use syntax_pos::{BytePos, Loc, FileLinesResult, FileName, MultiSpan, Span, NO_EXPANSION}; use syntax_pos::MacroBacktrace; -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)] pub enum RenderSpan { /// A FullSpan renders with both with an initial line for the /// message, prefixed by file:linenum, followed by a summary of @@ -63,7 +64,7 @@ pub enum RenderSpan { Suggestion(CodeSuggestion), } -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)] pub struct CodeSuggestion { pub msp: MultiSpan, pub substitutes: Vec, @@ -477,7 +478,7 @@ impl Handler { } -#[derive(Copy, PartialEq, Clone, Debug)] +#[derive(Copy, PartialEq, Clone, Debug, RustcEncodable, RustcDecodable)] pub enum Level { Bug, Fatal, diff --git a/src/librustc_errors/snippet.rs b/src/librustc_errors/snippet.rs index 95b03677b7285..5debbf4d37c20 100644 --- a/src/librustc_errors/snippet.rs +++ b/src/librustc_errors/snippet.rs @@ -204,7 +204,7 @@ pub struct StyledString { pub style: Style, } -#[derive(Copy, Clone, Debug, PartialEq)] +#[derive(Copy, Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)] pub enum Style { HeaderMsg, FileNameStyle, diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index 6215b4498dc68..441d427fe499e 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -311,23 +311,25 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { let t_cast = self.cast_ty; let t_expr = self.expr_ty; if t_cast.is_numeric() && t_expr.is_numeric() { - fcx.tcx.sess.add_lint(lint::builtin::TRIVIAL_NUMERIC_CASTS, - self.expr.id, - self.span, - format!("trivial numeric cast: `{}` as `{}`. Cast can be \ - replaced by coercion, this might require type \ - ascription or a temporary variable", - fcx.ty_to_string(t_expr), - fcx.ty_to_string(t_cast))); + fcx.tables.borrow_mut().lints.add_lint( + lint::builtin::TRIVIAL_NUMERIC_CASTS, + self.expr.id, + self.span, + format!("trivial numeric cast: `{}` as `{}`. Cast can be \ + replaced by coercion, this might require type \ + ascription or a temporary variable", + fcx.ty_to_string(t_expr), + fcx.ty_to_string(t_cast))); } else { - fcx.tcx.sess.add_lint(lint::builtin::TRIVIAL_CASTS, - self.expr.id, - self.span, - format!("trivial cast: `{}` as `{}`. Cast can be \ - replaced by coercion, this might require type \ - ascription or a temporary variable", - fcx.ty_to_string(t_expr), - fcx.ty_to_string(t_cast))); + fcx.tables.borrow_mut().lints.add_lint( + lint::builtin::TRIVIAL_CASTS, + self.expr.id, + self.span, + format!("trivial cast: `{}` as `{}`. Cast can be \ + replaced by coercion, this might require type \ + ascription or a temporary variable", + fcx.ty_to_string(t_expr), + fcx.ty_to_string(t_cast))); } } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index c435f9341253e..573cbfcc3b062 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1521,9 +1521,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if self.diverges.get() == Diverges::Always { self.diverges.set(Diverges::WarnedAlways); - self.tcx.sess.add_lint(lint::builtin::UNREACHABLE_CODE, - id, span, - format!("unreachable {}", kind)); + self.tables.borrow_mut().lints.add_lint( + lint::builtin::UNREACHABLE_CODE, + id, span, + format!("unreachable {}", kind)); } } diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 7f82d7829ce52..3a467c0296a52 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -52,6 +52,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { wbcx.visit_deferred_obligations(item_id); wbcx.visit_type_nodes(); wbcx.visit_cast_types(); + wbcx.visit_lints(); let tables = self.tcx.alloc_tables(wbcx.tables); self.tcx.tables.borrow_mut().insert(item_def_id, tables); @@ -301,6 +302,14 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { self.fcx.tables.borrow().cast_kinds.iter().map(|(&key, &value)| (key, value))); } + fn visit_lints(&mut self) { + if self.fcx.writeback_errors.get() { + return + } + + self.fcx.tables.borrow_mut().lints.transfer(&mut self.tables.lints); + } + fn visit_anon_types(&self) { if self.fcx.writeback_errors.get() { return diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index 92fdb45caaaef..3808923e7728f 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -66,7 +66,7 @@ pub struct Span { /// the error, and would be rendered with `^^^`. /// - they can have a *label*. In this case, the label is written next /// to the mark in the snippet when we render. -#[derive(Clone, Debug, Hash, PartialEq, Eq)] +#[derive(Clone, Debug, Hash, PartialEq, Eq, RustcEncodable, RustcDecodable)] pub struct MultiSpan { primary_spans: Vec, span_labels: Vec<(Span, String)>, From fdd7e3c74419385541e2ba244117e7aa65f72a01 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 1 Feb 2017 16:07:21 -0500 Subject: [PATCH 067/137] remove some of the ways to mutate a `DepTrackingMap` It is pretty suspect to insert an entry twice. --- src/librustc/dep_graph/dep_tracking_map.rs | 22 +++------------------ src/librustc_mir/mir_map.rs | 2 +- src/librustc_typeck/coherence/mod.rs | 23 +++++++++++++++------- src/librustc_typeck/collect.rs | 13 ++++-------- src/librustc_typeck/variance/solve.rs | 8 +++----- src/librustc_typeck/variance/terms.rs | 6 ++---- 6 files changed, 29 insertions(+), 45 deletions(-) diff --git a/src/librustc/dep_graph/dep_tracking_map.rs b/src/librustc/dep_graph/dep_tracking_map.rs index 9660758220368..103f8ef653c1e 100644 --- a/src/librustc/dep_graph/dep_tracking_map.rs +++ b/src/librustc/dep_graph/dep_tracking_map.rs @@ -61,15 +61,10 @@ impl DepTrackingMap { self.map.get(k) } - pub fn get_mut(&mut self, k: &M::Key) -> Option<&mut M::Value> { - self.read(k); - self.write(k); - self.map.get_mut(k) - } - - pub fn insert(&mut self, k: M::Key, v: M::Value) -> Option { + pub fn insert(&mut self, k: M::Key, v: M::Value) { self.write(&k); - self.map.insert(k, v) + let _old_value = self.map.insert(k, v); + // assert!(old_value.is_none()); } pub fn contains_key(&self, k: &M::Key) -> bool { @@ -80,17 +75,6 @@ impl DepTrackingMap { pub fn keys(&self) -> Vec { self.map.keys().cloned().collect() } - - /// Append `elem` to the vector stored for `k`, creating a new vector if needed. - /// This is considered a write to `k`. - pub fn push(&mut self, k: M::Key, elem: E) - where M: DepTrackingMapConfig> - { - self.write(&k); - self.map.entry(k) - .or_insert(Vec::new()) - .push(elem); - } } impl MemoizationMap for RefCell> { diff --git a/src/librustc_mir/mir_map.rs b/src/librustc_mir/mir_map.rs index c71255dcc7c61..b7f90682c7c74 100644 --- a/src/librustc_mir/mir_map.rs +++ b/src/librustc_mir/mir_map.rs @@ -139,7 +139,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BuildMir<'a, 'tcx> { let mir = tcx.alloc_mir(mir); let def_id = tcx.hir.local_def_id(src.item_id()); - assert!(tcx.mir_map.borrow_mut().insert(def_id, mir).is_none()); + tcx.mir_map.borrow_mut().insert(def_id, mir); }); let body = self.tcx.hir.body(body_id); diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index e9c710d2fec4c..4a96a5e960dbe 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -29,17 +29,19 @@ use rustc::dep_graph::DepNode; use rustc::hir::itemlikevisit::ItemLikeVisitor; use rustc::hir::{Item, ItemImpl}; use rustc::hir; +use rustc::util::nodemap::DefIdMap; mod builtin; mod orphan; mod overlap; mod unsafety; -struct CoherenceChecker<'a, 'tcx: 'a> { +struct CoherenceCollect<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, + inherent_impls: DefIdMap>, } -impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for CoherenceChecker<'a, 'tcx> { +impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for CoherenceCollect<'a, 'tcx> { fn visit_item(&mut self, item: &Item) { if let ItemImpl(..) = item.node { self.check_implementation(item) @@ -53,7 +55,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for CoherenceChecker<'a, 'tcx> { } } -impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> { +impl<'a, 'tcx> CoherenceCollect<'a, 'tcx> { // Returns the def ID of the base type, if there is one. fn get_base_type_def_id(&self, span: Span, ty: Ty<'tcx>) -> Option { match ty.sty { @@ -80,9 +82,14 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> { // containing the inherent methods and extension methods. It also // builds up the trait inheritance table. self.tcx.visit_all_item_likes_in_krate(DepNode::CoherenceCheckImpl, self); + + // Transfer the inherent impl lists, not that they are known, into the tcx + for (ty_def_id, impl_def_ids) in self.inherent_impls.drain() { + self.tcx.inherent_impls.borrow_mut().insert(ty_def_id, impl_def_ids); + } } - fn check_implementation(&self, item: &Item) { + fn check_implementation(&mut self, item: &Item) { let tcx = self.tcx; let impl_did = tcx.hir.local_def_id(item.id); let self_type = tcx.item_type(impl_did); @@ -119,8 +126,10 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> { } } - fn add_inherent_impl(&self, base_def_id: DefId, impl_def_id: DefId) { - self.tcx.inherent_impls.borrow_mut().push(base_def_id, impl_def_id); + fn add_inherent_impl(&mut self, base_def_id: DefId, impl_def_id: DefId) { + self.inherent_impls.entry(base_def_id) + .or_insert(vec![]) + .push(impl_def_id); } fn add_trait_impl(&self, impl_trait_ref: ty::TraitRef<'tcx>, impl_def_id: DefId) { @@ -161,7 +170,7 @@ fn enforce_trait_manually_implementable(tcx: TyCtxt, sp: Span, trait_def_id: Def pub fn check_coherence(ccx: &CrateCtxt) { let _task = ccx.tcx.dep_graph.in_task(DepNode::Coherence); - CoherenceChecker { tcx: ccx.tcx }.check(); + CoherenceCollect { tcx: ccx.tcx, inherent_impls: DefIdMap() }.check(); unsafety::check(ccx.tcx); orphan::check(ccx.tcx); overlap::check(ccx.tcx); diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index bbd0c8058151f..cb0a6cccb03d4 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -634,7 +634,7 @@ fn convert_field<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, ccx.tcx.item_types.borrow_mut().insert(ty_f.did, tt); let def_id = ccx.tcx.hir.local_def_id(field.id); - ccx.tcx.item_types.borrow_mut().insert(def_id, tt); + assert_eq!(def_id, ty_f.did); ccx.tcx.generics.borrow_mut().insert(def_id, struct_generics); ccx.tcx.predicates.borrow_mut().insert(def_id, struct_predicates.clone()); } @@ -1283,9 +1283,7 @@ fn convert_trait_predicates<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &hir::Item) items); trait_predicates.predicates.extend(assoc_predicates); - let prev_predicates = tcx.predicates.borrow_mut().insert(def_id, trait_predicates); - assert!(prev_predicates.is_none()); - + tcx.predicates.borrow_mut().insert(def_id, trait_predicates); return; fn predicates_for_associated_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, @@ -1592,9 +1590,7 @@ fn predicates_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, }; let predicates = ty_generic_predicates(ccx, generics, None, vec![], false); - let prev_predicates = ccx.tcx.predicates.borrow_mut().insert(def_id, - predicates.clone()); - assert!(prev_predicates.is_none()); + ccx.tcx.predicates.borrow_mut().insert(def_id, predicates.clone()); predicates } @@ -1617,8 +1613,7 @@ fn convert_foreign_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, }; let predicates = ty_generic_predicates(ccx, generics, None, vec![], false); - let prev_predicates = ccx.tcx.predicates.borrow_mut().insert(def_id, predicates); - assert!(prev_predicates.is_none()); + ccx.tcx.predicates.borrow_mut().insert(def_id, predicates); } // Is it marked with ?Sized diff --git a/src/librustc_typeck/variance/solve.rs b/src/librustc_typeck/variance/solve.rs index bdf1d0590bcc7..3ccec97d606ea 100644 --- a/src/librustc_typeck/variance/solve.rs +++ b/src/librustc_typeck/variance/solve.rs @@ -137,11 +137,9 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> { item_variances); } - let newly_added = tcx.item_variance_map - .borrow_mut() - .insert(item_def_id, Rc::new(item_variances)) - .is_none(); - assert!(newly_added); + tcx.item_variance_map + .borrow_mut() + .insert(item_def_id, Rc::new(item_variances)); } } diff --git a/src/librustc_typeck/variance/terms.rs b/src/librustc_typeck/variance/terms.rs index 0e09d34cc9bd3..253d7a25b632f 100644 --- a/src/librustc_typeck/variance/terms.rs +++ b/src/librustc_typeck/variance/terms.rs @@ -178,12 +178,10 @@ impl<'a, 'tcx> TermsContext<'a, 'tcx> { // parameters". if self.num_inferred() == inferreds_on_entry { let item_def_id = self.tcx.hir.local_def_id(item_id); - let newly_added = self.tcx + self.tcx .item_variance_map .borrow_mut() - .insert(item_def_id, self.empty_variances.clone()) - .is_none(); - assert!(newly_added); + .insert(item_def_id, self.empty_variances.clone()); } } From 2add6ac14a29d5d828f4da01ee0a09db0f472975 Mon Sep 17 00:00:00 2001 From: Jimmy Cuadra Date: Thu, 2 Feb 2017 17:40:44 -0800 Subject: [PATCH 068/137] Add a name for the parameter to `TryFrom::try_from`. Although signatures with anonymous parameters may not be deprecated or removed at this point, the team seems to agree that the ability to have an anonymous parameter is unfortunate historical baggage, and that we shouldn't create new code that uses it. Context: https://github.com/rust-lang/rust/issues/33417#issuecomment-276933861 --- src/libcore/convert.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs index abd686b15e22b..4e170794c1d6e 100644 --- a/src/libcore/convert.rs +++ b/src/libcore/convert.rs @@ -225,7 +225,7 @@ pub trait TryFrom: Sized { type Err; /// Performs the conversion. - fn try_from(T) -> Result; + fn try_from(value: T) -> Result; } //////////////////////////////////////////////////////////////////////////////// From 78f7ac561c0b360650b36a175f39475bc237230f Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sat, 28 Jan 2017 06:34:07 -0500 Subject: [PATCH 069/137] rejigger how we handle used trait imports The previous way was not friendly to incremental compilation. The new plan is to compute, for each body, a set of trait imports used in that body (slightly subtle: for a closure, we assign the trait imports to the enclosing fn). Then we walk all bodies and union these sets. The reason we do this is that we can save the individual sets in the incremental state, and then recompute only those sets that are needed. Before we were planning to save only the final union, but in that case if some components are invalidated we have to recompute *all* of them since we don't have enough information to "partly" invalidate a result. In truth, this set probably ought to be part of the `TypeckTables`; however, I opted not to do that because I don't want to have to save/restore the entire tables in the incremental state yet (since it contains a lot of `NodeId` references, and removing those is a significant refactoring). --- src/librustc/dep_graph/dep_node.rs | 3 +++ src/librustc/ty/context.rs | 4 ++-- src/librustc/ty/maps.rs | 2 ++ src/librustc_typeck/check/method/mod.rs | 6 ++++-- src/librustc_typeck/check/mod.rs | 8 +++++++- src/librustc_typeck/check/writeback.rs | 8 +++++++- src/librustc_typeck/check_unused.rs | 27 ++++++++++++++++++++----- src/librustc_typeck/lib.rs | 1 + 8 files changed, 48 insertions(+), 11 deletions(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index df6db366df5b3..006de1c06e2d9 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -113,6 +113,7 @@ pub enum DepNode { AssociatedItemDefIds(D), InherentImpls(D), TypeckTables(D), + UsedTraitImports(D), // The set of impls for a given trait. Ultimately, it would be // nice to get more fine-grained here (e.g., to include a @@ -162,6 +163,7 @@ impl DepNode { AssociatedItemDefIds, InherentImpls, TypeckTables, + UsedTraitImports, TraitImpls, ReprHints, } @@ -230,6 +232,7 @@ impl DepNode { AssociatedItemDefIds(ref d) => op(d).map(AssociatedItemDefIds), InherentImpls(ref d) => op(d).map(InherentImpls), TypeckTables(ref d) => op(d).map(TypeckTables), + UsedTraitImports(ref d) => op(d).map(UsedTraitImports), TraitImpls(ref d) => op(d).map(TraitImpls), TraitItems(ref d) => op(d).map(TraitItems), ReprHints(ref d) => op(d).map(ReprHints), diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index a3b81586738b5..7dcbe04caf82b 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -499,7 +499,7 @@ pub struct GlobalCtxt<'tcx> { /// Set of trait imports actually used in the method resolution. /// This is used for warning unused imports. - pub used_trait_imports: RefCell, + pub used_trait_imports: RefCell>>, /// The set of external nominal types whose implementations have been read. /// This is used for lazy resolution of methods. @@ -788,7 +788,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { inherent_impls: RefCell::new(DepTrackingMap::new(dep_graph.clone())), used_unsafe: RefCell::new(NodeSet()), used_mut_nodes: RefCell::new(NodeSet()), - used_trait_imports: RefCell::new(DefIdSet()), + used_trait_imports: RefCell::new(DepTrackingMap::new(dep_graph.clone())), populated_external_types: RefCell::new(DefIdSet()), populated_external_primitive_impls: RefCell::new(DefIdSet()), stability: RefCell::new(stability), diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs index c0cf1d724273e..d7341d148b720 100644 --- a/src/librustc/ty/maps.rs +++ b/src/librustc/ty/maps.rs @@ -12,6 +12,7 @@ use dep_graph::{DepNode, DepTrackingMapConfig}; use hir::def_id::DefId; use mir; use ty::{self, Ty}; +use util::nodemap::DefIdSet; use std::cell::RefCell; use std::marker::PhantomData; @@ -49,3 +50,4 @@ dep_map_ty! { Mir: Mir(DefId) -> &'tcx RefCell> } dep_map_ty! { ClosureKinds: ItemSignature(DefId) -> ty::ClosureKind } dep_map_ty! { ClosureTypes: ItemSignature(DefId) -> ty::ClosureTy<'tcx> } dep_map_ty! { TypeckTables: TypeckTables(DefId) -> &'tcx ty::TypeckTables<'tcx> } +dep_map_ty! { UsedTraitImports: UsedTraitImports(DefId) -> DefIdSet } diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index f8b6fbc9e816b..eae8989bd342e 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -138,7 +138,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let Some(import_id) = pick.import_id { let import_def_id = self.tcx.hir.local_def_id(import_id); - self.tcx.used_trait_imports.borrow_mut().insert(import_def_id); + debug!("used_trait_import: {:?}", import_def_id); + self.used_trait_imports.borrow_mut().insert(import_def_id); } self.tcx.check_stability(pick.item.def_id, call_expr.id, span); @@ -338,7 +339,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let Some(import_id) = pick.import_id { let import_def_id = self.tcx.hir.local_def_id(import_id); - self.tcx.used_trait_imports.borrow_mut().insert(import_def_id); + debug!("used_trait_import: {:?}", import_def_id); + self.used_trait_imports.borrow_mut().insert(import_def_id); } let def = pick.item.def(); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 573cbfcc3b062..1d9913cd96dc3 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -102,7 +102,7 @@ use CrateCtxt; use TypeAndSubsts; use lint; use util::common::{ErrorReported, indenter}; -use util::nodemap::{DefIdMap, FxHashMap, FxHashSet, NodeMap}; +use util::nodemap::{DefIdMap, DefIdSet, FxHashMap, FxHashSet, NodeMap}; use std::cell::{Cell, RefCell}; use std::cmp; @@ -179,6 +179,11 @@ pub struct Inherited<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { // Obligations which will have to be checked at the end of // type-checking, after all functions have been inferred. deferred_obligations: RefCell>>, + + // a set of trait import def-ids that we use during method + // resolution; during writeback, this is written into + // `tcx.used_trait_imports` for this item def-id + used_trait_imports: RefCell>, } impl<'a, 'gcx, 'tcx> Deref for Inherited<'a, 'gcx, 'tcx> { @@ -513,6 +518,7 @@ impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> { deferred_cast_checks: RefCell::new(Vec::new()), anon_types: RefCell::new(DefIdMap()), deferred_obligations: RefCell::new(Vec::new()), + used_trait_imports: RefCell::new(DefIdSet()), } } diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 3a467c0296a52..9df0542f51fa1 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -19,9 +19,10 @@ use rustc::ty::{self, Ty, TyCtxt, MethodCall, MethodCallee}; use rustc::ty::adjustment; use rustc::ty::fold::{TypeFolder,TypeFoldable}; use rustc::infer::{InferCtxt, FixupError}; -use rustc::util::nodemap::DefIdMap; +use rustc::util::nodemap::{DefIdMap, DefIdSet}; use std::cell::Cell; +use std::mem; use syntax::ast; use syntax_pos::Span; @@ -56,6 +57,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let tables = self.tcx.alloc_tables(wbcx.tables); self.tcx.tables.borrow_mut().insert(item_def_id, tables); + + let used_trait_imports = mem::replace(&mut *self.used_trait_imports.borrow_mut(), + DefIdSet()); + debug!("used_trait_imports({:?}) = {:?}", item_def_id, used_trait_imports); + self.tcx.used_trait_imports.borrow_mut().insert(item_def_id, used_trait_imports); } } diff --git a/src/librustc_typeck/check_unused.rs b/src/librustc_typeck/check_unused.rs index c1ba53afad4e9..6dff6d57e4fac 100644 --- a/src/librustc_typeck/check_unused.rs +++ b/src/librustc_typeck/check_unused.rs @@ -17,19 +17,21 @@ use syntax_pos::{Span, DUMMY_SP}; use rustc::hir; use rustc::hir::itemlikevisit::ItemLikeVisitor; +use rustc::util::nodemap::DefIdSet; -struct UnusedTraitImportVisitor<'a, 'tcx: 'a> { +struct CheckVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, + used_trait_imports: DefIdSet, } -impl<'a, 'tcx> UnusedTraitImportVisitor<'a, 'tcx> { +impl<'a, 'tcx> CheckVisitor<'a, 'tcx> { fn check_import(&self, id: ast::NodeId, span: Span) { if !self.tcx.maybe_unused_trait_imports.contains(&id) { return; } let import_def_id = self.tcx.hir.local_def_id(id); - if self.tcx.used_trait_imports.borrow().contains(&import_def_id) { + if self.used_trait_imports.contains(&import_def_id) { return; } @@ -42,7 +44,7 @@ impl<'a, 'tcx> UnusedTraitImportVisitor<'a, 'tcx> { } } -impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for UnusedTraitImportVisitor<'a, 'tcx> { +impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for CheckVisitor<'a, 'tcx> { fn visit_item(&mut self, item: &hir::Item) { if item.vis == hir::Public || item.span == DUMMY_SP { return; @@ -61,6 +63,21 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for UnusedTraitImportVisitor<'a, 'tcx> { pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { let _task = tcx.dep_graph.in_task(DepNode::UnusedTraitCheck); - let mut visitor = UnusedTraitImportVisitor { tcx: tcx }; + + let mut used_trait_imports = DefIdSet(); + for &body_id in tcx.hir.krate().bodies.keys() { + let item_id = tcx.hir.body_owner(body_id); + let item_def_id = tcx.hir.local_def_id(item_id); + + // this will have been written by the main typeck pass + if let Some(imports) = tcx.used_trait_imports.borrow().get(&item_def_id) { + debug!("GatherVisitor: item_def_id={:?} with imports {:#?}", item_def_id, imports); + used_trait_imports.extend(imports); + } else { + debug!("GatherVisitor: item_def_id={:?} with no imports", item_def_id); + } + } + + let mut visitor = CheckVisitor { tcx, used_trait_imports }; tcx.hir.krate().visit_all_item_likes(&mut visitor); } diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 4ed116b88f6d9..f19a59a5d38ae 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -77,6 +77,7 @@ This API is completely unstable and subject to change. #![feature(box_patterns)] #![feature(box_syntax)] #![feature(conservative_impl_trait)] +#![feature(field_init_shorthand)] #![feature(loop_break_value)] #![feature(quote)] #![feature(rustc_diagnostic_macros)] From 4b5613cb1d7db44a7ef5cdd937c45e7d82743021 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 2 Feb 2017 05:26:24 -0500 Subject: [PATCH 070/137] prevent multiple writes to a single entry in a `DepTrackingMap` --- src/librustc/dep_graph/dep_tracking_map.rs | 4 ++-- src/librustc_typeck/collect.rs | 14 ++++++++------ 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/librustc/dep_graph/dep_tracking_map.rs b/src/librustc/dep_graph/dep_tracking_map.rs index 103f8ef653c1e..ad6c93bf8daac 100644 --- a/src/librustc/dep_graph/dep_tracking_map.rs +++ b/src/librustc/dep_graph/dep_tracking_map.rs @@ -63,8 +63,8 @@ impl DepTrackingMap { pub fn insert(&mut self, k: M::Key, v: M::Value) { self.write(&k); - let _old_value = self.map.insert(k, v); - // assert!(old_value.is_none()); + let old_value = self.map.insert(k, v); + assert!(old_value.is_none()); } pub fn contains_key(&self, k: &M::Key) -> bool { diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index cb0a6cccb03d4..266975994ec3a 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -848,9 +848,10 @@ fn convert_trait_item(ccx: &CrateCtxt, trait_item: &hir::TraitItem) { let const_def_id = ccx.tcx.hir.local_def_id(trait_item.id); generics_of_def_id(ccx, const_def_id); let ty = ccx.icx(&trait_predicates).to_ty(&ty); - tcx.item_types.borrow_mut().insert(const_def_id, ty); - convert_associated_const(ccx, TraitContainer(trait_def_id), - trait_item.id, ty); + convert_associated_const(ccx, + TraitContainer(trait_def_id), + trait_item.id, + ty); } hir::TraitItemKind::Type(_, ref opt_ty) => { @@ -884,9 +885,10 @@ fn convert_impl_item(ccx: &CrateCtxt, impl_item: &hir::ImplItem) { let const_def_id = ccx.tcx.hir.local_def_id(impl_item.id); generics_of_def_id(ccx, const_def_id); let ty = ccx.icx(&impl_predicates).to_ty(&ty); - tcx.item_types.borrow_mut().insert(const_def_id, ty); - convert_associated_const(ccx, ImplContainer(impl_def_id), - impl_item.id, ty); + convert_associated_const(ccx, + ImplContainer(impl_def_id), + impl_item.id, + ty); } hir::ImplItemKind::Type(ref ty) => { From 681bc5c66cf6f99f7a95ebd5ed38cdd3fb3c4245 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 2 Feb 2017 19:24:20 -0800 Subject: [PATCH 071/137] rustbuild: Add x.py to source tarballs We should be sure to add our build system entry point! Closes #39476 --- src/bootstrap/dist.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 5fac142f777ff..9327cc0cf7faf 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -381,7 +381,8 @@ pub fn rust_src(build: &Build) { "README.md", "RELEASES.md", "configure", - "Makefile.in" + "Makefile.in", + "x.py", ]; let src_dirs = [ "man", From 3cf485c96322085f0af162b2a1458bfca0423f3c Mon Sep 17 00:00:00 2001 From: Clar Charr Date: Thu, 2 Feb 2017 23:56:10 -0500 Subject: [PATCH 072/137] Move rfind to DoubleEndedIterator, add tracking issue. --- src/libcore/iter/iterator.rs | 58 ------------------------------------ src/libcore/iter/traits.rs | 58 ++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 58 deletions(-) diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs index 0d34e06193c8f..3b406873d4b19 100644 --- a/src/libcore/iter/iterator.rs +++ b/src/libcore/iter/iterator.rs @@ -1488,64 +1488,6 @@ pub trait Iterator { None } - /// Searches for an element of an iterator from the right that satisfies a predicate. - /// - /// `rfind()` takes a closure that returns `true` or `false`. It applies - /// this closure to each element of the iterator, starting at the end, and if any - /// of them return `true`, then `rfind()` returns [`Some(element)`]. If they all return - /// `false`, it returns [`None`]. - /// - /// `rfind()` is short-circuiting; in other words, it will stop processing - /// as soon as the closure returns `true`. - /// - /// Because `rfind()` takes a reference, and many iterators iterate over - /// references, this leads to a possibly confusing situation where the - /// argument is a double reference. You can see this effect in the - /// examples below, with `&&x`. - /// - /// [`Some(element)`]: ../../std/option/enum.Option.html#variant.Some - /// [`None`]: ../../std/option/enum.Option.html#variant.None - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// #![feature(iter_rfind)] - /// - /// let a = [1, 2, 3]; - /// - /// assert_eq!(a.iter().rfind(|&&x| x == 2), Some(&2)); - /// - /// assert_eq!(a.iter().rfind(|&&x| x == 5), None); - /// ``` - /// - /// Stopping at the first `true`: - /// - /// ``` - /// #![feature(iter_rfind)] - /// - /// let a = [1, 2, 3]; - /// - /// let mut iter = a.iter(); - /// - /// assert_eq!(iter.rfind(|&&x| x == 2), Some(&2)); - /// - /// // we can still use `iter`, as there are more elements. - /// assert_eq!(iter.next_back(), Some(&1)); - /// ``` - #[inline] - #[unstable(feature = "iter_rfind", issue = "0")] - fn rfind

(&mut self, mut predicate: P) -> Option where - Self: Sized + DoubleEndedIterator, - P: FnMut(&Self::Item) -> bool - { - for x in self.by_ref().rev() { - if predicate(&x) { return Some(x) } - } - None - } - /// Searches for an element in an iterator, returning its index. /// /// `position()` takes a closure that returns `true` or `false`. It applies diff --git a/src/libcore/iter/traits.rs b/src/libcore/iter/traits.rs index 1e12714830067..a86ceb9ac0d37 100644 --- a/src/libcore/iter/traits.rs +++ b/src/libcore/iter/traits.rs @@ -414,6 +414,64 @@ pub trait DoubleEndedIterator: Iterator { /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn next_back(&mut self) -> Option; + + /// Searches for an element of an iterator from the right that satisfies a predicate. + /// + /// `rfind()` takes a closure that returns `true` or `false`. It applies + /// this closure to each element of the iterator, starting at the end, and if any + /// of them return `true`, then `rfind()` returns [`Some(element)`]. If they all return + /// `false`, it returns [`None`]. + /// + /// `rfind()` is short-circuiting; in other words, it will stop processing + /// as soon as the closure returns `true`. + /// + /// Because `rfind()` takes a reference, and many iterators iterate over + /// references, this leads to a possibly confusing situation where the + /// argument is a double reference. You can see this effect in the + /// examples below, with `&&x`. + /// + /// [`Some(element)`]: ../../std/option/enum.Option.html#variant.Some + /// [`None`]: ../../std/option/enum.Option.html#variant.None + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(iter_rfind)] + /// + /// let a = [1, 2, 3]; + /// + /// assert_eq!(a.iter().rfind(|&&x| x == 2), Some(&2)); + /// + /// assert_eq!(a.iter().rfind(|&&x| x == 5), None); + /// ``` + /// + /// Stopping at the first `true`: + /// + /// ``` + /// #![feature(iter_rfind)] + /// + /// let a = [1, 2, 3]; + /// + /// let mut iter = a.iter(); + /// + /// assert_eq!(iter.rfind(|&&x| x == 2), Some(&2)); + /// + /// // we can still use `iter`, as there are more elements. + /// assert_eq!(iter.next_back(), Some(&1)); + /// ``` + #[inline] + #[unstable(feature = "iter_rfind", issue = "39480")] + fn rfind

(&mut self, mut predicate: P) -> Option where + Self: Sized, + P: FnMut(&Self::Item) -> bool + { + for x in self.by_ref().rev() { + if predicate(&x) { return Some(x) } + } + None + } } #[stable(feature = "rust1", since = "1.0.0")] From 3ccb87a532159701486ae0ca33346c838791c699 Mon Sep 17 00:00:00 2001 From: Tatsuyuki Ishi Date: Fri, 3 Feb 2017 16:15:34 +0900 Subject: [PATCH 073/137] liballoc_jemalloc: fix linking with system library --- src/liballoc_jemalloc/build.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/liballoc_jemalloc/build.rs b/src/liballoc_jemalloc/build.rs index 1143df0c6302d..297f5ce99fd5e 100644 --- a/src/liballoc_jemalloc/build.rs +++ b/src/liballoc_jemalloc/build.rs @@ -42,6 +42,12 @@ fn main() { return; } + if target.contains("android") { + println!("cargo:rustc-link-lib=gcc"); + } else if !target.contains("windows") && !target.contains("musl") { + println!("cargo:rustc-link-lib=pthread"); + } + if let Some(jemalloc) = env::var_os("JEMALLOC_OVERRIDE") { let jemalloc = PathBuf::from(jemalloc); println!("cargo:rustc-link-search=native={}", @@ -176,11 +182,6 @@ fn main() { println!("cargo:rustc-link-lib=static=jemalloc_pic"); } println!("cargo:rustc-link-search=native={}/lib", build_dir.display()); - if target.contains("android") { - println!("cargo:rustc-link-lib=gcc"); - } else if !target.contains("windows") && !target.contains("musl") { - println!("cargo:rustc-link-lib=pthread"); - } // The pthread_atfork symbols is used by jemalloc on android but the really // old android we're building on doesn't have them defined, so just make From 458167e3a066ae7a032dbd457d003c9266d6b080 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-S=C3=A9bastien=20P=C3=A9dron?= Date: Wed, 25 Jan 2017 21:09:18 +0100 Subject: [PATCH 074/137] Add `aarch64-unknown-freebsd` to the supported targets --- mk/cfg/aarch64-unknown-freebsd.mk | 1 + .../target/aarch64_unknown_freebsd.rs | 34 +++++++++++++++++++ src/librustc_back/target/mod.rs | 1 + 3 files changed, 36 insertions(+) create mode 100644 mk/cfg/aarch64-unknown-freebsd.mk create mode 100644 src/librustc_back/target/aarch64_unknown_freebsd.rs diff --git a/mk/cfg/aarch64-unknown-freebsd.mk b/mk/cfg/aarch64-unknown-freebsd.mk new file mode 100644 index 0000000000000..34aee77ae2107 --- /dev/null +++ b/mk/cfg/aarch64-unknown-freebsd.mk @@ -0,0 +1 @@ +# rustbuild-only target diff --git a/src/librustc_back/target/aarch64_unknown_freebsd.rs b/src/librustc_back/target/aarch64_unknown_freebsd.rs new file mode 100644 index 0000000000000..3c5d6308ee6ba --- /dev/null +++ b/src/librustc_back/target/aarch64_unknown_freebsd.rs @@ -0,0 +1,34 @@ +// 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. + +use target::{Target, TargetOptions, TargetResult}; + +pub fn target() -> TargetResult { + let mut base = super::freebsd_base::opts(); + base.max_atomic_width = Some(128); + + // see #36994 + base.exe_allocation_crate = "alloc_system".to_string(); + + Ok(Target { + llvm_target: "aarch64-unknown-freebsd".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "64".to_string(), + data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(), + arch: "aarch64".to_string(), + target_os: "freebsd".to_string(), + target_env: "".to_string(), + target_vendor: "unknown".to_string(), + options: TargetOptions { + abi_blacklist: super::arm_base::abi_blacklist(), + .. base + }, + }) +} diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs index 5afa85d155279..d6acdceb3f5e2 100644 --- a/src/librustc_back/target/mod.rs +++ b/src/librustc_back/target/mod.rs @@ -165,6 +165,7 @@ supported_targets! { ("armv7-linux-androideabi", armv7_linux_androideabi), ("aarch64-linux-android", aarch64_linux_android), + ("aarch64-unknown-freebsd", aarch64_unknown_freebsd), ("i686-unknown-freebsd", i686_unknown_freebsd), ("x86_64-unknown-freebsd", x86_64_unknown_freebsd), From f6c6b31d26b5b08fbd1df907e37c5c02c7d71f90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-S=C3=A9bastien=20P=C3=A9dron?= Date: Fri, 3 Feb 2017 08:56:46 +0100 Subject: [PATCH 075/137] `aarch64` CPU type is called `arm64` on FreeBSD --- configure | 2 +- src/bootstrap/bootstrap.py | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/configure b/configure index 208fb7e683637..eea70b33e7ea9 100755 --- a/configure +++ b/configure @@ -517,7 +517,7 @@ case $CFG_CPUTYPE in CFG_OSTYPE="${CFG_OSTYPE}eabihf" ;; - aarch64) + aarch64 | arm64) CFG_CPUTYPE=aarch64 ;; diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 85e8dbce1a955..7265d183000d3 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -379,6 +379,8 @@ def build_triple(self): ostype += 'eabihf' elif cputype == 'aarch64': cputype = 'aarch64' + elif cputype == 'arm64': + cputype = 'aarch64' elif cputype == 'mips': if sys.byteorder == 'big': cputype = 'mips' From 5e41ec2cccb86db1a9677d2bfb9d2f623755f3de Mon Sep 17 00:00:00 2001 From: king6cong Date: Wed, 1 Feb 2017 11:49:24 +0800 Subject: [PATCH 076/137] rename other than copy/remove --- src/librustc_driver/driver.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index a04a5b106b8f1..6fe6541c1d919 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -1084,10 +1084,9 @@ pub fn phase_5_run_llvm_passes(sess: &Session, // are going to build an executable if sess.opts.output_types.contains_key(&OutputType::Exe) { let f = outputs.path(OutputType::Object); - fs::copy(&f, + fs::rename(&f, f.with_file_name(format!("{}.0.o", f.file_stem().unwrap().to_string_lossy()))).unwrap(); - fs::remove_file(f).unwrap(); } // Remove assembly source, unless --save-temps was specified From 768f6a9b57c83030919adb30565918f1b520596f Mon Sep 17 00:00:00 2001 From: king6cong Date: Fri, 3 Feb 2017 17:42:01 +0800 Subject: [PATCH 077/137] add and use rename_or_copy_remove fn that fallback to copy & remove --- src/librustc/util/fs.rs | 25 +++++++++++++++++++++++++ src/librustc_driver/driver.rs | 3 ++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/librustc/util/fs.rs b/src/librustc/util/fs.rs index c290d8f893e9e..7f8a69de60723 100644 --- a/src/librustc/util/fs.rs +++ b/src/librustc/util/fs.rs @@ -82,6 +82,31 @@ pub fn link_or_copy, Q: AsRef>(p: P, q: Q) -> io::Result

  • , Q: AsRef>(p: P, q: Q) -> io::Result { + let p = p.as_ref(); + let q = q.as_ref(); + match fs::rename(p, q) { + Ok(()) => Ok(RenameOrCopyRemove::Rename), + Err(_) => { + match fs::copy(p, q) { + Ok(_) => { + fs::remove_file(p)?; + Ok(RenameOrCopyRemove::CopyRemove) + }, + Err(e) => Err(e) + } + } + } +} + // Like std::fs::create_dir_all, except handles concurrent calls among multiple // threads or processes. pub fn create_dir_racy(path: &Path) -> io::Result<()> { diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 6fe6541c1d919..33bf4d5276adf 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -22,6 +22,7 @@ use rustc::middle::privacy::AccessLevels; use rustc::ty::{self, TyCtxt, Resolutions, GlobalArenas}; use rustc::util::common::time; use rustc::util::nodemap::{NodeSet, NodeMap}; +use rustc::util::fs::rename_or_copy_remove; use rustc_borrowck as borrowck; use rustc_incremental::{self, IncrementalHashesMap}; use rustc_incremental::ich::Fingerprint; @@ -1084,7 +1085,7 @@ pub fn phase_5_run_llvm_passes(sess: &Session, // are going to build an executable if sess.opts.output_types.contains_key(&OutputType::Exe) { let f = outputs.path(OutputType::Object); - fs::rename(&f, + rename_or_copy_remove(&f, f.with_file_name(format!("{}.0.o", f.file_stem().unwrap().to_string_lossy()))).unwrap(); } From 230234f3a8eb38dcfa26d086c9c6e61be48f46ac Mon Sep 17 00:00:00 2001 From: ggomez Date: Wed, 7 Sep 2016 16:43:18 +0200 Subject: [PATCH 078/137] Add information in case of markdown block code test failure --- src/librustdoc/html/markdown.rs | 7 ++++++- src/librustdoc/test.rs | 35 ++++++++++++++++++++------------- 2 files changed, 27 insertions(+), 15 deletions(-) diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 442a2f4074215..3df476907d953 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -448,7 +448,8 @@ pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector) { tests.add_test(text.to_owned(), block_info.should_panic, block_info.no_run, block_info.ignore, block_info.test_harness, - block_info.compile_fail, block_info.error_codes); + block_info.compile_fail, block_info.error_codes, + block_info.original); } } @@ -488,6 +489,7 @@ pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector) { #[derive(Eq, PartialEq, Clone, Debug)] struct LangString { + original: String, should_panic: bool, no_run: bool, ignore: bool, @@ -500,6 +502,7 @@ struct LangString { impl LangString { fn all_false() -> LangString { LangString { + original: String::new(), should_panic: false, no_run: false, ignore: false, @@ -521,6 +524,7 @@ impl LangString { allow_error_code_check = true; } + data.original = string.to_owned(); let tokens = string.split(|c: char| !(c == '_' || c == '-' || c.is_alphanumeric()) ); @@ -647,6 +651,7 @@ mod tests { test_harness: test_harness, compile_fail: compile_fail, error_codes: error_codes, + original: s.to_owned(), }) } diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index ab0ac02fd88f1..00327007dd00d 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -161,13 +161,15 @@ fn runtest(test: &str, cratename: &str, cfgs: Vec, libs: SearchPaths, externs: Externs, should_panic: bool, no_run: bool, as_test_harness: bool, compile_fail: bool, mut error_codes: Vec, opts: &TestOptions, - maybe_sysroot: Option) { + maybe_sysroot: Option, + original: &str) { // the test harness wants its own `main` & top level functions, so // never wrap the test in `fn main() { ... }` - let test = maketest(test, Some(cratename), as_test_harness, opts); + let new_test = maketest(test, Some(cratename), as_test_harness, opts); + let test = format!("```{}\n{}\n```\n", original, test); let input = config::Input::Str { name: driver::anon_src(), - input: test.to_owned(), + input: new_test.to_owned(), }; let outputs = OutputTypes::new(&[(OutputType::Exe, None)]); @@ -249,20 +251,22 @@ fn runtest(test: &str, cratename: &str, cfgs: Vec, libs: SearchPaths, if count > 0 && !compile_fail { sess.fatal("aborting due to previous error(s)") } else if count == 0 && compile_fail { - panic!("test compiled while it wasn't supposed to") + panic!("test compiled while it wasn't supposed to:\n\n{}\n", test) } if count > 0 && error_codes.len() > 0 { let out = String::from_utf8(data.lock().unwrap().to_vec()).unwrap(); error_codes.retain(|err| !out.contains(err)); } } - Ok(()) if compile_fail => panic!("test compiled while it wasn't supposed to"), + Ok(()) if compile_fail => { + panic!("test compiled while it wasn't supposed to:\n\n{}\n", test) + } _ => {} } } Err(_) => { if !compile_fail { - panic!("couldn't compile the test"); + panic!("couldn't compile the test:\n\n{}\n", test); } if error_codes.len() > 0 { let out = String::from_utf8(data.lock().unwrap().to_vec()).unwrap(); @@ -272,7 +276,7 @@ fn runtest(test: &str, cratename: &str, cfgs: Vec, libs: SearchPaths, } if error_codes.len() > 0 { - panic!("Some expected error codes were not found: {:?}", error_codes); + panic!("Some expected error codes were not found: {:?}\n\n{}\n", error_codes, test); } if no_run { return } @@ -294,17 +298,18 @@ fn runtest(test: &str, cratename: &str, cfgs: Vec, libs: SearchPaths, cmd.env(var, &newpath); match cmd.output() { - Err(e) => panic!("couldn't run the test: {}{}", e, + Err(e) => panic!("couldn't run the test: {}{}\n\n{}\n", e, if e.kind() == io::ErrorKind::PermissionDenied { " - maybe your tempdir is mounted with noexec?" - } else { "" }), + } else { "" }, test), Ok(out) => { if should_panic && out.status.success() { - panic!("test executable succeeded when it should have failed"); + panic!("test executable succeeded when it should have failed\n\n{}\n", test); } else if !should_panic && !out.status.success() { - panic!("test executable failed:\n{}\n{}", + panic!("test executable failed:\n{}\n{}\n\n{}\n", str::from_utf8(&out.stdout).unwrap_or(""), - str::from_utf8(&out.stderr).unwrap_or("")); + str::from_utf8(&out.stderr).unwrap_or(""), + test); } } } @@ -406,7 +411,8 @@ impl Collector { pub fn add_test(&mut self, test: String, should_panic: bool, no_run: bool, should_ignore: bool, - as_test_harness: bool, compile_fail: bool, error_codes: Vec) { + as_test_harness: bool, compile_fail: bool, error_codes: Vec, + original: String) { let name = if self.use_headers { let s = self.current_header.as_ref().map(|s| &**s).unwrap_or(""); format!("{}_{}", s, self.cnt) @@ -446,7 +452,8 @@ impl Collector { compile_fail, error_codes, &opts, - maybe_sysroot) + maybe_sysroot, + &original) }) } { Ok(()) => (), From 902460d2182198e096de47850c3e8ab72fbbafc5 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 2 Oct 2016 02:11:45 +0200 Subject: [PATCH 079/137] Add line number and filename in error message --- src/librustdoc/markdown.rs | 2 +- src/librustdoc/test.rs | 59 ++++++++++++++++++++++++++++++++++---- 2 files changed, 55 insertions(+), 6 deletions(-) diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs index 369e18948ad5b..50f748deb0b9e 100644 --- a/src/librustdoc/markdown.rs +++ b/src/librustdoc/markdown.rs @@ -154,7 +154,7 @@ pub fn test(input: &str, cfgs: Vec, libs: SearchPaths, externs: Externs, let mut opts = TestOptions::default(); opts.no_crate_inject = true; let mut collector = Collector::new(input.to_string(), cfgs, libs, externs, - true, opts, maybe_sysroot); + true, opts, maybe_sysroot, &input_str, "input".to_string()); find_testable_code(&input_str, &mut collector); test_args.insert(0, "rustdoctest".to_string()); testing::test_main(&test_args, collector.tests); diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 00327007dd00d..a772a52da727a 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::collections::HashMap; use std::env; use std::ffi::OsString; +use std::fs::File; use std::io::prelude::*; use std::io; use std::path::PathBuf; @@ -96,13 +98,24 @@ pub fn run(input: &str, link::find_crate_name(None, &hir_forest.krate().attrs, &input) }); let opts = scrape_test_config(hir_forest.krate()); + let filename = input_path.to_str().unwrap_or("").to_owned(); + let mut f = match File::open(input_path) { + Ok(f) => f, + _ => return 1, + }; + let mut file_content = String::new(); + if let Err(_) = f.read_to_string(&mut file_content) { + return 1; + } let mut collector = Collector::new(crate_name, cfgs, libs, externs, false, opts, - maybe_sysroot); + maybe_sysroot, + &file_content, + filename); { let dep_graph = DepGraph::new(false); @@ -162,11 +175,12 @@ fn runtest(test: &str, cratename: &str, cfgs: Vec, libs: SearchPaths, should_panic: bool, no_run: bool, as_test_harness: bool, compile_fail: bool, mut error_codes: Vec, opts: &TestOptions, maybe_sysroot: Option, - original: &str) { + original: &str, line_number: u32, filename: &str) { // the test harness wants its own `main` & top level functions, so // never wrap the test in `fn main() { ... }` let new_test = maketest(test, Some(cratename), as_test_harness, opts); - let test = format!("```{}\n{}\n```\n", original, test); + let test = format!("Error on {}:{}\n\n```{}\n{}\n```\n", + filename, line_number, original, test); let input = config::Input::Str { name: driver::anon_src(), input: new_test.to_owned(), @@ -389,11 +403,27 @@ pub struct Collector { cratename: String, opts: TestOptions, maybe_sysroot: Option, + code_blocks: HashMap>, + filename: String, } impl Collector { pub fn new(cratename: String, cfgs: Vec, libs: SearchPaths, externs: Externs, - use_headers: bool, opts: TestOptions, maybe_sysroot: Option) -> Collector { + use_headers: bool, opts: TestOptions, maybe_sysroot: Option, + file_content: &str, filename: String) -> Collector { + let mut line_number = 1; + let mut block_lines = HashMap::new(); + for (pos, block) in file_content.split("```").enumerate() { + if (pos & 1) != 0 { + let key = format!("{}", block.replace("/// ", "").replace("//!", "")); + if !block_lines.contains_key(&key) { + block_lines.insert(key.clone(), Vec::new()); + } + block_lines.get_mut(&key).unwrap().push(line_number); + } + line_number += block.lines().count() as u32 - 1; + } + Collector { tests: Vec::new(), names: Vec::new(), @@ -406,7 +436,22 @@ impl Collector { cratename: cratename, opts: opts, maybe_sysroot: maybe_sysroot, + code_blocks: block_lines, + filename: filename, + } + } + + fn get_line_from_key(&mut self, key: &String) -> u32 { + let (line, need_removal) = if let Some(l) = self.code_blocks.get_mut(key) { + let need_removal = l.len() > 1; + (l.pop().unwrap_or(1), need_removal) + } else { + return 1; + }; + if need_removal { + self.code_blocks.remove(key); } + line } pub fn add_test(&mut self, test: String, @@ -427,6 +472,8 @@ impl Collector { let opts = self.opts.clone(); let maybe_sysroot = self.maybe_sysroot.clone(); debug!("Creating test {}: {}", name, test); + let line_number = self.get_line_from_key(&format!("{}\n{}\n", original, test)); + let filename = self.filename.clone(); self.tests.push(testing::TestDescAndFn { desc: testing::TestDesc { name: testing::DynTestName(name), @@ -453,7 +500,9 @@ impl Collector { error_codes, &opts, maybe_sysroot, - &original) + &original, + line_number, + &filename) }) } { Ok(()) => (), From 59ac401b39b8cf18327acea5ce144ac94e9ed537 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 9 Oct 2016 14:14:49 +0200 Subject: [PATCH 080/137] Truncate output example to 10 lines --- src/librustdoc/test.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index a772a52da727a..bba9fa5ed7524 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -178,9 +178,14 @@ fn runtest(test: &str, cratename: &str, cfgs: Vec, libs: SearchPaths, original: &str, line_number: u32, filename: &str) { // the test harness wants its own `main` & top level functions, so // never wrap the test in `fn main() { ... }` + let mut trunc_test = test.split("\n").take(11).collect::>(); + if trunc_test.len() == 11 { + trunc_test[10] = "..."; + } let new_test = maketest(test, Some(cratename), as_test_harness, opts); let test = format!("Error on {}:{}\n\n```{}\n{}\n```\n", - filename, line_number, original, test); + filename, line_number, original, + trunc_test.join("\n")); let input = config::Input::Str { name: driver::anon_src(), input: new_test.to_owned(), From 5fe3915a05deac257dade7cf0839e3150221c18a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 15 Nov 2016 22:29:46 +0100 Subject: [PATCH 081/137] Rework rustdoc test output a bit --- src/librustdoc/test.rs | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index bba9fa5ed7524..566e78e34e573 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -178,18 +178,13 @@ fn runtest(test: &str, cratename: &str, cfgs: Vec, libs: SearchPaths, original: &str, line_number: u32, filename: &str) { // the test harness wants its own `main` & top level functions, so // never wrap the test in `fn main() { ... }` - let mut trunc_test = test.split("\n").take(11).collect::>(); - if trunc_test.len() == 11 { - trunc_test[10] = "..."; - } - let new_test = maketest(test, Some(cratename), as_test_harness, opts); - let test = format!("Error on {}:{}\n\n```{}\n{}\n```\n", - filename, line_number, original, - trunc_test.join("\n")); + let test = maketest(test, Some(cratename), as_test_harness, opts); let input = config::Input::Str { name: driver::anon_src(), - input: new_test.to_owned(), + input: test.to_owned(), }; + let test = format!("Error in \"{}\" at line {}.\n", + filename, line_number); let outputs = OutputTypes::new(&[(OutputType::Exe, None)]); let sessopts = config::Options { From a0ad4adf5977316494f8be2d549e6352c6a9b620 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 19 Nov 2016 17:51:25 +0100 Subject: [PATCH 082/137] Change thread name --- src/librustdoc/test.rs | 33 ++++++++++++--------------------- 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 566e78e34e573..3b910c276ee0c 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -88,7 +88,7 @@ pub fn run(input: &str, config::build_configuration(&sess, config::parse_cfgspecs(cfgs.clone())); let krate = panictry!(driver::phase_1_parse_input(&sess, &input)); - let driver::ExpansionResult { defs, mut hir_forest, .. } = { + let driver::ExpansionResult { hir_forest, .. } = { phase_2_configure_and_expand( &sess, &cstore, krate, None, "rustdoc-test", None, MakeGlobMap::No, |_| Ok(()) ).expect("phase_2_configure_and_expand aborted in rustdoc!") @@ -183,8 +183,6 @@ fn runtest(test: &str, cratename: &str, cfgs: Vec, libs: SearchPaths, name: driver::anon_src(), input: test.to_owned(), }; - let test = format!("Error in \"{}\" at line {}.\n", - filename, line_number); let outputs = OutputTypes::new(&[(OutputType::Exe, None)]); let sessopts = config::Options { @@ -265,7 +263,7 @@ fn runtest(test: &str, cratename: &str, cfgs: Vec, libs: SearchPaths, if count > 0 && !compile_fail { sess.fatal("aborting due to previous error(s)") } else if count == 0 && compile_fail { - panic!("test compiled while it wasn't supposed to:\n\n{}\n", test) + panic!("test compiled while it wasn't supposed to") } if count > 0 && error_codes.len() > 0 { let out = String::from_utf8(data.lock().unwrap().to_vec()).unwrap(); @@ -273,14 +271,14 @@ fn runtest(test: &str, cratename: &str, cfgs: Vec, libs: SearchPaths, } } Ok(()) if compile_fail => { - panic!("test compiled while it wasn't supposed to:\n\n{}\n", test) + panic!("test compiled while it wasn't supposed to") } _ => {} } } Err(_) => { if !compile_fail { - panic!("couldn't compile the test:\n\n{}\n", test); + panic!("couldn't compile the test"); } if error_codes.len() > 0 { let out = String::from_utf8(data.lock().unwrap().to_vec()).unwrap(); @@ -290,7 +288,7 @@ fn runtest(test: &str, cratename: &str, cfgs: Vec, libs: SearchPaths, } if error_codes.len() > 0 { - panic!("Some expected error codes were not found: {:?}\n\n{}\n", error_codes, test); + panic!("Some expected error codes were not found: {:?}", error_codes); } if no_run { return } @@ -312,18 +310,17 @@ fn runtest(test: &str, cratename: &str, cfgs: Vec, libs: SearchPaths, cmd.env(var, &newpath); match cmd.output() { - Err(e) => panic!("couldn't run the test: {}{}\n\n{}\n", e, + Err(e) => panic!("couldn't run the test: {}{}", e, if e.kind() == io::ErrorKind::PermissionDenied { " - maybe your tempdir is mounted with noexec?" - } else { "" }, test), + } else { "" }), Ok(out) => { if should_panic && out.status.success() { - panic!("test executable succeeded when it should have failed\n\n{}\n", test); + panic!("test executable succeeded when it should have failed"); } else if !should_panic && !out.status.success() { - panic!("test executable failed:\n{}\n{}\n\n{}\n", + panic!("test executable failed:\n{}\n{}\n", str::from_utf8(&out.stdout).unwrap_or(""), - str::from_utf8(&out.stderr).unwrap_or(""), - test); + str::from_utf8(&out.stderr).unwrap_or("")); } } } @@ -458,12 +455,8 @@ impl Collector { should_panic: bool, no_run: bool, should_ignore: bool, as_test_harness: bool, compile_fail: bool, error_codes: Vec, original: String) { - let name = if self.use_headers { - let s = self.current_header.as_ref().map(|s| &**s).unwrap_or(""); - format!("{}_{}", s, self.cnt) - } else { - format!("{}_{}", self.names.join("::"), self.cnt) - }; + let line_number = self.get_line_from_key(&format!("{}\n{}\n", original, test)); + let name = format!("{} - line {}", self.filename, line_number); self.cnt += 1; let cfgs = self.cfgs.clone(); let libs = self.libs.clone(); @@ -472,8 +465,6 @@ impl Collector { let opts = self.opts.clone(); let maybe_sysroot = self.maybe_sysroot.clone(); debug!("Creating test {}: {}", name, test); - let line_number = self.get_line_from_key(&format!("{}\n{}\n", original, test)); - let filename = self.filename.clone(); self.tests.push(testing::TestDescAndFn { desc: testing::TestDesc { name: testing::DynTestName(name), From 409e8ba34e03fd48d9a2395d5f602ddc4e8bc97a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 12 Jan 2017 20:33:01 +0100 Subject: [PATCH 083/137] Move to my own hoedown repository --- .gitmodules | 2 +- src/librustdoc/html/markdown.rs | 45 ++++++++++++++++++++------------- src/librustdoc/test.rs | 10 +++----- src/rt/hoedown | 2 +- 4 files changed, 33 insertions(+), 26 deletions(-) diff --git a/.gitmodules b/.gitmodules index 39288a7ae4907..73824b7b42c9c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,7 +7,7 @@ url = https://github.com/rust-lang/compiler-rt.git [submodule "src/rt/hoedown"] path = src/rt/hoedown - url = https://github.com/rust-lang/hoedown.git + url = https://github.com/GuillaumeGomez/hoedown.git [submodule "src/jemalloc"] path = src/jemalloc url = https://github.com/rust-lang/jemalloc.git diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 3df476907d953..c35342e25b523 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -71,29 +71,31 @@ const HOEDOWN_EXTENSIONS: libc::c_uint = enum hoedown_document {} type blockcodefn = extern "C" fn(*mut hoedown_buffer, *const hoedown_buffer, - *const hoedown_buffer, *const hoedown_renderer_data); + *const hoedown_buffer, *const hoedown_renderer_data, + libc::size_t); type blockquotefn = extern "C" fn(*mut hoedown_buffer, *const hoedown_buffer, - *const hoedown_renderer_data); + *const hoedown_renderer_data, libc::size_t); type headerfn = extern "C" fn(*mut hoedown_buffer, *const hoedown_buffer, - libc::c_int, *const hoedown_renderer_data); + libc::c_int, *const hoedown_renderer_data, + libc::size_t); type blockhtmlfn = extern "C" fn(*mut hoedown_buffer, *const hoedown_buffer, - *const hoedown_renderer_data); + *const hoedown_renderer_data, libc::size_t); type codespanfn = extern "C" fn(*mut hoedown_buffer, *const hoedown_buffer, - *const hoedown_renderer_data) -> libc::c_int; + *const hoedown_renderer_data, libc::size_t) -> libc::c_int; type linkfn = extern "C" fn (*mut hoedown_buffer, *const hoedown_buffer, *const hoedown_buffer, *const hoedown_buffer, - *const hoedown_renderer_data) -> libc::c_int; + *const hoedown_renderer_data, libc::size_t) -> libc::c_int; type entityfn = extern "C" fn (*mut hoedown_buffer, *const hoedown_buffer, - *const hoedown_renderer_data); + *const hoedown_renderer_data, libc::size_t); type normaltextfn = extern "C" fn(*mut hoedown_buffer, *const hoedown_buffer, - *const hoedown_renderer_data); + *const hoedown_renderer_data, libc::size_t); #[repr(C)] struct hoedown_renderer_data { @@ -147,7 +149,8 @@ struct html_toc_data { struct MyOpaque { dfltblk: extern "C" fn(*mut hoedown_buffer, *const hoedown_buffer, - *const hoedown_buffer, *const hoedown_renderer_data), + *const hoedown_buffer, *const hoedown_renderer_data, + libc::size_t), toc_builder: Option, } @@ -229,7 +232,8 @@ pub fn render(w: &mut fmt::Formatter, print_toc: bool, html_flags: libc::c_uint) -> fmt::Result { extern fn block(ob: *mut hoedown_buffer, orig_text: *const hoedown_buffer, - lang: *const hoedown_buffer, data: *const hoedown_renderer_data) { + lang: *const hoedown_buffer, data: *const hoedown_renderer_data, + line: libc::size_t) { unsafe { if orig_text.is_null() { return } @@ -246,7 +250,8 @@ pub fn render(w: &mut fmt::Formatter, let rlang = str::from_utf8(rlang).unwrap(); if !LangString::parse(rlang).rust { (my_opaque.dfltblk)(ob, orig_text, lang, - opaque as *const hoedown_renderer_data); + opaque as *const hoedown_renderer_data, + line); true } else { false @@ -312,7 +317,8 @@ pub fn render(w: &mut fmt::Formatter, } extern fn header(ob: *mut hoedown_buffer, text: *const hoedown_buffer, - level: libc::c_int, data: *const hoedown_renderer_data) { + level: libc::c_int, data: *const hoedown_renderer_data, + _: libc::size_t) { // hoedown does this, we may as well too unsafe { hoedown_buffer_puts(ob, "\n\0".as_ptr() as *const _); } @@ -373,6 +379,7 @@ pub fn render(w: &mut fmt::Formatter, ob: *mut hoedown_buffer, text: *const hoedown_buffer, _: *const hoedown_renderer_data, + _: libc::size_t ) -> libc::c_int { let content = if text.is_null() { "".to_owned() @@ -426,7 +433,8 @@ pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector) { extern fn block(_ob: *mut hoedown_buffer, text: *const hoedown_buffer, lang: *const hoedown_buffer, - data: *const hoedown_renderer_data) { + data: *const hoedown_renderer_data, + _: libc::size_t) { unsafe { if text.is_null() { return } let block_info = if lang.is_null() { @@ -455,7 +463,8 @@ pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector) { extern fn header(_ob: *mut hoedown_buffer, text: *const hoedown_buffer, - level: libc::c_int, data: *const hoedown_renderer_data) { + level: libc::c_int, data: *const hoedown_renderer_data, + _: libc::size_t) { unsafe { let opaque = (*data).opaque as *mut hoedown_html_renderer_state; let tests = &mut *((*opaque).opaque as *mut ::test::Collector); @@ -590,7 +599,8 @@ pub fn plain_summary_line(md: &str) -> String { _link: *const hoedown_buffer, _title: *const hoedown_buffer, content: *const hoedown_buffer, - data: *const hoedown_renderer_data) -> libc::c_int + data: *const hoedown_renderer_data, + _: libc::size_t) -> libc::c_int { unsafe { if !content.is_null() && (*content).size > 0 { @@ -603,8 +613,9 @@ pub fn plain_summary_line(md: &str) -> String { } extern fn normal_text(_ob: *mut hoedown_buffer, - text: *const hoedown_buffer, - data: *const hoedown_renderer_data) + text: *const hoedown_buffer, + data: *const hoedown_renderer_data, + _: libc::size_t) { unsafe { let ob = (*data).opaque as *mut hoedown_buffer; diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 3b910c276ee0c..bad2986ab628b 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -88,7 +88,7 @@ pub fn run(input: &str, config::build_configuration(&sess, config::parse_cfgspecs(cfgs.clone())); let krate = panictry!(driver::phase_1_parse_input(&sess, &input)); - let driver::ExpansionResult { hir_forest, .. } = { + let driver::ExpansionResult { defs, mut hir_forest, .. } = { phase_2_configure_and_expand( &sess, &cstore, krate, None, "rustdoc-test", None, MakeGlobMap::No, |_| Ok(()) ).expect("phase_2_configure_and_expand aborted in rustdoc!") @@ -174,8 +174,7 @@ fn runtest(test: &str, cratename: &str, cfgs: Vec, libs: SearchPaths, externs: Externs, should_panic: bool, no_run: bool, as_test_harness: bool, compile_fail: bool, mut error_codes: Vec, opts: &TestOptions, - maybe_sysroot: Option, - original: &str, line_number: u32, filename: &str) { + maybe_sysroot: Option) { // the test harness wants its own `main` & top level functions, so // never wrap the test in `fn main() { ... }` let test = maketest(test, Some(cratename), as_test_harness, opts); @@ -490,10 +489,7 @@ impl Collector { compile_fail, error_codes, &opts, - maybe_sysroot, - &original, - line_number, - &filename) + maybe_sysroot) }) } { Ok(()) => (), diff --git a/src/rt/hoedown b/src/rt/hoedown index a3736a0a1907c..78e7b6f69d3fa 160000 --- a/src/rt/hoedown +++ b/src/rt/hoedown @@ -1 +1 @@ -Subproject commit a3736a0a1907cbc8bf619708738815a5fd789c80 +Subproject commit 78e7b6f69d3fa0cb6ae6e7fb9278c3fd167ec0d1 From 62fb7fc54a6b7cca2c690ca84ee54e4a86ab5ba4 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 17 Jan 2017 23:54:51 +0100 Subject: [PATCH 084/137] Switch logic to Span instead of HashMap --- src/librustdoc/clean/mod.rs | 10 ++++- src/librustdoc/html/markdown.rs | 8 ++-- src/librustdoc/markdown.rs | 5 ++- src/librustdoc/test.rs | 71 ++++++++++++--------------------- src/libsyntax/attr.rs | 12 +++--- src/libsyntax/print/pprust.rs | 5 ++- src/libsyntax/std_inject.rs | 3 +- src/libsyntax/test.rs | 3 +- 8 files changed, 54 insertions(+), 63 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index cdb24a56367fc..fe2edcad25c20 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -521,17 +521,22 @@ impl<'a, I: IntoIterator> NestedAttributesExt for #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug, Default)] pub struct Attributes { pub doc_strings: Vec, - pub other_attrs: Vec + pub other_attrs: Vec, + pub span: Option, } impl Attributes { pub fn from_ast(attrs: &[ast::Attribute]) -> Attributes { let mut doc_strings = vec![]; + let mut sp = None; let other_attrs = attrs.iter().filter_map(|attr| { attr.with_desugared_doc(|attr| { if let Some(value) = attr.value_str() { if attr.check_name("doc") { doc_strings.push(value.to_string()); + if sp.is_none() { + sp = Some(attr.span); + } return None; } } @@ -541,7 +546,8 @@ impl Attributes { }).collect(); Attributes { doc_strings: doc_strings, - other_attrs: other_attrs + other_attrs: other_attrs, + span: sp, } } diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index c35342e25b523..e8ff8930bdd7d 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -429,12 +429,12 @@ pub fn render(w: &mut fmt::Formatter, } } -pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector) { +pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector, start_line: usize) { extern fn block(_ob: *mut hoedown_buffer, text: *const hoedown_buffer, lang: *const hoedown_buffer, data: *const hoedown_renderer_data, - _: libc::size_t) { + line: libc::size_t) { unsafe { if text.is_null() { return } let block_info = if lang.is_null() { @@ -453,11 +453,12 @@ pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector) { stripped_filtered_line(l).unwrap_or(l) }); let text = lines.collect::>().join("\n"); + let line = tests.get_line() + line; tests.add_test(text.to_owned(), block_info.should_panic, block_info.no_run, block_info.ignore, block_info.test_harness, block_info.compile_fail, block_info.error_codes, - block_info.original); + line); } } @@ -478,6 +479,7 @@ pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector) { } } + tests.set_line(start_line); unsafe { let ob = hoedown_buffer_new(DEF_OUNIT); let renderer = hoedown_html_renderer_new(0, 0); diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs index 50f748deb0b9e..49497957be980 100644 --- a/src/librustdoc/markdown.rs +++ b/src/librustdoc/markdown.rs @@ -154,8 +154,9 @@ pub fn test(input: &str, cfgs: Vec, libs: SearchPaths, externs: Externs, let mut opts = TestOptions::default(); opts.no_crate_inject = true; let mut collector = Collector::new(input.to_string(), cfgs, libs, externs, - true, opts, maybe_sysroot, &input_str, "input".to_string()); - find_testable_code(&input_str, &mut collector); + true, opts, maybe_sysroot, "input".to_string(), + None); + find_testable_code(&input_str, &mut collector, 0); test_args.insert(0, "rustdoctest".to_string()); testing::test_main(&test_args, collector.tests); 0 diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index bad2986ab628b..d5451d6a6c37d 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -8,10 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::collections::HashMap; use std::env; use std::ffi::OsString; -use std::fs::File; use std::io::prelude::*; use std::io; use std::path::PathBuf; @@ -39,6 +37,7 @@ use rustc_trans::back::link; use syntax::ast; use syntax::codemap::CodeMap; use syntax::feature_gate::UnstableFeatures; +use syntax_pos::{BytePos, DUMMY_SP, Pos}; use errors; use errors::emitter::ColorConfig; @@ -81,7 +80,7 @@ pub fn run(input: &str, let _ignore = dep_graph.in_ignore(); let cstore = Rc::new(CStore::new(&dep_graph)); let mut sess = session::build_session_( - sessopts, &dep_graph, Some(input_path.clone()), handler, codemap, cstore.clone(), + sessopts, &dep_graph, Some(input_path.clone()), handler, codemap.clone(), cstore.clone(), ); rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess)); sess.parse_sess.config = @@ -99,14 +98,6 @@ pub fn run(input: &str, }); let opts = scrape_test_config(hir_forest.krate()); let filename = input_path.to_str().unwrap_or("").to_owned(); - let mut f = match File::open(input_path) { - Ok(f) => f, - _ => return 1, - }; - let mut file_content = String::new(); - if let Err(_) = f.read_to_string(&mut file_content) { - return 1; - } let mut collector = Collector::new(crate_name, cfgs, libs, @@ -114,8 +105,8 @@ pub fn run(input: &str, false, opts, maybe_sysroot, - &file_content, - filename); + filename, + Some(codemap)); { let dep_graph = DepGraph::new(false); @@ -399,27 +390,15 @@ pub struct Collector { cratename: String, opts: TestOptions, maybe_sysroot: Option, - code_blocks: HashMap>, filename: String, + start_line: usize, + codemap: Option>, } impl Collector { pub fn new(cratename: String, cfgs: Vec, libs: SearchPaths, externs: Externs, use_headers: bool, opts: TestOptions, maybe_sysroot: Option, - file_content: &str, filename: String) -> Collector { - let mut line_number = 1; - let mut block_lines = HashMap::new(); - for (pos, block) in file_content.split("```").enumerate() { - if (pos & 1) != 0 { - let key = format!("{}", block.replace("/// ", "").replace("//!", "")); - if !block_lines.contains_key(&key) { - block_lines.insert(key.clone(), Vec::new()); - } - block_lines.get_mut(&key).unwrap().push(line_number); - } - line_number += block.lines().count() as u32 - 1; - } - + filename: String, codemap: Option>) -> Collector { Collector { tests: Vec::new(), names: Vec::new(), @@ -432,30 +411,17 @@ impl Collector { cratename: cratename, opts: opts, maybe_sysroot: maybe_sysroot, - code_blocks: block_lines, filename: filename, + start_line: 0, + codemap: codemap, } } - fn get_line_from_key(&mut self, key: &String) -> u32 { - let (line, need_removal) = if let Some(l) = self.code_blocks.get_mut(key) { - let need_removal = l.len() > 1; - (l.pop().unwrap_or(1), need_removal) - } else { - return 1; - }; - if need_removal { - self.code_blocks.remove(key); - } - line - } - pub fn add_test(&mut self, test: String, should_panic: bool, no_run: bool, should_ignore: bool, as_test_harness: bool, compile_fail: bool, error_codes: Vec, - original: String) { - let line_number = self.get_line_from_key(&format!("{}\n{}\n", original, test)); - let name = format!("{} - line {}", self.filename, line_number); + line: usize) { + let name = format!("{} - line {}", self.filename, line); self.cnt += 1; let cfgs = self.cfgs.clone(); let libs = self.libs.clone(); @@ -499,6 +465,18 @@ impl Collector { }); } + pub fn get_line(&self) -> usize { + if let Some(ref codemap) = self.codemap{ + codemap.lookup_char_pos(BytePos(self.start_line as u32)).line - 1 + } else { + self.start_line + } + } + + pub fn set_line(&mut self, start_line: usize) { + self.start_line = start_line; + } + pub fn register_header(&mut self, name: &str, level: u32) { if self.use_headers && level == 1 { // we use these headings as test names, so it's good if @@ -539,7 +517,8 @@ impl<'a, 'hir> HirCollector<'a, 'hir> { attrs.unindent_doc_comments(); if let Some(doc) = attrs.doc_value() { self.collector.cnt = 0; - markdown::find_testable_code(doc, self.collector); + markdown::find_testable_code(doc, self.collector, + attrs.span.unwrap_or(DUMMY_SP).lo.to_usize()); } nested(self); diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index 099ca8f02d2b2..455a6a0fb32e2 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -280,9 +280,9 @@ impl Attribute { Symbol::intern("doc"), Symbol::intern(&strip_doc_comment_decoration(&comment.as_str()))); if self.style == ast::AttrStyle::Outer { - f(&mk_attr_outer(self.id, meta)) + f(&mk_attr_outer(self.span, self.id, meta)) } else { - f(&mk_attr_inner(self.id, meta)) + f(&mk_attr_inner(self.span, self.id, meta)) } } else { f(self) @@ -339,8 +339,8 @@ pub fn mk_attr_id() -> AttrId { } /// Returns an inner attribute with the given value. -pub fn mk_attr_inner(id: AttrId, item: MetaItem) -> Attribute { - mk_spanned_attr_inner(DUMMY_SP, id, item) +pub fn mk_attr_inner(span: Span, id: AttrId, item: MetaItem) -> Attribute { + mk_spanned_attr_inner(span, id, item) } /// Returns an innter attribute with the given value and span. @@ -356,8 +356,8 @@ pub fn mk_spanned_attr_inner(sp: Span, id: AttrId, item: MetaItem) -> Attribute /// Returns an outer attribute with the given value. -pub fn mk_attr_outer(id: AttrId, item: MetaItem) -> Attribute { - mk_spanned_attr_outer(DUMMY_SP, id, item) +pub fn mk_attr_outer(span: Span, id: AttrId, item: MetaItem) -> Attribute { + mk_spanned_attr_outer(span, id, item) } /// Returns an outer attribute with the given value and span. diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index e75671d27aa24..9d7f57b2af934 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -27,6 +27,7 @@ use print::pp::Breaks::{Consistent, Inconsistent}; use ptr::P; use std_inject; use symbol::{Symbol, keywords}; +use syntax_pos::DUMMY_SP; use tokenstream::{self, TokenTree}; use rustc_i128::i128; @@ -118,12 +119,12 @@ pub fn print_crate<'a>(cm: &'a CodeMap, // #![feature(prelude_import)] let prelude_import_meta = attr::mk_list_word_item(Symbol::intern("prelude_import")); let list = attr::mk_list_item(Symbol::intern("feature"), vec![prelude_import_meta]); - let fake_attr = attr::mk_attr_inner(attr::mk_attr_id(), list); + let fake_attr = attr::mk_attr_inner(DUMMY_SP, attr::mk_attr_id(), list); s.print_attribute(&fake_attr)?; // #![no_std] let no_std_meta = attr::mk_word_item(Symbol::intern("no_std")); - let fake_attr = attr::mk_attr_inner(attr::mk_attr_id(), no_std_meta); + let fake_attr = attr::mk_attr_inner(DUMMY_SP, attr::mk_attr_id(), no_std_meta); s.print_attribute(&fake_attr)?; } diff --git a/src/libsyntax/std_inject.rs b/src/libsyntax/std_inject.rs index 68d807b24a788..4a2dfaf61247c 100644 --- a/src/libsyntax/std_inject.rs +++ b/src/libsyntax/std_inject.rs @@ -56,7 +56,8 @@ pub fn maybe_inject_crates_ref(sess: &ParseSess, let crate_name = Symbol::intern(&alt_std_name.unwrap_or(name.to_string())); krate.module.items.insert(0, P(ast::Item { - attrs: vec![attr::mk_attr_outer(attr::mk_attr_id(), + attrs: vec![attr::mk_attr_outer(DUMMY_SP, + attr::mk_attr_id(), attr::mk_word_item(Symbol::intern("macro_use")))], vis: ast::Visibility::Inherited, node: ast::ItemKind::ExternCrate(Some(crate_name)), diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs index 74ec33fdd2a85..dd2756cd2b22c 100644 --- a/src/libsyntax/test.rs +++ b/src/libsyntax/test.rs @@ -195,7 +195,8 @@ impl fold::Folder for EntryPointCleaner { let dead_code_str = Symbol::intern("dead_code"); let word_vec = vec![attr::mk_list_word_item(dead_code_str)]; let allow_dead_code_item = attr::mk_list_item(allow_str, word_vec); - let allow_dead_code = attr::mk_attr_outer(attr::mk_attr_id(), + let allow_dead_code = attr::mk_attr_outer(DUMMY_SP, + attr::mk_attr_id(), allow_dead_code_item); ast::Item { From d97226c132e820b4636df6e7f8287d45377c64b7 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 19 Jan 2017 16:47:17 +0100 Subject: [PATCH 085/137] Add new rustdoc ui tests --- src/bootstrap/check.rs | 71 +++++++++++++++++++++++++++++++++++ src/bootstrap/step.rs | 5 +++ src/test/rustdoc-test/test.rs | 14 +++++++ 3 files changed, 90 insertions(+) create mode 100644 src/test/rustdoc-test/test.rs diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 19aac0f36bb27..1801d5bdd80e1 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -19,6 +19,7 @@ use std::collections::HashSet; use std::env; use std::fmt; use std::fs; +use std::io::Read; use std::path::{PathBuf, Path}; use std::process::Command; @@ -316,6 +317,76 @@ fn markdown_test(build: &Build, compiler: &Compiler, markdown: &Path) { build.run(&mut cmd); } +pub fn markdown_test_output_check(build: &Build, compiler: &Compiler) { + let _time = util::timeit(); + for entry in fs::read_dir("src/test/rustdoc-test") + .expect("markdown_test_output_check: read_dir failed") { + if let Ok(entry) = entry { + if entry.path().extension().and_then(|s| s.to_str()) != Some("rs") { + continue + } + markdown_test_output_check_entry(build, compiler, entry.path().as_path()); + } + } +} + +fn markdown_test_output_check_entry(build: &Build, compiler: &Compiler, path: &Path) { + let mut file = fs::File::open(path) + .expect("markdown_test_output_check_entry File::open failed"); + let mut content = String::new(); + file.read_to_string(&mut content) + .expect("markdown_test_output_check_entry read_to_string failed"); + let mut ignore = false; + let mut v: Vec = + content.split("\n") + .enumerate() + .filter_map(|(line_nb, line)| { + let sline = line.split("///").last().unwrap_or(""); + let line = sline.trim_left(); + if line.starts_with("```") && + !line.contains("ignore") { + if ignore { + ignore = false; + None + } else { + ignore = true; + Some(line_nb + 1) + } + } else { + None + } + }) + .collect(); + let mut cmd = Command::new(build.rustdoc(compiler)); + build.add_rustc_lib_path(compiler, &mut cmd); + build.add_rust_test_threads(&mut cmd); + cmd.arg("--test"); + cmd.arg(path); + cmd.env("RUSTC_BOOTSTRAP", "1"); + + cmd.arg("--test-args").arg(build.flags.cmd.test_args().join(" ")); + + output(&mut cmd).split("\n") + .filter(|s| s.starts_with("test ")) + .inspect(|s| { + let tmp: Vec<&str> = s.split(" - line ").collect(); + if tmp.len() == 2 { + let line = usize::from_str_radix(tmp[1].split(" ...") + .next() + .unwrap_or("0"), 10) + .unwrap_or(0); + if let Ok(pos) = v.binary_search(&line) { + v.remove(pos); + } else { + panic!("Not found doc test: \"{}\" in {:?}", s, v); + } + } + }).all(|_| true); + if v.len() != 0 { + panic!("Not found test at line{} {:?}", if v.len() > 1 { "s" } else { "" }, v); + } +} + /// Run all unit tests plus documentation tests for an entire crate DAG defined /// by a `Cargo.toml` /// diff --git a/src/bootstrap/step.rs b/src/bootstrap/step.rs index 3932a7cf8c563..c3e0e08223065 100644 --- a/src/bootstrap/step.rs +++ b/src/bootstrap/step.rs @@ -474,6 +474,11 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { .default(true) .host(true) .run(move |s| check::docs(build, &s.compiler())); + rules.test("check-rustdoc-output", "src/test/rustdoc-test") + .dep(|s| s.name("libtest")) + .default(true) + .host(true) + .run(move |s| check::markdown_test_output_check(build, &s.compiler())); rules.test("check-distcheck", "distcheck") .dep(|s| s.name("dist-src")) .run(move |_| check::distcheck(build)); diff --git a/src/test/rustdoc-test/test.rs b/src/test/rustdoc-test/test.rs new file mode 100644 index 0000000000000..96a4a35282beb --- /dev/null +++ b/src/test/rustdoc-test/test.rs @@ -0,0 +1,14 @@ +/// This is a Foo; +/// +/// ``` +/// println!("baaaaaar"); +/// ``` +#[unstable] +pub struct Foo; + +/// This is a Bar; +/// +/// ``` +/// println!("fooooo"); +/// ``` +pub struct Bar; From aea6f3234af12f0a7c098c2a80803061aba76608 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 20 Jan 2017 19:03:09 +0100 Subject: [PATCH 086/137] Put rustdoc --test ui check at the end of docs check --- src/bootstrap/check.rs | 3 +-- src/bootstrap/step.rs | 5 ----- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 1801d5bdd80e1..f8c31d7337191 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -275,6 +275,7 @@ pub fn docs(build: &Build, compiler: &Compiler) { println!("doc tests for: {}", p.display()); markdown_test(build, compiler, &p); } + markdown_test(build, compiler, &output); } /// Run the error index generator tool to execute the tests located in the error @@ -296,8 +297,6 @@ pub fn error_index(build: &Build, compiler: &Compiler) { .arg("markdown") .arg(&output) .env("CFG_BUILD", &build.config.build)); - - markdown_test(build, compiler, &output); } fn markdown_test(build: &Build, compiler: &Compiler, markdown: &Path) { diff --git a/src/bootstrap/step.rs b/src/bootstrap/step.rs index c3e0e08223065..3932a7cf8c563 100644 --- a/src/bootstrap/step.rs +++ b/src/bootstrap/step.rs @@ -474,11 +474,6 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { .default(true) .host(true) .run(move |s| check::docs(build, &s.compiler())); - rules.test("check-rustdoc-output", "src/test/rustdoc-test") - .dep(|s| s.name("libtest")) - .default(true) - .host(true) - .run(move |s| check::markdown_test_output_check(build, &s.compiler())); rules.test("check-distcheck", "distcheck") .dep(|s| s.name("dist-src")) .run(move |_| check::distcheck(build)); From 44b59be0f2ad38c39b67a6c8ebfe826c4c30cbd9 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 20 Jan 2017 23:24:20 +0100 Subject: [PATCH 087/137] Move test from bootstrap to compiletest --- src/bootstrap/check.rs | 74 +--------------- src/test/rustdoc-test/test.rs | 14 ---- src/test/rustdoc/test_option_check/test.rs | 27 ++++++ src/tools/compiletest/src/runtest.rs | 98 ++++++++++++++++++---- 4 files changed, 113 insertions(+), 100 deletions(-) delete mode 100644 src/test/rustdoc-test/test.rs create mode 100644 src/test/rustdoc/test_option_check/test.rs diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index f8c31d7337191..19aac0f36bb27 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -19,7 +19,6 @@ use std::collections::HashSet; use std::env; use std::fmt; use std::fs; -use std::io::Read; use std::path::{PathBuf, Path}; use std::process::Command; @@ -275,7 +274,6 @@ pub fn docs(build: &Build, compiler: &Compiler) { println!("doc tests for: {}", p.display()); markdown_test(build, compiler, &p); } - markdown_test(build, compiler, &output); } /// Run the error index generator tool to execute the tests located in the error @@ -297,6 +295,8 @@ pub fn error_index(build: &Build, compiler: &Compiler) { .arg("markdown") .arg(&output) .env("CFG_BUILD", &build.config.build)); + + markdown_test(build, compiler, &output); } fn markdown_test(build: &Build, compiler: &Compiler, markdown: &Path) { @@ -316,76 +316,6 @@ fn markdown_test(build: &Build, compiler: &Compiler, markdown: &Path) { build.run(&mut cmd); } -pub fn markdown_test_output_check(build: &Build, compiler: &Compiler) { - let _time = util::timeit(); - for entry in fs::read_dir("src/test/rustdoc-test") - .expect("markdown_test_output_check: read_dir failed") { - if let Ok(entry) = entry { - if entry.path().extension().and_then(|s| s.to_str()) != Some("rs") { - continue - } - markdown_test_output_check_entry(build, compiler, entry.path().as_path()); - } - } -} - -fn markdown_test_output_check_entry(build: &Build, compiler: &Compiler, path: &Path) { - let mut file = fs::File::open(path) - .expect("markdown_test_output_check_entry File::open failed"); - let mut content = String::new(); - file.read_to_string(&mut content) - .expect("markdown_test_output_check_entry read_to_string failed"); - let mut ignore = false; - let mut v: Vec = - content.split("\n") - .enumerate() - .filter_map(|(line_nb, line)| { - let sline = line.split("///").last().unwrap_or(""); - let line = sline.trim_left(); - if line.starts_with("```") && - !line.contains("ignore") { - if ignore { - ignore = false; - None - } else { - ignore = true; - Some(line_nb + 1) - } - } else { - None - } - }) - .collect(); - let mut cmd = Command::new(build.rustdoc(compiler)); - build.add_rustc_lib_path(compiler, &mut cmd); - build.add_rust_test_threads(&mut cmd); - cmd.arg("--test"); - cmd.arg(path); - cmd.env("RUSTC_BOOTSTRAP", "1"); - - cmd.arg("--test-args").arg(build.flags.cmd.test_args().join(" ")); - - output(&mut cmd).split("\n") - .filter(|s| s.starts_with("test ")) - .inspect(|s| { - let tmp: Vec<&str> = s.split(" - line ").collect(); - if tmp.len() == 2 { - let line = usize::from_str_radix(tmp[1].split(" ...") - .next() - .unwrap_or("0"), 10) - .unwrap_or(0); - if let Ok(pos) = v.binary_search(&line) { - v.remove(pos); - } else { - panic!("Not found doc test: \"{}\" in {:?}", s, v); - } - } - }).all(|_| true); - if v.len() != 0 { - panic!("Not found test at line{} {:?}", if v.len() > 1 { "s" } else { "" }, v); - } -} - /// Run all unit tests plus documentation tests for an entire crate DAG defined /// by a `Cargo.toml` /// diff --git a/src/test/rustdoc-test/test.rs b/src/test/rustdoc-test/test.rs deleted file mode 100644 index 96a4a35282beb..0000000000000 --- a/src/test/rustdoc-test/test.rs +++ /dev/null @@ -1,14 +0,0 @@ -/// This is a Foo; -/// -/// ``` -/// println!("baaaaaar"); -/// ``` -#[unstable] -pub struct Foo; - -/// This is a Bar; -/// -/// ``` -/// println!("fooooo"); -/// ``` -pub struct Bar; diff --git a/src/test/rustdoc/test_option_check/test.rs b/src/test/rustdoc/test_option_check/test.rs new file mode 100644 index 0000000000000..772d258bc800f --- /dev/null +++ b/src/test/rustdoc/test_option_check/test.rs @@ -0,0 +1,27 @@ +// 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. + +// compile-flags:--test +// check-stdout + +/// This is a Foo; +/// +/// ``` +/// println!("baaaaaar"); +/// ``` +#[unstable] +pub struct Foo; + +/// This is a Bar; +/// +/// ``` +/// println!("fooooo"); +/// ``` +pub struct Bar; diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 86fa5e70c9c28..11c43b7150f9d 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -43,7 +43,7 @@ pub fn run(config: Config, testpaths: &TestPaths) { } _ => { - // android has it's own gdb handling + // android has its own gdb handling if config.mode == DebugInfoGdb && config.gdb.is_none() { panic!("gdb not available but debuginfo gdb debuginfo test requested"); } @@ -1879,22 +1879,92 @@ actual:\n\ fn run_rustdoc_test(&self) { assert!(self.revision.is_none(), "revisions not relevant here"); - let out_dir = self.output_base_name(); - let _ = fs::remove_dir_all(&out_dir); - self.create_dir_racy(&out_dir); + if self.props.compile_flags.contains(&"--test".to_owned()) && + self.props.check_stdout == true { + self.check_rustdoc_test_option(); + } else { + let out_dir = self.output_base_name(); + let _ = fs::remove_dir_all(&out_dir); + self.create_dir_racy(&out_dir); - let proc_res = self.document(&out_dir); - if !proc_res.status.success() { - self.fatal_proc_rec("rustdoc failed!", &proc_res); + let proc_res = self.document(&out_dir); + if !proc_res.status.success() { + self.fatal_proc_rec("rustdoc failed!", &proc_res); + } + let root = self.find_rust_src_root().unwrap(); + + let res = self.cmd2procres(Command::new(&self.config.docck_python) + .arg(root.join("src/etc/htmldocck.py")) + .arg(out_dir) + .arg(&self.testpaths.file)); + if !res.status.success() { + self.fatal_proc_rec("htmldocck failed!", &res); + } } - let root = self.find_rust_src_root().unwrap(); + } + + fn check_rustdoc_test_option(&self) { + let mut file = fs::File::open(&self.testpaths.file) + .expect("markdown_test_output_check_entry File::open failed"); + let mut content = String::new(); + file.read_to_string(&mut content) + .expect("markdown_test_output_check_entry read_to_string failed"); + let mut ignore = false; + let mut v: Vec = + content.split("\n") + .enumerate() + .filter_map(|(line_nb, line)| { + let sline = line.split("///").last().unwrap_or(""); + let line = sline.trim_left(); + if line.starts_with("```") && + !line.contains("ignore") { + if ignore { + ignore = false; + None + } else { + ignore = true; + Some(line_nb + 1) + } + } else { + None + } + }) + .collect(); - let res = self.cmd2procres(Command::new(&self.config.docck_python) - .arg(root.join("src/etc/htmldocck.py")) - .arg(out_dir) - .arg(&self.testpaths.file)); - if !res.status.success() { - self.fatal_proc_rec("htmldocck failed!", &res); + let args = ProcArgs { + prog: self.config.rustdoc_path.to_str().unwrap().to_owned(), + args: vec!["--test".to_owned(), self.testpaths.file.to_str().unwrap().to_owned()], + }; + let env = self.props.exec_env.clone(); + let res = self.compose_and_run(args, + env, + self.config.run_lib_path.to_str().unwrap(), + None, + None); + + res.stdout.split("\n") + .filter(|s| s.starts_with("test ")) + .inspect(|s| { + let tmp: Vec<&str> = s.split(" - line ").collect(); + if tmp.len() == 2 { + let line = usize::from_str_radix(tmp[1].split(" ...") + .next() + .unwrap_or("0"), 10) + .unwrap_or(0); + if let Ok(pos) = v.binary_search(&line) { + v.remove(pos); + } else { + self.fatal_proc_rec(&format!("Not found doc test: \"{}\" in {:?}", + s, v), + &res); + } + } + }) + .all(|_| true); + if v.len() != 0 { + self.fatal_proc_rec(&format!("Not found test at line{} {:?}", + if v.len() > 1 { "s" } else { "" }, v), + &res); } } From 6756b72a1ddbebe657e36b40064170685c7e140f Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 23 Jan 2017 22:46:18 +0100 Subject: [PATCH 088/137] Create new flag to test rustdoc --test --- .gitmodules | 2 +- src/librustdoc/test.rs | 3 +- src/rt/hoedown | 2 +- src/test/rustdoc/test_option_check/test.rs | 5 +- src/tools/compiletest/src/header.rs | 11 +++ src/tools/compiletest/src/runtest.rs | 85 ++++++++++------------ 6 files changed, 55 insertions(+), 53 deletions(-) diff --git a/.gitmodules b/.gitmodules index 73824b7b42c9c..39288a7ae4907 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,7 +7,7 @@ url = https://github.com/rust-lang/compiler-rt.git [submodule "src/rt/hoedown"] path = src/rt/hoedown - url = https://github.com/GuillaumeGomez/hoedown.git + url = https://github.com/rust-lang/hoedown.git [submodule "src/jemalloc"] path = src/jemalloc url = https://github.com/rust-lang/jemalloc.git diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index d5451d6a6c37d..6b6330ef12a94 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -467,7 +467,8 @@ impl Collector { pub fn get_line(&self) -> usize { if let Some(ref codemap) = self.codemap{ - codemap.lookup_char_pos(BytePos(self.start_line as u32)).line - 1 + let line = codemap.lookup_char_pos(BytePos(self.start_line as u32)).line; + if line > 0 { line - 1 } else { line } } else { self.start_line } diff --git a/src/rt/hoedown b/src/rt/hoedown index 78e7b6f69d3fa..a3736a0a1907c 160000 --- a/src/rt/hoedown +++ b/src/rt/hoedown @@ -1 +1 @@ -Subproject commit 78e7b6f69d3fa0cb6ae6e7fb9278c3fd167ec0d1 +Subproject commit a3736a0a1907cbc8bf619708738815a5fd789c80 diff --git a/src/test/rustdoc/test_option_check/test.rs b/src/test/rustdoc/test_option_check/test.rs index 772d258bc800f..b2afe43204d41 100644 --- a/src/test/rustdoc/test_option_check/test.rs +++ b/src/test/rustdoc/test_option_check/test.rs @@ -8,15 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags:--test -// check-stdout +// compile-flags: --test +// check-test-line-numbers-match /// This is a Foo; /// /// ``` /// println!("baaaaaar"); /// ``` -#[unstable] pub struct Foo; /// This is a Bar; diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index ac1ac1c2f6c08..71d8d62c75b69 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -224,6 +224,8 @@ pub struct TestProps { pub incremental_dir: Option, // Specifies that a cfail test must actually compile without errors. pub must_compile_successfully: bool, + // rustdoc will test the output of the `--test` option + pub check_test_line_numbers_match: bool, } impl TestProps { @@ -248,6 +250,7 @@ impl TestProps { forbid_output: vec![], incremental_dir: None, must_compile_successfully: false, + check_test_line_numbers_match: false, } } @@ -347,6 +350,10 @@ impl TestProps { if !self.must_compile_successfully { self.must_compile_successfully = parse_must_compile_successfully(ln); } + + if !self.check_test_line_numbers_match { + self.check_test_line_numbers_match = parse_check_test_line_numbers_match(ln); + } }); for key in vec!["RUST_TEST_NOCAPTURE", "RUST_TEST_THREADS"] { @@ -458,6 +465,10 @@ fn parse_must_compile_successfully(line: &str) -> bool { parse_name_directive(line, "must-compile-successfully") } +fn parse_check_test_line_numbers_match(line: &str) -> bool { + parse_name_directive(line, "check-test-line-numbers-match") +} + fn parse_env(line: &str, name: &str) -> Option<(String, String)> { parse_name_value_directive(line, name).map(|nv| { // nv is either FOO or FOO=BAR diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 11c43b7150f9d..a8c46722e163b 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1879,20 +1879,19 @@ actual:\n\ fn run_rustdoc_test(&self) { assert!(self.revision.is_none(), "revisions not relevant here"); - if self.props.compile_flags.contains(&"--test".to_owned()) && - self.props.check_stdout == true { - self.check_rustdoc_test_option(); - } else { - let out_dir = self.output_base_name(); - let _ = fs::remove_dir_all(&out_dir); - self.create_dir_racy(&out_dir); + let out_dir = self.output_base_name(); + let _ = fs::remove_dir_all(&out_dir); + self.create_dir_racy(&out_dir); - let proc_res = self.document(&out_dir); - if !proc_res.status.success() { - self.fatal_proc_rec("rustdoc failed!", &proc_res); - } - let root = self.find_rust_src_root().unwrap(); + let proc_res = self.document(&out_dir); + if !proc_res.status.success() { + self.fatal_proc_rec("rustdoc failed!", &proc_res); + } + if self.props.check_test_line_numbers_match == true { + self.check_rustdoc_test_option(proc_res); + } else { + let root = self.find_rust_src_root().unwrap(); let res = self.cmd2procres(Command::new(&self.config.docck_python) .arg(root.join("src/etc/htmldocck.py")) .arg(out_dir) @@ -1903,7 +1902,7 @@ actual:\n\ } } - fn check_rustdoc_test_option(&self) { + fn check_rustdoc_test_option(&self, res: ProcRes) { let mut file = fs::File::open(&self.testpaths.file) .expect("markdown_test_output_check_entry File::open failed"); let mut content = String::new(); @@ -1911,13 +1910,12 @@ actual:\n\ .expect("markdown_test_output_check_entry read_to_string failed"); let mut ignore = false; let mut v: Vec = - content.split("\n") + content.lines() .enumerate() .filter_map(|(line_nb, line)| { let sline = line.split("///").last().unwrap_or(""); let line = sline.trim_left(); - if line.starts_with("```") && - !line.contains("ignore") { + if line.starts_with("```") { if ignore { ignore = false; None @@ -1931,37 +1929,30 @@ actual:\n\ }) .collect(); - let args = ProcArgs { - prog: self.config.rustdoc_path.to_str().unwrap().to_owned(), - args: vec!["--test".to_owned(), self.testpaths.file.to_str().unwrap().to_owned()], - }; - let env = self.props.exec_env.clone(); - let res = self.compose_and_run(args, - env, - self.config.run_lib_path.to_str().unwrap(), - None, - None); - - res.stdout.split("\n") - .filter(|s| s.starts_with("test ")) - .inspect(|s| { - let tmp: Vec<&str> = s.split(" - line ").collect(); - if tmp.len() == 2 { - let line = usize::from_str_radix(tmp[1].split(" ...") - .next() - .unwrap_or("0"), 10) - .unwrap_or(0); - if let Ok(pos) = v.binary_search(&line) { - v.remove(pos); - } else { - self.fatal_proc_rec(&format!("Not found doc test: \"{}\" in {:?}", - s, v), - &res); - } - } - }) - .all(|_| true); - if v.len() != 0 { + let mut tested = 0; + for _ in res.stdout.split("\n") + .filter(|s| s.starts_with("test ")) + .inspect(|s| { + let tmp: Vec<&str> = s.split(" - line ").collect(); + if tmp.len() == 2 { + tested += 1; + let line = tmp[1].split(" ...") + .next() + .unwrap_or("0") + .parse() + .unwrap_or(0); + if let Ok(pos) = v.binary_search(&line) { + v.remove(pos); + } else { + self.fatal_proc_rec( + &format!("Not found doc test: \"{}\" in {:?}", s, v), + &res); + } + } + }) {} + if tested == 0 { + self.fatal_proc_rec("No test has been found", &res); + } else if v.len() != 0 { self.fatal_proc_rec(&format!("Not found test at line{} {:?}", if v.len() > 1 { "s" } else { "" }, v), &res); From f14479505882170f6394eedf4856ed1f5307b3a6 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 28 Jan 2017 16:38:12 +0100 Subject: [PATCH 089/137] Set correct hoedown submodule branch --- .gitmodules | 1 + src/rt/hoedown | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index 39288a7ae4907..86c5c780c5eb2 100644 --- a/.gitmodules +++ b/.gitmodules @@ -8,6 +8,7 @@ [submodule "src/rt/hoedown"] path = src/rt/hoedown url = https://github.com/rust-lang/hoedown.git + branch = rust-2015-09-21-do-not-delete [submodule "src/jemalloc"] path = src/jemalloc url = https://github.com/rust-lang/jemalloc.git diff --git a/src/rt/hoedown b/src/rt/hoedown index a3736a0a1907c..da282f1bb7277 160000 --- a/src/rt/hoedown +++ b/src/rt/hoedown @@ -1 +1 @@ -Subproject commit a3736a0a1907cbc8bf619708738815a5fd789c80 +Subproject commit da282f1bb7277b4d30fa1599ee29ad8eb4dd2a92 From 7c4b79c80aafe0fc5c900ce5e31795dd973f7794 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 28 Jan 2017 18:26:37 +0100 Subject: [PATCH 090/137] Update run-make/issue-22131 to new rustdoc --test format --- src/test/run-make/issue-22131/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/run-make/issue-22131/Makefile b/src/test/run-make/issue-22131/Makefile index 1e8568626a6a1..f65cc9e06a329 100644 --- a/src/test/run-make/issue-22131/Makefile +++ b/src/test/run-make/issue-22131/Makefile @@ -4,4 +4,4 @@ all: foo.rs $(RUSTC) --cfg 'feature="bar"' --crate-type lib foo.rs $(HOST_RPATH_ENV) '$(RUSTDOC)' --test --cfg 'feature="bar"' \ -L $(TMPDIR) foo.rs |\ - grep -q 'test foo_0 ... ok' + grep -q 'foo.rs - line 11 ... ok' From 723eed32287d1de64f4d49c3108f863966c2cecd Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 2 Feb 2017 19:53:37 +0100 Subject: [PATCH 091/137] Update cargo version to last master --- src/tools/cargotest/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargotest/main.rs b/src/tools/cargotest/main.rs index 83fd766c54739..2dc8837a7d878 100644 --- a/src/tools/cargotest/main.rs +++ b/src/tools/cargotest/main.rs @@ -25,7 +25,7 @@ const TEST_REPOS: &'static [Test] = &[ Test { name: "cargo", repo: "https://github.com/rust-lang/cargo", - sha: "2324c2bbaf7fc6ea9cbdd77c034ef1af769cb617", + sha: "38f52ea846db202f322071f00b083ae8defdda3a", lock: None, }, Test { From 2cc84df44cca1b6ab4b1f4d01a7680c72d7f20d9 Mon Sep 17 00:00:00 2001 From: Andrew Cann Date: Wed, 11 Jan 2017 15:58:37 +0800 Subject: [PATCH 092/137] Add warning for () to ! switch --- src/librustc/middle/mem_categorization.rs | 2 +- src/librustc/mir/tcx.rs | 5 +- src/librustc/traits/select.rs | 63 ++++++++++++++++--- src/librustc/traits/util.rs | 2 +- src/librustc/ty/contents.rs | 2 +- src/librustc/ty/context.rs | 13 ++-- src/librustc/ty/error.rs | 4 +- src/librustc/ty/fast_reject.rs | 2 +- src/librustc/ty/flags.rs | 2 +- src/librustc/ty/inhabitedness/mod.rs | 2 +- src/librustc/ty/item_path.rs | 6 +- src/librustc/ty/layout.rs | 4 +- src/librustc/ty/mod.rs | 23 ++++++- src/librustc/ty/relate.rs | 5 +- src/librustc/ty/structural_impls.rs | 4 +- src/librustc/ty/sty.rs | 10 ++- src/librustc/ty/util.rs | 6 +- src/librustc/ty/walk.rs | 2 +- src/librustc/ty/wf.rs | 2 +- src/librustc/util/ppaux.rs | 4 +- src/librustc_borrowck/borrowck/fragments.rs | 2 +- .../borrowck/mir/elaborate_drops.rs | 2 +- src/librustc_const_eval/_match.rs | 4 +- src/librustc_const_eval/pattern.rs | 2 +- src/librustc_driver/test.rs | 8 +-- src/librustc_lint/types.rs | 2 +- src/librustc_lint/unused.rs | 2 +- src/librustc_mir/build/expr/as_rvalue.rs | 2 +- src/librustc_mir/transform/type_check.rs | 2 +- src/librustc_save_analysis/dump_visitor.rs | 2 +- src/librustc_trans/abi.rs | 2 +- src/librustc_trans/adt.rs | 2 +- src/librustc_trans/callee.rs | 2 +- src/librustc_trans/collector.rs | 2 +- src/librustc_trans/common.rs | 2 +- src/librustc_trans/debuginfo/metadata.rs | 8 +-- src/librustc_trans/debuginfo/mod.rs | 4 +- src/librustc_trans/debuginfo/type_names.rs | 2 +- src/librustc_trans/glue.rs | 2 +- src/librustc_trans/mir/block.rs | 2 +- src/librustc_trans/mir/constant.rs | 2 +- src/librustc_trans/mir/mod.rs | 2 +- src/librustc_trans/mir/rvalue.rs | 2 +- src/librustc_trans/trans_item.rs | 2 +- src/librustc_trans/type_of.rs | 4 +- src/librustc_typeck/astconv.rs | 4 +- src/librustc_typeck/check/_match.rs | 4 +- src/librustc_typeck/check/closure.rs | 4 +- src/librustc_typeck/check/dropck.rs | 2 +- src/librustc_typeck/check/intrinsic.rs | 8 +-- src/librustc_typeck/check/mod.rs | 20 +++--- src/librustc_typeck/variance/constraints.rs | 2 +- src/librustdoc/clean/mod.rs | 8 +-- 53 files changed, 178 insertions(+), 105 deletions(-) diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 0e8e1921de700..9d1bcb8164a9e 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -1199,7 +1199,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { PatKind::Tuple(ref subpats, ddpos) => { // (p1, ..., pN) let expected_len = match self.pat_ty(&pat)?.sty { - ty::TyTuple(ref tys) => tys.len(), + ty::TyTuple(ref tys, _) => tys.len(), ref ty => span_bug!(pat.span, "tuple pattern unexpected type {:?}", ty), }; for (i, subpat) in subpats.iter().enumerate_and_adjust(expected_len, ddpos) { diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs index 03530945e046d..f1268521d6708 100644 --- a/src/librustc/mir/tcx.rs +++ b/src/librustc/mir/tcx.rs @@ -163,7 +163,7 @@ impl<'tcx> Rvalue<'tcx> { let lhs_ty = lhs.ty(mir, tcx); let rhs_ty = rhs.ty(mir, tcx); let ty = op.ty(tcx, lhs_ty, rhs_ty); - let ty = tcx.intern_tup(&[ty, tcx.types.bool]); + let ty = tcx.intern_tup(&[ty, tcx.types.bool], false); Some(ty) } &Rvalue::UnaryOp(_, ref operand) => { @@ -184,7 +184,8 @@ impl<'tcx> Rvalue<'tcx> { } AggregateKind::Tuple => { Some(tcx.mk_tup( - ops.iter().map(|op| op.ty(mir, tcx)) + ops.iter().map(|op| op.ty(mir, tcx)), + false )) } AggregateKind::Adt(def, _, substs, _) => { diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index d51332f833d77..451f075dfeed7 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -407,19 +407,66 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { debug!("select({:?})", obligation); assert!(!obligation.predicate.has_escaping_regions()); + let tcx = self.tcx(); let dep_node = obligation.predicate.dep_node(); - let _task = self.tcx().dep_graph.in_task(dep_node); + let _task = tcx.dep_graph.in_task(dep_node); let stack = self.push_stack(TraitObligationStackList::empty(), obligation); - match self.candidate_from_obligation(&stack)? { - None => Ok(None), + let ret = match self.candidate_from_obligation(&stack)? { + None => None, Some(candidate) => { let mut candidate = self.confirm_candidate(obligation, candidate)?; let inferred_obligations = (*self.inferred_obligations).into_iter().cloned(); candidate.nested_obligations_mut().extend(inferred_obligations); - Ok(Some(candidate)) + Some(candidate) }, + }; + + // Test whether this is a `()` which was produced by defaulting a + // diverging type variable with `!` disabled. If so, we may need + // to raise a warning. + if let ty::TyTuple(_, true) = obligation.predicate.skip_binder() + .self_ty().sty { + + let mut raise_warning = true; + // Don't raise a warning if the trait is implemented for ! and only + // permits a trivial implementation for !. This stops us warning + // about (for example) `(): Clone` becoming `!: Clone` because such + // a switch can't cause code to stop compiling or execute + // differently. + let mut never_obligation = obligation.clone(); + let def_id = never_obligation.predicate.skip_binder().trait_ref.def_id; + never_obligation.predicate = never_obligation.predicate.map_bound(|mut trait_pred| { + // Swap out () with ! so we can check if the trait is impld for ! + { + let mut trait_ref = &mut trait_pred.trait_ref; + let unit_substs = trait_ref.substs; + let mut never_substs = Vec::with_capacity(unit_substs.len()); + never_substs.push(From::from(tcx.types.never)); + never_substs.extend(&unit_substs[1..]); + trait_ref.substs = tcx.intern_substs(&never_substs); + } + trait_pred + }); + if let Ok(Some(..)) = self.select(&never_obligation) { + if !tcx.trait_relevant_for_never(def_id) { + // The trait is also implemented for ! and the resulting + // implementation cannot actually be invoked in any way. + raise_warning = false; + } + } + + if raise_warning { + let sess = tcx.sess; + let span = obligation.cause.span; + let mut warn = sess.struct_span_warn(span, "code relies on type inference rules \ + which are likely to change"); + warn.span_label(span, &"the type of this expression may change from () \ + to ! in a future version of Rust"); + warn.emit(); + } } + Ok(ret) } /////////////////////////////////////////////////////////////////////////// @@ -1744,7 +1791,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { ty::TyStr | ty::TySlice(_) | ty::TyDynamic(..) => Never, - ty::TyTuple(tys) => { + ty::TyTuple(tys, _) => { Where(ty::Binder(tys.last().into_iter().cloned().collect())) } @@ -1752,7 +1799,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { let sized_crit = def.sized_constraint(self.tcx()); // (*) binder moved here Where(ty::Binder(match sized_crit.sty { - ty::TyTuple(tys) => tys.to_vec().subst(self.tcx(), substs), + ty::TyTuple(tys, _) => tys.to_vec().subst(self.tcx(), substs), ty::TyBool => vec![], _ => vec![sized_crit.subst(self.tcx(), substs)] })) @@ -1799,7 +1846,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { Where(ty::Binder(vec![element_ty])) } - ty::TyTuple(tys) => { + ty::TyTuple(tys, _) => { // (*) binder moved here Where(ty::Binder(tys.to_vec())) } @@ -1874,7 +1921,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { vec![element_ty] } - ty::TyTuple(ref tys) => { + ty::TyTuple(ref tys, _) => { // (T1, ..., Tn) -- meets any bound that all of T1...Tn meet tys.to_vec() } diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs index cebd8bf87d736..7b2882bb64f2c 100644 --- a/src/librustc/traits/util.rs +++ b/src/librustc/traits/util.rs @@ -489,7 +489,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { let arguments_tuple = match tuple_arguments { TupleArgumentsFlag::No => sig.skip_binder().inputs()[0], TupleArgumentsFlag::Yes => - self.intern_tup(sig.skip_binder().inputs()), + self.intern_tup(sig.skip_binder().inputs(), false), }; let trait_ref = ty::TraitRef { def_id: fn_trait_def_id, diff --git a/src/librustc/ty/contents.rs b/src/librustc/ty/contents.rs index 00c6dca21b1ef..56621c57eb8f7 100644 --- a/src/librustc/ty/contents.rs +++ b/src/librustc/ty/contents.rs @@ -201,7 +201,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> { |ty| tc_ty(tcx, &ty, cache)) } - ty::TyTuple(ref tys) => { + ty::TyTuple(ref tys, _) => { TypeContents::union(&tys[..], |ty| tc_ty(tcx, *ty, cache)) } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index ce4a6a3182635..95751346908ec 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1379,23 +1379,24 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.mk_ty(TySlice(ty)) } - pub fn intern_tup(self, ts: &[Ty<'tcx>]) -> Ty<'tcx> { - self.mk_ty(TyTuple(self.intern_type_list(ts))) + pub fn intern_tup(self, ts: &[Ty<'tcx>], defaulted: bool) -> Ty<'tcx> { + self.mk_ty(TyTuple(self.intern_type_list(ts), defaulted)) } - pub fn mk_tup], Ty<'tcx>>>(self, iter: I) -> I::Output { - iter.intern_with(|ts| self.mk_ty(TyTuple(self.intern_type_list(ts)))) + pub fn mk_tup], Ty<'tcx>>>(self, iter: I, + defaulted: bool) -> I::Output { + iter.intern_with(|ts| self.mk_ty(TyTuple(self.intern_type_list(ts), defaulted))) } pub fn mk_nil(self) -> Ty<'tcx> { - self.intern_tup(&[]) + self.intern_tup(&[], false) } pub fn mk_diverging_default(self) -> Ty<'tcx> { if self.sess.features.borrow().never_type { self.types.never } else { - self.mk_nil() + self.intern_tup(&[], true) } } diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index 29d855a7fcb78..3ab3fc899e78c 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -178,7 +178,7 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> { match self.sty { ty::TyBool | ty::TyChar | ty::TyInt(_) | ty::TyUint(_) | ty::TyFloat(_) | ty::TyStr | ty::TyNever => self.to_string(), - ty::TyTuple(ref tys) if tys.is_empty() => self.to_string(), + ty::TyTuple(ref tys, _) if tys.is_empty() => self.to_string(), ty::TyAdt(def, _) => format!("{} `{}`", def.descr(), tcx.item_path_str(def.did)), ty::TyArray(_, n) => format!("array of {} elements", n), @@ -209,7 +209,7 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> { |p| format!("trait {}", tcx.item_path_str(p.def_id()))) } ty::TyClosure(..) => "closure".to_string(), - ty::TyTuple(_) => "tuple".to_string(), + ty::TyTuple(..) => "tuple".to_string(), ty::TyInfer(ty::TyVar(_)) => "inferred type".to_string(), ty::TyInfer(ty::IntVar(_)) => "integral variable".to_string(), ty::TyInfer(ty::FloatVar(_)) => "floating-point variable".to_string(), diff --git a/src/librustc/ty/fast_reject.rs b/src/librustc/ty/fast_reject.rs index 94b9abc72025f..981cf0897a034 100644 --- a/src/librustc/ty/fast_reject.rs +++ b/src/librustc/ty/fast_reject.rs @@ -72,7 +72,7 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, Some(ClosureSimplifiedType(def_id)) } ty::TyNever => Some(NeverSimplifiedType), - ty::TyTuple(ref tys) => { + ty::TyTuple(ref tys, _) => { Some(TupleSimplifiedType(tys.len())) } ty::TyFnDef(.., ref f) | ty::TyFnPtr(ref f) => { diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs index 0de77526b5a46..2012917f93a87 100644 --- a/src/librustc/ty/flags.rs +++ b/src/librustc/ty/flags.rs @@ -151,7 +151,7 @@ impl FlagComputation { self.add_ty(m.ty); } - &ty::TyTuple(ref ts) => { + &ty::TyTuple(ref ts, _) => { self.add_tys(&ts[..]); } diff --git a/src/librustc/ty/inhabitedness/mod.rs b/src/librustc/ty/inhabitedness/mod.rs index 6c49493a65559..18a3f1a218d85 100644 --- a/src/librustc/ty/inhabitedness/mod.rs +++ b/src/librustc/ty/inhabitedness/mod.rs @@ -178,7 +178,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { }, TyNever => DefIdForest::full(tcx), - TyTuple(ref tys) => { + TyTuple(ref tys, _) => { DefIdForest::union(tcx, tys.iter().map(|ty| { ty.uninhabited_from(visited, tcx) })) diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index b719911d18cf8..f45f00b4dec96 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -319,9 +319,9 @@ pub fn characteristic_def_id_of_type(ty: Ty) -> Option { ty::TyRawPtr(mt) | ty::TyRef(_, mt) => characteristic_def_id_of_type(mt.ty), - ty::TyTuple(ref tys) => tys.iter() - .filter_map(|ty| characteristic_def_id_of_type(ty)) - .next(), + ty::TyTuple(ref tys, _) => tys.iter() + .filter_map(|ty| characteristic_def_id_of_type(ty)) + .next(), ty::TyFnDef(def_id, ..) | ty::TyClosure(def_id, _) => Some(def_id), diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 78364abdaecba..a7351943dd7c4 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -792,7 +792,7 @@ impl<'a, 'gcx, 'tcx> Struct { Some(&variant.memory_index[..])) } // Can we use one of the fields in this tuple? - (&Univariant { ref variant, .. }, &ty::TyTuple(tys)) => { + (&Univariant { ref variant, .. }, &ty::TyTuple(tys, _)) => { Struct::non_zero_field_paths(infcx, tys.iter().cloned(), Some(&variant.memory_index[..])) } @@ -1158,7 +1158,7 @@ impl<'a, 'gcx, 'tcx> Layout { Univariant { variant: st, non_zero: false } } - ty::TyTuple(tys) => { + ty::TyTuple(tys, _) => { // FIXME(camlorn): if we ever allow unsized tuples, this needs to be checked. // See the univariant case below to learn how. let st = Struct::new(dl, diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 5ab45e746e7f2..978a8aa0fffee 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -197,6 +197,17 @@ impl AssociatedItem { AssociatedKind::Type => Def::AssociatedTy(self.def_id), } } + + /// Tests whether the associated item admits a non-trivial implementation + /// for ! + pub fn relevant_for_never<'tcx>(&self) -> bool { + match self.kind { + AssociatedKind::Const => true, + AssociatedKind::Type => true, + // TODO(canndrew): Be more thorough here, check if any argument is uninhabited. + AssociatedKind::Method => !self.method_has_self_argument, + } + } } #[derive(Clone, Debug, PartialEq, Eq, Copy, RustcEncodable, RustcDecodable)] @@ -1603,7 +1614,7 @@ impl<'a, 'gcx, 'tcx> AdtDef { _ if tys.references_error() => tcx.types.err, 0 => tcx.types.bool, 1 => tys[0], - _ => tcx.intern_tup(&tys[..]) + _ => tcx.intern_tup(&tys[..], false) }; let old = tcx.adt_sized_constraint.borrow().get(&self.did).cloned(); @@ -1638,7 +1649,7 @@ impl<'a, 'gcx, 'tcx> AdtDef { vec![ty] } - TyTuple(ref tys) => { + TyTuple(ref tys, _) => { match tys.last() { None => vec![], Some(ty) => self.sized_constraint_for_ty(tcx, stack, ty) @@ -1652,7 +1663,7 @@ impl<'a, 'gcx, 'tcx> AdtDef { .subst(tcx, substs); debug!("sized_constraint_for_ty({:?}) intermediate = {:?}", ty, adt_ty); - if let ty::TyTuple(ref tys) = adt_ty.sty { + if let ty::TyTuple(ref tys, _) = adt_ty.sty { tys.iter().flat_map(|ty| { self.sized_constraint_for_ty(tcx, stack, ty) }).collect() @@ -2010,6 +2021,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } + pub fn trait_relevant_for_never(self, did: DefId) -> bool { + self.associated_items(did).any(|item| { + item.relevant_for_never() + }) + } + pub fn custom_coerce_unsized_kind(self, did: DefId) -> adjustment::CustomCoerceUnsized { self.custom_coerce_unsized_kinds.memoize(did, || { let (kind, src) = if did.krate != LOCAL_CRATE { diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index 89514085e1c78..adedf78bba7c0 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -447,10 +447,11 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R, Ok(tcx.mk_slice(t)) } - (&ty::TyTuple(as_), &ty::TyTuple(bs)) => + (&ty::TyTuple(as_, a_defaulted), &ty::TyTuple(bs, b_defaulted)) => { if as_.len() == bs.len() { - Ok(tcx.mk_tup(as_.iter().zip(bs).map(|(a, b)| relation.relate(a, b)))?) + let defaulted = a_defaulted || b_defaulted; + Ok(tcx.mk_tup(as_.iter().zip(bs).map(|(a, b)| relation.relate(a, b)), defaulted)?) } else if !(as_.is_empty() || bs.is_empty()) { Err(TypeError::TupleSize( expected_found(relation, &as_.len(), &bs.len()))) diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 05f4abad46921..aa74e7cc0d043 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -474,7 +474,7 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { ty::TyAdt(tid, substs) => ty::TyAdt(tid, substs.fold_with(folder)), ty::TyDynamic(ref trait_ty, ref region) => ty::TyDynamic(trait_ty.fold_with(folder), region.fold_with(folder)), - ty::TyTuple(ts) => ty::TyTuple(ts.fold_with(folder)), + ty::TyTuple(ts, defaulted) => ty::TyTuple(ts.fold_with(folder), defaulted), ty::TyFnDef(def_id, substs, f) => { ty::TyFnDef(def_id, substs.fold_with(folder), @@ -511,7 +511,7 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { ty::TyAdt(_, substs) => substs.visit_with(visitor), ty::TyDynamic(ref trait_ty, ref reg) => trait_ty.visit_with(visitor) || reg.visit_with(visitor), - ty::TyTuple(ts) => ts.visit_with(visitor), + ty::TyTuple(ts, _) => ts.visit_with(visitor), ty::TyFnDef(_, substs, ref f) => { substs.visit_with(visitor) || f.visit_with(visitor) } diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 113534e4529cd..62b70d4420180 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -151,7 +151,11 @@ pub enum TypeVariants<'tcx> { TyNever, /// A tuple type. For example, `(i32, bool)`. - TyTuple(&'tcx Slice>), + /// The bool indicates whether this is a unit tuple and was created by + /// defaulting a diverging type variable with feature(never_type) disabled. + /// It's only purpose is for raising future-compatibility warnings for when + /// diverging type variables start defaulting to ! instead of (). + TyTuple(&'tcx Slice>, bool), /// The projection of an associated type. For example, /// `>::N`. @@ -961,7 +965,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { pub fn is_nil(&self) -> bool { match self.sty { - TyTuple(ref tys) => tys.is_empty(), + TyTuple(ref tys, _) => tys.is_empty(), _ => false } } @@ -1355,7 +1359,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { TySlice(_) | TyRawPtr(_) | TyNever | - TyTuple(_) | + TyTuple(..) | TyParam(_) | TyInfer(_) | TyError => { diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index ba49aa1ef4866..f667100465dac 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -207,7 +207,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // Don't use `struct_variant`, this may be a univariant enum. adt.variants[0].fields.get(i).map(|f| f.ty(self, substs)) } - (&TyTuple(ref v), None) => v.get(i).cloned(), + (&TyTuple(ref v, _), None) => v.get(i).cloned(), _ => None } } @@ -466,7 +466,7 @@ impl<'a, 'gcx, 'tcx, W> TypeVisitor<'tcx> for TypeIdHasher<'a, 'gcx, 'tcx, W> self.def_id(d); } } - TyTuple(tys) => { + TyTuple(tys, _) => { self.hash(tys.len()); } TyParam(p) => { @@ -675,7 +675,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> { seen: &mut Vec>, ty: Ty<'tcx>) -> Representability { match ty.sty { - TyTuple(ref ts) => { + TyTuple(ref ts, _) => { find_nonrepresentable(tcx, sp, seen, ts.iter().cloned()) } // Fixed-length vectors. diff --git a/src/librustc/ty/walk.rs b/src/librustc/ty/walk.rs index 0d1dc2e4d7c21..01f31e5024c0d 100644 --- a/src/librustc/ty/walk.rs +++ b/src/librustc/ty/walk.rs @@ -112,7 +112,7 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) { ty::TyClosure(_, ref substs) => { stack.extend(substs.substs.types().rev()); } - ty::TyTuple(ts) => { + ty::TyTuple(ts, _) => { stack.extend(ts.iter().cloned().rev()); } ty::TyFnDef(_, substs, ref ft) => { diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs index 33b70b09dcb7b..8a5bd6862cf45 100644 --- a/src/librustc/ty/wf.rs +++ b/src/librustc/ty/wf.rs @@ -315,7 +315,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { self.require_sized(subty, traits::SliceOrArrayElem); } - ty::TyTuple(ref tys) => { + ty::TyTuple(ref tys, _) => { if let Some((_last, rest)) = tys.split_last() { for elem in rest { self.require_sized(elem, traits::TupleElem); diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index aa2eb2955debe..5d6ee1a277a5f 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -156,7 +156,7 @@ pub fn parameterized(f: &mut fmt::Formatter, if !verbose && fn_trait_kind.is_some() && projections.len() == 1 { let projection_ty = projections[0].ty; - if let TyTuple(ref args) = substs.type_at(1).sty { + if let TyTuple(ref args, _) = substs.type_at(1).sty { return fn_sig(f, args, false, projection_ty); } } @@ -724,7 +724,7 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> { write!(f, "{}", tm) } TyNever => write!(f, "!"), - TyTuple(ref tys) => { + TyTuple(ref tys, _) => { write!(f, "(")?; let mut tys = tys.iter(); if let Some(&ty) = tys.next() { diff --git a/src/librustc_borrowck/borrowck/fragments.rs b/src/librustc_borrowck/borrowck/fragments.rs index 285f3ab9047c8..dbab3bca52b4e 100644 --- a/src/librustc_borrowck/borrowck/fragments.rs +++ b/src/librustc_borrowck/borrowck/fragments.rs @@ -423,7 +423,7 @@ fn add_fragment_siblings_for_extension<'a, 'tcx>(this: &MoveData<'tcx>, }; match parent_ty.sty { - ty::TyTuple(ref v) => { + ty::TyTuple(ref v, _) => { let tuple_idx = match *origin_field_name { mc::PositionalField(tuple_idx) => tuple_idx, mc::NamedField(_) => diff --git a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs index 9e89a3689c7ac..d2f744bde2d63 100644 --- a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs +++ b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs @@ -713,7 +713,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { let tys : Vec<_> = substs.upvar_tys(def_id, self.tcx).collect(); self.open_drop_for_tuple(c, &tys) } - ty::TyTuple(tys) => { + ty::TyTuple(tys, _) => { self.open_drop_for_tuple(c, tys) } ty::TyAdt(def, _) if def.is_box() => { diff --git a/src/librustc_const_eval/_match.rs b/src/librustc_const_eval/_match.rs index 94b2ba58c9aa5..7a64ff7114a7e 100644 --- a/src/librustc_const_eval/_match.rs +++ b/src/librustc_const_eval/_match.rs @@ -721,7 +721,7 @@ fn pat_constructors(_cx: &mut MatchCheckCtxt, fn constructor_arity(_cx: &MatchCheckCtxt, ctor: &Constructor, ty: Ty) -> usize { debug!("constructor_arity({:?}, {:?})", ctor, ty); match ty.sty { - ty::TyTuple(ref fs) => fs.len(), + ty::TyTuple(ref fs, _) => fs.len(), ty::TySlice(..) | ty::TyArray(..) => match *ctor { Slice(length) => length, ConstantValue(_) => 0, @@ -745,7 +745,7 @@ fn constructor_sub_pattern_tys<'a, 'tcx: 'a>(cx: &MatchCheckCtxt<'a, 'tcx>, { debug!("constructor_sub_pattern_tys({:?}, {:?})", ctor, ty); match ty.sty { - ty::TyTuple(ref fs) => fs.into_iter().map(|t| *t).collect(), + ty::TyTuple(ref fs, _) => fs.into_iter().map(|t| *t).collect(), ty::TySlice(ty) | ty::TyArray(ty, _) => match *ctor { Slice(length) => repeat(ty).take(length).collect(), ConstantValue(_) => vec![], diff --git a/src/librustc_const_eval/pattern.rs b/src/librustc_const_eval/pattern.rs index c6272613f4d09..609fb3e39d62c 100644 --- a/src/librustc_const_eval/pattern.rs +++ b/src/librustc_const_eval/pattern.rs @@ -342,7 +342,7 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { PatKind::Tuple(ref subpatterns, ddpos) => { let ty = self.tables.node_id_to_type(pat.id); match ty.sty { - ty::TyTuple(ref tys) => { + ty::TyTuple(ref tys, _) => { let subpatterns = subpatterns.iter() .enumerate_and_adjust(tys.len(), ddpos) diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index 1086d75f02cb4..41e5a4d53122f 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -280,7 +280,7 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> { } pub fn t_pair(&self, ty1: Ty<'tcx>, ty2: Ty<'tcx>) -> Ty<'tcx> { - self.infcx.tcx.intern_tup(&[ty1, ty2]) + self.infcx.tcx.intern_tup(&[ty1, ty2], false) } pub fn t_param(&self, index: u32) -> Ty<'tcx> { @@ -803,8 +803,8 @@ fn walk_ty() { let tcx = env.infcx.tcx; let int_ty = tcx.types.isize; let uint_ty = tcx.types.usize; - let tup1_ty = tcx.intern_tup(&[int_ty, uint_ty, int_ty, uint_ty]); - let tup2_ty = tcx.intern_tup(&[tup1_ty, tup1_ty, uint_ty]); + let tup1_ty = tcx.intern_tup(&[int_ty, uint_ty, int_ty, uint_ty], false); + let tup2_ty = tcx.intern_tup(&[tup1_ty, tup1_ty, uint_ty], false); let walked: Vec<_> = tup2_ty.walk().collect(); assert_eq!(walked, [tup2_ty, tup1_ty, int_ty, uint_ty, int_ty, uint_ty, tup1_ty, int_ty, @@ -818,7 +818,7 @@ fn walk_ty_skip_subtree() { let tcx = env.infcx.tcx; let int_ty = tcx.types.isize; let uint_ty = tcx.types.usize; - let tup1_ty = tcx.intern_tup(&[int_ty, uint_ty, int_ty, uint_ty]); + let tup1_ty = tcx.intern_tup(&[int_ty, uint_ty, int_ty, uint_ty], false); let tup2_ty = tcx.intern_tup(&[tup1_ty, tup1_ty, uint_ty]); // types we expect to see (in order), plus a boolean saying diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index 9669efa2d86b3..dc3fd3328a648 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -534,7 +534,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { consider using a `*const libc::c_char`") } - ty::TyTuple(_) => { + ty::TyTuple(..) => { FfiUnsafe("found Rust tuple type in foreign module; \ consider using a struct instead") } diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index a85b47c8ada7a..28ce9126019eb 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -141,7 +141,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults { let t = cx.tables.expr_ty(&expr); let warned = match t.sty { - ty::TyTuple(ref tys) if tys.is_empty() => return, + ty::TyTuple(ref tys, _) if tys.is_empty() => return, ty::TyNever => return, ty::TyBool => return, ty::TyAdt(def, _) => { diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index 48690a275c205..c212054205da5 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -258,7 +258,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let source_info = self.source_info(span); let bool_ty = self.hir.bool_ty(); if self.hir.check_overflow() && op.is_checkable() && ty.is_integral() { - let result_tup = self.hir.tcx().intern_tup(&[ty, bool_ty]); + let result_tup = self.hir.tcx().intern_tup(&[ty, bool_ty], false); let result_value = self.temp(result_tup); self.cfg.push_assign(block, source_info, diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs index c9195f29f1784..529fe564af02b 100644 --- a/src/librustc_mir/transform/type_check.rs +++ b/src/librustc_mir/transform/type_check.rs @@ -282,7 +282,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> { }) } } - ty::TyTuple(tys) => { + ty::TyTuple(tys, _) => { return match tys.get(field.index()) { Some(&ty) => Ok(ty), None => Err(FieldAccessError::OutOfRange { diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index f128167bbf621..41f91a1d2acc1 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -1440,7 +1440,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, }.lower(self.tcx)); } } - ty::TyTuple(_) => {} + ty::TyTuple(..) => {} _ => span_bug!(ex.span, "Expected struct or tuple type, found {:?}", ty), diff --git a/src/librustc_trans/abi.rs b/src/librustc_trans/abi.rs index d392ebaa33d42..a476b1d29e5fb 100644 --- a/src/librustc_trans/abi.rs +++ b/src/librustc_trans/abi.rs @@ -367,7 +367,7 @@ impl FnType { assert!(!sig.variadic && extra_args.is_empty()); match sig.inputs().last().unwrap().sty { - ty::TyTuple(ref tupled_arguments) => { + ty::TyTuple(ref tupled_arguments, _) => { inputs = &sig.inputs()[0..sig.inputs().len() - 1]; &tupled_arguments[..] } diff --git a/src/librustc_trans/adt.rs b/src/librustc_trans/adt.rs index c3b9a56ac9778..bc1e07e708c24 100644 --- a/src/librustc_trans/adt.rs +++ b/src/librustc_trans/adt.rs @@ -72,7 +72,7 @@ pub fn compute_fields<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>, monomorphize::field_ty(cx.tcx(), substs, f) }).collect::>() }, - ty::TyTuple(fields) => fields.to_vec(), + ty::TyTuple(fields, _) => fields.to_vec(), ty::TyClosure(def_id, substs) => { if variant_index > 0 { bug!("{} is a closure, which only has one variant", t);} substs.upvar_tys(def_id, cx.tcx()).collect() diff --git a/src/librustc_trans/callee.rs b/src/librustc_trans/callee.rs index 58d0c46850353..c6b86c6ba48de 100644 --- a/src/librustc_trans/callee.rs +++ b/src/librustc_trans/callee.rs @@ -485,7 +485,7 @@ fn trans_fn_pointer_shim<'a, 'tcx>( } }; let sig = tcx.erase_late_bound_regions_and_normalize(sig); - let tuple_input_ty = tcx.intern_tup(sig.inputs()); + let tuple_input_ty = tcx.intern_tup(sig.inputs(), false); let sig = tcx.mk_fn_sig( [bare_fn_ty_maybe_ref, tuple_input_ty].iter().cloned(), sig.output(), diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs index 392c270c130a8..89f5c00e9c11a 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans/collector.rs @@ -823,7 +823,7 @@ fn find_drop_glue_neighbors<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, output.push(TransItem::DropGlue(DropGlueKind::Ty(inner_type))); } } - ty::TyTuple(args) => { + ty::TyTuple(args, _) => { for arg in args { let arg = glue::get_drop_glue_type(scx, arg); if scx.type_needs_drop(arg) { diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs index 0ba94fdfe635c..98ea06c4cb278 100644 --- a/src/librustc_trans/common.rs +++ b/src/librustc_trans/common.rs @@ -95,7 +95,7 @@ pub fn type_pair_fields<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) } })) } - ty::TyTuple(tys) => { + ty::TyTuple(tys, _) => { if tys.len() != 2 { return None; } diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs index b7e319f2de434..c83e2f4854bf5 100644 --- a/src/librustc_trans/debuginfo/metadata.rs +++ b/src/librustc_trans/debuginfo/metadata.rs @@ -383,7 +383,7 @@ fn subroutine_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, // return type signature_metadata.push(match signature.output().sty { - ty::TyTuple(ref tys) if tys.is_empty() => ptr::null_mut(), + ty::TyTuple(ref tys, _) if tys.is_empty() => ptr::null_mut(), _ => type_metadata(cx, signature.output(), span) }); @@ -528,7 +528,7 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, ty::TyFloat(_) => { MetadataCreationResult::new(basic_type_metadata(cx, t), false) } - ty::TyTuple(ref elements) if elements.is_empty() => { + ty::TyTuple(ref elements, _) if elements.is_empty() => { MetadataCreationResult::new(basic_type_metadata(cx, t), false) } ty::TyArray(typ, len) => { @@ -603,7 +603,7 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, usage_site_span).finalize(cx) } }, - ty::TyTuple(ref elements) => { + ty::TyTuple(ref elements, _) => { prepare_tuple_metadata(cx, t, &elements[..], @@ -706,7 +706,7 @@ fn basic_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, let (name, encoding) = match t.sty { ty::TyNever => ("!", DW_ATE_unsigned), - ty::TyTuple(ref elements) if elements.is_empty() => + ty::TyTuple(ref elements, _) if elements.is_empty() => ("()", DW_ATE_unsigned), ty::TyBool => ("bool", DW_ATE_boolean), ty::TyChar => ("char", DW_ATE_unsigned_char), diff --git a/src/librustc_trans/debuginfo/mod.rs b/src/librustc_trans/debuginfo/mod.rs index e9468e56637d2..501f891befa8d 100644 --- a/src/librustc_trans/debuginfo/mod.rs +++ b/src/librustc_trans/debuginfo/mod.rs @@ -295,7 +295,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, // Return type -- llvm::DIBuilder wants this at index 0 signature.push(match sig.output().sty { - ty::TyTuple(ref tys) if tys.is_empty() => ptr::null_mut(), + ty::TyTuple(ref tys, _) if tys.is_empty() => ptr::null_mut(), _ => type_metadata(cx, sig.output(), syntax_pos::DUMMY_SP) }); @@ -311,7 +311,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, } if abi == Abi::RustCall && !sig.inputs().is_empty() { - if let ty::TyTuple(args) = sig.inputs()[sig.inputs().len() - 1].sty { + if let ty::TyTuple(args, _) = sig.inputs()[sig.inputs().len() - 1].sty { for &argument_type in args { signature.push(type_metadata(cx, argument_type, syntax_pos::DUMMY_SP)); } diff --git a/src/librustc_trans/debuginfo/type_names.rs b/src/librustc_trans/debuginfo/type_names.rs index 8e11bf6b8976a..018bbb6e97d34 100644 --- a/src/librustc_trans/debuginfo/type_names.rs +++ b/src/librustc_trans/debuginfo/type_names.rs @@ -48,7 +48,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, push_item_name(cx, def.did, qualified, output); push_type_params(cx, substs, output); }, - ty::TyTuple(component_types) => { + ty::TyTuple(component_types, _) => { output.push('('); for &component_type in component_types { push_debuginfo_type_name(cx, component_type, true, output); diff --git a/src/librustc_trans/glue.rs b/src/librustc_trans/glue.rs index 1415ca6029f53..fdefd37549ced 100644 --- a/src/librustc_trans/glue.rs +++ b/src/librustc_trans/glue.rs @@ -442,7 +442,7 @@ fn drop_structural_ty<'a, 'tcx>( cx = tvec::slice_for_each(&cx, ptr.llval, unit_ty, ptr.llextra, |bb, vv| drop_ty(bb, LvalueRef::new_sized_ty(vv, unit_ty))); } - ty::TyTuple(ref args) => { + ty::TyTuple(ref args, _) => { for (i, arg) in args.iter().enumerate() { let llfld_a = ptr.trans_field_ptr(&cx, i); drop_ty(&cx, LvalueRef::new_sized_ty(llfld_a, *arg)); diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs index 7d4a1ab5ae70e..027779aca63e4 100644 --- a/src/librustc_trans/mir/block.rs +++ b/src/librustc_trans/mir/block.rs @@ -695,7 +695,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { let tuple = self.trans_operand(bcx, operand); let arg_types = match tuple.ty.sty { - ty::TyTuple(ref tys) => tys, + ty::TyTuple(ref tys, _) => tys, _ => span_bug!(self.mir.span, "bad final argument to \"rust-call\" fn {:?}", tuple.ty) }; diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs index 9ac2bea3b82fb..d28133d982549 100644 --- a/src/librustc_trans/mir/constant.rs +++ b/src/librustc_trans/mir/constant.rs @@ -737,7 +737,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { let rhs = self.const_operand(rhs, span)?; let ty = lhs.ty; let val_ty = op.ty(tcx, lhs.ty, rhs.ty); - let binop_ty = tcx.intern_tup(&[val_ty, tcx.types.bool]); + let binop_ty = tcx.intern_tup(&[val_ty, tcx.types.bool], false); let (lhs, rhs) = (lhs.llval, rhs.llval); assert!(!ty.is_fp()); diff --git a/src/librustc_trans/mir/mod.rs b/src/librustc_trans/mir/mod.rs index 30c138310da9c..8a0a97a563439 100644 --- a/src/librustc_trans/mir/mod.rs +++ b/src/librustc_trans/mir/mod.rs @@ -384,7 +384,7 @@ fn arg_local_refs<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, // individual LLVM function arguments. let tupled_arg_tys = match arg_ty.sty { - ty::TyTuple(ref tys) => tys, + ty::TyTuple(ref tys, _) => tys, _ => bug!("spread argument isn't a tuple?!") }; diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs index 1b97a8d010cfe..81b241b485175 100644 --- a/src/librustc_trans/mir/rvalue.rs +++ b/src/librustc_trans/mir/rvalue.rs @@ -402,7 +402,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { lhs.immediate(), rhs.immediate(), lhs.ty); let val_ty = op.ty(bcx.tcx(), lhs.ty, rhs.ty); - let operand_ty = bcx.tcx().intern_tup(&[val_ty, bcx.tcx().types.bool]); + let operand_ty = bcx.tcx().intern_tup(&[val_ty, bcx.tcx().types.bool], false); let operand = OperandRef { val: result, ty: operand_ty diff --git a/src/librustc_trans/trans_item.rs b/src/librustc_trans/trans_item.rs index d58a93e3cb71c..04a6cb27501b3 100644 --- a/src/librustc_trans/trans_item.rs +++ b/src/librustc_trans/trans_item.rs @@ -409,7 +409,7 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { self.push_def_path(adt_def.did, output); self.push_type_params(substs, iter::empty(), output); }, - ty::TyTuple(component_types) => { + ty::TyTuple(component_types, _) => { output.push('('); for &component_type in component_types { self.push_type_name(component_type, output); diff --git a/src/librustc_trans/type_of.rs b/src/librustc_trans/type_of.rs index 4df0e989ada99..87af3b6c5e153 100644 --- a/src/librustc_trans/type_of.rs +++ b/src/librustc_trans/type_of.rs @@ -74,7 +74,7 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ Type::array(&llty, size) } - ty::TyTuple(ref tys) if tys.is_empty() => { + ty::TyTuple(ref tys, _) if tys.is_empty() => { Type::nil(cx) } @@ -276,7 +276,7 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> let sig = cx.tcx().erase_late_bound_regions_and_normalize(&f.sig); FnType::new(cx, f.abi, &sig, &[]).llvm_type(cx).ptr_to() } - ty::TyTuple(ref tys) if tys.is_empty() => Type::nil(cx), + ty::TyTuple(ref tys, _) if tys.is_empty() => Type::nil(cx), ty::TyTuple(..) => { adt::type_of(cx, t) } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index bb9a487802e7b..a3373f6da2852 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -421,7 +421,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { span: output_span }; - (self.tcx().mk_ty(ty::TyTuple(inputs)), output_binding) + (self.tcx().mk_ty(ty::TyTuple(inputs, false)), output_binding) } /// Instantiates the path for the given trait reference, assuming that it's @@ -1170,7 +1170,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { tcx.types.never }, hir::TyTup(ref fields) => { - tcx.mk_tup(fields.iter().map(|t| self.ast_ty_to_ty(&t))) + tcx.mk_tup(fields.iter().map(|t| self.ast_ty_to_ty(&t)), false) } hir::TyBareFn(ref bf) => { require_c_abi_if_variadic(tcx, &bf.decl, bf.abi, ast_ty.span); diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 932e7ae1dd426..feed5752cf8fb 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -164,7 +164,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let mut expected_len = elements.len(); if ddpos.is_some() { // Require known type only when `..` is present - if let ty::TyTuple(ref tys) = + if let ty::TyTuple(ref tys, _) = self.structurally_resolved_type(pat.span, expected).sty { expected_len = tys.len(); } @@ -176,7 +176,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // from all tuple elements isn't trivial. TypeVariableOrigin::TypeInference(pat.span))); let element_tys = tcx.mk_type_list(element_tys_iter); - let pat_ty = tcx.mk_ty(ty::TyTuple(element_tys)); + let pat_ty = tcx.mk_ty(ty::TyTuple(element_tys, false)); self.demand_eqtype(pat.span, expected, pat_ty); for (i, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) { self.check_pat(elem, &element_tys[i]); diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 2e6592b550179..7979edbf5e27a 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -89,7 +89,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Tuple up the arguments and insert the resulting function type into // the `closures` table. fn_ty.sig.0 = self.tcx.mk_fn_sig( - iter::once(self.tcx.intern_tup(fn_ty.sig.skip_binder().inputs())), + iter::once(self.tcx.intern_tup(fn_ty.sig.skip_binder().inputs(), false)), fn_ty.sig.skip_binder().output(), fn_ty.sig.variadic() ); @@ -218,7 +218,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { arg_param_ty); let input_tys = match arg_param_ty.sty { - ty::TyTuple(tys) => tys.into_iter(), + ty::TyTuple(tys, _) => tys.into_iter(), _ => { return None; } diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index 34aa4eda772ad..f701bc3220848 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -489,7 +489,7 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'b, 'gcx, 'tcx>( Ok(()) } - ty::TyTuple(tys) => { + ty::TyTuple(tys, _) => { for ty in tys { iterate_over_potentially_unsafe_regions_in_type(cx, context, ty, depth+1)? } diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index 7ead7ada893d7..cb4e85e842c2a 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -87,7 +87,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &hir::ForeignItem) { "cxchg" | "cxchgweak" => (1, vec![tcx.mk_mut_ptr(param(ccx, 0)), param(ccx, 0), param(ccx, 0)], - tcx.intern_tup(&[param(ccx, 0), tcx.types.bool])), + tcx.intern_tup(&[param(ccx, 0), tcx.types.bool], false)), "load" => (1, vec![tcx.mk_imm_ptr(param(ccx, 0))], param(ccx, 0)), "store" => (1, vec![tcx.mk_mut_ptr(param(ccx, 0)), param(ccx, 0)], @@ -272,7 +272,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &hir::ForeignItem) { "add_with_overflow" | "sub_with_overflow" | "mul_with_overflow" => (1, vec![param(ccx, 0), param(ccx, 0)], - tcx.intern_tup(&[param(ccx, 0), tcx.types.bool])), + tcx.intern_tup(&[param(ccx, 0), tcx.types.bool], false)), "unchecked_div" | "unchecked_rem" => (1, vec![param(ccx, 0), param(ccx, 0)], param(ccx, 0)), @@ -420,7 +420,7 @@ fn match_intrinsic_type_to_type<'tcx, 'a>( match *expected { Void => match t.sty { - ty::TyTuple(ref v) if v.is_empty() => {}, + ty::TyTuple(ref v, _) if v.is_empty() => {}, _ => simple_error(&format!("`{}`", t), "()"), }, // (The width we pass to LLVM doesn't concern the type checker.) @@ -494,7 +494,7 @@ fn match_intrinsic_type_to_type<'tcx, 'a>( } Aggregate(_flatten, ref expected_contents) => { match t.sty { - ty::TyTuple(contents) => { + ty::TyTuple(contents, _) => { if contents.len() != expected_contents.len() { simple_error(&format!("tuple with length {}", contents.len()), &format!("tuple with length {}", expected_contents.len())); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index c435f9341253e..0f429bd0c3aaa 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1940,7 +1940,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } /// Apply "fallbacks" to some types - /// ! gets replaced with (), unconstrained ints with i32, and unconstrained floats with f64. + /// unconstrained types get replaced with ! or () (depending on whether + /// feature(never_type) is enabled), unconstrained ints with i32, and + /// unconstrained floats with f64. fn default_type_parameters(&self) { use rustc::ty::error::UnconstrainedNumeric::Neither; use rustc::ty::error::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat}; @@ -2401,7 +2403,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let err_inputs = match tuple_arguments { DontTupleArguments => err_inputs, - TupleArguments => vec![self.tcx.intern_tup(&err_inputs[..])], + TupleArguments => vec![self.tcx.intern_tup(&err_inputs[..], false)], }; self.check_argument_types(sp, &err_inputs[..], &[], args_no_rcvr, @@ -2498,16 +2500,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let formal_tys = if tuple_arguments == TupleArguments { let tuple_type = self.structurally_resolved_type(sp, fn_inputs[0]); match tuple_type.sty { - ty::TyTuple(arg_types) if arg_types.len() != args.len() => { + ty::TyTuple(arg_types, _) if arg_types.len() != args.len() => { parameter_count_error(tcx.sess, sp_args, arg_types.len(), args.len(), "E0057", false, def_span); expected_arg_tys = &[]; self.err_args(args.len()) } - ty::TyTuple(arg_types) => { + ty::TyTuple(arg_types, _) => { expected_arg_tys = match expected_arg_tys.get(0) { Some(&ty) => match ty.sty { - ty::TyTuple(ref tys) => &tys, + ty::TyTuple(ref tys, _) => &tys, _ => &[] }, None => &[] @@ -3065,7 +3067,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } }) } - ty::TyTuple(ref v) => { + ty::TyTuple(ref v, _) => { tuple_like = true; v.get(idx.node).cloned() } @@ -3857,7 +3859,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { hir::ExprTup(ref elts) => { let flds = expected.only_has_type(self).and_then(|ty| { match ty.sty { - ty::TyTuple(ref flds) => Some(&flds[..]), + ty::TyTuple(ref flds, _) => Some(&flds[..]), _ => None } }); @@ -3875,7 +3877,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }; t }); - let tuple = tcx.mk_tup(elt_ts_iter); + let tuple = tcx.mk_tup(elt_ts_iter, false); if tuple.references_error() { tcx.types.err } else { @@ -3916,7 +3918,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }, base_t); // Try to give some advice about indexing tuples. - if let ty::TyTuple(_) = base_t.sty { + if let ty::TyTuple(..) = base_t.sty { let mut needs_note = true; // If the index is an integer, we can show the actual // fixed expression: diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index 40e82959336de..860f6d98370ad 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -338,7 +338,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { self.add_constraints_from_mt(generics, mt, variance); } - ty::TyTuple(subtys) => { + ty::TyTuple(subtys, _) => { for &subty in subtys { self.add_constraints_from_ty(generics, subty, variance); } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index cdb24a56367fc..fea92d9517c24 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -649,7 +649,7 @@ fn external_path_params(cx: &DocContext, trait_did: Option, has_self: boo Some(did) if cx.tcx.lang_items.fn_trait_kind(did).is_some() => { assert_eq!(types.len(), 1); let inputs = match types[0].sty { - ty::TyTuple(ref tys) => tys.iter().map(|t| t.clean(cx)).collect(), + ty::TyTuple(ref tys, _) => tys.iter().map(|t| t.clean(cx)).collect(), _ => { return PathParameters::AngleBracketed { lifetimes: lifetimes, @@ -661,7 +661,7 @@ fn external_path_params(cx: &DocContext, trait_did: Option, has_self: boo let output = None; // FIXME(#20299) return type comes from a projection now // match types[1].sty { - // ty::TyTuple(ref v) if v.is_empty() => None, // -> () + // ty::TyTuple(ref v, _) if v.is_empty() => None, // -> () // _ => Some(types[1].clean(cx)) // }; PathParameters::Parenthesized { @@ -704,7 +704,7 @@ impl<'tcx> Clean for ty::TraitRef<'tcx> { // collect any late bound regions let mut late_bounds = vec![]; for ty_s in self.input_types().skip(1) { - if let ty::TyTuple(ts) = ty_s.sty { + if let ty::TyTuple(ts, _) = ty_s.sty { for &ty_s in ts { if let ty::TyRef(ref reg, _) = ty_s.sty { if let &ty::Region::ReLateBound(..) = *reg { @@ -1889,7 +1889,7 @@ impl<'tcx> Clean for ty::Ty<'tcx> { Never } } - ty::TyTuple(ref t) => Tuple(t.clean(cx)), + ty::TyTuple(ref t, _) => Tuple(t.clean(cx)), ty::TyProjection(ref data) => data.clean(cx), From c570cd663601694b017bc3c739bb9c260c88324b Mon Sep 17 00:00:00 2001 From: Andrew Cann Date: Thu, 12 Jan 2017 15:36:37 +0800 Subject: [PATCH 093/137] Fix make tidy --- src/librustc/ty/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 978a8aa0fffee..c9ae3b3df028c 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -204,7 +204,7 @@ impl AssociatedItem { match self.kind { AssociatedKind::Const => true, AssociatedKind::Type => true, - // TODO(canndrew): Be more thorough here, check if any argument is uninhabited. + // FIXME(canndrew): Be more thorough here, check if any argument is uninhabited. AssociatedKind::Method => !self.method_has_self_argument, } } From 5dbaefb608ac71afedadd9810e0bba6348e27c6a Mon Sep 17 00:00:00 2001 From: Andrew Cann Date: Fri, 13 Jan 2017 00:50:15 +0800 Subject: [PATCH 094/137] Hash TyTuple's defaulted flag --- src/librustc/ty/util.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index f667100465dac..b01b77bbcf8a5 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -466,8 +466,9 @@ impl<'a, 'gcx, 'tcx, W> TypeVisitor<'tcx> for TypeIdHasher<'a, 'gcx, 'tcx, W> self.def_id(d); } } - TyTuple(tys, _) => { + TyTuple(tys, defaulted) => { self.hash(tys.len()); + self.hash(defaulted); } TyParam(p) => { self.hash(p.idx); From 085f046c280639ce2f545108740d02c8a470cdd6 Mon Sep 17 00:00:00 2001 From: Andrew Cann Date: Sat, 21 Jan 2017 14:02:43 +0800 Subject: [PATCH 095/137] Add is_defaulted_unit helper method --- src/librustc/traits/select.rs | 4 +--- src/librustc/ty/sty.rs | 9 +++++++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 451f075dfeed7..d5efc8f18939e 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -425,9 +425,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // Test whether this is a `()` which was produced by defaulting a // diverging type variable with `!` disabled. If so, we may need // to raise a warning. - if let ty::TyTuple(_, true) = obligation.predicate.skip_binder() - .self_ty().sty { - + if obligation.predicate.skip_binder().self_ty().is_defaulted_unit() { let mut raise_warning = true; // Don't raise a warning if the trait is implemented for ! and only // permits a trivial implementation for !. This stops us warning diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 62b70d4420180..9bba4c6e37a69 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -977,6 +977,15 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { } } + // Test whether this is a `()` which was produced by defaulting a + // diverging type variable with feature(never_type) disabled. + pub fn is_defaulted_unit(&self) -> bool { + match self.sty { + TyTuple(_, true) => true, + _ => false, + } + } + /// Checks whether a type is visibly uninhabited from a particular module. /// # Example /// ```rust From 5c90dd797883ad2084e8bbc92420b42b9f7fb7d7 Mon Sep 17 00:00:00 2001 From: Andrew Cann Date: Sat, 21 Jan 2017 15:15:23 +0800 Subject: [PATCH 096/137] Use a proper future-compatibility lint --- src/librustc/lint/builtin.rs | 8 ++++++ src/librustc/traits/select.rs | 13 +++++----- src/librustc_lint/lib.rs | 4 +++ .../compile-fail/defaulted-unit-warning.rs | 26 +++++++++++++++++++ 4 files changed, 44 insertions(+), 7 deletions(-) create mode 100644 src/test/compile-fail/defaulted-unit-warning.rs diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index e1605959922c0..70f03e02f46d9 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -192,6 +192,13 @@ declare_lint! { "lifetimes or labels named `'_` were erroneously allowed" } +declare_lint! { + pub RESOLVE_TRAIT_ON_DEFAULTED_UNIT, + Warn, + "attempt to resolve a trait on an expression whose type cannot be inferred but which \ + currently defaults to ()" +} + declare_lint! { pub SAFE_EXTERN_STATICS, Warn, @@ -272,6 +279,7 @@ impl LintPass for HardwiredLints { SUPER_OR_SELF_IN_GLOBAL_PATH, HR_LIFETIME_IN_ASSOC_TYPE, LIFETIME_UNDERSCORE, + RESOLVE_TRAIT_ON_DEFAULTED_UNIT, SAFE_EXTERN_STATICS, PATTERNS_IN_FNS_WITHOUT_BODY, EXTRA_REQUIREMENT_IN_IMPL, diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index d5efc8f18939e..41f3f825c3d19 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -52,6 +52,7 @@ use std::mem; use std::rc::Rc; use syntax::abi::Abi; use hir; +use lint; use util::nodemap::FxHashMap; struct InferredObligationsSnapshotVecDelegate<'tcx> { @@ -455,13 +456,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } if raise_warning { - let sess = tcx.sess; - let span = obligation.cause.span; - let mut warn = sess.struct_span_warn(span, "code relies on type inference rules \ - which are likely to change"); - warn.span_label(span, &"the type of this expression may change from () \ - to ! in a future version of Rust"); - warn.emit(); + tcx.sess.add_lint(lint::builtin::RESOLVE_TRAIT_ON_DEFAULTED_UNIT, + obligation.cause.body_id, + obligation.cause.span, + format!("code relies on type inference rules which are likely \ + to change")); } } Ok(ret) diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 18067cb86739b..81ba49f56f050 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -220,6 +220,10 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { id: LintId::of(LIFETIME_UNDERSCORE), reference: "issue #36892 ", }, + FutureIncompatibleInfo { + id: LintId::of(RESOLVE_TRAIT_ON_DEFAULTED_UNIT), + reference: "issue #39216 ", + }, FutureIncompatibleInfo { id: LintId::of(SAFE_EXTERN_STATICS), reference: "issue #36247 ", diff --git a/src/test/compile-fail/defaulted-unit-warning.rs b/src/test/compile-fail/defaulted-unit-warning.rs new file mode 100644 index 0000000000000..7a15ac025ef85 --- /dev/null +++ b/src/test/compile-fail/defaulted-unit-warning.rs @@ -0,0 +1,26 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![deny(resolve_trait_on_defaulted_unit)] + +trait Deserialize { + fn deserialize() -> Result +} + +fn doit() -> Result<(), String> { + let _ = Deserialize::deserialize()?; + //~^ ERROR attempt to resolve a trait + Ok(()) +} + +fn main() { + doit(); +} + From 6a99573513054ec3839a75174e084351e2da87fc Mon Sep 17 00:00:00 2001 From: Andrew Cann Date: Sat, 21 Jan 2017 16:03:28 +0800 Subject: [PATCH 097/137] Fix test --- src/test/compile-fail/defaulted-unit-warning.rs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/test/compile-fail/defaulted-unit-warning.rs b/src/test/compile-fail/defaulted-unit-warning.rs index 7a15ac025ef85..e48ff2bbcdb42 100644 --- a/src/test/compile-fail/defaulted-unit-warning.rs +++ b/src/test/compile-fail/defaulted-unit-warning.rs @@ -10,17 +10,24 @@ #![deny(resolve_trait_on_defaulted_unit)] -trait Deserialize { - fn deserialize() -> Result +trait Deserialize: Sized { + fn deserialize() -> Result; +} + +impl Deserialize for () { + fn deserialize() -> Result<(), String> { + Ok(()) + } } fn doit() -> Result<(), String> { let _ = Deserialize::deserialize()?; - //~^ ERROR attempt to resolve a trait + //~^ ERROR code relies on type + //~| WARNING previously accepted Ok(()) } fn main() { - doit(); + let _ = doit(); } From 40c9538d2cb391e6be11cb7c9ede9f302bef3d59 Mon Sep 17 00:00:00 2001 From: Andrew Cann Date: Sun, 29 Jan 2017 23:49:01 +0800 Subject: [PATCH 098/137] Fix test --- src/test/compile-fail/defaulted-unit-warning.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/test/compile-fail/defaulted-unit-warning.rs b/src/test/compile-fail/defaulted-unit-warning.rs index e48ff2bbcdb42..2b6bd01f907c1 100644 --- a/src/test/compile-fail/defaulted-unit-warning.rs +++ b/src/test/compile-fail/defaulted-unit-warning.rs @@ -21,9 +21,12 @@ impl Deserialize for () { } fn doit() -> Result<(), String> { - let _ = Deserialize::deserialize()?; - //~^ ERROR code relies on type - //~| WARNING previously accepted + let _ = match Deserialize::deserialize() { + //~^ ERROR code relies on type + //~| WARNING previously accepted + Ok(x) => x, + Err(e) => return Err(e), + }; Ok(()) } From ef9ae8581ff17dd88eb0260076bfe80d8d9c4aba Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 3 Feb 2017 06:08:16 -0500 Subject: [PATCH 099/137] make dirty process O(dirty) The old algorithm was O(graph) --- src/librustc_incremental/persist/data.rs | 17 +++-- src/librustc_incremental/persist/load.rs | 92 ++++++++++++++---------- src/librustc_incremental/persist/save.rs | 7 +- 3 files changed, 66 insertions(+), 50 deletions(-) diff --git a/src/librustc_incremental/persist/data.rs b/src/librustc_incremental/persist/data.rs index f0e4f4f99ef08..60f24b71de245 100644 --- a/src/librustc_incremental/persist/data.rs +++ b/src/librustc_incremental/persist/data.rs @@ -21,7 +21,7 @@ use super::directory::DefPathIndex; /// Data for use when recompiling the **current crate**. #[derive(Debug, RustcEncodable, RustcDecodable)] pub struct SerializedDepGraph { - pub edges: Vec, + pub edges: Vec, /// These are hashes of two things: /// - the HIR nodes in this crate @@ -45,14 +45,13 @@ pub struct SerializedDepGraph { pub hashes: Vec, } -/// Represents a "reduced" dependency edge. Unlike the full dep-graph, -/// the dep-graph we serialize contains only edges `S -> T` where the -/// source `S` is something hashable (a HIR node or foreign metadata) -/// and the target `T` is something significant, like a work-product. -/// Normally, significant nodes are only those that have saved data on -/// disk, but in unit-testing the set of significant nodes can be -/// increased. -pub type SerializedEdge = (DepNode, DepNode); +/// Represents a set of "reduced" dependency edge. We group the +/// outgoing edges from a single source together. +#[derive(Debug, RustcEncodable, RustcDecodable)] +pub struct SerializedEdgeSet { + pub source: DepNode, + pub targets: Vec> +} #[derive(Debug, RustcEncodable, RustcDecodable)] pub struct SerializedHash { diff --git a/src/librustc_incremental/persist/load.rs b/src/librustc_incremental/persist/load.rs index e9a59fd762972..b371ab6aa31bc 100644 --- a/src/librustc_incremental/persist/load.rs +++ b/src/librustc_incremental/persist/load.rs @@ -152,6 +152,11 @@ pub fn decode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let directory = DefIdDirectory::decode(&mut dep_graph_decoder)?; let serialized_dep_graph = SerializedDepGraph::decode(&mut dep_graph_decoder)?; + let edge_map: FxHashMap<_, _> = serialized_dep_graph.edges + .into_iter() + .map(|s| (s.source, s.targets)) + .collect(); + // Retrace the paths in the directory to find their current location (if any). let retraced = directory.retrace(tcx); @@ -166,46 +171,48 @@ pub fn decode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, incremental_hashes_map, &serialized_dep_graph.hashes, &retraced); - let dirty_raw_nodes = transitive_dirty_nodes(&serialized_dep_graph.edges, dirty_raw_nodes); + let dirty_raw_nodes = transitive_dirty_nodes(&edge_map, dirty_raw_nodes); // Recreate the edges in the graph that are still clean. let mut clean_work_products = FxHashSet(); let mut dirty_work_products = FxHashSet(); // incomplete; just used to suppress debug output - for edge in &serialized_dep_graph.edges { - // If the target is dirty, skip the edge. If this is an edge - // that targets a work-product, we can print the blame - // information now. - if let Some(blame) = dirty_raw_nodes.get(&edge.1) { - if let DepNode::WorkProduct(ref wp) = edge.1 { - if tcx.sess.opts.debugging_opts.incremental_info { - if dirty_work_products.insert(wp.clone()) { - // It'd be nice to pretty-print these paths better than just - // using the `Debug` impls, but wev. - println!("incremental: module {:?} is dirty because {:?} \ - changed or was removed", - wp, - blame.map_def(|&index| { - Some(directory.def_path_string(tcx, index)) - }).unwrap()); + for (source, targets) in &edge_map { + for target in targets { + // If the target is dirty, skip the edge. If this is an edge + // that targets a work-product, we can print the blame + // information now. + if let Some(blame) = dirty_raw_nodes.get(target) { + if let DepNode::WorkProduct(ref wp) = *target { + if tcx.sess.opts.debugging_opts.incremental_info { + if dirty_work_products.insert(wp.clone()) { + // It'd be nice to pretty-print these paths better than just + // using the `Debug` impls, but wev. + println!("incremental: module {:?} is dirty because {:?} \ + changed or was removed", + wp, + blame.map_def(|&index| { + Some(directory.def_path_string(tcx, index)) + }).unwrap()); + } } } + continue; } - continue; - } - // If the source is dirty, the target will be dirty. - assert!(!dirty_raw_nodes.contains_key(&edge.0)); - - // Retrace the source -> target edges to def-ids and then - // create an edge in the graph. Retracing may yield none if - // some of the data happens to have been removed; this ought - // to be impossible unless it is dirty, so we can unwrap. - let source_node = retraced.map(&edge.0).unwrap(); - let target_node = retraced.map(&edge.1).unwrap(); - let _task = tcx.dep_graph.in_task(target_node); - tcx.dep_graph.read(source_node); - if let DepNode::WorkProduct(ref wp) = edge.1 { - clean_work_products.insert(wp.clone()); + // If the source is dirty, the target will be dirty. + assert!(!dirty_raw_nodes.contains_key(source)); + + // Retrace the source -> target edges to def-ids and then + // create an edge in the graph. Retracing may yield none if + // some of the data happens to have been removed; this ought + // to be impossible unless it is dirty, so we can unwrap. + let source_node = retraced.map(source).unwrap(); + let target_node = retraced.map(target).unwrap(); + let _task = tcx.dep_graph.in_task(target_node); + tcx.dep_graph.read(source_node); + if let DepNode::WorkProduct(ref wp) = *target { + clean_work_products.insert(wp.clone()); + } } } @@ -268,16 +275,23 @@ fn initial_dirty_nodes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, dirty_nodes } -fn transitive_dirty_nodes(edges: &[SerializedEdge], +fn transitive_dirty_nodes(edge_map: &FxHashMap, Vec>>, mut dirty_nodes: DirtyNodes) -> DirtyNodes { - let mut len = 0; - while len != dirty_nodes.len() { - len = dirty_nodes.len(); - for edge in edges { - if let Some(n) = dirty_nodes.get(&edge.0).cloned() { - dirty_nodes.insert(edge.1.clone(), n); + let mut stack: Vec<(DepNode, DepNode)> = vec![]; + stack.extend(dirty_nodes.iter().map(|(s, b)| (s.clone(), b.clone()))); + while let Some((source, blame)) = stack.pop() { + // we know the source is dirty (because of the node `blame`)... + assert!(dirty_nodes.contains_key(&source)); + + // ...so we dirty all the targets (with the same blame) + if let Some(targets) = edge_map.get(&source) { + for target in targets { + if !dirty_nodes.contains_key(target) { + dirty_nodes.insert(target.clone(), blame.clone()); + stack.push((target.clone(), blame.clone())); + } } } } diff --git a/src/librustc_incremental/persist/save.rs b/src/librustc_incremental/persist/save.rs index 80f51700d60e4..93600631b8d3e 100644 --- a/src/librustc_incremental/persist/save.rs +++ b/src/librustc_incremental/persist/save.rs @@ -178,7 +178,7 @@ pub fn encode_dep_graph(preds: &Predecessors, // Create a flat list of (Input, WorkProduct) edges for // serialization. - let mut edges = vec![]; + let mut edges = FxHashMap(); for edge in preds.reduced_graph.all_edges() { let source = *preds.reduced_graph.node_data(edge.source()); let target = *preds.reduced_graph.node_data(edge.target()); @@ -194,7 +194,7 @@ pub fn encode_dep_graph(preds: &Predecessors, debug!("serialize edge: {:?} -> {:?}", source, target); let source = builder.map(source); let target = builder.map(target); - edges.push((source, target)); + edges.entry(source).or_insert(vec![]).push(target); } if tcx.sess.opts.debugging_opts.incremental_dump_hash { @@ -204,6 +204,9 @@ pub fn encode_dep_graph(preds: &Predecessors, } // Create the serialized dep-graph. + let edges = edges.into_iter() + .map(|(k, v)| SerializedEdgeSet { source: k, targets: v }) + .collect(); let graph = SerializedDepGraph { edges: edges, hashes: preds.hashes From afbf6c82464b6cf0e0b77d3f8458ae31ac38fd6e Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 3 Feb 2017 06:09:47 -0500 Subject: [PATCH 100/137] s/in_index/input_index/ --- .../persist/preds/compress/dag_id.rs | 4 ++-- src/librustc_incremental/persist/preds/compress/mod.rs | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/librustc_incremental/persist/preds/compress/dag_id.rs b/src/librustc_incremental/persist/preds/compress/dag_id.rs index 5ebabc98fda94..c79930bfae513 100644 --- a/src/librustc_incremental/persist/preds/compress/dag_id.rs +++ b/src/librustc_incremental/persist/preds/compress/dag_id.rs @@ -7,11 +7,11 @@ pub struct DagId { } impl DagId { - pub fn from_in_index(n: NodeIndex) -> Self { + pub fn from_input_index(n: NodeIndex) -> Self { DagId { index: n.0 as u32 } } - pub fn as_in_index(&self) -> NodeIndex { + pub fn as_input_index(&self) -> NodeIndex { NodeIndex(self.index as usize) } } diff --git a/src/librustc_incremental/persist/preds/compress/mod.rs b/src/librustc_incremental/persist/preds/compress/mod.rs index ecd6d72e22d50..974a2221a4575 100644 --- a/src/librustc_incremental/persist/preds/compress/mod.rs +++ b/src/librustc_incremental/persist/preds/compress/mod.rs @@ -89,7 +89,7 @@ impl<'q, N, I, O> GraphReduce<'q, N, I, O> // correspond to the indices from the input graph for i in 0..in_graph.len_nodes() { let k = unify.new_key(()); - assert!(k == DagId::from_in_index(NodeIndex(i))); + assert!(k == DagId::from_input_index(NodeIndex(i))); } GraphReduce { in_graph, unify, is_input, is_output } @@ -105,8 +105,8 @@ impl<'q, N, I, O> GraphReduce<'q, N, I, O> } fn mark_cycle(&mut self, in_node1: NodeIndex, in_node2: NodeIndex) { - let dag_id1 = DagId::from_in_index(in_node1); - let dag_id2 = DagId::from_in_index(in_node2); + let dag_id1 = DagId::from_input_index(in_node1); + let dag_id2 = DagId::from_input_index(in_node2); self.unify.union(dag_id1, dag_id2); } @@ -114,8 +114,8 @@ impl<'q, N, I, O> GraphReduce<'q, N, I, O> /// be a no-op unless `in_node` participates in a cycle, in which /// case a distinct node *may* be returned. fn cycle_head(&mut self, in_node: NodeIndex) -> NodeIndex { - let i = DagId::from_in_index(in_node); - self.unify.find(i).as_in_index() + let i = DagId::from_input_index(in_node); + self.unify.find(i).as_input_index() } #[cfg(test)] From b7f1d7a4bdf1a06d4ac1fc1d01eb7568608351a0 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 3 Feb 2017 13:55:18 +0100 Subject: [PATCH 101/137] Update to last cargo version --- src/tools/cargotest/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargotest/main.rs b/src/tools/cargotest/main.rs index 2dc8837a7d878..786b3192e0675 100644 --- a/src/tools/cargotest/main.rs +++ b/src/tools/cargotest/main.rs @@ -25,7 +25,7 @@ const TEST_REPOS: &'static [Test] = &[ Test { name: "cargo", repo: "https://github.com/rust-lang/cargo", - sha: "38f52ea846db202f322071f00b083ae8defdda3a", + sha: "0e1e34be7540bdaed4918457654fbf028cf69e56", lock: None, }, Test { From 3c020df3e905f6486fb793a0c41f3ac63f3aa255 Mon Sep 17 00:00:00 2001 From: Son Date: Sat, 4 Feb 2017 00:16:56 +1100 Subject: [PATCH 102/137] tiny doc wording change --- src/libstd/sync/condvar.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/sync/condvar.rs b/src/libstd/sync/condvar.rs index 8ab30c51b282e..5c85c4879a839 100644 --- a/src/libstd/sync/condvar.rs +++ b/src/libstd/sync/condvar.rs @@ -36,7 +36,7 @@ impl WaitTimeoutResult { /// consumes no CPU time while waiting for an event to occur. Condition /// variables are typically associated with a boolean predicate (a condition) /// and a mutex. The predicate is always verified inside of the mutex before -/// determining that thread must block. +/// determining that a thread must block. /// /// Functions in this module will block the current **thread** of execution and /// are bindings to system-provided condition variables where possible. Note From 7abab8aee09cdc8d23ec8fae5b5ec7675486aef0 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 3 Feb 2017 12:42:18 -0500 Subject: [PATCH 103/137] add a comment about optimality that somehow got removed --- .../persist/preds/compress/construct.rs | 12 ++ .../persist/preds/compress/test.rs | 122 +++++++++--------- 2 files changed, 76 insertions(+), 58 deletions(-) diff --git a/src/librustc_incremental/persist/preds/compress/construct.rs b/src/librustc_incremental/persist/preds/compress/construct.rs index b0dcb63758e8c..965c773597ede 100644 --- a/src/librustc_incremental/persist/preds/compress/construct.rs +++ b/src/librustc_incremental/persist/preds/compress/construct.rs @@ -78,6 +78,18 @@ pub(super) fn construct_graph<'g, N, I, O>(r: &mut GraphReduce<'g, N, I, O>, dag // // Now if we were to remove Y, we would have a total of 8 edges: both WP0 and WP1 // depend on INPUT0...INPUT3. As it is, we have 6 edges. + // + // NB: The current rules are not optimal. For example, given this + // input graph: + // + // OUT0 -rf-> X + // OUT1 -rf-> X + // X -rf -> INPUT0 + // + // we will preserve X because it has two "consumers" (OUT0 and + // OUT1). We could as easily skip it, but we'd have to tally up + // the number of input nodes that it (transitively) reaches, and I + // was too lazy to do so. This is the unit test `suboptimal`. let mut retain_map = FxHashMap(); let mut new_graph = Graph::new(); diff --git a/src/librustc_incremental/persist/preds/compress/test.rs b/src/librustc_incremental/persist/preds/compress/test.rs index 6ac834ee53fbc..be91677f4d14b 100644 --- a/src/librustc_incremental/persist/preds/compress/test.rs +++ b/src/librustc_incremental/persist/preds/compress/test.rs @@ -151,62 +151,69 @@ fn test3() { ]); } -//#[test] -//fn test_cached_dfs_cyclic() { -// -// // 0 1 <---- 2 3 -// // ^ | ^ ^ -// // | v | | -// // 4 ----> 5 ----> 6 ----> 7 -// // ^ ^ ^ ^ -// // | | | | -// // 8 9 10 11 -// -// -// let mut g: Graph = Graph::new(); -// g.add_node(false); -// g.add_node(false); -// g.add_node(false); -// g.add_node(false); -// g.add_node(false); -// g.add_node(false); -// g.add_node(false); -// g.add_node(false); -// g.add_node(true); -// g.add_node(true); -// g.add_node(true); -// g.add_node(true); -// -// g.add_edge(NodeIndex( 4), NodeIndex(0), ()); -// g.add_edge(NodeIndex( 8), NodeIndex(4), ()); -// g.add_edge(NodeIndex( 4), NodeIndex(5), ()); -// g.add_edge(NodeIndex( 1), NodeIndex(5), ()); -// g.add_edge(NodeIndex( 9), NodeIndex(5), ()); -// g.add_edge(NodeIndex( 5), NodeIndex(6), ()); -// g.add_edge(NodeIndex( 6), NodeIndex(2), ()); -// g.add_edge(NodeIndex( 2), NodeIndex(1), ()); -// g.add_edge(NodeIndex(10), NodeIndex(6), ()); -// g.add_edge(NodeIndex( 6), NodeIndex(7), ()); -// g.add_edge(NodeIndex(11), NodeIndex(7), ()); -// g.add_edge(NodeIndex( 7), NodeIndex(3), ()); -// -// let mut ws1 = DfsWorkspace::new(g.len_nodes()); -// let mut ws2 = DfsWorkspace::new(g.len_nodes()); -// let mut visit_counts: Vec<_> = g.all_nodes().iter().map(|_| 0u32).collect(); -// let mut cache: Vec>> = g.all_nodes().iter().map(|_| None).collect(); -// -// fn is_root(x: &bool) -> bool { *x } -// -// for _ in 0 .. CACHING_THRESHOLD + 1 { -// find_roots(&g, 2, &mut visit_counts, &mut cache[..], is_root, &mut ws1, Some(&mut ws2)); -// ws1.output.nodes.sort(); -// assert_eq!(ws1.output.nodes, vec![8, 9, 10]); -// -// find_roots(&g, 3, &mut visit_counts, &mut cache[..], is_root, &mut ws1, Some(&mut ws2)); -// ws1.output.nodes.sort(); -// assert_eq!(ws1.output.nodes, vec![8, 9, 10, 11]); -// } -//} +#[test] +fn test_cached_dfs_cyclic() { + + // 0 1 <---- 2 3 + // ^ | ^ ^ + // | v | | + // 4 ----> 5 ----> 6 ----> 7 + // ^ ^ ^ ^ + // | | | | + // 8 9 10 11 + + let (graph, _nodes) = graph! { + // edges from above diagram, in columns, top-to-bottom: + n4 -> n0, + n8 -> n4, + n4 -> n5, + n1 -> n5, + n9 -> n5, + n2 -> n1, + n5 -> n6, + n6 -> n2, + n10 -> n6, + n6 -> n7, + n7 -> n3, + n11 -> n7, + }; + + // 0 1 2 3 + // ^ ^ / ^ + // | |/ | + // 4 ----> 5 --------------+ + // ^ ^ \ | + // | | \ | + // 8 9 10 11 + + reduce(&graph, &["n8", "n9", "n10", "n11"], &["n0", "n1", "n2", "n3"], &[ + "n10 -> n5", + "n11 -> n3", + "n4 -> n0", + "n4 -> n5", + "n5 -> n1", + "n5 -> n2", + "n5 -> n3", + "n8 -> n4", + "n9 -> n5" + ]); +} + +/// Demonstrates the case where we don't reduce as much as we could. +#[test] +fn suboptimal() { + let (graph, _nodes) = graph! { + INPUT0 -> X, + X -> OUTPUT0, + X -> OUTPUT1, + }; + + reduce(&graph, &["INPUT0"], &["OUTPUT0", "OUTPUT1"], &[ + "INPUT0 -> X", + "X -> OUTPUT0", + "X -> OUTPUT1" + ]); +} #[test] fn test_cycle_output() { @@ -229,7 +236,7 @@ fn test_cycle_output() { D -> C1, }; - // [A] -> [C0] <-> [D] + // [A] -> [C0] --> [D] // +----> [E] // ^ // [B] -------------+ @@ -238,6 +245,5 @@ fn test_cycle_output() { "B -> E", "C0 -> D", "C0 -> E", - "D -> C0" ]); } From 626e754473da96a670c917b9cbefd1c1ea888a9c Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 1 Feb 2017 15:57:50 -0800 Subject: [PATCH 104/137] Bump version, upgrade bootstrap This commit updates the version number to 1.17.0 as we're not on that version of the nightly compiler, and at the same time this updates src/stage0.txt to bootstrap from freshly minted beta compiler and beta Cargo. --- mk/crates.mk | 23 +-- mk/main.mk | 2 +- src/Cargo.lock | 16 -- src/liballoc/boxed.rs | 1 - src/liballoc/heap.rs | 8 - src/libcompiler_builtins/lib.rs | 193 ++++++------------ src/libcore/clone.rs | 2 - src/libcore/cmp.rs | 12 +- src/libcore/default.rs | 2 - src/libcore/fmt/num.rs | 8 +- src/libcore/hash/mod.rs | 5 - src/libcore/iter/range.rs | 1 - src/libcore/lib.rs | 8 +- src/libcore/nonzero.rs | 2 - src/libcore/num/mod.rs | 78 +------ src/libcore/num/wrapping.rs | 4 +- src/libcore/ops.rs | 96 ++------- src/librustc/Cargo.toml | 1 - src/librustc/lib.rs | 4 +- src/librustc/ty/layout.rs | 1 - src/librustc_const_eval/Cargo.toml | 1 - src/librustc_const_eval/eval.rs | 2 - src/librustc_const_eval/lib.rs | 3 +- src/librustc_const_math/Cargo.toml | 1 - src/librustc_const_math/int.rs | 11 - src/librustc_const_math/is.rs | 1 - src/librustc_const_math/lib.rs | 6 +- src/librustc_const_math/us.rs | 1 - src/librustc_data_structures/Cargo.toml | 1 - src/librustc_data_structures/lib.rs | 3 +- src/librustc_data_structures/stable_hasher.rs | 1 - src/librustc_i128/Cargo.toml | 8 - src/librustc_i128/lib.rs | 29 --- src/librustc_lint/Cargo.toml | 1 - src/librustc_lint/lib.rs | 3 +- src/librustc_lint/types.rs | 2 - src/librustc_metadata/Cargo.toml | 1 - src/librustc_metadata/decoder.rs | 1 - src/librustc_metadata/encoder.rs | 2 - src/librustc_metadata/lib.rs | 2 +- src/librustc_metadata/schema.rs | 2 - src/librustc_mir/Cargo.toml | 1 - src/librustc_mir/build/expr/as_rvalue.rs | 1 - src/librustc_mir/lib.rs | 3 +- src/librustc_trans/Cargo.toml | 1 - src/librustc_trans/common.rs | 9 - src/librustc_trans/intrinsic.rs | 2 - src/librustc_trans/lib.rs | 2 +- src/librustc_trans/mir/constant.rs | 2 - src/libserialize/Cargo.toml | 3 - src/libserialize/json.rs | 2 - src/libserialize/leb128.rs | 2 - src/libserialize/lib.rs | 3 +- src/libserialize/opaque.rs | 2 - src/libserialize/serialize.rs | 5 - src/libstd/lib.rs | 2 - src/libsyntax/Cargo.toml | 1 - src/libsyntax/ast.rs | 2 - src/libsyntax/ext/build.rs | 1 - src/libsyntax/ext/quote.rs | 1 - src/libsyntax/lib.rs | 3 +- src/libsyntax/parse/mod.rs | 2 - src/libsyntax/parse/parser.rs | 2 - src/libsyntax/print/pprust.rs | 2 - src/stage0.txt | 2 +- 65 files changed, 111 insertions(+), 494 deletions(-) delete mode 100644 src/librustc_i128/Cargo.toml delete mode 100644 src/librustc_i128/lib.rs diff --git a/mk/crates.mk b/mk/crates.mk index f801605d9fa97..320ba44ed805d 100644 --- a/mk/crates.mk +++ b/mk/crates.mk @@ -54,7 +54,7 @@ TARGET_CRATES := libc std term \ compiler_builtins core alloc \ std_unicode rustc_bitflags \ alloc_system alloc_jemalloc \ - panic_abort panic_unwind unwind rustc_i128 + panic_abort panic_unwind unwind RUSTC_CRATES := rustc rustc_typeck rustc_mir rustc_borrowck rustc_resolve rustc_driver \ rustc_trans rustc_back rustc_llvm rustc_privacy rustc_lint \ rustc_data_structures rustc_platform_intrinsics rustc_errors \ @@ -92,25 +92,24 @@ DEPS_getopts := std DEPS_graphviz := std DEPS_log := std DEPS_num := std -DEPS_serialize := std log rustc_i128 +DEPS_serialize := std log DEPS_term := std DEPS_test := std getopts term native:rust_test_helpers -DEPS_rustc_i128 = std DEPS_syntax := std term serialize log arena libc rustc_bitflags std_unicode rustc_errors \ - syntax_pos rustc_data_structures rustc_i128 + syntax_pos rustc_data_structures DEPS_syntax_ext := syntax syntax_pos rustc_errors fmt_macros proc_macro DEPS_proc_macro := syntax syntax_pos rustc_plugin log DEPS_syntax_pos := serialize DEPS_proc_macro_plugin := syntax syntax_pos rustc_plugin -DEPS_rustc_const_math := std syntax log serialize rustc_i128 +DEPS_rustc_const_math := std syntax log serialize DEPS_rustc_const_eval := rustc_const_math rustc syntax log serialize \ - rustc_back graphviz syntax_pos rustc_i128 + rustc_back graphviz syntax_pos DEPS_rustc := syntax fmt_macros flate arena serialize getopts \ log graphviz rustc_llvm rustc_back rustc_data_structures\ - rustc_const_math syntax_pos rustc_errors rustc_i128 + rustc_const_math syntax_pos rustc_errors DEPS_rustc_back := std syntax flate log libc DEPS_rustc_borrowck := rustc log graphviz syntax syntax_pos rustc_errors rustc_mir DEPS_rustc_data_structures := std log serialize libc @@ -121,20 +120,19 @@ DEPS_rustc_driver := arena flate getopts graphviz libc rustc rustc_back rustc_bo rustc_passes rustc_save_analysis rustc_const_eval \ rustc_incremental syntax_pos rustc_errors proc_macro rustc_data_structures DEPS_rustc_errors := log libc serialize syntax_pos -DEPS_rustc_lint := rustc log syntax syntax_pos rustc_const_eval rustc_i128 +DEPS_rustc_lint := rustc log syntax syntax_pos rustc_const_eval DEPS_rustc_llvm := native:rustllvm libc std rustc_bitflags DEPS_proc_macro := std syntax DEPS_rustc_metadata := rustc syntax syntax_pos rustc_errors rustc_const_math \ - proc_macro syntax_ext rustc_i128 + proc_macro syntax_ext DEPS_rustc_passes := syntax syntax_pos rustc core rustc_const_eval rustc_errors -DEPS_rustc_mir := rustc syntax syntax_pos rustc_const_math rustc_const_eval rustc_bitflags \ - rustc_i128 +DEPS_rustc_mir := rustc syntax syntax_pos rustc_const_math rustc_const_eval rustc_bitflags DEPS_rustc_resolve := arena rustc log syntax syntax_pos rustc_errors DEPS_rustc_platform_intrinsics := std DEPS_rustc_plugin := rustc rustc_metadata syntax syntax_pos rustc_errors DEPS_rustc_privacy := rustc log syntax syntax_pos DEPS_rustc_trans := arena flate getopts graphviz libc rustc rustc_back \ - log syntax serialize rustc_llvm rustc_platform_intrinsics rustc_i128 \ + log syntax serialize rustc_llvm rustc_platform_intrinsics \ rustc_const_math rustc_const_eval rustc_incremental rustc_errors syntax_pos DEPS_rustc_incremental := rustc syntax_pos serialize rustc_data_structures DEPS_rustc_save_analysis := rustc log syntax syntax_pos serialize @@ -162,7 +160,6 @@ ONLY_RLIB_alloc := 1 ONLY_RLIB_rand := 1 ONLY_RLIB_collections := 1 ONLY_RLIB_std_unicode := 1 -ONLY_RLIB_rustc_i128 := 1 ONLY_RLIB_rustc_bitflags := 1 ONLY_RLIB_alloc_system := 1 ONLY_RLIB_alloc_jemalloc := 1 diff --git a/mk/main.mk b/mk/main.mk index 9cd30be6531d1..6b409eebc74c8 100644 --- a/mk/main.mk +++ b/mk/main.mk @@ -13,7 +13,7 @@ ###################################################################### # The version number -CFG_RELEASE_NUM=1.16.0 +CFG_RELEASE_NUM=1.17.0 # An optional number to put after the label, e.g. '.2' -> '-beta.2' # NB Make sure it starts with a dot to conform to semver pre-release diff --git a/src/Cargo.lock b/src/Cargo.lock index 93bbf0f227b1b..9a0d136510715 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -245,7 +245,6 @@ dependencies = [ "rustc_const_math 0.0.0", "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", - "rustc_i128 0.0.0", "rustc_llvm 0.0.0", "serialize 0.0.0", "syntax 0.0.0", @@ -305,7 +304,6 @@ dependencies = [ "rustc_const_math 0.0.0", "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", - "rustc_i128 0.0.0", "syntax 0.0.0", "syntax_pos 0.0.0", ] @@ -314,7 +312,6 @@ dependencies = [ name = "rustc_const_math" version = "0.0.0" dependencies = [ - "rustc_i128 0.0.0", "serialize 0.0.0", "syntax 0.0.0", ] @@ -324,7 +321,6 @@ name = "rustc_data_structures" version = "0.0.0" dependencies = [ "log 0.0.0", - "rustc_i128 0.0.0", "serialize 0.0.0", ] @@ -367,10 +363,6 @@ dependencies = [ "syntax_pos 0.0.0", ] -[[package]] -name = "rustc_i128" -version = "0.0.0" - [[package]] name = "rustc_incremental" version = "0.0.0" @@ -392,7 +384,6 @@ dependencies = [ "rustc 0.0.0", "rustc_back 0.0.0", "rustc_const_eval 0.0.0", - "rustc_i128 0.0.0", "syntax 0.0.0", "syntax_pos 0.0.0", ] @@ -418,7 +409,6 @@ dependencies = [ "rustc_const_math 0.0.0", "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", - "rustc_i128 0.0.0", "rustc_llvm 0.0.0", "serialize 0.0.0", "syntax 0.0.0", @@ -437,7 +427,6 @@ dependencies = [ "rustc_const_eval 0.0.0", "rustc_const_math 0.0.0", "rustc_data_structures 0.0.0", - "rustc_i128 0.0.0", "syntax 0.0.0", "syntax_pos 0.0.0", ] @@ -516,7 +505,6 @@ dependencies = [ "rustc_const_math 0.0.0", "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", - "rustc_i128 0.0.0", "rustc_incremental 0.0.0", "rustc_llvm 0.0.0", "rustc_platform_intrinsics 0.0.0", @@ -568,9 +556,6 @@ dependencies = [ [[package]] name = "serialize" version = "0.0.0" -dependencies = [ - "rustc_i128 0.0.0", -] [[package]] name = "std" @@ -615,7 +600,6 @@ dependencies = [ "rustc_bitflags 0.0.0", "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", - "rustc_i128 0.0.0", "serialize 0.0.0", "syntax_pos 0.0.0", ] diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index b6f490e09cddf..82d361fb0e853 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -293,7 +293,6 @@ impl Box { } } -#[cfg(not(stage0))] #[stable(feature = "rust1", since = "1.0.0")] unsafe impl<#[may_dangle] T: ?Sized> Drop for Box { fn drop(&mut self) { diff --git a/src/liballoc/heap.rs b/src/liballoc/heap.rs index 81ed4be7763e9..51e6f2f8bd7a6 100644 --- a/src/liballoc/heap.rs +++ b/src/liballoc/heap.rs @@ -143,14 +143,6 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 { } } -#[cfg(not(test))] -#[cfg(stage0)] -#[lang = "exchange_free"] -#[inline] -unsafe fn exchange_free(ptr: *mut u8, old_size: usize, align: usize) { - deallocate(ptr, old_size, align); -} - #[cfg(not(test))] #[lang = "box_free"] #[inline] diff --git a/src/libcompiler_builtins/lib.rs b/src/libcompiler_builtins/lib.rs index 662d7422f5f00..b2a615456aa59 100644 --- a/src/libcompiler_builtins/lib.rs +++ b/src/libcompiler_builtins/lib.rs @@ -20,7 +20,6 @@ #![feature(staged_api, core_intrinsics, repr_simd, i128_type, core_float, abi_unadjusted, associated_consts)] #![allow(non_camel_case_types, unused_variables, unused_imports)] -#![cfg_attr(stage0, allow(dead_code))] #[cfg(any(target_pointer_width="32", target_pointer_width="16", target_os="windows", target_arch="mips64"))] @@ -32,17 +31,6 @@ pub mod reimpls { use core::intrinsics::unchecked_rem; use core::ptr; - // C API is expected to tolerate some amount of size mismatch in ABI. Hopefully the amount of - // handling is sufficient for bootstrapping. - #[cfg(stage0)] - type u128_ = u64; - #[cfg(stage0)] - type i128_ = i64; - #[cfg(not(stage0))] - type u128_ = u128; - #[cfg(not(stage0))] - type i128_ = i128; - macro_rules! ashl { ($a:expr, $b:expr, $ty:ty) => {{ let (a, b) = ($a, $b); @@ -63,8 +51,8 @@ pub mod reimpls { } #[export_name="__ashlti3"] - pub extern "C" fn shl(a: u128_, b: u128_) -> u128_ { - ashl!(a, b, u128_) + pub extern "C" fn shl(a: u128, b: u128) -> u128 { + ashl!(a, b, u128) } macro_rules! ashr { @@ -88,8 +76,8 @@ pub mod reimpls { } #[export_name="__ashrti3"] - pub extern "C" fn shr(a: i128_, b: i128_) -> i128_ { - ashr!(a, b, i128_) + pub extern "C" fn shr(a: i128, b: i128) -> i128 { + ashr!(a, b, i128) } macro_rules! lshr { @@ -111,22 +99,11 @@ pub mod reimpls { #[export_name="__lshrti3"] - pub extern "C" fn lshr(a: u128_, b: u128_) -> u128_ { - lshr!(a, b, u128_) - } - - #[cfg(stage0)] - pub extern "C" fn u128_div_mod(n: u128_, d: u128_, rem: *mut u128_) -> u128_ { - unsafe { - if !rem.is_null() { - *rem = unchecked_rem(n, d); - } - unchecked_div(n, d) - } + pub extern "C" fn lshr(a: u128, b: u128) -> u128 { + lshr!(a, b, u128) } - #[cfg(not(stage0))] - pub extern "C" fn u128_div_mod(n: u128_, d: u128_, rem: *mut u128_) -> u128_ { + pub extern "C" fn u128_div_mod(n: u128, d: u128, rem: *mut u128) -> u128 { // Translated from Figure 3-40 of The PowerPC Compiler Writer's Guide unsafe { // special cases, X is unknown, K != 0 @@ -291,36 +268,30 @@ pub mod reimpls { } } - fn i128_mod(a: i128_, b: i128_) -> i128_ { + fn i128_mod(a: i128, b: i128) -> i128 { let b = b.uabs(); let sa = a.signum(); let a = a.uabs(); unsafe { let mut r = ::core::mem::zeroed(); u128_div_mod(a, b, &mut r); - if sa == -1 { (r as i128_).unchecked_neg() } else { r as i128_ } + if sa == -1 { (r as i128).unchecked_neg() } else { r as i128 } } } - fn i128_div(a: i128_, b: i128_) -> i128_ { + fn i128_div(a: i128, b: i128) -> i128 { let sa = a.signum(); let sb = b.signum(); let a = a.uabs(); let b = b.uabs(); let sr = sa.wrapping_mul(sb); // sign of quotient (if sr == -1 { - (u128_div_mod(a, b, ptr::null_mut()) as i128_).unchecked_neg() + (u128_div_mod(a, b, ptr::null_mut()) as i128).unchecked_neg() } else { - u128_div_mod(a, b, ptr::null_mut()) as i128_ + u128_div_mod(a, b, ptr::null_mut()) as i128 }) } - #[cfg(stage0)] - #[export_name="__udivti3"] - pub extern "C" fn u128_div(a: u128_, b: u128_) -> u128_ { - (a / b) - } - macro_rules! mulo { ($a:expr, $b:expr, $o: expr, $ty: ty) => {{ let (a, b, overflow) = ($a, $b, $o); @@ -367,35 +338,6 @@ pub mod reimpls { fn high(self) -> Self::HighHalf; fn from_parts(low: Self::LowHalf, high: Self::HighHalf) -> Self; } - impl LargeInt for u64 { - type LowHalf = u32; - type HighHalf = u32; - - fn low(self) -> u32 { - self as u32 - } - fn high(self) -> u32 { - (self.wrapping_shr(32)) as u32 - } - fn from_parts(low: u32, high: u32) -> u64 { - low as u64 | (high as u64).wrapping_shl(32) - } - } - impl LargeInt for i64 { - type LowHalf = u32; - type HighHalf = i32; - - fn low(self) -> u32 { - self as u32 - } - fn high(self) -> i32 { - self.wrapping_shr(32) as i32 - } - fn from_parts(low: u32, high: i32) -> i64 { - u64::from_parts(low, high as u32) as i64 - } - } - #[cfg(not(stage0))] impl LargeInt for u128 { type LowHalf = u64; type HighHalf = u64; @@ -410,7 +352,6 @@ pub mod reimpls { (high as u128).wrapping_shl(64) | low as u128 } } - #[cfg(not(stage0))] impl LargeInt for i128 { type LowHalf = u64; type HighHalf = i64; @@ -455,47 +396,31 @@ pub mod reimpls { }} } - #[cfg(stage0)] #[export_name="__multi3"] - pub extern "C" fn u128_mul(a: i128_, b: i128_) -> i128_ { - ((a as i64).wrapping_mul(b as i64) as i128_) - } - - #[cfg(not(stage0))] - #[export_name="__multi3"] - pub extern "C" fn u128_mul(a: i128_, b: i128_) -> i128_ { - mul!(a, b, i128_, i64) + pub extern "C" fn u128_mul(a: i128, b: i128) -> i128 { + mul!(a, b, i128, i64) } trait AbsExt: Sized { - fn uabs(self) -> u128_ { - self.iabs() as u128_ - } - fn iabs(self) -> i128_; - } - - #[cfg(stage0)] - impl AbsExt for i128_ { - fn iabs(self) -> i128_ { - let s = self >> 63; - ((self ^ s).wrapping_sub(s)) + fn uabs(self) -> u128 { + self.iabs() as u128 } + fn iabs(self) -> i128; } - #[cfg(not(stage0))] - impl AbsExt for i128_ { - fn iabs(self) -> i128_ { + impl AbsExt for i128 { + fn iabs(self) -> i128 { let s = self >> 127; ((self ^ s).wrapping_sub(s)) } } trait NegExt: Sized { - fn unchecked_neg(self) -> i128_; + fn unchecked_neg(self) -> i128; } - impl NegExt for i128_ { - fn unchecked_neg(self) -> i128_ { + impl NegExt for i128 { + fn unchecked_neg(self) -> i128 { (!self).wrapping_add(1) } } @@ -551,9 +476,9 @@ pub mod reimpls { let exponent = $from.get_exponent(); let mantissa_fraction = repr & <$fromty as FloatStuff>::MANTISSA_MASK; let mantissa = mantissa_fraction | <$fromty as FloatStuff>::MANTISSA_LEAD_BIT; - if sign == -1.0 || exponent < 0 { return 0 as u128_; } + if sign == -1.0 || exponent < 0 { return 0 as u128; } if exponent > ::core::mem::size_of::<$outty>() as i32 * 8 { - return !(0 as u128_); + return !(0 as u128); } (if exponent < (<$fromty as FloatStuff>::MANTISSA_BITS) as i32 { (mantissa as $outty) @@ -576,7 +501,7 @@ pub mod reimpls { let mantissa_fraction = repr & <$fromty as FloatStuff>::MANTISSA_MASK; let mantissa = mantissa_fraction | <$fromty as FloatStuff>::MANTISSA_LEAD_BIT; - if exponent < 0 { return 0 as i128_; } + if exponent < 0 { return 0 as i128; } if exponent > ::core::mem::size_of::<$outty>() as i32 * 8 { let ret = if sign > 0.0 { <$outty>::max_value() } else { <$outty>::min_value() }; return ret @@ -595,7 +520,7 @@ pub mod reimpls { } - fn i128_as_f64(a: i128_) -> f64 { + fn i128_as_f64(a: i128) -> f64 { match a.signum() { 1 => u128_as_f64(a.uabs()), 0 => 0.0, @@ -603,7 +528,7 @@ pub mod reimpls { } } - fn i128_as_f32(a: i128_) -> f32 { + fn i128_as_f32(a: i128) -> f32 { match a.signum() { 1 => u128_as_f32(a.uabs()), 0 => 0.0, @@ -611,7 +536,7 @@ pub mod reimpls { } } - fn u128_as_f64(mut a: u128_) -> f64 { + fn u128_as_f64(mut a: u128) -> f64 { use ::core::f64::MANTISSA_DIGITS; if a == 0 { return 0.0; } let sd = 128u32.wrapping_sub(a.leading_zeros()); @@ -620,7 +545,7 @@ pub mod reimpls { const MD2 : u32 = MANTISSA_DIGITS + 2; // SNAP: replace this with !0u128 - let negn :u128_ = !0; + let negn :u128 = !0; if sd > MANTISSA_DIGITS { a = match sd { @@ -628,7 +553,7 @@ pub mod reimpls { MD2 => a, _ => a.wrapping_shr(sd.wrapping_sub(MANTISSA_DIGITS + 2)) | (if (a & (negn.wrapping_shr(128 + MANTISSA_DIGITS + 2) - .wrapping_sub(sd as u128_))) == 0 { 0 } else { 1 }) + .wrapping_sub(sd as u128))) == 0 { 0 } else { 1 }) }; a |= if (a & 4) == 0 { 0 } else { 1 }; a = a.wrapping_add(1); @@ -646,7 +571,7 @@ pub mod reimpls { } } - fn u128_as_f32(mut a: u128_) -> f32 { + fn u128_as_f32(mut a: u128) -> f32 { use ::core::f32::MANTISSA_DIGITS; if a == 0 { return 0.0; } let sd = 128u32.wrapping_sub(a.leading_zeros()); @@ -655,7 +580,7 @@ pub mod reimpls { const MD2 : u32 = MANTISSA_DIGITS + 2; // SNAP: replace this with !0u128 - let negn :u128_ = !0; + let negn :u128 = !0; if sd > MANTISSA_DIGITS { a = match sd { @@ -663,7 +588,7 @@ pub mod reimpls { MD2 => a, _ => a.wrapping_shr(sd.wrapping_sub(MANTISSA_DIGITS + 2)) | (if (a & (negn.wrapping_shr(128 + MANTISSA_DIGITS + 2) - .wrapping_sub(sd as u128_))) == 0 { 0 } else { 1 }) + .wrapping_sub(sd as u128))) == 0 { 0 } else { 1 }) }; a |= if (a & 4) == 0 { 0 } else { 1 }; a = a.wrapping_add(1); @@ -684,7 +609,7 @@ pub mod reimpls { macro_rules! why_are_abi_strings_checked_by_parser { ($cret:ty, $conv:expr, $unadj:tt) => { mod imp { - use super::{i128_, u128_, LargeInt, FloatStuff, NegExt, AbsExt}; + use super::{LargeInt, FloatStuff, NegExt, AbsExt}; use super::{i128_as_f64, i128_as_f32, u128_as_f64, u128_as_f32, i128_div, i128_mod, u128_div_mod, unchecked_div, ptr}; // For x64 @@ -692,8 +617,8 @@ pub mod reimpls { // aka. // define i128 @__muloti4(i128, i128, i32*) #[export_name="__muloti4"] - pub unsafe extern $unadj fn i128_mul_oflow(a: i128_, b: i128_, o: *mut i32) -> i128_ { - mulo!(a, b, o, i128_) + pub unsafe extern $unadj fn i128_mul_oflow(a: i128, b: i128, o: *mut i32) -> i128 { + mulo!(a, b, o, i128) } // For x64 @@ -701,19 +626,19 @@ pub mod reimpls { // aka. // define double @__muloti4(i128) #[export_name="__floattidf"] - pub extern $unadj fn i128_as_f64_(a: i128_) -> f64 { + pub extern $unadj fn i128_as_f64_(a: i128) -> f64 { i128_as_f64(a) } #[export_name="__floattisf"] - pub extern $unadj fn i128_as_f32_(a: i128_) -> f32 { + pub extern $unadj fn i128_as_f32_(a: i128) -> f32 { i128_as_f32(a) } #[export_name="__floatuntidf"] - pub extern $unadj fn u128_as_f64_(a: u128_) -> f64 { + pub extern $unadj fn u128_as_f64_(a: u128) -> f64 { u128_as_f64(a) } #[export_name="__floatuntisf"] - pub extern $unadj fn u128_as_f32_(a: u128_) -> f32 { + pub extern $unadj fn u128_as_f32_(a: u128) -> f32 { u128_as_f32(a) } @@ -722,23 +647,23 @@ pub mod reimpls { // aka. // define i128 @stuff(double) #[export_name="__fixunsdfti"] - pub extern $unadj fn f64_as_u128(a: f64) -> u128_ { - float_as_unsigned!(a, f64, u128_) + pub extern $unadj fn f64_as_u128(a: f64) -> u128 { + float_as_unsigned!(a, f64, u128) } #[export_name="__fixunssfti"] - pub extern "unadjusted" fn f32_as_u128(a: f32) -> u128_ { - float_as_unsigned!(a, f32, u128_) + pub extern "unadjusted" fn f32_as_u128(a: f32) -> u128 { + float_as_unsigned!(a, f32, u128) } #[export_name="__fixdfti"] - pub extern "unadjusted" fn f64_as_i128(a: f64) -> i128_ { - float_as_signed!(a, f64, i128_) + pub extern "unadjusted" fn f64_as_i128(a: f64) -> i128 { + float_as_signed!(a, f64, i128) } #[export_name="__fixsfti"] - pub extern "unadjusted" fn f32_as_i128(a: f32) -> i128_ { - float_as_signed!(a, f32, i128_) + pub extern "unadjusted" fn f32_as_i128(a: f32) -> i128 { + float_as_signed!(a, f32, i128) } #[repr(simd)] @@ -751,19 +676,19 @@ pub mod reimpls { // // That almost matches the C ABI, so we simply use the C ABI #[export_name="__udivmodti4"] - pub extern "C" fn u128_div_mod_(n: u128_, d: u128_, rem: *mut u128_) -> $cret { + pub extern "C" fn u128_div_mod_(n: u128, d: u128, rem: *mut u128) -> $cret { let x = u128_div_mod(n, d, rem); ($conv)(x) } #[export_name="__udivti3"] - pub extern "C" fn u128_div_(a: u128_, b: u128_) -> $cret { + pub extern "C" fn u128_div_(a: u128, b: u128) -> $cret { let x = u128_div_mod(a, b, ptr::null_mut()); ($conv)(x) } #[export_name="__umodti3"] - pub extern "C" fn u128_mod_(a: u128_, b: u128_) -> $cret { + pub extern "C" fn u128_mod_(a: u128, b: u128) -> $cret { unsafe { let mut r = ::core::mem::zeroed(); u128_div_mod(a, b, &mut r); @@ -772,30 +697,26 @@ pub mod reimpls { } #[export_name="__divti3"] - pub extern "C" fn i128_div_(a: i128_, b: i128_) -> $cret { + pub extern "C" fn i128_div_(a: i128, b: i128) -> $cret { let x = i128_div(a, b); - ($conv)(x as u128_) + ($conv)(x as u128) } #[export_name="__modti3"] - pub extern "C" fn i128_mod_(a: i128_, b: i128_) -> $cret { + pub extern "C" fn i128_mod_(a: i128, b: i128) -> $cret { let x = i128_mod(a, b); - ($conv)(x as u128_) + ($conv)(x as u128) } } } } // LLVM expectations for ABI on windows x64 are pure madness. - #[cfg(not(stage0))] #[cfg(all(windows, target_pointer_width="64"))] why_are_abi_strings_checked_by_parser!(u64x2, - |i: u128_| u64x2(i.low(), i.high()), + |i: u128| u64x2(i.low(), i.high()), "unadjusted"); - #[cfg(not(stage0))] #[cfg(not(all(windows, target_pointer_width="64")))] - why_are_abi_strings_checked_by_parser!(u128_, |i|{ i }, "C"); - - #[cfg(not(stage0))] + why_are_abi_strings_checked_by_parser!(u128, |i|{ i }, "C"); pub use self::imp::*; } diff --git a/src/libcore/clone.rs b/src/libcore/clone.rs index cd2e8f1018141..8dbbc5928f45a 100644 --- a/src/libcore/clone.rs +++ b/src/libcore/clone.rs @@ -153,7 +153,6 @@ clone_impl! { i8 } clone_impl! { i16 } clone_impl! { i32 } clone_impl! { i64 } -#[cfg(not(stage0))] clone_impl! { i128 } clone_impl! { usize } @@ -161,7 +160,6 @@ clone_impl! { u8 } clone_impl! { u16 } clone_impl! { u32 } clone_impl! { u64 } -#[cfg(not(stage0))] clone_impl! { u128 } clone_impl! { f32 } diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index a78d27ea3afc1..cc066099cf8b0 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -679,10 +679,8 @@ mod impls { } partial_eq_impl! { - bool char usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 + bool char usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } - #[cfg(not(stage0))] - partial_eq_impl! { u128 i128 } macro_rules! eq_impl { ($($t:ty)*) => ($( @@ -691,9 +689,7 @@ mod impls { )*) } - eq_impl! { () bool char usize u8 u16 u32 u64 isize i8 i16 i32 i64 } - #[cfg(not(stage0))] - eq_impl! { u128 i128 } + eq_impl! { () bool char usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } macro_rules! partial_ord_impl { ($($t:ty)*) => ($( @@ -782,9 +778,7 @@ mod impls { } } - ord_impl! { char usize u8 u16 u32 u64 isize i8 i16 i32 i64 } - #[cfg(not(stage0))] - ord_impl! { u128 i128 } + ord_impl! { char usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } #[unstable(feature = "never_type_impls", issue = "35121")] impl PartialEq for ! { diff --git a/src/libcore/default.rs b/src/libcore/default.rs index ccd4343336f5e..0d7c1672fbcd2 100644 --- a/src/libcore/default.rs +++ b/src/libcore/default.rs @@ -144,7 +144,6 @@ default_impl! { u8, 0 } default_impl! { u16, 0 } default_impl! { u32, 0 } default_impl! { u64, 0 } -#[cfg(not(stage0))] default_impl! { u128, 0 } default_impl! { isize, 0 } @@ -152,7 +151,6 @@ default_impl! { i8, 0 } default_impl! { i16, 0 } default_impl! { i32, 0 } default_impl! { i64, 0 } -#[cfg(not(stage0))] default_impl! { i128, 0 } default_impl! { f32, 0.0f32 } diff --git a/src/libcore/fmt/num.rs b/src/libcore/fmt/num.rs index cd725392b665f..a324a4aed2576 100644 --- a/src/libcore/fmt/num.rs +++ b/src/libcore/fmt/num.rs @@ -30,7 +30,6 @@ trait Int: Zero + PartialEq + PartialOrd + Div + Rem + fn to_u16(&self) -> u16; fn to_u32(&self) -> u32; fn to_u64(&self) -> u64; - #[cfg(not(stage0))] fn to_u128(&self) -> u128; } @@ -41,13 +40,10 @@ macro_rules! doit { fn to_u16(&self) -> u16 { *self as u16 } fn to_u32(&self) -> u32 { *self as u32 } fn to_u64(&self) -> u64 { *self as u64 } - #[cfg(not(stage0))] fn to_u128(&self) -> u128 { *self as u128 } })*) } -doit! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize } -#[cfg(not(stage0))] -doit! { i128 u128 } +doit! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize } /// A type that represents a specific radix #[doc(hidden)] @@ -188,7 +184,6 @@ integer! { i8, u8 } integer! { i16, u16 } integer! { i32, u32 } integer! { i64, u64 } -#[cfg(not(stage0))] integer! { i128, u128 } const DEC_DIGITS_LUT: &'static[u8] = @@ -265,7 +260,6 @@ macro_rules! impl_Display { impl_Display!(i8, u8, i16, u16, i32, u32: to_u32); impl_Display!(i64, u64: to_u64); -#[cfg(not(stage0))] impl_Display!(i128, u128: to_u128); #[cfg(target_pointer_width = "16")] impl_Display!(isize, usize: to_u16); diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs index dd6edc7d39af0..f0d8d1a321917 100644 --- a/src/libcore/hash/mod.rs +++ b/src/libcore/hash/mod.rs @@ -186,7 +186,6 @@ pub trait Hasher { fn write_u64(&mut self, i: u64) { self.write(&unsafe { mem::transmute::<_, [u8; 8]>(i) }) } - #[cfg(not(stage0))] /// Writes a single `u128` into this hasher. #[inline] #[unstable(feature = "i128", issue = "35118")] @@ -227,7 +226,6 @@ pub trait Hasher { fn write_i64(&mut self, i: i64) { self.write_u64(i as u64) } - #[cfg(not(stage0))] /// Writes a single `i128` into this hasher. #[inline] #[unstable(feature = "i128", issue = "35118")] @@ -376,9 +374,6 @@ mod impls { (i32, write_i32), (i64, write_i64), (isize, write_isize), - } - #[cfg(not(stage0))] - impl_write! { (u128, write_u128), (i128, write_i128), } diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index 9d22037882f21..687c477f19e4c 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -242,7 +242,6 @@ step_impl_signed!(i64); // assume here that it is less than 64-bits. #[cfg(not(target_pointer_width = "64"))] step_impl_no_between!(u64 i64); -#[cfg(not(stage0))] step_impl_no_between!(u128 i128); /// An adapter for stepping range iterators by a custom amount. diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 98871bd084e3c..3d124a8aa8b75 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -89,7 +89,7 @@ #![feature(staged_api)] #![feature(unboxed_closures)] #![feature(never_type)] -#![cfg_attr(not(stage0), feature(i128_type))] +#![feature(i128_type)] #![feature(prelude_import)] #[prelude_import] @@ -119,9 +119,6 @@ mod uint_macros; #[path = "num/i16.rs"] pub mod i16; #[path = "num/i32.rs"] pub mod i32; #[path = "num/i64.rs"] pub mod i64; - -// SNAP -#[cfg(not(stage0))] #[path = "num/i128.rs"] pub mod i128; #[path = "num/usize.rs"] pub mod usize; @@ -129,9 +126,6 @@ mod uint_macros; #[path = "num/u16.rs"] pub mod u16; #[path = "num/u32.rs"] pub mod u32; #[path = "num/u64.rs"] pub mod u64; - -// SNAP -#[cfg(not(stage0))] #[path = "num/u128.rs"] pub mod u128; #[path = "num/f32.rs"] pub mod f32; diff --git a/src/libcore/nonzero.rs b/src/libcore/nonzero.rs index 539ad00bd30e0..d7382501bc325 100644 --- a/src/libcore/nonzero.rs +++ b/src/libcore/nonzero.rs @@ -30,9 +30,7 @@ unsafe impl Zeroable for i32 {} unsafe impl Zeroable for u32 {} unsafe impl Zeroable for i64 {} unsafe impl Zeroable for u64 {} -#[cfg(not(stage0))] unsafe impl Zeroable for i128 {} -#[cfg(not(stage0))] unsafe impl Zeroable for u128 {} /// A wrapper type for raw pointers and integers that will never be diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 61c687313dcb6..e907eae18bcbb 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -144,9 +144,7 @@ macro_rules! zero_one_impl { } )*) } -zero_one_impl! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize } -#[cfg(not(stage0))] -zero_one_impl! { u128 i128 } +zero_one_impl! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize } macro_rules! zero_one_impl_float { ($($t:ty)*) => ($( @@ -1300,8 +1298,6 @@ impl i64 { intrinsics::mul_with_overflow } } -// SNAP -#[cfg(not(stage0))] #[lang = "i128"] impl i128 { int_impl! { i128, u128, 128, @@ -2342,8 +2338,6 @@ impl u64 { intrinsics::mul_with_overflow } } -// SNAP -#[cfg(not(stage0))] #[lang = "u128"] impl u128 { uint_impl! { u128, 128, @@ -2568,9 +2562,7 @@ macro_rules! from_str_radix_int_impl { } )*} } -from_str_radix_int_impl! { isize i8 i16 i32 i64 usize u8 u16 u32 u64 } -#[cfg(not(stage0))] -from_str_radix_int_impl! { u128 i128 } +from_str_radix_int_impl! { isize i8 i16 i32 i64 i128 usize u8 u16 u32 u64 u128 } /// The error type returned when a checked integral type conversion fails. #[unstable(feature = "try_from", issue = "33417")] @@ -2614,50 +2606,17 @@ macro_rules! same_sign_try_from_int_impl { )*} } -#[cfg(stage0)] -same_sign_try_from_int_impl!(u64, u8, u8, u16, u32, u64, usize); -#[cfg(stage0)] -same_sign_try_from_int_impl!(i64, i8, i8, i16, i32, i64, isize); -#[cfg(stage0)] -same_sign_try_from_int_impl!(u64, u16, u8, u16, u32, u64, usize); -#[cfg(stage0)] -same_sign_try_from_int_impl!(i64, i16, i8, i16, i32, i64, isize); -#[cfg(stage0)] -same_sign_try_from_int_impl!(u64, u32, u8, u16, u32, u64, usize); -#[cfg(stage0)] -same_sign_try_from_int_impl!(i64, i32, i8, i16, i32, i64, isize); -#[cfg(stage0)] -same_sign_try_from_int_impl!(u64, u64, u8, u16, u32, u64, usize); -#[cfg(stage0)] -same_sign_try_from_int_impl!(i64, i64, i8, i16, i32, i64, isize); -#[cfg(stage0)] -same_sign_try_from_int_impl!(u64, usize, u8, u16, u32, u64, usize); -#[cfg(stage0)] -same_sign_try_from_int_impl!(i64, isize, i8, i16, i32, i64, isize); - -#[cfg(not(stage0))] same_sign_try_from_int_impl!(u128, u8, u8, u16, u32, u64, u128, usize); -#[cfg(not(stage0))] same_sign_try_from_int_impl!(i128, i8, i8, i16, i32, i64, i128, isize); -#[cfg(not(stage0))] same_sign_try_from_int_impl!(u128, u16, u8, u16, u32, u64, u128, usize); -#[cfg(not(stage0))] same_sign_try_from_int_impl!(i128, i16, i8, i16, i32, i64, i128, isize); -#[cfg(not(stage0))] same_sign_try_from_int_impl!(u128, u32, u8, u16, u32, u64, u128, usize); -#[cfg(not(stage0))] same_sign_try_from_int_impl!(i128, i32, i8, i16, i32, i64, i128, isize); -#[cfg(not(stage0))] same_sign_try_from_int_impl!(u128, u64, u8, u16, u32, u64, u128, usize); -#[cfg(not(stage0))] same_sign_try_from_int_impl!(i128, i64, i8, i16, i32, i64, i128, isize); -#[cfg(not(stage0))] same_sign_try_from_int_impl!(u128, u128, u8, u16, u32, u64, u128, usize); -#[cfg(not(stage0))] same_sign_try_from_int_impl!(i128, i128, i8, i16, i32, i64, i128, isize); -#[cfg(not(stage0))] same_sign_try_from_int_impl!(u128, usize, u8, u16, u32, u64, u128, usize); -#[cfg(not(stage0))] same_sign_try_from_int_impl!(i128, isize, i8, i16, i32, i64, i128, isize); macro_rules! cross_sign_from_int_impl { @@ -2692,28 +2651,11 @@ macro_rules! cross_sign_from_int_impl { )*} } -#[cfg(stage0)] -cross_sign_from_int_impl!(u8, i8, i16, i32, i64, isize); -#[cfg(stage0)] -cross_sign_from_int_impl!(u16, i8, i16, i32, i64, isize); -#[cfg(stage0)] -cross_sign_from_int_impl!(u32, i8, i16, i32, i64, isize); -#[cfg(stage0)] -cross_sign_from_int_impl!(u64, i8, i16, i32, i64, isize); -#[cfg(stage0)] -cross_sign_from_int_impl!(usize, i8, i16, i32, i64, isize); - -#[cfg(not(stage0))] cross_sign_from_int_impl!(u8, i8, i16, i32, i64, i128, isize); -#[cfg(not(stage0))] cross_sign_from_int_impl!(u16, i8, i16, i32, i64, i128, isize); -#[cfg(not(stage0))] cross_sign_from_int_impl!(u32, i8, i16, i32, i64, i128, isize); -#[cfg(not(stage0))] cross_sign_from_int_impl!(u64, i8, i16, i32, i64, i128, isize); -#[cfg(not(stage0))] cross_sign_from_int_impl!(u128, i8, i16, i32, i64, i128, isize); -#[cfg(not(stage0))] cross_sign_from_int_impl!(usize, i8, i16, i32, i64, i128, isize); #[doc(hidden)] @@ -2742,9 +2684,7 @@ macro_rules! doit { } })*) } -doit! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize } -#[cfg(not(stage0))] -doit! { i128 u128 } +doit! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize } fn from_str_radix(src: &str, radix: u32) -> Result { use self::IntErrorKind::*; @@ -2878,50 +2818,38 @@ macro_rules! impl_from { impl_from! { u8, u16 } impl_from! { u8, u32 } impl_from! { u8, u64 } -#[cfg(not(stage0))] impl_from! { u8, u128 } impl_from! { u8, usize } impl_from! { u16, u32 } impl_from! { u16, u64 } -#[cfg(not(stage0))] impl_from! { u16, u128 } impl_from! { u32, u64 } -#[cfg(not(stage0))] impl_from! { u32, u128 } -#[cfg(not(stage0))] impl_from! { u64, u128 } // Signed -> Signed impl_from! { i8, i16 } impl_from! { i8, i32 } impl_from! { i8, i64 } -#[cfg(not(stage0))] impl_from! { i8, i128 } impl_from! { i8, isize } impl_from! { i16, i32 } impl_from! { i16, i64 } -#[cfg(not(stage0))] impl_from! { i16, i128 } impl_from! { i32, i64 } -#[cfg(not(stage0))] impl_from! { i32, i128 } -#[cfg(not(stage0))] impl_from! { i64, i128 } // Unsigned -> Signed impl_from! { u8, i16 } impl_from! { u8, i32 } impl_from! { u8, i64 } -#[cfg(not(stage0))] impl_from! { u8, i128 } impl_from! { u16, i32 } impl_from! { u16, i64 } -#[cfg(not(stage0))] impl_from! { u16, i128 } impl_from! { u32, i64 } -#[cfg(not(stage0))] impl_from! { u32, i128 } -#[cfg(not(stage0))] impl_from! { u64, i128 } // Note: integers can only be represented with full precision in a float if diff --git a/src/libcore/num/wrapping.rs b/src/libcore/num/wrapping.rs index b3c2c25551e0d..50007c7d9b01a 100644 --- a/src/libcore/num/wrapping.rs +++ b/src/libcore/num/wrapping.rs @@ -297,9 +297,7 @@ macro_rules! wrapping_impl { )*) } -wrapping_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 } -#[cfg(not(stage0))] -wrapping_impl! { u128 i128 } +wrapping_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } mod shift_max { #![allow(non_upper_case_globals)] diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs index 9ff4725c9b365..566fb89365a51 100644 --- a/src/libcore/ops.rs +++ b/src/libcore/ops.rs @@ -267,9 +267,7 @@ macro_rules! add_impl { )*) } -add_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 } -#[cfg(not(stage0))] -add_impl! { u128 i128 } +add_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } /// The `Sub` trait is used to specify the functionality of `-`. /// @@ -342,9 +340,7 @@ macro_rules! sub_impl { )*) } -sub_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 } -#[cfg(not(stage0))] -sub_impl! { u128 i128 } +sub_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } /// The `Mul` trait is used to specify the functionality of `*`. /// @@ -466,9 +462,7 @@ macro_rules! mul_impl { )*) } -mul_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 } -#[cfg(not(stage0))] -mul_impl! { u128 i128 } +mul_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } /// The `Div` trait is used to specify the functionality of `/`. /// @@ -597,9 +591,7 @@ macro_rules! div_impl_integer { )*) } -div_impl_integer! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 } -#[cfg(not(stage0))] -div_impl_integer! { u128 i128 } +div_impl_integer! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } macro_rules! div_impl_float { ($($t:ty)*) => ($( @@ -678,9 +670,7 @@ macro_rules! rem_impl_integer { )*) } -rem_impl_integer! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 } -#[cfg(not(stage0))] -rem_impl_integer! { u128 i128 } +rem_impl_integer! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } macro_rules! rem_impl_float { @@ -776,9 +766,7 @@ macro_rules! neg_impl_unsigned { } // neg_impl_unsigned! { usize u8 u16 u32 u64 } -neg_impl_numeric! { isize i8 i16 i32 i64 f32 f64 } -#[cfg(not(stage0))] -neg_impl_numeric! { i128 } +neg_impl_numeric! { isize i8 i16 i32 i64 i128 f32 f64 } /// The `Not` trait is used to specify the functionality of unary `!`. /// @@ -836,9 +824,7 @@ macro_rules! not_impl { )*) } -not_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 } -#[cfg(not(stage0))] -not_impl! { u128 i128 } +not_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } /// The `BitAnd` trait is used to specify the functionality of `&`. /// @@ -921,9 +907,7 @@ macro_rules! bitand_impl { )*) } -bitand_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 } -#[cfg(not(stage0))] -bitand_impl! { u128 i128 } +bitand_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } /// The `BitOr` trait is used to specify the functionality of `|`. /// @@ -1006,9 +990,7 @@ macro_rules! bitor_impl { )*) } -bitor_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 } -#[cfg(not(stage0))] -bitor_impl! { u128 i128 } +bitor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } /// The `BitXor` trait is used to specify the functionality of `^`. /// @@ -1094,9 +1076,7 @@ macro_rules! bitxor_impl { )*) } -bitxor_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 } -#[cfg(not(stage0))] -bitxor_impl! { u128 i128 } +bitxor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } /// The `Shl` trait is used to specify the functionality of `<<`. /// @@ -1187,7 +1167,6 @@ macro_rules! shl_impl_all { shl_impl! { $t, u16 } shl_impl! { $t, u32 } shl_impl! { $t, u64 } - #[cfg(not(stage0))] shl_impl! { $t, u128 } shl_impl! { $t, usize } @@ -1195,15 +1174,12 @@ macro_rules! shl_impl_all { shl_impl! { $t, i16 } shl_impl! { $t, i32 } shl_impl! { $t, i64 } - #[cfg(not(stage0))] shl_impl! { $t, i128 } shl_impl! { $t, isize } )*) } -shl_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize } -#[cfg(not(stage0))] -shl_impl_all! { u128 i128 } +shl_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 isize i128 } /// The `Shr` trait is used to specify the functionality of `>>`. /// @@ -1294,7 +1270,6 @@ macro_rules! shr_impl_all { shr_impl! { $t, u16 } shr_impl! { $t, u32 } shr_impl! { $t, u64 } - #[cfg(not(stage0))] shr_impl! { $t, u128 } shr_impl! { $t, usize } @@ -1302,15 +1277,12 @@ macro_rules! shr_impl_all { shr_impl! { $t, i16 } shr_impl! { $t, i32 } shr_impl! { $t, i64 } - #[cfg(not(stage0))] shr_impl! { $t, i128 } shr_impl! { $t, isize } )*) } -shr_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize } -#[cfg(not(stage0))] -shr_impl_all! { u128 i128 } +shr_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize } /// The `AddAssign` trait is used to specify the functionality of `+=`. /// @@ -1366,9 +1338,7 @@ macro_rules! add_assign_impl { )+) } -add_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 } -#[cfg(not(stage0))] -add_assign_impl! { u128 i128 } +add_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } /// The `SubAssign` trait is used to specify the functionality of `-=`. /// @@ -1424,9 +1394,7 @@ macro_rules! sub_assign_impl { )+) } -sub_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 } -#[cfg(not(stage0))] -sub_assign_impl! { u128 i128 } +sub_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } /// The `MulAssign` trait is used to specify the functionality of `*=`. /// @@ -1471,9 +1439,7 @@ macro_rules! mul_assign_impl { )+) } -mul_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 } -#[cfg(not(stage0))] -mul_assign_impl! { u128 i128 } +mul_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } /// The `DivAssign` trait is used to specify the functionality of `/=`. /// @@ -1517,9 +1483,7 @@ macro_rules! div_assign_impl { )+) } -div_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 } -#[cfg(not(stage0))] -div_assign_impl! { u128 i128 } +div_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } /// The `RemAssign` trait is used to specify the functionality of `%=`. /// @@ -1563,9 +1527,7 @@ macro_rules! rem_assign_impl { )+) } -rem_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 } -#[cfg(not(stage0))] -rem_assign_impl! { u128 i128 } +rem_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } /// The `BitAndAssign` trait is used to specify the functionality of `&=`. /// @@ -1651,9 +1613,7 @@ macro_rules! bitand_assign_impl { )+) } -bitand_assign_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 } -#[cfg(not(stage0))] -bitand_assign_impl! { u128 i128 } +bitand_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } /// The `BitOrAssign` trait is used to specify the functionality of `|=`. /// @@ -1697,9 +1657,7 @@ macro_rules! bitor_assign_impl { )+) } -bitor_assign_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 } -#[cfg(not(stage0))] -bitor_assign_impl! { u128 i128 } +bitor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } /// The `BitXorAssign` trait is used to specify the functionality of `^=`. /// @@ -1743,9 +1701,7 @@ macro_rules! bitxor_assign_impl { )+) } -bitxor_assign_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 } -#[cfg(not(stage0))] -bitxor_assign_impl! { u128 i128 } +bitxor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } /// The `ShlAssign` trait is used to specify the functionality of `<<=`. /// @@ -1798,7 +1754,6 @@ macro_rules! shl_assign_impl_all { shl_assign_impl! { $t, u16 } shl_assign_impl! { $t, u32 } shl_assign_impl! { $t, u64 } - #[cfg(not(stage0))] shl_assign_impl! { $t, u128 } shl_assign_impl! { $t, usize } @@ -1806,15 +1761,12 @@ macro_rules! shl_assign_impl_all { shl_assign_impl! { $t, i16 } shl_assign_impl! { $t, i32 } shl_assign_impl! { $t, i64 } - #[cfg(not(stage0))] shl_assign_impl! { $t, i128 } shl_assign_impl! { $t, isize } )*) } -shl_assign_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize } -#[cfg(not(stage0))] -shl_assign_impl_all! { u128 i128 } +shl_assign_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize } /// The `ShrAssign` trait is used to specify the functionality of `>>=`. /// @@ -1867,7 +1819,6 @@ macro_rules! shr_assign_impl_all { shr_assign_impl! { $t, u16 } shr_assign_impl! { $t, u32 } shr_assign_impl! { $t, u64 } - #[cfg(not(stage0))] shr_assign_impl! { $t, u128 } shr_assign_impl! { $t, usize } @@ -1875,15 +1826,12 @@ macro_rules! shr_assign_impl_all { shr_assign_impl! { $t, i16 } shr_assign_impl! { $t, i32 } shr_assign_impl! { $t, i64 } - #[cfg(not(stage0))] shr_assign_impl! { $t, i128 } shr_assign_impl! { $t, isize } )*) } -shr_assign_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize } -#[cfg(not(stage0))] -shr_assign_impl_all! { u128 i128 } +shr_assign_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize } /// The `Index` trait is used to specify the functionality of indexing operations /// like `container[index]` when used in an immutable context. diff --git a/src/librustc/Cargo.toml b/src/librustc/Cargo.toml index 3c455eb05011e..5d53c60ad7fdc 100644 --- a/src/librustc/Cargo.toml +++ b/src/librustc/Cargo.toml @@ -19,7 +19,6 @@ rustc_const_math = { path = "../librustc_const_math" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_errors = { path = "../librustc_errors" } rustc_llvm = { path = "../librustc_llvm" } -rustc_i128 = { path = "../librustc_i128" } serialize = { path = "../libserialize" } syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 855f4a8197e35..5c0ec8de7ecd2 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -30,6 +30,7 @@ #![feature(const_fn)] #![feature(core_intrinsics)] #![feature(field_init_shorthand)] +#![feature(i128_type)] #![feature(libc)] #![feature(loop_break_value)] #![feature(nonzero)] @@ -60,9 +61,6 @@ extern crate syntax_pos; extern crate serialize as rustc_serialize; // used by deriving -// SNAP: -extern crate rustc_i128; - #[macro_use] mod macros; diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 78364abdaecba..b5efd2cfc686a 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -20,7 +20,6 @@ use ty::{self, Ty, TyCtxt, TypeFoldable}; use syntax::ast::{FloatTy, IntTy, UintTy}; use syntax::attr; use syntax_pos::DUMMY_SP; -use rustc_i128::u128; use rustc_const_math::ConstInt; use std::cmp; diff --git a/src/librustc_const_eval/Cargo.toml b/src/librustc_const_eval/Cargo.toml index ff028c202a849..780b2c16a32ec 100644 --- a/src/librustc_const_eval/Cargo.toml +++ b/src/librustc_const_eval/Cargo.toml @@ -19,4 +19,3 @@ rustc_errors = { path = "../librustc_errors" } syntax = { path = "../libsyntax" } graphviz = { path = "../libgraphviz" } syntax_pos = { path = "../libsyntax_pos" } -rustc_i128 = { path = "../librustc_i128" } diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index 47a98155fc4b0..e2e76cdfb6ebd 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -37,8 +37,6 @@ use std::cmp::Ordering; use rustc_const_math::*; use rustc_errors::DiagnosticBuilder; -use rustc_i128::{i128, u128}; - macro_rules! math { ($e:expr, $op:expr) => { match $op { diff --git a/src/librustc_const_eval/lib.rs b/src/librustc_const_eval/lib.rs index 2b6f487c2c942..198e49daabc63 100644 --- a/src/librustc_const_eval/lib.rs +++ b/src/librustc_const_eval/lib.rs @@ -29,6 +29,7 @@ #![feature(box_patterns)] #![feature(box_syntax)] #![feature(const_fn)] +#![feature(i128_type)] extern crate arena; #[macro_use] extern crate syntax; @@ -41,8 +42,6 @@ extern crate rustc_errors; extern crate graphviz; extern crate syntax_pos; -extern crate rustc_i128; - // NB: This module needs to be declared first so diagnostics are // registered before they are used. pub mod diagnostics; diff --git a/src/librustc_const_math/Cargo.toml b/src/librustc_const_math/Cargo.toml index e6db1557fbe3d..e74c1ef693ce0 100644 --- a/src/librustc_const_math/Cargo.toml +++ b/src/librustc_const_math/Cargo.toml @@ -11,4 +11,3 @@ crate-type = ["dylib"] [dependencies] serialize = { path = "../libserialize" } syntax = { path = "../libsyntax" } -rustc_i128 = { path = "../librustc_i128" } diff --git a/src/librustc_const_math/int.rs b/src/librustc_const_math/int.rs index 53f185b661b41..3618bfa20811f 100644 --- a/src/librustc_const_math/int.rs +++ b/src/librustc_const_math/int.rs @@ -11,7 +11,6 @@ use std::cmp::Ordering; use syntax::attr::IntType; use syntax::ast::{IntTy, UintTy}; -use rustc_i128::{i128, u128}; use super::is::*; use super::us::*; @@ -54,7 +53,6 @@ macro_rules! bounds { mod ubounds { #![allow(dead_code)] - use rustc_i128::{u128, i128}; bounds!{u128: 0, i8 I8MIN I8MAX i16 I16MIN I16MAX i32 I32MIN I32MAX i64 I64MIN I64MAX i128 I128MIN I128MAX u8 U8MIN U8MAX u16 U16MIN U16MAX u32 U32MIN U32MAX u64 U64MIN U64MAX u128 U128MIN U128MAX @@ -65,12 +63,6 @@ mod ubounds { mod ibounds { #![allow(dead_code)] - use rustc_i128::i128; - #[cfg(stage0)] - pub const U64MIN: i128 = 0; - #[cfg(stage0)] - pub const U64MAX: i128 = i128::max_value(); - #[cfg(not(stage0))] bounds!(i128, u64 U64MIN U64MAX); pub const U128MIN: i128 = 0; @@ -483,10 +475,7 @@ derive_binop!(BitAnd, bitand); derive_binop!(BitOr, bitor); derive_binop!(BitXor, bitxor); -#[cfg(not(stage0))] const I128_MIN: i128 = ::std::i128::MIN; -#[cfg(stage0)] -const I128_MIN: i128 = ::std::i64::MIN; fn check_division( lhs: ConstInt, diff --git a/src/librustc_const_math/is.rs b/src/librustc_const_math/is.rs index 19ae0c91fc5f9..8f28ba14c6aef 100644 --- a/src/librustc_const_math/is.rs +++ b/src/librustc_const_math/is.rs @@ -10,7 +10,6 @@ use syntax::ast; use super::err::*; -use rustc_i128::i128; /// Depending on the target only one variant is ever used in a compilation. /// Anything else is an error. This invariant is checked at several locations diff --git a/src/librustc_const_math/lib.rs b/src/librustc_const_math/lib.rs index d40a6aa32fd46..13764ce5bbbfd 100644 --- a/src/librustc_const_math/lib.rs +++ b/src/librustc_const_math/lib.rs @@ -26,13 +26,11 @@ #![feature(rustc_private)] #![feature(staged_api)] #![feature(const_fn)] -#![cfg_attr(not(stage0), feature(i128))] +#![feature(i128)] +#![feature(i128_type)] extern crate syntax; -// SNAP: remove use of this crate -extern crate rustc_i128; - extern crate serialize as rustc_serialize; // used by deriving mod float; diff --git a/src/librustc_const_math/us.rs b/src/librustc_const_math/us.rs index 9ebf5cab6bb06..76443f584abac 100644 --- a/src/librustc_const_math/us.rs +++ b/src/librustc_const_math/us.rs @@ -10,7 +10,6 @@ use syntax::ast; use super::err::*; -use rustc_i128::u128; /// Depending on the target only one variant is ever used in a compilation. /// Anything else is an error. This invariant is checked at several locations diff --git a/src/librustc_data_structures/Cargo.toml b/src/librustc_data_structures/Cargo.toml index bb6103748102d..e2e16059d9871 100644 --- a/src/librustc_data_structures/Cargo.toml +++ b/src/librustc_data_structures/Cargo.toml @@ -11,4 +11,3 @@ crate-type = ["dylib"] [dependencies] log = { path = "../liblog" } serialize = { path = "../libserialize" } -rustc_i128 = { path = "../librustc_i128" } diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs index b003cba292c80..cf6bf1cf1d483 100644 --- a/src/librustc_data_structures/lib.rs +++ b/src/librustc_data_structures/lib.rs @@ -36,6 +36,7 @@ #![feature(untagged_unions)] #![feature(associated_consts)] #![feature(unsize)] +#![feature(i128_type)] #![cfg_attr(unix, feature(libc))] #![cfg_attr(test, feature(test))] @@ -47,8 +48,6 @@ extern crate serialize as rustc_serialize; // used by deriving #[cfg(unix)] extern crate libc; -extern crate rustc_i128; - pub use rustc_serialize::hex::ToHex; pub mod array_vec; diff --git a/src/librustc_data_structures/stable_hasher.rs b/src/librustc_data_structures/stable_hasher.rs index 87048eff5b78b..231c01c9ab78d 100644 --- a/src/librustc_data_structures/stable_hasher.rs +++ b/src/librustc_data_structures/stable_hasher.rs @@ -13,7 +13,6 @@ use std::marker::PhantomData; use std::mem; use blake2b::Blake2bHasher; use rustc_serialize::leb128; -use rustc_i128::{u128,i128}; fn write_unsigned_leb128_to_buf(buf: &mut [u8; 16], value: u64) -> usize { leb128::write_unsigned_leb128_to(value as u128, |i, v| buf[i] = v) diff --git a/src/librustc_i128/Cargo.toml b/src/librustc_i128/Cargo.toml deleted file mode 100644 index 6fd67637db7e6..0000000000000 --- a/src/librustc_i128/Cargo.toml +++ /dev/null @@ -1,8 +0,0 @@ -[package] -authors = ["The Rust Project Developers"] -name = "rustc_i128" -version = "0.0.0" - -[lib] -name = "rustc_i128" -path = "lib.rs" diff --git a/src/librustc_i128/lib.rs b/src/librustc_i128/lib.rs deleted file mode 100644 index 80f550c7f50e2..0000000000000 --- a/src/librustc_i128/lib.rs +++ /dev/null @@ -1,29 +0,0 @@ -// 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. -#![allow(non_camel_case_types)] -#![cfg_attr(not(stage0), feature(i128_type))] -#![no_std] -#![crate_type="rlib"] -#![crate_name="rustc_i128"] - -#[cfg(stage0)] -pub type i128 = i64; -#[cfg(stage0)] -pub type u128 = u64; - -#[cfg(not(stage0))] -pub type i128 = int::_i128; -#[cfg(not(stage0))] -pub type u128 = int::_u128; -#[cfg(not(stage0))] -mod int { - pub type _i128 = i128; - pub type _u128 = u128; -} diff --git a/src/librustc_lint/Cargo.toml b/src/librustc_lint/Cargo.toml index 272f8b4f64dbd..4d5c0d7ba0ae1 100644 --- a/src/librustc_lint/Cargo.toml +++ b/src/librustc_lint/Cargo.toml @@ -14,6 +14,5 @@ log = { path = "../liblog" } rustc = { path = "../librustc" } rustc_back = { path = "../librustc_back" } rustc_const_eval = { path = "../librustc_const_eval" } -rustc_i128 = { path = "../librustc_i128" } syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 18067cb86739b..d1ad3730aa2b3 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -31,6 +31,7 @@ #![cfg_attr(test, feature(test))] #![feature(box_patterns)] #![feature(box_syntax)] +#![feature(i128_type)] #![feature(quote)] #![feature(rustc_diagnostic_macros)] #![feature(rustc_private)] @@ -46,8 +47,6 @@ extern crate rustc_back; extern crate rustc_const_eval; extern crate syntax_pos; -extern crate rustc_i128; - pub use rustc::lint; pub use rustc::middle; pub use rustc::session; diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index 9669efa2d86b3..2c3d71cd8de1d 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -33,8 +33,6 @@ use syntax::codemap; use rustc::hir; -use rustc_i128::{i128, u128}; - declare_lint! { UNUSED_COMPARISONS, Warn, diff --git a/src/librustc_metadata/Cargo.toml b/src/librustc_metadata/Cargo.toml index 4bd98c087f517..6f7f03ca216b9 100644 --- a/src/librustc_metadata/Cargo.toml +++ b/src/librustc_metadata/Cargo.toml @@ -18,7 +18,6 @@ rustc_const_math = { path = "../librustc_const_math" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_errors = { path = "../librustc_errors" } rustc_llvm = { path = "../librustc_llvm" } -rustc_i128 = { path = "../librustc_i128" } serialize = { path = "../libserialize" } syntax = { path = "../libsyntax" } syntax_ext = { path = "../libsyntax_ext" } diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index dd44ef202dc27..f4a35ea5fd0cf 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -42,7 +42,6 @@ use syntax::attr; use syntax::ast; use syntax::codemap; use syntax_pos::{self, Span, BytePos, Pos, DUMMY_SP}; -use rustc_i128::{u128, i128}; pub struct DecodeContext<'a, 'tcx: 'a> { opaque: opaque::Decoder<'a>, diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index b9c2f0622b698..69e1bbd77662b 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -43,8 +43,6 @@ use rustc::hir::itemlikevisit::ItemLikeVisitor; use rustc::hir::intravisit::{Visitor, NestedVisitorMap}; use rustc::hir::intravisit; -use rustc_i128::{u128, i128}; - use super::index_builder::{FromId, IndexBuilder, Untracked}; pub struct EncodeContext<'a, 'tcx: 'a> { diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs index 484e0df658303..2fbdb8c0de676 100644 --- a/src/librustc_metadata/lib.rs +++ b/src/librustc_metadata/lib.rs @@ -20,6 +20,7 @@ #![feature(box_patterns)] #![feature(conservative_impl_trait)] #![feature(core_intrinsics)] +#![feature(i128_type)] #![feature(proc_macro_internals)] #![feature(quote)] #![feature(rustc_diagnostic_macros)] @@ -44,7 +45,6 @@ extern crate rustc_back; extern crate rustc_const_math; extern crate rustc_data_structures; extern crate rustc_llvm; -extern crate rustc_i128; mod diagnostics; diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index d9c639f2bc573..d13628e9ce7a3 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -28,8 +28,6 @@ use syntax_pos::{self, Span}; use std::marker::PhantomData; -use rustc_i128::u128; - pub fn rustc_version() -> String { format!("rustc {}", option_env!("CFG_VERSION").unwrap_or("unknown version")) diff --git a/src/librustc_mir/Cargo.toml b/src/librustc_mir/Cargo.toml index 9f49d02f86cec..531be0b6ae9f5 100644 --- a/src/librustc_mir/Cargo.toml +++ b/src/librustc_mir/Cargo.toml @@ -16,6 +16,5 @@ rustc_const_eval = { path = "../librustc_const_eval" } rustc_const_math = { path = "../librustc_const_math" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_bitflags = { path = "../librustc_bitflags" } -rustc_i128 = { path = "../librustc_i128" } syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index 48690a275c205..b1e1e75912da3 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -15,7 +15,6 @@ use std; use rustc_const_math::{ConstMathErr, Op}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::indexed_vec::Idx; -use rustc_i128::i128; use build::{BlockAnd, BlockAndExtension, Builder}; use build::expr::category::{Category, RvalueFunc}; diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index e7764d58d75ff..61ba9d90fef38 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -22,6 +22,7 @@ Rust MIR: a lowered representation of Rust. Also: an experiment! #![feature(associated_consts)] #![feature(box_patterns)] +#![feature(i128_type)] #![feature(rustc_diagnostic_macros)] #![feature(rustc_private)] #![feature(staged_api)] @@ -40,8 +41,6 @@ extern crate syntax_pos; extern crate rustc_const_math; extern crate rustc_const_eval; -extern crate rustc_i128; - pub mod diagnostics; pub mod build; diff --git a/src/librustc_trans/Cargo.toml b/src/librustc_trans/Cargo.toml index 36d2ba4f3676b..fa48a63b6b8f5 100644 --- a/src/librustc_trans/Cargo.toml +++ b/src/librustc_trans/Cargo.toml @@ -21,7 +21,6 @@ rustc_data_structures = { path = "../librustc_data_structures" } rustc_errors = { path = "../librustc_errors" } rustc_incremental = { path = "../librustc_incremental" } rustc_llvm = { path = "../librustc_llvm" } -rustc_i128 = { path = "../librustc_i128" } rustc_platform_intrinsics = { path = "../librustc_platform_intrinsics" } syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs index 0ba94fdfe635c..01b2aeef004db 100644 --- a/src/librustc_trans/common.rs +++ b/src/librustc_trans/common.rs @@ -40,8 +40,6 @@ use syntax::ast; use syntax::symbol::InternedString; use syntax_pos::Span; -use rustc_i128::u128; - pub use context::{CrateContext, SharedCrateContext}; pub fn type_is_fat_ptr<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool { @@ -399,13 +397,6 @@ fn is_const_integral(v: ValueRef) -> bool { } #[inline] -#[cfg(stage0)] -fn hi_lo_to_u128(lo: u64, _: u64) -> u128 { - lo as u128 -} - -#[inline] -#[cfg(not(stage0))] fn hi_lo_to_u128(lo: u64, hi: u64) -> u128 { ((hi as u128) << 64) | (lo as u128) } diff --git a/src/librustc_trans/intrinsic.rs b/src/librustc_trans/intrinsic.rs index 842a21e98db46..37f63e7499689 100644 --- a/src/librustc_trans/intrinsic.rs +++ b/src/librustc_trans/intrinsic.rs @@ -33,8 +33,6 @@ use builder::Builder; use rustc::session::Session; use syntax_pos::Span; -use rustc_i128::u128; - use std::cmp::Ordering; use std::iter; diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index 659dbb441ee35..21c92cb4a4ad2 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -29,6 +29,7 @@ #![feature(const_fn)] #![feature(custom_attribute)] #![allow(unused_attributes)] +#![feature(i128_type)] #![feature(libc)] #![feature(quote)] #![feature(rustc_diagnostic_macros)] @@ -53,7 +54,6 @@ extern crate rustc_const_eval; #[macro_use] #[no_link] extern crate rustc_bitflags; -extern crate rustc_i128; #[macro_use] extern crate log; #[macro_use] extern crate syntax; diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs index 9ac2bea3b82fb..3d5e1694355b3 100644 --- a/src/librustc_trans/mir/constant.rs +++ b/src/librustc_trans/mir/constant.rs @@ -43,8 +43,6 @@ use std::ptr; use super::operand::{OperandRef, OperandValue}; use super::MirContext; -use rustc_i128::{u128, i128}; - /// A sized constant rvalue. /// The LLVM type might not be the same for a single Rust type, /// e.g. each enum variant would have its own LLVM struct type. diff --git a/src/libserialize/Cargo.toml b/src/libserialize/Cargo.toml index 47403b459817b..a896c4a634c36 100644 --- a/src/libserialize/Cargo.toml +++ b/src/libserialize/Cargo.toml @@ -7,6 +7,3 @@ version = "0.0.0" name = "serialize" path = "lib.rs" crate-type = ["dylib", "rlib"] - -[dependencies] -rustc_i128 = { path = "../librustc_i128" } diff --git a/src/libserialize/json.rs b/src/libserialize/json.rs index 3e62026f51219..07417565e314f 100644 --- a/src/libserialize/json.rs +++ b/src/libserialize/json.rs @@ -211,8 +211,6 @@ use std::string; use std::{char, f64, fmt, str}; use std; -use rustc_i128::{i128, u128}; - use Encodable; /// Represents a json value diff --git a/src/libserialize/leb128.rs b/src/libserialize/leb128.rs index 392f332d508dd..a9638717c66fa 100644 --- a/src/libserialize/leb128.rs +++ b/src/libserialize/leb128.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use rustc_i128::{i128, u128}; - #[inline] fn write_to_vec(vec: &mut Vec, position: usize, byte: u8) { if position == vec.len() { diff --git a/src/libserialize/lib.rs b/src/libserialize/lib.rs index 1cb83fa33da06..2b31e2f410806 100644 --- a/src/libserialize/lib.rs +++ b/src/libserialize/lib.rs @@ -30,14 +30,13 @@ Core encoding and decoding interfaces. #![feature(box_syntax)] #![feature(collections)] #![feature(core_intrinsics)] +#![feature(i128_type)] #![feature(specialization)] #![feature(staged_api)] #![cfg_attr(test, feature(test))] extern crate collections; -extern crate rustc_i128; - pub use self::serialize::{Decoder, Encoder, Decodable, Encodable}; pub use self::serialize::{SpecializationError, SpecializedEncoder, SpecializedDecoder}; diff --git a/src/libserialize/opaque.rs b/src/libserialize/opaque.rs index 8a0648d5851a1..9c3db64d4d863 100644 --- a/src/libserialize/opaque.rs +++ b/src/libserialize/opaque.rs @@ -13,8 +13,6 @@ use std::borrow::Cow; use std::io::{self, Write}; use serialize; -use rustc_i128::{i128, u128}; - // ----------------------------------------------------------------------------- // Encoder // ----------------------------------------------------------------------------- diff --git a/src/libserialize/serialize.rs b/src/libserialize/serialize.rs index 395f2ccbe6d28..ba39fcdec6f88 100644 --- a/src/libserialize/serialize.rs +++ b/src/libserialize/serialize.rs @@ -20,7 +20,6 @@ use std::path; use std::rc::Rc; use std::cell::{Cell, RefCell}; use std::sync::Arc; -use rustc_i128::{i128, u128}; pub trait Encoder { type Error; @@ -333,14 +332,12 @@ impl Decodable for u64 { } } -#[cfg(not(stage0))] impl Encodable for u128 { fn encode(&self, s: &mut S) -> Result<(), S::Error> { s.emit_u128(*self) } } -#[cfg(not(stage0))] impl Decodable for u128 { fn decode(d: &mut D) -> Result { d.read_u128() @@ -407,14 +404,12 @@ impl Decodable for i64 { } } -#[cfg(not(stage0))] impl Encodable for i128 { fn encode(&self, s: &mut S) -> Result<(), S::Error> { s.emit_i128(*self) } } -#[cfg(not(stage0))] impl Decodable for i128 { fn decode(d: &mut D) -> Result { d.read_i128() diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 37632ac76f2db..181694dead03c 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -399,7 +399,6 @@ pub use core::i32; #[stable(feature = "rust1", since = "1.0.0")] pub use core::i64; #[unstable(feature = "i128", issue = "35118")] -#[cfg(not(stage0))] pub use core::i128; #[stable(feature = "rust1", since = "1.0.0")] pub use core::usize; @@ -430,7 +429,6 @@ pub use core_collections::vec; #[stable(feature = "rust1", since = "1.0.0")] pub use std_unicode::char; #[unstable(feature = "i128", issue = "35118")] -#[cfg(not(stage0))] pub use core::u128; pub mod f32; diff --git a/src/libsyntax/Cargo.toml b/src/libsyntax/Cargo.toml index a200da6c293ea..0b38f5450b63f 100644 --- a/src/libsyntax/Cargo.toml +++ b/src/libsyntax/Cargo.toml @@ -15,4 +15,3 @@ rustc_bitflags = { path = "../librustc_bitflags" } syntax_pos = { path = "../libsyntax_pos" } rustc_errors = { path = "../librustc_errors" } rustc_data_structures = { path = "../librustc_data_structures" } -rustc_i128 = { path = "../librustc_i128" } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index d18215be3e638..09fb369cd3568 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -33,8 +33,6 @@ use std::u32; use serialize::{self, Encodable, Decodable, Encoder, Decoder}; -use rustc_i128::{u128, i128}; - /// An identifier contains a Name (index into the interner /// table) and a SyntaxContext to track renaming and /// macro expansion per Flatt et al., "Macros That Work Together" diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 1837fa1e5fee8..f8d4eff80b2d1 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -16,7 +16,6 @@ use codemap::{dummy_spanned, respan, Spanned}; use ext::base::ExtCtxt; use ptr::P; use symbol::{Symbol, keywords}; -use rustc_i128::u128; // Transitional reexports so qquote can find the paths it is looking for mod syntax { diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs index 8258a7427b62b..6c46f90f3d4b9 100644 --- a/src/libsyntax/ext/quote.rs +++ b/src/libsyntax/ext/quote.rs @@ -41,7 +41,6 @@ pub mod rt { pub use parse::new_parser_from_tts; pub use syntax_pos::{BytePos, Span, DUMMY_SP}; pub use codemap::{dummy_spanned}; - use rustc_i128::{u128}; pub trait ToTokens { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec; diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 871e6b3783a41..25be9e91a6ac9 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -33,6 +33,7 @@ #![feature(unicode)] #![feature(rustc_diagnostic_macros)] #![feature(specialization)] +#![feature(i128_type)] extern crate serialize; #[macro_use] extern crate log; @@ -42,8 +43,6 @@ pub extern crate rustc_errors as errors; extern crate syntax_pos; extern crate rustc_data_structures; -extern crate rustc_i128; - extern crate serialize as rustc_serialize; // used by deriving // A variant of 'try!' that panics on an Err. This is used as a crutch on the diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index f1a3b523cfd93..20e80afc115f5 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -28,8 +28,6 @@ use std::path::{Path, PathBuf}; use std::rc::Rc; use std::str; -use rustc_i128::u128; - pub type PResult<'a, T> = Result>; #[macro_use] diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 2532a1def7dda..fd7c56f136f48 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -65,8 +65,6 @@ use std::path::{Path, PathBuf}; use std::rc::Rc; use std::slice; -use rustc_i128::u128; - bitflags! { flags Restrictions: u8 { const RESTRICTION_STMT_EXPR = 1 << 0, diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index e75671d27aa24..ffdd3b2e93e2e 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -29,8 +29,6 @@ use std_inject; use symbol::{Symbol, keywords}; use tokenstream::{self, TokenTree}; -use rustc_i128::i128; - use std::ascii; use std::io::{self, Write, Read}; use std::iter; diff --git a/src/stage0.txt b/src/stage0.txt index 4be9e3e57baac..cda9a5a96432b 100644 --- a/src/stage0.txt +++ b/src/stage0.txt @@ -12,5 +12,5 @@ # tarball for a stable release you'll likely see `1.x.0-$date` where `1.x.0` was # released on `$date` -rustc: beta-2016-12-20 +rustc: beta-2017-02-01 cargo: bfee18f73287687c543bda8c35e4e33808792715 From 2a8ee8c80406c95757f7e27ec81b303e241756f3 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 3 Feb 2017 22:38:44 +0100 Subject: [PATCH 105/137] Add missing urls in HashMap --- src/libstd/collections/hash/map.rs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index a314717a8772b..8058972e75093 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -198,9 +198,9 @@ impl DefaultResizePolicy { /// attacks such as HashDoS. /// /// The hashing algorithm can be replaced on a per-`HashMap` basis using the -/// `HashMap::default`, `HashMap::with_hasher`, and -/// `HashMap::with_capacity_and_hasher` methods. Many alternative algorithms -/// are available on crates.io, such as the `fnv` crate. +/// [`HashMap::default`], [`HashMap::with_hasher`], and +/// [`HashMap::with_capacity_and_hasher`] methods. Many alternative algorithms +/// are available on crates.io, such as the [`fnv`] crate. /// /// It is required that the keys implement the [`Eq`] and [`Hash`] traits, although /// this can frequently be achieved by using `#[derive(PartialEq, Eq, Hash)]`. @@ -302,6 +302,10 @@ impl DefaultResizePolicy { /// [`PartialEq`]: ../../std/cmp/trait.PartialEq.html /// [`RefCell`]: ../../std/cell/struct.RefCell.html /// [`Cell`]: ../../std/cell/struct.Cell.html +/// [`HashMap::default`]: #method.default +/// [`HashMap::with_hasher`]: #method.with_hasher +/// [`HashMap::with_capacity_and_hasher`]: #method.with_capacity_and_hasher +/// [`fnv`]: https://crates.io/crates/fnv /// /// ``` /// use std::collections::HashMap; @@ -680,7 +684,9 @@ impl HashMap /// /// # Panics /// - /// Panics if the new allocation size overflows `usize`. + /// Panics if the new allocation size overflows [`usize`]. + /// + /// [`usize`]: ../../std/primitive.usize.html /// /// # Examples /// @@ -1141,13 +1147,14 @@ impl HashMap /// Inserts a key-value pair into the map. /// - /// If the map did not have this key present, `None` is returned. + /// If the map did not have this key present, [`None`] is returned. /// /// If the map did have this key present, the value is updated, and the old /// value is returned. The key is not updated, though; this matters for /// types that can be `==` without being identical. See the [module-level /// documentation] for more. /// + /// [`None`]: ../../std/option/enum.Option.html#variant.None /// [module-level documentation]: index.html#insert-and-complex-keys /// /// # Examples From d14b268b9d0f37811c47cc6b1ebf2433fbb0ad0e Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 4 Feb 2017 01:18:10 +0300 Subject: [PATCH 106/137] libbacktrace: Fix uninitialized variable --- src/libbacktrace/pecoff.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libbacktrace/pecoff.c b/src/libbacktrace/pecoff.c index 04e0bafb14981..2d6a9877219dc 100644 --- a/src/libbacktrace/pecoff.c +++ b/src/libbacktrace/pecoff.c @@ -607,7 +607,9 @@ coff_add (struct backtrace_state *state, int descriptor, // against the upstream libbacktrace, that's what's going on. uint32_t str_size; off_t str_off; - struct backtrace_view syms_view; + // NOTE: upstream doesn't have `{0}`, this is a fix for Rust issue #39468. + // If syms_view is not initialized, then `free(syms_view.base)` may segfault later. + struct backtrace_view syms_view = {0}; off_t syms_off; size_t syms_size; int syms_view_valid; From 34f444de5d2fbab533eb523f8d8b0b75bf07217d Mon Sep 17 00:00:00 2001 From: Son Date: Sat, 4 Feb 2017 10:04:22 +1100 Subject: [PATCH 107/137] Extract libcore benchmarks to a separate folder --- src/libcore/Cargo.toml | 7 +- src/libcore/bench/any.rs | 22 +++ src/libcore/bench/hash/mod.rs | 11 ++ src/libcore/bench/hash/sip.rs | 151 ++++++++++++++++++ src/libcore/bench/iter.rs | 101 ++++++++++++ src/libcore/bench/lib.rs | 25 +++ src/libcore/bench/mem.rs | 70 ++++++++ src/libcore/bench/num/dec2flt/mod.rs | 68 ++++++++ src/libcore/bench/num/flt2dec/mod.rs | 24 +++ .../bench/num/flt2dec/strategy/dragon.rs | 70 ++++++++ .../bench/num/flt2dec/strategy/grisu.rs | 77 +++++++++ src/libcore/bench/num/mod.rs | 12 ++ src/libcore/bench/ops.rs | 30 ++++ src/libcoretest/any.rs | 13 +- src/libcoretest/hash/sip.rs | 130 --------------- src/libcoretest/iter.rs | 91 ----------- src/libcoretest/mem.rs | 60 +------ src/libcoretest/num/dec2flt/mod.rs | 57 ------- .../num/flt2dec/strategy/dragon.rs | 57 ------- src/libcoretest/num/flt2dec/strategy/grisu.rs | 58 +------ src/libcoretest/ops.rs | 19 --- 21 files changed, 667 insertions(+), 486 deletions(-) create mode 100644 src/libcore/bench/any.rs create mode 100644 src/libcore/bench/hash/mod.rs create mode 100644 src/libcore/bench/hash/sip.rs create mode 100644 src/libcore/bench/iter.rs create mode 100644 src/libcore/bench/lib.rs create mode 100644 src/libcore/bench/mem.rs create mode 100644 src/libcore/bench/num/dec2flt/mod.rs create mode 100644 src/libcore/bench/num/flt2dec/mod.rs create mode 100644 src/libcore/bench/num/flt2dec/strategy/dragon.rs create mode 100644 src/libcore/bench/num/flt2dec/strategy/grisu.rs create mode 100644 src/libcore/bench/num/mod.rs create mode 100644 src/libcore/bench/ops.rs diff --git a/src/libcore/Cargo.toml b/src/libcore/Cargo.toml index e0dbc096cd0d9..4f7cd7b016d66 100644 --- a/src/libcore/Cargo.toml +++ b/src/libcore/Cargo.toml @@ -13,7 +13,6 @@ bench = false name = "coretest" path = "../libcoretest/lib.rs" -# FIXME: need to extract benchmarks to a separate crate -#[[bench]] -#name = "coretest" -#path = "../libcoretest/lib.rs" +[[bench]] +name = "corebench" +path = "../libcore/bench/lib.rs" diff --git a/src/libcore/bench/any.rs b/src/libcore/bench/any.rs new file mode 100644 index 0000000000000..67e02cf9509b6 --- /dev/null +++ b/src/libcore/bench/any.rs @@ -0,0 +1,22 @@ +// 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. + +use core::any::*; +use test::{Bencher, black_box}; + +#[bench] +fn bench_downcast_ref(b: &mut Bencher) { + b.iter(|| { + let mut x = 0; + let mut y = &mut x as &mut Any; + black_box(&mut y); + black_box(y.downcast_ref::() == Some(&0)); + }); +} diff --git a/src/libcore/bench/hash/mod.rs b/src/libcore/bench/hash/mod.rs new file mode 100644 index 0000000000000..55d9e3e091380 --- /dev/null +++ b/src/libcore/bench/hash/mod.rs @@ -0,0 +1,11 @@ +// 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. + +mod sip; diff --git a/src/libcore/bench/hash/sip.rs b/src/libcore/bench/hash/sip.rs new file mode 100644 index 0000000000000..3379c85bbec7d --- /dev/null +++ b/src/libcore/bench/hash/sip.rs @@ -0,0 +1,151 @@ +// 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(deprecated)] + +use core::hash::*; +use test::{Bencher, black_box}; + +fn hash_bytes(mut s: H, x: &[u8]) -> u64 { + Hasher::write(&mut s, x); + s.finish() +} + +fn hash_with(mut st: H, x: &T) -> u64 { + x.hash(&mut st); + st.finish() +} + +fn hash(x: &T) -> u64 { + hash_with(SipHasher::new(), x) +} + +#[bench] +fn bench_str_under_8_bytes(b: &mut Bencher) { + let s = "foo"; + b.iter(|| { + assert_eq!(hash(&s), 16262950014981195938); + }) +} + +#[bench] +fn bench_str_of_8_bytes(b: &mut Bencher) { + let s = "foobar78"; + b.iter(|| { + assert_eq!(hash(&s), 4898293253460910787); + }) +} + +#[bench] +fn bench_str_over_8_bytes(b: &mut Bencher) { + let s = "foobarbaz0"; + b.iter(|| { + assert_eq!(hash(&s), 10581415515220175264); + }) +} + +#[bench] +fn bench_long_str(b: &mut Bencher) { + let s = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor \ +incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud \ +exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute \ +irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla \ +pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui \ +officia deserunt mollit anim id est laborum."; + b.iter(|| { + assert_eq!(hash(&s), 17717065544121360093); + }) +} + +#[bench] +fn bench_u32(b: &mut Bencher) { + let u = 162629500u32; + let u = black_box(u); + b.iter(|| { + hash(&u) + }); + b.bytes = 8; +} + +#[bench] +fn bench_u32_keyed(b: &mut Bencher) { + let u = 162629500u32; + let u = black_box(u); + let k1 = black_box(0x1); + let k2 = black_box(0x2); + b.iter(|| { + hash_with(SipHasher::new_with_keys(k1, k2), &u) + }); + b.bytes = 8; +} + +#[bench] +fn bench_u64(b: &mut Bencher) { + let u = 16262950014981195938u64; + let u = black_box(u); + b.iter(|| { + hash(&u) + }); + b.bytes = 8; +} + +#[bench] +fn bench_bytes_4(b: &mut Bencher) { + let data = black_box([b' '; 4]); + b.iter(|| { + hash_bytes(SipHasher::default(), &data) + }); + b.bytes = 4; +} + +#[bench] +fn bench_bytes_7(b: &mut Bencher) { + let data = black_box([b' '; 7]); + b.iter(|| { + hash_bytes(SipHasher::default(), &data) + }); + b.bytes = 7; +} + +#[bench] +fn bench_bytes_8(b: &mut Bencher) { + let data = black_box([b' '; 8]); + b.iter(|| { + hash_bytes(SipHasher::default(), &data) + }); + b.bytes = 8; +} + +#[bench] +fn bench_bytes_a_16(b: &mut Bencher) { + let data = black_box([b' '; 16]); + b.iter(|| { + hash_bytes(SipHasher::default(), &data) + }); + b.bytes = 16; +} + +#[bench] +fn bench_bytes_b_32(b: &mut Bencher) { + let data = black_box([b' '; 32]); + b.iter(|| { + hash_bytes(SipHasher::default(), &data) + }); + b.bytes = 32; +} + +#[bench] +fn bench_bytes_c_128(b: &mut Bencher) { + let data = black_box([b' '; 128]); + b.iter(|| { + hash_bytes(SipHasher::default(), &data) + }); + b.bytes = 128; +} diff --git a/src/libcore/bench/iter.rs b/src/libcore/bench/iter.rs new file mode 100644 index 0000000000000..93d38a5bc83bb --- /dev/null +++ b/src/libcore/bench/iter.rs @@ -0,0 +1,101 @@ +// 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. + +use core::iter::*; +use test::{Bencher, black_box}; + +#[bench] +fn bench_rposition(b: &mut Bencher) { + let it: Vec = (0..300).collect(); + b.iter(|| { + it.iter().rposition(|&x| x <= 150); + }); +} + +#[bench] +fn bench_skip_while(b: &mut Bencher) { + b.iter(|| { + let it = 0..100; + let mut sum = 0; + it.skip_while(|&x| { sum += x; sum < 4000 }).all(|_| true); + }); +} + +#[bench] +fn bench_multiple_take(b: &mut Bencher) { + let mut it = (0..42).cycle(); + b.iter(|| { + let n = it.next().unwrap(); + for _ in 0..n { + it.clone().take(it.next().unwrap()).all(|_| true); + } + }); +} + +fn scatter(x: i32) -> i32 { (x * 31) % 127 } + +#[bench] +fn bench_max_by_key(b: &mut Bencher) { + b.iter(|| { + let it = 0..100; + it.max_by_key(|&x| scatter(x)) + }) +} + +// http://www.reddit.com/r/rust/comments/31syce/using_iterators_to_find_the_index_of_the_min_or/ +#[bench] +fn bench_max_by_key2(b: &mut Bencher) { + fn max_index_iter(array: &[i32]) -> usize { + array.iter().enumerate().max_by_key(|&(_, item)| item).unwrap().0 + } + + let mut data = vec![0; 1638]; + data[514] = 9999; + + b.iter(|| max_index_iter(&data)); +} + +#[bench] +fn bench_max(b: &mut Bencher) { + b.iter(|| { + let it = 0..100; + it.map(scatter).max() + }) +} + +pub fn copy_zip(xs: &[u8], ys: &mut [u8]) { + for (a, b) in ys.iter_mut().zip(xs) { + *a = *b; + } +} + +pub fn add_zip(xs: &[f32], ys: &mut [f32]) { + for (a, b) in ys.iter_mut().zip(xs) { + *a += *b; + } +} + +#[bench] +fn bench_zip_copy(b: &mut Bencher) { + let source = vec![0u8; 16 * 1024]; + let mut dst = black_box(vec![0u8; 16 * 1024]); + b.iter(|| { + copy_zip(&source, &mut dst) + }) +} + +#[bench] +fn bench_zip_add(b: &mut Bencher) { + let source = vec![1.; 16 * 1024]; + let mut dst = vec![0.; 16 * 1024]; + b.iter(|| { + add_zip(&source, &mut dst) + }); +} diff --git a/src/libcore/bench/lib.rs b/src/libcore/bench/lib.rs new file mode 100644 index 0000000000000..d2db329da7999 --- /dev/null +++ b/src/libcore/bench/lib.rs @@ -0,0 +1,25 @@ +// 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. + +#![deny(warnings)] + +#![feature(flt2dec)] +#![feature(slice_patterns)] +#![feature(test)] + +extern crate core; +extern crate test; + +mod any; +mod hash; +mod iter; +mod mem; +mod num; +mod ops; diff --git a/src/libcore/bench/mem.rs b/src/libcore/bench/mem.rs new file mode 100644 index 0000000000000..8e541d92a7f17 --- /dev/null +++ b/src/libcore/bench/mem.rs @@ -0,0 +1,70 @@ +// 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. + +use test::Bencher; + +// FIXME #13642 (these benchmarks should be in another place) +// Completely miscellaneous language-construct benchmarks. +// Static/dynamic method dispatch + +struct Struct { + field: isize +} + +trait Trait { + fn method(&self) -> isize; +} + +impl Trait for Struct { + fn method(&self) -> isize { + self.field + } +} + +#[bench] +fn trait_vtable_method_call(b: &mut Bencher) { + let s = Struct { field: 10 }; + let t = &s as &Trait; + b.iter(|| { + t.method() + }); +} + +#[bench] +fn trait_static_method_call(b: &mut Bencher) { + let s = Struct { field: 10 }; + b.iter(|| { + s.method() + }); +} + +// Overhead of various match forms + +#[bench] +fn match_option_some(b: &mut Bencher) { + let x = Some(10); + b.iter(|| { + match x { + Some(y) => y, + None => 11 + } + }); +} + +#[bench] +fn match_vec_pattern(b: &mut Bencher) { + let x = [1,2,3,4,5,6]; + b.iter(|| { + match x { + [1,2,3,..] => 10, + _ => 11, + } + }); +} diff --git a/src/libcore/bench/num/dec2flt/mod.rs b/src/libcore/bench/num/dec2flt/mod.rs new file mode 100644 index 0000000000000..562866e11777c --- /dev/null +++ b/src/libcore/bench/num/dec2flt/mod.rs @@ -0,0 +1,68 @@ +// 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. + +use std::f64; +use test::Bencher; + +#[bench] +fn bench_0(b: &mut Bencher) { + b.iter(|| "0.0".parse::()); +} + +#[bench] +fn bench_42(b: &mut Bencher) { + b.iter(|| "42".parse::()); +} + +#[bench] +fn bench_huge_int(b: &mut Bencher) { + // 2^128 - 1 + b.iter(|| "170141183460469231731687303715884105727".parse::()); +} + +#[bench] +fn bench_short_decimal(b: &mut Bencher) { + b.iter(|| "1234.5678".parse::()); +} + +#[bench] +fn bench_pi_long(b: &mut Bencher) { + b.iter(|| "3.14159265358979323846264338327950288".parse::()); +} + +#[bench] +fn bench_pi_short(b: &mut Bencher) { + b.iter(|| "3.141592653589793".parse::()) +} + +#[bench] +fn bench_1e150(b: &mut Bencher) { + b.iter(|| "1e150".parse::()); +} + +#[bench] +fn bench_long_decimal_and_exp(b: &mut Bencher) { + b.iter(|| "727501488517303786137132964064381141071e-123".parse::()); +} + +#[bench] +fn bench_min_subnormal(b: &mut Bencher) { + b.iter(|| "5e-324".parse::()); +} + +#[bench] +fn bench_min_normal(b: &mut Bencher) { + b.iter(|| "2.2250738585072014e-308".parse::()); +} + +#[bench] +fn bench_max(b: &mut Bencher) { + b.iter(|| "1.7976931348623157e308".parse::()); +} diff --git a/src/libcore/bench/num/flt2dec/mod.rs b/src/libcore/bench/num/flt2dec/mod.rs new file mode 100644 index 0000000000000..1de2bf4921f58 --- /dev/null +++ b/src/libcore/bench/num/flt2dec/mod.rs @@ -0,0 +1,24 @@ +// 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. + +mod strategy { + mod dragon; + mod grisu; +} + +use core::num::flt2dec::{decode, DecodableFloat, FullDecoded, Decoded}; +use core::num::flt2dec::MAX_SIG_DIGITS; + +pub fn decode_finite(v: T) -> Decoded { + match decode(v).1 { + FullDecoded::Finite(decoded) => decoded, + full_decoded => panic!("expected finite, got {:?} instead", full_decoded) + } +} diff --git a/src/libcore/bench/num/flt2dec/strategy/dragon.rs b/src/libcore/bench/num/flt2dec/strategy/dragon.rs new file mode 100644 index 0000000000000..6824cf40ed2ae --- /dev/null +++ b/src/libcore/bench/num/flt2dec/strategy/dragon.rs @@ -0,0 +1,70 @@ +// 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. + +use std::{i16, f64}; +use super::super::*; +use core::num::flt2dec::strategy::dragon::*; +use test::Bencher; + +#[bench] +fn bench_small_shortest(b: &mut Bencher) { + let decoded = decode_finite(3.141592f64); + let mut buf = [0; MAX_SIG_DIGITS]; + b.iter(|| format_shortest(&decoded, &mut buf)); +} + +#[bench] +fn bench_big_shortest(b: &mut Bencher) { + let decoded = decode_finite(f64::MAX); + let mut buf = [0; MAX_SIG_DIGITS]; + b.iter(|| format_shortest(&decoded, &mut buf)); +} + +#[bench] +fn bench_small_exact_3(b: &mut Bencher) { + let decoded = decode_finite(3.141592f64); + let mut buf = [0; 3]; + b.iter(|| format_exact(&decoded, &mut buf, i16::MIN)); +} + +#[bench] +fn bench_big_exact_3(b: &mut Bencher) { + let decoded = decode_finite(f64::MAX); + let mut buf = [0; 3]; + b.iter(|| format_exact(&decoded, &mut buf, i16::MIN)); +} + +#[bench] +fn bench_small_exact_12(b: &mut Bencher) { + let decoded = decode_finite(3.141592f64); + let mut buf = [0; 12]; + b.iter(|| format_exact(&decoded, &mut buf, i16::MIN)); +} + +#[bench] +fn bench_big_exact_12(b: &mut Bencher) { + let decoded = decode_finite(f64::MAX); + let mut buf = [0; 12]; + b.iter(|| format_exact(&decoded, &mut buf, i16::MIN)); +} + +#[bench] +fn bench_small_exact_inf(b: &mut Bencher) { + let decoded = decode_finite(3.141592f64); + let mut buf = [0; 1024]; + b.iter(|| format_exact(&decoded, &mut buf, i16::MIN)); +} + +#[bench] +fn bench_big_exact_inf(b: &mut Bencher) { + let decoded = decode_finite(f64::MAX); + let mut buf = [0; 1024]; + b.iter(|| format_exact(&decoded, &mut buf, i16::MIN)); +} diff --git a/src/libcore/bench/num/flt2dec/strategy/grisu.rs b/src/libcore/bench/num/flt2dec/strategy/grisu.rs new file mode 100644 index 0000000000000..82e1a858fca9f --- /dev/null +++ b/src/libcore/bench/num/flt2dec/strategy/grisu.rs @@ -0,0 +1,77 @@ +// 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. + +use std::{i16, f64}; +use super::super::*; +use core::num::flt2dec::strategy::grisu::*; +use test::Bencher; + +pub fn decode_finite(v: T) -> Decoded { + match decode(v).1 { + FullDecoded::Finite(decoded) => decoded, + full_decoded => panic!("expected finite, got {:?} instead", full_decoded) + } +} + +#[bench] +fn bench_small_shortest(b: &mut Bencher) { + let decoded = decode_finite(3.141592f64); + let mut buf = [0; MAX_SIG_DIGITS]; + b.iter(|| format_shortest(&decoded, &mut buf)); +} + +#[bench] +fn bench_big_shortest(b: &mut Bencher) { + let decoded = decode_finite(f64::MAX); + let mut buf = [0; MAX_SIG_DIGITS]; + b.iter(|| format_shortest(&decoded, &mut buf)); +} + +#[bench] +fn bench_small_exact_3(b: &mut Bencher) { + let decoded = decode_finite(3.141592f64); + let mut buf = [0; 3]; + b.iter(|| format_exact(&decoded, &mut buf, i16::MIN)); +} + +#[bench] +fn bench_big_exact_3(b: &mut Bencher) { + let decoded = decode_finite(f64::MAX); + let mut buf = [0; 3]; + b.iter(|| format_exact(&decoded, &mut buf, i16::MIN)); +} + +#[bench] +fn bench_small_exact_12(b: &mut Bencher) { + let decoded = decode_finite(3.141592f64); + let mut buf = [0; 12]; + b.iter(|| format_exact(&decoded, &mut buf, i16::MIN)); +} + +#[bench] +fn bench_big_exact_12(b: &mut Bencher) { + let decoded = decode_finite(f64::MAX); + let mut buf = [0; 12]; + b.iter(|| format_exact(&decoded, &mut buf, i16::MIN)); +} + +#[bench] +fn bench_small_exact_inf(b: &mut Bencher) { + let decoded = decode_finite(3.141592f64); + let mut buf = [0; 1024]; + b.iter(|| format_exact(&decoded, &mut buf, i16::MIN)); +} + +#[bench] +fn bench_big_exact_inf(b: &mut Bencher) { + let decoded = decode_finite(f64::MAX); + let mut buf = [0; 1024]; + b.iter(|| format_exact(&decoded, &mut buf, i16::MIN)); +} diff --git a/src/libcore/bench/num/mod.rs b/src/libcore/bench/num/mod.rs new file mode 100644 index 0000000000000..55f0bdb57ec82 --- /dev/null +++ b/src/libcore/bench/num/mod.rs @@ -0,0 +1,12 @@ +// 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. + +mod flt2dec; +mod dec2flt; diff --git a/src/libcore/bench/ops.rs b/src/libcore/bench/ops.rs new file mode 100644 index 0000000000000..7f36a4b0771aa --- /dev/null +++ b/src/libcore/bench/ops.rs @@ -0,0 +1,30 @@ +// 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. + +use core::ops::*; +use test::Bencher; + +// Overhead of dtors + +struct HasDtor { + _x: isize +} + +impl Drop for HasDtor { + fn drop(&mut self) { + } +} + +#[bench] +fn alloc_obj_with_dtor(b: &mut Bencher) { + b.iter(|| { + HasDtor { _x : 10 }; + }) +} diff --git a/src/libcoretest/any.rs b/src/libcoretest/any.rs index a9fc8913182b3..2d3e81aa131ed 100644 --- a/src/libcoretest/any.rs +++ b/src/libcoretest/any.rs @@ -7,9 +7,8 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. + use core::any::*; -use test::Bencher; -use test; #[derive(PartialEq, Debug)] struct Test; @@ -124,13 +123,3 @@ fn any_unsized() { fn is_any() {} is_any::<[i32]>(); } - -#[bench] -fn bench_downcast_ref(b: &mut Bencher) { - b.iter(|| { - let mut x = 0; - let mut y = &mut x as &mut Any; - test::black_box(&mut y); - test::black_box(y.downcast_ref::() == Some(&0)); - }); -} diff --git a/src/libcoretest/hash/sip.rs b/src/libcoretest/hash/sip.rs index fa3bfdea42df8..4a9657e03404a 100644 --- a/src/libcoretest/hash/sip.rs +++ b/src/libcoretest/hash/sip.rs @@ -10,8 +10,6 @@ #![allow(deprecated)] -use test::{Bencher, black_box}; - use core::hash::{Hash, Hasher}; use core::hash::{SipHasher, SipHasher13, SipHasher24}; use core::{slice, mem}; @@ -58,11 +56,6 @@ fn hash(x: &T) -> u64 { hash_with(SipHasher::new(), x) } -fn hash_bytes(mut s: H, x: &[u8]) -> u64 { - Hasher::write(&mut s, x); - s.finish() -} - #[test] #[allow(unused_must_use)] fn test_siphash_1_3() { @@ -347,126 +340,3 @@ fn test_write_short_works() { h2.write(&[0xFFu8, 0x01u8]); assert_eq!(h1.finish(), h2.finish()); } - -#[bench] -fn bench_str_under_8_bytes(b: &mut Bencher) { - let s = "foo"; - b.iter(|| { - assert_eq!(hash(&s), 16262950014981195938); - }) -} - -#[bench] -fn bench_str_of_8_bytes(b: &mut Bencher) { - let s = "foobar78"; - b.iter(|| { - assert_eq!(hash(&s), 4898293253460910787); - }) -} - -#[bench] -fn bench_str_over_8_bytes(b: &mut Bencher) { - let s = "foobarbaz0"; - b.iter(|| { - assert_eq!(hash(&s), 10581415515220175264); - }) -} - -#[bench] -fn bench_long_str(b: &mut Bencher) { - let s = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor \ -incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud \ -exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute \ -irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla \ -pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui \ -officia deserunt mollit anim id est laborum."; - b.iter(|| { - assert_eq!(hash(&s), 17717065544121360093); - }) -} - -#[bench] -fn bench_u32(b: &mut Bencher) { - let u = 162629500u32; - let u = black_box(u); - b.iter(|| { - hash(&u) - }); - b.bytes = 8; -} - -#[bench] -fn bench_u32_keyed(b: &mut Bencher) { - let u = 162629500u32; - let u = black_box(u); - let k1 = black_box(0x1); - let k2 = black_box(0x2); - b.iter(|| { - hash_with(SipHasher::new_with_keys(k1, k2), &u) - }); - b.bytes = 8; -} - -#[bench] -fn bench_u64(b: &mut Bencher) { - let u = 16262950014981195938u64; - let u = black_box(u); - b.iter(|| { - hash(&u) - }); - b.bytes = 8; -} - -#[bench] -fn bench_bytes_4(b: &mut Bencher) { - let data = black_box([b' '; 4]); - b.iter(|| { - hash_bytes(SipHasher::default(), &data) - }); - b.bytes = 4; -} - -#[bench] -fn bench_bytes_7(b: &mut Bencher) { - let data = black_box([b' '; 7]); - b.iter(|| { - hash_bytes(SipHasher::default(), &data) - }); - b.bytes = 7; -} - -#[bench] -fn bench_bytes_8(b: &mut Bencher) { - let data = black_box([b' '; 8]); - b.iter(|| { - hash_bytes(SipHasher::default(), &data) - }); - b.bytes = 8; -} - -#[bench] -fn bench_bytes_a_16(b: &mut Bencher) { - let data = black_box([b' '; 16]); - b.iter(|| { - hash_bytes(SipHasher::default(), &data) - }); - b.bytes = 16; -} - -#[bench] -fn bench_bytes_b_32(b: &mut Bencher) { - let data = black_box([b' '; 32]); - b.iter(|| { - hash_bytes(SipHasher::default(), &data) - }); - b.bytes = 32; -} - -#[bench] -fn bench_bytes_c_128(b: &mut Bencher) { - let data = black_box([b' '; 128]); - b.iter(|| { - hash_bytes(SipHasher::default(), &data) - }); - b.bytes = 128; -} diff --git a/src/libcoretest/iter.rs b/src/libcoretest/iter.rs index 6d02f76c33d16..89f59a9c2de76 100644 --- a/src/libcoretest/iter.rs +++ b/src/libcoretest/iter.rs @@ -12,9 +12,6 @@ use core::iter::*; use core::{i8, i16, isize}; use core::usize; -use test::Bencher; -use test::black_box; - #[test] fn test_lt() { let empty: [isize; 0] = []; @@ -1079,91 +1076,3 @@ fn test_chain_fold() { assert_eq!(&[2, 3, 1, 2, 0], &result[..]); } -#[bench] -fn bench_rposition(b: &mut Bencher) { - let it: Vec = (0..300).collect(); - b.iter(|| { - it.iter().rposition(|&x| x <= 150); - }); -} - -#[bench] -fn bench_skip_while(b: &mut Bencher) { - b.iter(|| { - let it = 0..100; - let mut sum = 0; - it.skip_while(|&x| { sum += x; sum < 4000 }).all(|_| true); - }); -} - -#[bench] -fn bench_multiple_take(b: &mut Bencher) { - let mut it = (0..42).cycle(); - b.iter(|| { - let n = it.next().unwrap(); - for _ in 0..n { - it.clone().take(it.next().unwrap()).all(|_| true); - } - }); -} - -fn scatter(x: i32) -> i32 { (x * 31) % 127 } - -#[bench] -fn bench_max_by_key(b: &mut Bencher) { - b.iter(|| { - let it = 0..100; - it.max_by_key(|&x| scatter(x)) - }) -} - -// http://www.reddit.com/r/rust/comments/31syce/using_iterators_to_find_the_index_of_the_min_or/ -#[bench] -fn bench_max_by_key2(b: &mut Bencher) { - fn max_index_iter(array: &[i32]) -> usize { - array.iter().enumerate().max_by_key(|&(_, item)| item).unwrap().0 - } - - let mut data = vec![0; 1638]; - data[514] = 9999; - - b.iter(|| max_index_iter(&data)); -} - -#[bench] -fn bench_max(b: &mut Bencher) { - b.iter(|| { - let it = 0..100; - it.map(scatter).max() - }) -} - -pub fn copy_zip(xs: &[u8], ys: &mut [u8]) { - for (a, b) in ys.iter_mut().zip(xs) { - *a = *b; - } -} - -pub fn add_zip(xs: &[f32], ys: &mut [f32]) { - for (a, b) in ys.iter_mut().zip(xs) { - *a += *b; - } -} - -#[bench] -fn bench_zip_copy(b: &mut Bencher) { - let source = vec![0u8; 16 * 1024]; - let mut dst = black_box(vec![0u8; 16 * 1024]); - b.iter(|| { - copy_zip(&source, &mut dst) - }) -} - -#[bench] -fn bench_zip_add(b: &mut Bencher) { - let source = vec![1.; 16 * 1024]; - let mut dst = vec![0.; 16 * 1024]; - b.iter(|| { - add_zip(&source, &mut dst) - }); -} diff --git a/src/libcoretest/mem.rs b/src/libcoretest/mem.rs index 01bafe49a7acd..86e59c736ba4a 100644 --- a/src/libcoretest/mem.rs +++ b/src/libcoretest/mem.rs @@ -7,8 +7,8 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. + use core::mem::*; -use test::Bencher; #[test] fn size_of_basic() { @@ -121,61 +121,3 @@ fn test_transmute() { } } -// FIXME #13642 (these benchmarks should be in another place) -/// Completely miscellaneous language-construct benchmarks. -// Static/dynamic method dispatch - -struct Struct { - field: isize -} - -trait Trait { - fn method(&self) -> isize; -} - -impl Trait for Struct { - fn method(&self) -> isize { - self.field - } -} - -#[bench] -fn trait_vtable_method_call(b: &mut Bencher) { - let s = Struct { field: 10 }; - let t = &s as &Trait; - b.iter(|| { - t.method() - }); -} - -#[bench] -fn trait_static_method_call(b: &mut Bencher) { - let s = Struct { field: 10 }; - b.iter(|| { - s.method() - }); -} - -// Overhead of various match forms - -#[bench] -fn match_option_some(b: &mut Bencher) { - let x = Some(10); - b.iter(|| { - match x { - Some(y) => y, - None => 11 - } - }); -} - -#[bench] -fn match_vec_pattern(b: &mut Bencher) { - let x = [1,2,3,4,5,6]; - b.iter(|| { - match x { - [1,2,3,..] => 10, - _ => 11, - } - }); -} diff --git a/src/libcoretest/num/dec2flt/mod.rs b/src/libcoretest/num/dec2flt/mod.rs index fe6f52406fbc8..5d546c643e7ee 100644 --- a/src/libcoretest/num/dec2flt/mod.rs +++ b/src/libcoretest/num/dec2flt/mod.rs @@ -11,7 +11,6 @@ #![allow(overflowing_literals)] use std::{i64, f32, f64}; -use test; mod parse; mod rawfp; @@ -144,59 +143,3 @@ fn borderline_overflow() { // It makes no sense to enshrine that in a test, the important part is that it doesn't panic. let _ = s.parse::(); } - -#[bench] -fn bench_0(b: &mut test::Bencher) { - b.iter(|| "0.0".parse::()); -} - -#[bench] -fn bench_42(b: &mut test::Bencher) { - b.iter(|| "42".parse::()); -} - -#[bench] -fn bench_huge_int(b: &mut test::Bencher) { - // 2^128 - 1 - b.iter(|| "170141183460469231731687303715884105727".parse::()); -} - -#[bench] -fn bench_short_decimal(b: &mut test::Bencher) { - b.iter(|| "1234.5678".parse::()); -} - -#[bench] -fn bench_pi_long(b: &mut test::Bencher) { - b.iter(|| "3.14159265358979323846264338327950288".parse::()); -} - -#[bench] -fn bench_pi_short(b: &mut test::Bencher) { - b.iter(|| "3.141592653589793".parse::()) -} - -#[bench] -fn bench_1e150(b: &mut test::Bencher) { - b.iter(|| "1e150".parse::()); -} - -#[bench] -fn bench_long_decimal_and_exp(b: &mut test::Bencher) { - b.iter(|| "727501488517303786137132964064381141071e-123".parse::()); -} - -#[bench] -fn bench_min_subnormal(b: &mut test::Bencher) { - b.iter(|| "5e-324".parse::()); -} - -#[bench] -fn bench_min_normal(b: &mut test::Bencher) { - b.iter(|| "2.2250738585072014e-308".parse::()); -} - -#[bench] -fn bench_max(b: &mut test::Bencher) { - b.iter(|| "1.7976931348623157e308".parse::()); -} diff --git a/src/libcoretest/num/flt2dec/strategy/dragon.rs b/src/libcoretest/num/flt2dec/strategy/dragon.rs index 08c2cd0a7326f..4edb0f3df60c4 100644 --- a/src/libcoretest/num/flt2dec/strategy/dragon.rs +++ b/src/libcoretest/num/flt2dec/strategy/dragon.rs @@ -9,7 +9,6 @@ // except according to those terms. use std::prelude::v1::*; -use std::{i16, f64}; use super::super::*; use core::num::bignum::Big32x40 as Big; use core::num::flt2dec::strategy::dragon::*; @@ -53,62 +52,6 @@ fn exact_sanity_test() { f32_exact_sanity_test(format_exact); } -#[bench] -fn bench_small_shortest(b: &mut Bencher) { - let decoded = decode_finite(3.141592f64); - let mut buf = [0; MAX_SIG_DIGITS]; - b.iter(|| format_shortest(&decoded, &mut buf)); -} - -#[bench] -fn bench_big_shortest(b: &mut Bencher) { - let decoded = decode_finite(f64::MAX); - let mut buf = [0; MAX_SIG_DIGITS]; - b.iter(|| format_shortest(&decoded, &mut buf)); -} - -#[bench] -fn bench_small_exact_3(b: &mut Bencher) { - let decoded = decode_finite(3.141592f64); - let mut buf = [0; 3]; - b.iter(|| format_exact(&decoded, &mut buf, i16::MIN)); -} - -#[bench] -fn bench_big_exact_3(b: &mut Bencher) { - let decoded = decode_finite(f64::MAX); - let mut buf = [0; 3]; - b.iter(|| format_exact(&decoded, &mut buf, i16::MIN)); -} - -#[bench] -fn bench_small_exact_12(b: &mut Bencher) { - let decoded = decode_finite(3.141592f64); - let mut buf = [0; 12]; - b.iter(|| format_exact(&decoded, &mut buf, i16::MIN)); -} - -#[bench] -fn bench_big_exact_12(b: &mut Bencher) { - let decoded = decode_finite(f64::MAX); - let mut buf = [0; 12]; - b.iter(|| format_exact(&decoded, &mut buf, i16::MIN)); -} - -#[bench] -fn bench_small_exact_inf(b: &mut Bencher) { - let decoded = decode_finite(3.141592f64); - let mut buf = [0; 1024]; - b.iter(|| format_exact(&decoded, &mut buf, i16::MIN)); -} - -#[bench] -fn bench_big_exact_inf(b: &mut Bencher) { - let decoded = decode_finite(f64::MAX); - let mut buf = [0; 1024]; - b.iter(|| format_exact(&decoded, &mut buf, i16::MIN)); -} - #[test] fn test_to_shortest_str() { to_shortest_str_test(format_shortest); diff --git a/src/libcoretest/num/flt2dec/strategy/grisu.rs b/src/libcoretest/num/flt2dec/strategy/grisu.rs index 311bd252353c7..79e66ee669e14 100644 --- a/src/libcoretest/num/flt2dec/strategy/grisu.rs +++ b/src/libcoretest/num/flt2dec/strategy/grisu.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::{i16, f64}; +use std::i16; use super::super::*; use core::num::flt2dec::strategy::grisu::*; @@ -102,62 +102,6 @@ fn exact_f64_random_equivalence_test() { } } -#[bench] -fn bench_small_shortest(b: &mut Bencher) { - let decoded = decode_finite(3.141592f64); - let mut buf = [0; MAX_SIG_DIGITS]; - b.iter(|| format_shortest(&decoded, &mut buf)); -} - -#[bench] -fn bench_big_shortest(b: &mut Bencher) { - let decoded = decode_finite(f64::MAX); - let mut buf = [0; MAX_SIG_DIGITS]; - b.iter(|| format_shortest(&decoded, &mut buf)); -} - -#[bench] -fn bench_small_exact_3(b: &mut Bencher) { - let decoded = decode_finite(3.141592f64); - let mut buf = [0; 3]; - b.iter(|| format_exact(&decoded, &mut buf, i16::MIN)); -} - -#[bench] -fn bench_big_exact_3(b: &mut Bencher) { - let decoded = decode_finite(f64::MAX); - let mut buf = [0; 3]; - b.iter(|| format_exact(&decoded, &mut buf, i16::MIN)); -} - -#[bench] -fn bench_small_exact_12(b: &mut Bencher) { - let decoded = decode_finite(3.141592f64); - let mut buf = [0; 12]; - b.iter(|| format_exact(&decoded, &mut buf, i16::MIN)); -} - -#[bench] -fn bench_big_exact_12(b: &mut Bencher) { - let decoded = decode_finite(f64::MAX); - let mut buf = [0; 12]; - b.iter(|| format_exact(&decoded, &mut buf, i16::MIN)); -} - -#[bench] -fn bench_small_exact_inf(b: &mut Bencher) { - let decoded = decode_finite(3.141592f64); - let mut buf = [0; 1024]; - b.iter(|| format_exact(&decoded, &mut buf, i16::MIN)); -} - -#[bench] -fn bench_big_exact_inf(b: &mut Bencher) { - let decoded = decode_finite(f64::MAX); - let mut buf = [0; 1024]; - b.iter(|| format_exact(&decoded, &mut buf, i16::MIN)); -} - #[test] fn test_to_shortest_str() { to_shortest_str_test(format_shortest); diff --git a/src/libcoretest/ops.rs b/src/libcoretest/ops.rs index 33674a3abd870..1c6c13b0d02e8 100644 --- a/src/libcoretest/ops.rs +++ b/src/libcoretest/ops.rs @@ -8,27 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use test::Bencher; use core::ops::{Range, RangeFull, RangeFrom, RangeTo}; -// Overhead of dtors - -struct HasDtor { - _x: isize -} - -impl Drop for HasDtor { - fn drop(&mut self) { - } -} - -#[bench] -fn alloc_obj_with_dtor(b: &mut Bencher) { - b.iter(|| { - HasDtor { _x : 10 }; - }) -} - // Test the Range structs without the syntactic sugar. #[test] From efeb42be2837842d1beb47b51bb693c7474aba3d Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Sat, 4 Feb 2017 01:10:12 +0100 Subject: [PATCH 108/137] Use less syscalls in `FileDesc::set_{nonblocking,cloexec}` Only set the flags if they differ from what the OS reported, use `FIONBIO` to atomically set the non-blocking IO flag on Linux. --- src/libstd/sys/unix/fd.rs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/libstd/sys/unix/fd.rs b/src/libstd/sys/unix/fd.rs index dcab30aad8385..c690fd467ee41 100644 --- a/src/libstd/sys/unix/fd.rs +++ b/src/libstd/sys/unix/fd.rs @@ -144,11 +144,24 @@ impl FileDesc { pub fn set_cloexec(&self) -> io::Result<()> { unsafe { let previous = cvt(libc::fcntl(self.fd, libc::F_GETFD))?; - cvt(libc::fcntl(self.fd, libc::F_SETFD, previous | libc::FD_CLOEXEC))?; + let new = previous | libc::FD_CLOEXEC; + if new != previous { + cvt(libc::fcntl(self.fd, libc::F_SETFD, new))?; + } + Ok(()) + } + } + + #[cfg(target_os = "linux")] + pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { + unsafe { + let v = nonblocking as c_int; + cvt(libc::ioctl(self.fd, libc::FIONBIO, &v))?; Ok(()) } } + #[cfg(not(target_os = "linux"))] pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { unsafe { let previous = cvt(libc::fcntl(self.fd, libc::F_GETFL))?; @@ -157,7 +170,9 @@ impl FileDesc { } else { previous & !libc::O_NONBLOCK }; - cvt(libc::fcntl(self.fd, libc::F_SETFL, new))?; + if new != previous { + cvt(libc::fcntl(self.fd, libc::F_SETFL, new))?; + } Ok(()) } } From d650cf5c383aeed222e835009c28901c236820e1 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sat, 4 Feb 2017 01:12:38 +0000 Subject: [PATCH 109/137] Update relnotes for 1.15.1 I already checked this into stable, but it needs to be on master/beta too. --- RELEASES.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/RELEASES.md b/RELEASES.md index 99d6b7709ede9..f26c0b6b61161 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,11 @@ +Version 1.15.1 (2017-02-07) +=========================== + +* [Fix IntoIter::as_mut_slice's signature][39466] + +[39466]: https://github.com/rust-lang/rust/pull/39466 + + Version 1.15.0 (2017-02-02) =========================== From 3c161393b717c35702c164e5099cc6a34a5ddc80 Mon Sep 17 00:00:00 2001 From: est31 Date: Thu, 2 Feb 2017 22:32:20 +0100 Subject: [PATCH 110/137] Don't use "unadjusted" ABI on non windows platforms We introduced the unadjusted ABI to work around wrong (buggy) ABI expectations by LLVM on Windows [1]. Therefore, it should be solely used on Windows and not on other platforms, like right now is the case. [1]: see this comment for details https://github.com/rust-lang/rust/pull/38482#issuecomment-269074031 --- src/libcompiler_builtins/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libcompiler_builtins/lib.rs b/src/libcompiler_builtins/lib.rs index b2a615456aa59..4634301058b25 100644 --- a/src/libcompiler_builtins/lib.rs +++ b/src/libcompiler_builtins/lib.rs @@ -652,17 +652,17 @@ pub mod reimpls { } #[export_name="__fixunssfti"] - pub extern "unadjusted" fn f32_as_u128(a: f32) -> u128 { + pub extern $unadj fn f32_as_u128(a: f32) -> u128 { float_as_unsigned!(a, f32, u128) } #[export_name="__fixdfti"] - pub extern "unadjusted" fn f64_as_i128(a: f64) -> i128 { + pub extern $unadj fn f64_as_i128(a: f64) -> i128 { float_as_signed!(a, f64, i128) } #[export_name="__fixsfti"] - pub extern "unadjusted" fn f32_as_i128(a: f32) -> i128 { + pub extern $unadj fn f32_as_i128(a: f32) -> i128 { float_as_signed!(a, f32, i128) } From 2fc15868a2cd5a24cfe059457e40cbcad6da2d44 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 3 Feb 2017 21:13:59 -0500 Subject: [PATCH 111/137] go back to the older model of coherence collect --- src/librustc/dep_graph/dep_tracking_map.rs | 15 +++++++ src/librustc_typeck/coherence/mod.rs | 47 +++++++++++++--------- 2 files changed, 43 insertions(+), 19 deletions(-) diff --git a/src/librustc/dep_graph/dep_tracking_map.rs b/src/librustc/dep_graph/dep_tracking_map.rs index ad6c93bf8daac..2ffc3951cc94d 100644 --- a/src/librustc/dep_graph/dep_tracking_map.rs +++ b/src/librustc/dep_graph/dep_tracking_map.rs @@ -75,6 +75,21 @@ impl DepTrackingMap { pub fn keys(&self) -> Vec { self.map.keys().cloned().collect() } + + /// Append `elem` to the vector stored for `k`, creating a new vector if needed. + /// This is considered a write to `k`. + /// + /// NOTE: Caution is required when using this method. You should + /// be sure that nobody is **reading from the vector** while you + /// are writing to it. Eventually, it'd be nice to remove this. + pub fn push(&mut self, k: M::Key, elem: E) + where M: DepTrackingMapConfig> + { + self.write(&k); + self.map.entry(k) + .or_insert(Vec::new()) + .push(elem); + } } impl MemoizationMap for RefCell> { diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index 4a96a5e960dbe..b6a863fd2ed0d 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -15,8 +15,9 @@ // done by the orphan and overlap modules. Then we build up various // mappings. That mapping code resides here. +use dep_graph::DepTrackingMap; use hir::def_id::DefId; -use rustc::ty::{self, TyCtxt, TypeFoldable}; +use rustc::ty::{self, maps, TyCtxt, TypeFoldable}; use rustc::ty::{Ty, TyBool, TyChar, TyError}; use rustc::ty::{TyParam, TyRawPtr}; use rustc::ty::{TyRef, TyAdt, TyDynamic, TyNever, TyTuple}; @@ -29,7 +30,7 @@ use rustc::dep_graph::DepNode; use rustc::hir::itemlikevisit::ItemLikeVisitor; use rustc::hir::{Item, ItemImpl}; use rustc::hir; -use rustc::util::nodemap::DefIdMap; +use std::cell::RefMut; mod builtin; mod orphan; @@ -38,7 +39,7 @@ mod unsafety; struct CoherenceCollect<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, - inherent_impls: DefIdMap>, + inherent_impls: RefMut<'a, DepTrackingMap>>, } impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for CoherenceCollect<'a, 'tcx> { @@ -56,6 +57,16 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for CoherenceCollect<'a, 'tcx> { } impl<'a, 'tcx> CoherenceCollect<'a, 'tcx> { + fn check(tcx: TyCtxt<'a, 'tcx, 'tcx>) { + let inherent_impls = tcx.inherent_impls.borrow_mut(); + let mut this = &mut CoherenceCollect { tcx, inherent_impls }; + + // Check implementations and traits. This populates the tables + // containing the inherent methods and extension methods. It also + // builds up the trait inheritance table. + tcx.visit_all_item_likes_in_krate(DepNode::CoherenceCheckImpl, this); + } + // Returns the def ID of the base type, if there is one. fn get_base_type_def_id(&self, span: Span, ty: Ty<'tcx>) -> Option { match ty.sty { @@ -77,18 +88,6 @@ impl<'a, 'tcx> CoherenceCollect<'a, 'tcx> { } } - fn check(&mut self) { - // Check implementations and traits. This populates the tables - // containing the inherent methods and extension methods. It also - // builds up the trait inheritance table. - self.tcx.visit_all_item_likes_in_krate(DepNode::CoherenceCheckImpl, self); - - // Transfer the inherent impl lists, not that they are known, into the tcx - for (ty_def_id, impl_def_ids) in self.inherent_impls.drain() { - self.tcx.inherent_impls.borrow_mut().insert(ty_def_id, impl_def_ids); - } - } - fn check_implementation(&mut self, item: &Item) { let tcx = self.tcx; let impl_did = tcx.hir.local_def_id(item.id); @@ -127,9 +126,18 @@ impl<'a, 'tcx> CoherenceCollect<'a, 'tcx> { } fn add_inherent_impl(&mut self, base_def_id: DefId, impl_def_id: DefId) { - self.inherent_impls.entry(base_def_id) - .or_insert(vec![]) - .push(impl_def_id); + // Subtle: it'd be better to collect these into a local map + // and then write the vector only once all items are known, + // but that leads to degenerate dep-graphs. The problem is + // that the write of that big vector winds up having reads + // from *all* impls in the krate, since we've lost the + // precision basically. This would be ok in the firewall + // model so once we've made progess towards that we can modify + // the strategy here. In the meantime, using `push` is ok + // because we are doing this as a pre-pass before anyone + // actually reads from `inherent_impls` -- and we know this is + // true beacuse we hold the refcell lock. + self.inherent_impls.push(base_def_id, impl_def_id); } fn add_trait_impl(&self, impl_trait_ref: ty::TraitRef<'tcx>, impl_def_id: DefId) { @@ -169,8 +177,9 @@ fn enforce_trait_manually_implementable(tcx: TyCtxt, sp: Span, trait_def_id: Def } pub fn check_coherence(ccx: &CrateCtxt) { + CoherenceCollect::check(ccx.tcx); + let _task = ccx.tcx.dep_graph.in_task(DepNode::Coherence); - CoherenceCollect { tcx: ccx.tcx, inherent_impls: DefIdMap() }.check(); unsafety::check(ccx.tcx); orphan::check(ccx.tcx); overlap::check(ccx.tcx); From 7504897e6b4b1121191bc6612bcbcce1f70f5f06 Mon Sep 17 00:00:00 2001 From: Vadim Chugunov Date: Fri, 3 Feb 2017 18:25:20 -0800 Subject: [PATCH 112/137] Don't link "nobundle" libs which had already been included in upstream crate. --- src/librustc_metadata/creader.rs | 3 +++ src/librustc_trans/back/link.rs | 18 ++++++++++---- src/librustc_trans/back/linker.rs | 1 + src/test/run-make/static-nobundle/Makefile | 24 ++++++++++++------- .../run-make/static-nobundle/{foo.c => aaa.c} | 4 ++-- .../static-nobundle/{bar.rs => bbb.rs} | 8 +++---- src/test/run-make/static-nobundle/ccc.rs | 23 ++++++++++++++++++ .../static-nobundle/{main.rs => ddd.rs} | 7 +++--- 8 files changed, 67 insertions(+), 21 deletions(-) rename src/test/run-make/static-nobundle/{foo.c => aaa.c} (82%) rename src/test/run-make/static-nobundle/{bar.rs => bbb.rs} (76%) create mode 100644 src/test/run-make/static-nobundle/ccc.rs rename src/test/run-make/static-nobundle/{main.rs => ddd.rs} (81%) diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 87ba2edbfda7d..a228689363fc3 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -685,6 +685,9 @@ impl<'a> CrateLoader<'a> { for id in self.get_foreign_items_of_kind(cstore::NativeStatic) { self.cstore.add_statically_included_foreign_item(id); } + for id in self.get_foreign_items_of_kind(cstore::NativeStaticNobundle) { + self.cstore.add_statically_included_foreign_item(id); + } } fn register_dllimport_foreign_items(&mut self) { diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index aa42364f951c7..20842ea3fe54d 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -896,7 +896,7 @@ fn link_args(cmd: &mut Linker, // on other dylibs (e.g. other native deps). add_local_native_libraries(cmd, sess); add_upstream_rust_crates(cmd, sess, crate_type, tmpdir); - add_upstream_native_libraries(cmd, sess); + add_upstream_native_libraries(cmd, sess, crate_type); // # Telling the linker what we're doing @@ -1213,7 +1213,7 @@ fn add_upstream_rust_crates(cmd: &mut Linker, // generic function calls a native function, then the generic function must // be instantiated in the target crate, meaning that the native symbol must // also be resolved in the target crate. -fn add_upstream_native_libraries(cmd: &mut Linker, sess: &Session) { +fn add_upstream_native_libraries(cmd: &mut Linker, sess: &Session, crate_type: config::CrateType) { // Be sure to use a topological sorting of crates because there may be // interdependencies between native libraries. When passing -nodefaultlibs, // for example, almost all native libraries depend on libc, so we have to @@ -1223,6 +1223,9 @@ fn add_upstream_native_libraries(cmd: &mut Linker, sess: &Session) { // This passes RequireStatic, but the actual requirement doesn't matter, // we're just getting an ordering of crate numbers, we're not worried about // the paths. + let formats = sess.dependency_formats.borrow(); + let data = formats.get(&crate_type).unwrap(); + let crates = sess.cstore.used_crates(LinkagePreference::RequireStatic); for (cnum, _) in crates { for lib in sess.cstore.native_libraries(cnum) { @@ -1232,8 +1235,15 @@ fn add_upstream_native_libraries(cmd: &mut Linker, sess: &Session) { match lib.kind { NativeLibraryKind::NativeUnknown => cmd.link_dylib(&lib.name.as_str()), NativeLibraryKind::NativeFramework => cmd.link_framework(&lib.name.as_str()), - NativeLibraryKind::NativeStaticNobundle => cmd.link_staticlib(&lib.name.as_str()), - + NativeLibraryKind::NativeStaticNobundle => { + // Link "static-nobundle" native libs only if the crate they originate from + // is being linked statically to the current crate. If it's linked dynamically + // or is an rlib already included via some other dylib crate, the symbols from + // native libs will have already been included in that dylib. + if data[cnum.as_usize() - 1] == Linkage::Static { + cmd.link_staticlib(&lib.name.as_str()) + } + }, // ignore statically included native libraries here as we've // already included them when we included the rust library // previously diff --git a/src/librustc_trans/back/linker.rs b/src/librustc_trans/back/linker.rs index a147b598940a2..7f352f1da517d 100644 --- a/src/librustc_trans/back/linker.rs +++ b/src/librustc_trans/back/linker.rs @@ -450,6 +450,7 @@ impl<'a> Linker for MsvcLinker<'a> { writeln!(f, "LIBRARY")?; writeln!(f, "EXPORTS")?; for symbol in self.info.exports[&crate_type].iter() { + debug!(" _{}", symbol); writeln!(f, " {}", symbol)?; } Ok(()) diff --git a/src/test/run-make/static-nobundle/Makefile b/src/test/run-make/static-nobundle/Makefile index b184d54ff9c6f..3eac12f5cc9fd 100644 --- a/src/test/run-make/static-nobundle/Makefile +++ b/src/test/run-make/static-nobundle/Makefile @@ -1,13 +1,21 @@ -include ../tools.mk -all: $(call NATIVE_STATICLIB,foo) - $(RUSTC) bar.rs +# aaa is a native static library +# bbb is a rlib +# ccc is a dylib +# ddd is an executable - # Check that libbar.rlib does not contain the definition of `func` - nm $(TMPDIR)/libbar.rlib | (! grep "T _*func") - nm $(TMPDIR)/libbar.rlib | grep "U _*func" +all: $(call NATIVE_STATICLIB,aaa) + $(RUSTC) bbb.rs --crate-type=rlib - # Check that foo gets passed to the linker (as either `-l foo` or `foo.lib`) - $(RUSTC) main.rs -Z print-link-args | grep -e "-l[\" ]*foo" -e "foo.lib" + # Check that bbb does NOT contain the definition of `native_func` + nm $(TMPDIR)/libbbb.rlib | (! grep "T _*native_func") + nm $(TMPDIR)/libbbb.rlib | grep "U _*native_func" - $(call RUN,main) + # Check that aaa gets linked (either as `-l aaa` or `aaa.lib`) when building ccc. + $(RUSTC) ccc.rs -C prefer-dynamic --crate-type=dylib -Z print-link-args | grep -e "-l[\" ]*aaa" -e "aaa.lib" + + # Check that aaa does NOT get linked when building ddd. + $(RUSTC) ddd.rs -Z print-link-args | (! grep -e "-l[\" ]*aaa" -e "aaa.lib") + + $(call RUN,ddd) diff --git a/src/test/run-make/static-nobundle/foo.c b/src/test/run-make/static-nobundle/aaa.c similarity index 82% rename from src/test/run-make/static-nobundle/foo.c rename to src/test/run-make/static-nobundle/aaa.c index 5ccf713f79c61..806ef878c7052 100644 --- a/src/test/run-make/static-nobundle/foo.c +++ b/src/test/run-make/static-nobundle/aaa.c @@ -1,4 +1,4 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -8,4 +8,4 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -void func() {} +void native_func() {} diff --git a/src/test/run-make/static-nobundle/bar.rs b/src/test/run-make/static-nobundle/bbb.rs similarity index 76% rename from src/test/run-make/static-nobundle/bar.rs rename to src/test/run-make/static-nobundle/bbb.rs index c5d6237c9d594..2bd69c9932723 100644 --- a/src/test/run-make/static-nobundle/bar.rs +++ b/src/test/run-make/static-nobundle/bbb.rs @@ -1,4 +1,4 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -11,13 +11,13 @@ #![crate_type = "rlib"] #![feature(static_nobundle)] -#[link(name = "foo", kind = "static-nobundle")] +#[link(name = "aaa", kind = "static-nobundle")] extern { - pub fn func(); + pub fn native_func(); } pub fn wrapped_func() { unsafe { - func(); + native_func(); } } diff --git a/src/test/run-make/static-nobundle/ccc.rs b/src/test/run-make/static-nobundle/ccc.rs new file mode 100644 index 0000000000000..bd34753a00d12 --- /dev/null +++ b/src/test/run-make/static-nobundle/ccc.rs @@ -0,0 +1,23 @@ +// 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. + +#![crate_type = "dylib"] + +extern crate bbb; + +pub fn do_work() { + unsafe { bbb::native_func(); } + bbb::wrapped_func(); +} + +pub fn do_work_generic() { + unsafe { bbb::native_func(); } + bbb::wrapped_func(); +} diff --git a/src/test/run-make/static-nobundle/main.rs b/src/test/run-make/static-nobundle/ddd.rs similarity index 81% rename from src/test/run-make/static-nobundle/main.rs rename to src/test/run-make/static-nobundle/ddd.rs index 7aa730f1dd26b..f7d23a899f758 100644 --- a/src/test/run-make/static-nobundle/main.rs +++ b/src/test/run-make/static-nobundle/ddd.rs @@ -8,9 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern crate bar; +extern crate ccc; fn main() { - unsafe { bar::func(); } - bar::wrapped_func(); + ccc::do_work(); + ccc::do_work_generic::(); + ccc::do_work_generic::(); } From 5a21f42cb7f193663fa7a3e95f27e4bf805b5be2 Mon Sep 17 00:00:00 2001 From: king6cong Date: Sat, 4 Feb 2017 10:21:26 +0800 Subject: [PATCH 113/137] run rustfmt for librustc/util/fs.rs --- src/librustc/util/fs.rs | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/librustc/util/fs.rs b/src/librustc/util/fs.rs index 7f8a69de60723..3b4b3998c5745 100644 --- a/src/librustc/util/fs.rs +++ b/src/librustc/util/fs.rs @@ -31,7 +31,7 @@ use std::io; // https://github.com/rust-lang/rust/issues/25505#issuecomment-102876737 pub fn fix_windows_verbatim_for_gcc(p: &Path) -> PathBuf { if !cfg!(windows) { - return p.to_path_buf() + return p.to_path_buf(); } let mut components = p.components(); let prefix = match components.next() { @@ -58,7 +58,7 @@ pub fn fix_windows_verbatim_for_gcc(p: &Path) -> PathBuf { pub enum LinkOrCopy { Link, - Copy + Copy, } /// Copy `p` into `q`, preferring to use hard-linking if possible. If @@ -76,7 +76,7 @@ pub fn link_or_copy, Q: AsRef>(p: P, q: Q) -> io::Result
  • { match fs::copy(p, q) { Ok(_) => Ok(LinkOrCopy::Copy), - Err(e) => Err(e) + Err(e) => Err(e), } } } @@ -85,12 +85,15 @@ pub fn link_or_copy, Q: AsRef>(p: P, q: Q) -> io::Result
  • , Q: AsRef>(p: P, q: Q) -> io::Result { +/// If `rename` fails (rename may fail for reasons such as crossing +/// filesystem), fallback to copy & remove +pub fn rename_or_copy_remove, Q: AsRef>(p: P, + q: Q) + -> io::Result { let p = p.as_ref(); let q = q.as_ref(); match fs::rename(p, q) { @@ -100,8 +103,8 @@ pub fn rename_or_copy_remove, Q: AsRef>(p: P, q: Q) -> io:: Ok(_) => { fs::remove_file(p)?; Ok(RenameOrCopyRemove::CopyRemove) - }, - Err(e) => Err(e) + } + Err(e) => Err(e), } } } @@ -118,8 +121,7 @@ pub fn create_dir_racy(path: &Path) -> io::Result<()> { } match path.parent() { Some(p) => try!(create_dir_racy(p)), - None => return Err(io::Error::new(io::ErrorKind::Other, - "failed to create whole tree")), + None => return Err(io::Error::new(io::ErrorKind::Other, "failed to create whole tree")), } match fs::create_dir(path) { Ok(()) => Ok(()), From 87ace0d7200c12ae268e895ad880cf9589d1b1ac Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Sat, 4 Feb 2017 04:53:09 +0200 Subject: [PATCH 114/137] More snap cleanup --- src/libcompiler_builtins/lib.rs | 6 ++---- src/librustc_const_eval/eval.rs | 9 +++------ src/librustc_const_math/int.rs | 6 ++---- src/librustc_trans/common.rs | 13 ++++--------- src/librustc_trans/mir/constant.rs | 4 ++-- src/test/run-pass/issue-38987.rs | 4 ---- 6 files changed, 13 insertions(+), 29 deletions(-) diff --git a/src/libcompiler_builtins/lib.rs b/src/libcompiler_builtins/lib.rs index b2a615456aa59..5ed497f6159b0 100644 --- a/src/libcompiler_builtins/lib.rs +++ b/src/libcompiler_builtins/lib.rs @@ -544,8 +544,7 @@ pub mod reimpls { const MD1 : u32 = MANTISSA_DIGITS + 1; const MD2 : u32 = MANTISSA_DIGITS + 2; - // SNAP: replace this with !0u128 - let negn :u128 = !0; + let negn = !0u128; if sd > MANTISSA_DIGITS { a = match sd { @@ -579,8 +578,7 @@ pub mod reimpls { const MD1 : u32 = MANTISSA_DIGITS + 1; const MD2 : u32 = MANTISSA_DIGITS + 2; - // SNAP: replace this with !0u128 - let negn :u128 = !0; + let negn = !0u128; if sd > MANTISSA_DIGITS { a = match sd { diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index e2e76cdfb6ebd..af4f63a05613e 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -482,12 +482,9 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>, (&LitKind::Int(I64_OVERFLOW, Signed(IntTy::I64)), _) => { return Ok(Integral(I64(i64::min_value()))) }, - (&LitKind::Int(n, _), Some(&ty::TyInt(IntTy::I128))) | - (&LitKind::Int(n, Signed(IntTy::I128)), _) => { - // SNAP: replace n in pattern with I128_OVERFLOW and remove this if. - if n == I128_OVERFLOW { - return Ok(Integral(I128(i128::min_value()))) - } + (&LitKind::Int(I128_OVERFLOW, _), Some(&ty::TyInt(IntTy::I128))) | + (&LitKind::Int(I128_OVERFLOW, Signed(IntTy::I128)), _) => { + return Ok(Integral(I128(i128::min_value()))) }, (&LitKind::Int(n, _), Some(&ty::TyInt(IntTy::Is))) | (&LitKind::Int(n, Signed(IntTy::Is)), _) => { diff --git a/src/librustc_const_math/int.rs b/src/librustc_const_math/int.rs index 3618bfa20811f..17714f2fb2d6c 100644 --- a/src/librustc_const_math/int.rs +++ b/src/librustc_const_math/int.rs @@ -155,13 +155,11 @@ impl ConstInt { (InferSigned(a @ 0...ibounds::U8MAX), U8(_)) => U8(a as u8), (InferSigned(a @ 0...ibounds::U16MAX), U16(_)) => U16(a as u16), (InferSigned(a @ 0...ibounds::U32MAX), U32(_)) => U32(a as u32), - // SNAP: replace with U64MAX - (InferSigned(a @ 0...ibounds::I64MAX), U64(_)) => U64(a as u64), + (InferSigned(a @ 0...ibounds::U64MAX), U64(_)) => U64(a as u64), (InferSigned(a @ 0...ibounds::I128MAX), U128(_)) => U128(a as u128), (InferSigned(a @ 0...ibounds::U16MAX), Usize(Us16(_))) => Usize(Us16(a as u16)), (InferSigned(a @ 0...ibounds::U32MAX), Usize(Us32(_))) => Usize(Us32(a as u32)), - // SNAP: replace with U64MAX - (InferSigned(a @ 0...ibounds::I64MAX), Usize(Us64(_))) => Usize(Us64(a as u64)), + (InferSigned(a @ 0...ibounds::U64MAX), Usize(Us64(_))) => Usize(Us64(a as u64)), (InferSigned(_), _) => return Err(ConstMathErr::NotInRange), _ => self, // already known types }; diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs index 01b2aeef004db..b995760f5b7a3 100644 --- a/src/librustc_trans/common.rs +++ b/src/librustc_trans/common.rs @@ -229,15 +229,10 @@ pub fn C_integral(t: Type, u: u64, sign_extend: bool) -> ValueRef { } } -pub fn C_big_integral(t: Type, u: u128, sign_extend: bool) -> ValueRef { - if ::std::mem::size_of::() == 16 { - unsafe { - let words = [u as u64, u.wrapping_shr(64) as u64]; - llvm::LLVMConstIntOfArbitraryPrecision(t.to_ref(), 2, words.as_ptr()) - } - } else { - // SNAP: remove after snapshot - C_integral(t, u as u64, sign_extend) +pub fn C_big_integral(t: Type, u: u128) -> ValueRef { + unsafe { + let words = [u as u64, u.wrapping_shr(64) as u64]; + llvm::LLVMConstIntOfArbitraryPrecision(t.to_ref(), 2, words.as_ptr()) } } diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs index 3d5e1694355b3..2a427da4d683e 100644 --- a/src/librustc_trans/mir/constant.rs +++ b/src/librustc_trans/mir/constant.rs @@ -75,7 +75,7 @@ impl<'tcx> Const<'tcx> { ConstVal::Integral(I16(v)) => C_integral(Type::i16(ccx), v as u64, true), ConstVal::Integral(I32(v)) => C_integral(Type::i32(ccx), v as u64, true), ConstVal::Integral(I64(v)) => C_integral(Type::i64(ccx), v as u64, true), - ConstVal::Integral(I128(v)) => C_big_integral(Type::i128(ccx), v as u128, true), + ConstVal::Integral(I128(v)) => C_big_integral(Type::i128(ccx), v as u128), ConstVal::Integral(Isize(v)) => { let i = v.as_i64(ccx.tcx().sess.target.int_type); C_integral(Type::int(ccx), i as u64, true) @@ -84,7 +84,7 @@ impl<'tcx> Const<'tcx> { ConstVal::Integral(U16(v)) => C_integral(Type::i16(ccx), v as u64, false), ConstVal::Integral(U32(v)) => C_integral(Type::i32(ccx), v as u64, false), ConstVal::Integral(U64(v)) => C_integral(Type::i64(ccx), v, false), - ConstVal::Integral(U128(v)) => C_big_integral(Type::i128(ccx), v, false), + ConstVal::Integral(U128(v)) => C_big_integral(Type::i128(ccx), v), ConstVal::Integral(Usize(v)) => { let u = v.as_u64(ccx.tcx().sess.target.uint_type); C_integral(Type::int(ccx), u, false) diff --git a/src/test/run-pass/issue-38987.rs b/src/test/run-pass/issue-38987.rs index 29e96c162b8de..a513476d4a33a 100644 --- a/src/test/run-pass/issue-38987.rs +++ b/src/test/run-pass/issue-38987.rs @@ -9,10 +9,6 @@ // except according to those terms. #![feature(i128_type)] -// SNAP: run on all stages after snapshot, i128 currently doesn't work on stages 0 and 1 -// ignore-stage1 -// ignore-stage0 - fn main() { let _ = -0x8000_0000_0000_0000_0000_0000_0000_0000i128; } From 206ee202581688818e1b305f2c0376df12e65b72 Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Sat, 4 Feb 2017 06:12:23 +0200 Subject: [PATCH 115/137] Unignore stage0/1 i128 tests as well --- src/test/run-pass/i128-ffi.rs | 3 --- src/test/run-pass/i128.rs | 3 --- 2 files changed, 6 deletions(-) diff --git a/src/test/run-pass/i128-ffi.rs b/src/test/run-pass/i128-ffi.rs index 222f32754fb6b..473f1cc2301dc 100644 --- a/src/test/run-pass/i128-ffi.rs +++ b/src/test/run-pass/i128-ffi.rs @@ -8,9 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-stage0 -// ignore-stage1 - // MSVC doesn't support 128 bit integers, and other Windows // C compilers have very inconsistent views on how the ABI // should look like. diff --git a/src/test/run-pass/i128.rs b/src/test/run-pass/i128.rs index 3eb1c95050267..dc4f0774b9771 100644 --- a/src/test/run-pass/i128.rs +++ b/src/test/run-pass/i128.rs @@ -8,9 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-stage0 -// ignore-stage1 - // ignore-emscripten #![feature(i128_type, test)] From 7444d07154652c4d7a3e91e645eaa604a8bc4c84 Mon Sep 17 00:00:00 2001 From: Andrew Cann Date: Sat, 4 Feb 2017 14:03:28 +0800 Subject: [PATCH 116/137] Fix test --- src/librustc_driver/test.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index 41e5a4d53122f..5481de1811d78 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -819,7 +819,7 @@ fn walk_ty_skip_subtree() { let int_ty = tcx.types.isize; let uint_ty = tcx.types.usize; let tup1_ty = tcx.intern_tup(&[int_ty, uint_ty, int_ty, uint_ty], false); - let tup2_ty = tcx.intern_tup(&[tup1_ty, tup1_ty, uint_ty]); + let tup2_ty = tcx.intern_tup(&[tup1_ty, tup1_ty, uint_ty], false); // types we expect to see (in order), plus a boolean saying // whether to skip the subtree. From 42f3ac5ea610b351e404dd30199d13ffc91617d5 Mon Sep 17 00:00:00 2001 From: Andrew Cann Date: Sat, 4 Feb 2017 14:17:58 +0800 Subject: [PATCH 117/137] Expand defaulted unit test --- src/test/compile-fail/defaulted-unit-warning.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/test/compile-fail/defaulted-unit-warning.rs b/src/test/compile-fail/defaulted-unit-warning.rs index 2b6bd01f907c1..5213a189714dd 100644 --- a/src/test/compile-fail/defaulted-unit-warning.rs +++ b/src/test/compile-fail/defaulted-unit-warning.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] +#![allow(unreachable_code)] #![deny(resolve_trait_on_defaulted_unit)] trait Deserialize: Sized { @@ -30,6 +32,19 @@ fn doit() -> Result<(), String> { Ok(()) } +trait ImplementedForUnitButNotNever {} + +impl ImplementedForUnitButNotNever for () {} + +fn foo(_t: T) {} + +fn smeg() { + let _x = return; + foo(_x); + //~^ ERROR code relies on type + //~| WARNING previously accepted +} + fn main() { let _ = doit(); } From a1f42cd8930d465bf616d5b2bc5d7b1b945177ab Mon Sep 17 00:00:00 2001 From: Andrew Cann Date: Sat, 4 Feb 2017 16:27:45 +0800 Subject: [PATCH 118/137] Uninhabited while-let pattern fix --- src/librustc_const_eval/check_match.rs | 19 +++++++++++++++---- src/librustc_const_eval/lib.rs | 1 + src/test/compile-fail/uninhabited-patterns.rs | 8 ++++++++ 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs index 0b1f2465a4d59..ce478f1a4504e 100644 --- a/src/librustc_const_eval/check_match.rs +++ b/src/librustc_const_eval/check_match.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::ptr; use _match::{MatchCheckCtxt, Matrix, expand_pattern, is_useful}; use _match::Usefulness::*; use _match::WitnessPreference::*; @@ -302,10 +303,20 @@ fn check_arms<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>, let &(ref first_arm_pats, _) = &arms[0]; let first_pat = &first_arm_pats[0]; let span = first_pat.0.span; - struct_span_err!(cx.tcx.sess, span, E0165, - "irrefutable while-let pattern") - .span_label(span, &format!("irrefutable pattern")) - .emit(); + + // check which arm we're on. + if ptr::eq(first_arm_pats, pats) { + let mut diagnostic = Diagnostic::new(Level::Warning, + "unreachable pattern"); + diagnostic.set_span(pat.span); + cx.tcx.sess.add_lint_diagnostic(lint::builtin::UNREACHABLE_PATTERNS, + hir_pat.id, diagnostic); + } else { + struct_span_err!(cx.tcx.sess, span, E0165, + "irrefutable while-let pattern") + .span_label(span, &format!("irrefutable pattern")) + .emit(); + } }, hir::MatchSource::ForLoopDesugar | diff --git a/src/librustc_const_eval/lib.rs b/src/librustc_const_eval/lib.rs index 198e49daabc63..7c579f44e79f2 100644 --- a/src/librustc_const_eval/lib.rs +++ b/src/librustc_const_eval/lib.rs @@ -30,6 +30,7 @@ #![feature(box_syntax)] #![feature(const_fn)] #![feature(i128_type)] +#![feature(ptr_eq)] extern crate arena; #[macro_use] extern crate syntax; diff --git a/src/test/compile-fail/uninhabited-patterns.rs b/src/test/compile-fail/uninhabited-patterns.rs index 0de29f3a8d737..4c894b0bdd3dd 100644 --- a/src/test/compile-fail/uninhabited-patterns.rs +++ b/src/test/compile-fail/uninhabited-patterns.rs @@ -24,6 +24,10 @@ struct NotSoSecretlyEmpty { _priv: !, } +fn foo() -> Option { + None +} + fn main() { let x: &[!] = &[]; @@ -45,5 +49,9 @@ fn main() { Err(Err(_y)) => (), Err(Ok(_y)) => (), //~ ERROR unreachable pattern } + + while let Some(_y) = foo() { + //~^ ERROR unreachable pattern + } } From b4ef361a8c7ef75b29bad437ee970c1794793cb1 Mon Sep 17 00:00:00 2001 From: king6cong Date: Sat, 4 Feb 2017 16:44:23 +0800 Subject: [PATCH 119/137] README path correction --- src/bootstrap/bin/main.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/bin/main.rs b/src/bootstrap/bin/main.rs index c47f4fd8ec64b..5ca5ce1648f2f 100644 --- a/src/bootstrap/bin/main.rs +++ b/src/bootstrap/bin/main.rs @@ -11,8 +11,8 @@ //! rustbuild, the Rust build system //! //! This is the entry point for the build system used to compile the `rustc` -//! compiler. Lots of documentation can be found in the `README.md` file next to -//! this file, and otherwise documentation can be found throughout the `build` +//! compiler. Lots of documentation can be found in the `README.md` file in the +//! parent directory, and otherwise documentation can be found throughout the `build` //! directory in each respective module. #![deny(warnings)] From 768c6c081e4a8cac6b6f8eee5cde72ed13a7e87a Mon Sep 17 00:00:00 2001 From: Dylan McKay Date: Sat, 4 Feb 2017 23:22:05 +1300 Subject: [PATCH 120/137] Support a debug info API change for LLVM 4.0 Instead of directly creating a 'DIGlobalVariable', we now have to create a 'DIGlobalVariableExpression' which itself contains a reference to a 'DIGlobalVariable'. This is a straightforward change. In the future, we should rename 'DIGlobalVariable' in the FFI bindings, assuming we will only refer to 'DIGlobalVariableExpression' and not 'DIGlobalVariable'. --- src/librustc_llvm/ffi.rs | 6 ++++++ src/rustllvm/RustWrapper.cpp | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/src/librustc_llvm/ffi.rs b/src/librustc_llvm/ffi.rs index 58b2017ceb66e..8510b9f523cb5 100644 --- a/src/librustc_llvm/ffi.rs +++ b/src/librustc_llvm/ffi.rs @@ -8,6 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// FIXME: Rename 'DIGlobalVariable' to 'DIGlobalVariableExpression' +// once support for LLVM 3.9 is dropped. +// +// This method was changed in this LLVM patch: +// https://reviews.llvm.org/D26769 + use debuginfo::{DIBuilderRef, DIDescriptor, DIFile, DILexicalBlock, DISubprogram, DIType, DIBasicType, DIDerivedType, DICompositeType, DIScope, DIVariable, DIGlobalVariable, DIArray, DISubrange, DITemplateTypeParameter, DIEnumerator, diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index 34ee7d552f346..c7bcd2558186e 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -588,7 +588,11 @@ extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateStaticVariable( } #endif +#if LLVM_VERSION_GE(4, 0) + return wrap(Builder->createGlobalVariableExpression( +#else return wrap(Builder->createGlobalVariable( +#endif unwrapDI(Context), Name, LinkageName, unwrapDI(File), LineNo, unwrapDI(Ty), IsLocalToUnit, #if LLVM_VERSION_GE(4, 0) From 112a5a00e839bfb3dbdaa9166afe595163248174 Mon Sep 17 00:00:00 2001 From: Tim Neumann Date: Sat, 4 Feb 2017 11:44:29 +0100 Subject: [PATCH 121/137] ignore more gdb versions with buggy rust support --- src/test/debuginfo/borrowed-enum.rs | 2 +- src/test/debuginfo/generic-struct-style-enum.rs | 2 +- src/test/debuginfo/generic-tuple-style-enum.rs | 2 +- src/test/debuginfo/packed-struct.rs | 2 +- src/test/debuginfo/recursive-struct.rs | 2 +- src/test/debuginfo/struct-in-enum.rs | 2 +- src/test/debuginfo/struct-style-enum.rs | 2 +- src/test/debuginfo/tuple-style-enum.rs | 2 +- src/test/debuginfo/union-smoke.rs | 2 +- src/test/debuginfo/unique-enum.rs | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/test/debuginfo/borrowed-enum.rs b/src/test/debuginfo/borrowed-enum.rs index c457fed7ecd52..9e63beff3cb2e 100644 --- a/src/test/debuginfo/borrowed-enum.rs +++ b/src/test/debuginfo/borrowed-enum.rs @@ -10,7 +10,7 @@ // ignore-tidy-linelength // min-lldb-version: 310 -// ignore-gdb-version: 7.11.90 - 7.12 +// ignore-gdb-version: 7.11.90 - 7.12.9 // compile-flags:-g diff --git a/src/test/debuginfo/generic-struct-style-enum.rs b/src/test/debuginfo/generic-struct-style-enum.rs index df56ccccca3f5..4a1d14ccf6118 100644 --- a/src/test/debuginfo/generic-struct-style-enum.rs +++ b/src/test/debuginfo/generic-struct-style-enum.rs @@ -10,7 +10,7 @@ // ignore-tidy-linelength // min-lldb-version: 310 -// ignore-gdb-version: 7.11.90 - 7.12 +// ignore-gdb-version: 7.11.90 - 7.12.9 // compile-flags:-g diff --git a/src/test/debuginfo/generic-tuple-style-enum.rs b/src/test/debuginfo/generic-tuple-style-enum.rs index e538700f0f84c..012bd6140cdbe 100644 --- a/src/test/debuginfo/generic-tuple-style-enum.rs +++ b/src/test/debuginfo/generic-tuple-style-enum.rs @@ -10,7 +10,7 @@ // ignore-tidy-linelength // min-lldb-version: 310 -// ignore-gdb-version: 7.11.90 - 7.12 +// ignore-gdb-version: 7.11.90 - 7.12.9 // compile-flags:-g diff --git a/src/test/debuginfo/packed-struct.rs b/src/test/debuginfo/packed-struct.rs index c476e9fe0796f..16e6371a9c0a9 100644 --- a/src/test/debuginfo/packed-struct.rs +++ b/src/test/debuginfo/packed-struct.rs @@ -10,7 +10,7 @@ // ignore-tidy-linelength // min-lldb-version: 310 -// ignore-gdb-version: 7.11.90 - 7.12 +// ignore-gdb-version: 7.11.90 - 7.12.9 // compile-flags:-g diff --git a/src/test/debuginfo/recursive-struct.rs b/src/test/debuginfo/recursive-struct.rs index f33dfac07d203..75c2feb480ede 100644 --- a/src/test/debuginfo/recursive-struct.rs +++ b/src/test/debuginfo/recursive-struct.rs @@ -10,7 +10,7 @@ // ignore-tidy-linelength // ignore-lldb -// ignore-gdb-version: 7.11.90 - 7.12 +// ignore-gdb-version: 7.11.90 - 7.12.9 // compile-flags:-g diff --git a/src/test/debuginfo/struct-in-enum.rs b/src/test/debuginfo/struct-in-enum.rs index d9763aedd7c15..bd044188dbcbc 100644 --- a/src/test/debuginfo/struct-in-enum.rs +++ b/src/test/debuginfo/struct-in-enum.rs @@ -10,7 +10,7 @@ // ignore-tidy-linelength // min-lldb-version: 310 -// ignore-gdb-version: 7.11.90 - 7.12 +// ignore-gdb-version: 7.11.90 - 7.12.9 // compile-flags:-g diff --git a/src/test/debuginfo/struct-style-enum.rs b/src/test/debuginfo/struct-style-enum.rs index 6212caa69538d..b156a3be699e3 100644 --- a/src/test/debuginfo/struct-style-enum.rs +++ b/src/test/debuginfo/struct-style-enum.rs @@ -10,7 +10,7 @@ // ignore-tidy-linelength // min-lldb-version: 310 -// ignore-gdb-version: 7.11.90 - 7.12 +// ignore-gdb-version: 7.11.90 - 7.12.9 // compile-flags:-g diff --git a/src/test/debuginfo/tuple-style-enum.rs b/src/test/debuginfo/tuple-style-enum.rs index f85cd6a50f519..f36153d1f5c5a 100644 --- a/src/test/debuginfo/tuple-style-enum.rs +++ b/src/test/debuginfo/tuple-style-enum.rs @@ -10,7 +10,7 @@ // ignore-tidy-linelength // min-lldb-version: 310 -// ignore-gdb-version: 7.11.90 - 7.12 +// ignore-gdb-version: 7.11.90 - 7.12.9 // compile-flags:-g diff --git a/src/test/debuginfo/union-smoke.rs b/src/test/debuginfo/union-smoke.rs index 844e9405ba55c..0b2544151fd32 100644 --- a/src/test/debuginfo/union-smoke.rs +++ b/src/test/debuginfo/union-smoke.rs @@ -9,7 +9,7 @@ // except according to those terms. // min-lldb-version: 310 -// ignore-gdb-version: 7.11.90 - 7.12 +// ignore-gdb-version: 7.11.90 - 7.12.9 // compile-flags:-g diff --git a/src/test/debuginfo/unique-enum.rs b/src/test/debuginfo/unique-enum.rs index e8eb4315007af..5a99de7779cff 100644 --- a/src/test/debuginfo/unique-enum.rs +++ b/src/test/debuginfo/unique-enum.rs @@ -10,7 +10,7 @@ // ignore-tidy-linelength // min-lldb-version: 310 -// ignore-gdb-version: 7.11.90 - 7.12 +// ignore-gdb-version: 7.11.90 - 7.12.9 // compile-flags:-g From b3096e25c0a574cb20706adabe75667a215a86b9 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sat, 4 Feb 2017 06:09:19 -0500 Subject: [PATCH 122/137] pacify the mercilous tidy, improve cycle unit test --- .../persist/preds/compress/classify/mod.rs | 14 +++++++++- .../persist/preds/compress/classify/test.rs | 27 ++++++++++++++----- .../persist/preds/compress/construct.rs | 10 +++++++ .../persist/preds/compress/dag_id.rs | 10 +++++++ .../persist/preds/compress/test.rs | 10 +++++++ .../persist/preds/compress/test_macro.rs | 10 +++++++ src/librustc_incremental/persist/save.rs | 3 ++- 7 files changed, 76 insertions(+), 8 deletions(-) diff --git a/src/librustc_incremental/persist/preds/compress/classify/mod.rs b/src/librustc_incremental/persist/preds/compress/classify/mod.rs index f75063f8b9c9a..559bdbdd1e2e5 100644 --- a/src/librustc_incremental/persist/preds/compress/classify/mod.rs +++ b/src/librustc_incremental/persist/preds/compress/classify/mod.rs @@ -1,3 +1,13 @@ +// Copyright 2014 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. + //! First phase. Detect cycles and cross-edges. use super::*; @@ -122,7 +132,9 @@ impl<'a, 'g, N, I, O> Classify<'a, 'g, N, I, O> assert!(self.stack[stack_index] == child); for &n in &self.stack[stack_index..] { - debug!("cycle `{:?}` and `{:?}`", self.r.in_graph.node_data(n), self.r.in_graph.node_data(parent)); + debug!("cycle `{:?}` and `{:?}`", + self.r.in_graph.node_data(n), + self.r.in_graph.node_data(parent)); self.r.mark_cycle(n, parent); } } diff --git a/src/librustc_incremental/persist/preds/compress/classify/test.rs b/src/librustc_incremental/persist/preds/compress/classify/test.rs index 22067a10343d3..ca26f714a2a74 100644 --- a/src/librustc_incremental/persist/preds/compress/classify/test.rs +++ b/src/librustc_incremental/persist/preds/compress/classify/test.rs @@ -1,3 +1,13 @@ +// Copyright 2014 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. + use super::*; #[test] @@ -45,12 +55,17 @@ fn edge_order1() { let mut reduce = GraphReduce::new(&graph, |n| inputs.contains(n), |n| outputs.contains(n)); Classify::new(&mut reduce).walk(); - assert!(reduce.in_cycle(nodes("B"), nodes("C"))); - - assert!(!reduce.in_cycle(nodes("IN"), nodes("A"))); - assert!(!reduce.in_cycle(nodes("IN"), nodes("B"))); - assert!(!reduce.in_cycle(nodes("IN"), nodes("C"))); - assert!(!reduce.in_cycle(nodes("IN"), nodes("OUT"))); + // A, B, and C are mutually in a cycle, but IN/OUT are not participating. + let names = ["A", "B", "C", "IN", "OUT"]; + let cycle_names = ["A", "B", "C"]; + for &i in &names { + for &j in names.iter().filter(|&&j| j != i) { + let in_cycle = cycle_names.contains(&i) && cycle_names.contains(&j); + assert_eq!(reduce.in_cycle(nodes(i), nodes(j)), in_cycle, + "cycle status for nodes {} and {} is incorrect", + i, j); + } + } } /// Same as `edge_order1` but in reverse order so as to detect a failure diff --git a/src/librustc_incremental/persist/preds/compress/construct.rs b/src/librustc_incremental/persist/preds/compress/construct.rs index 965c773597ede..394be74f7835f 100644 --- a/src/librustc_incremental/persist/preds/compress/construct.rs +++ b/src/librustc_incremental/persist/preds/compress/construct.rs @@ -1,3 +1,13 @@ +// Copyright 2014 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. + //! Second phase. Construct new graph. The previous phase has //! converted the input graph into a DAG by detecting and unifying //! cycles. It provides us with the following (which is a diff --git a/src/librustc_incremental/persist/preds/compress/dag_id.rs b/src/librustc_incremental/persist/preds/compress/dag_id.rs index c79930bfae513..a286862e9551f 100644 --- a/src/librustc_incremental/persist/preds/compress/dag_id.rs +++ b/src/librustc_incremental/persist/preds/compress/dag_id.rs @@ -1,3 +1,13 @@ +// Copyright 2014 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. + use rustc_data_structures::graph::NodeIndex; use rustc_data_structures::unify::UnifyKey; diff --git a/src/librustc_incremental/persist/preds/compress/test.rs b/src/librustc_incremental/persist/preds/compress/test.rs index be91677f4d14b..1c5130845a855 100644 --- a/src/librustc_incremental/persist/preds/compress/test.rs +++ b/src/librustc_incremental/persist/preds/compress/test.rs @@ -1,3 +1,13 @@ +// Copyright 2014 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. + use super::*; fn reduce(graph: &Graph<&'static str, ()>, diff --git a/src/librustc_incremental/persist/preds/compress/test_macro.rs b/src/librustc_incremental/persist/preds/compress/test_macro.rs index 66712c018d06d..31b30d2b2857c 100644 --- a/src/librustc_incremental/persist/preds/compress/test_macro.rs +++ b/src/librustc_incremental/persist/preds/compress/test_macro.rs @@ -1,3 +1,13 @@ +// Copyright 2014 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. + macro_rules! graph { ($( $source:ident -> $target:ident, )*) => { { diff --git a/src/librustc_incremental/persist/save.rs b/src/librustc_incremental/persist/save.rs index 93600631b8d3e..34bb125ef3f45 100644 --- a/src/librustc_incremental/persist/save.rs +++ b/src/librustc_incremental/persist/save.rs @@ -290,7 +290,8 @@ pub fn encode_metadata_hashes(tcx: TyCtxt, .map(|index| preds.reduced_graph.node_data(index)) .filter(|dep_node| HashContext::is_hashable(dep_node)) .map(|dep_node| { - let hash_dep_node = dep_node.map_def(|&def_id| Some(def_id_hash(def_id))).unwrap(); + let hash_dep_node = dep_node.map_def(|&def_id| Some(def_id_hash(def_id))) + .unwrap(); let hash = preds.hashes[dep_node]; (hash_dep_node, hash) }) From a884a6c60d3ec2338d7dfed9998a7aa96e10260e Mon Sep 17 00:00:00 2001 From: Stjepan Glavina Date: Sat, 4 Feb 2017 16:26:01 +0100 Subject: [PATCH 123/137] Slightly optimize slice::sort First, get rid of some bound checks. Second, instead of comparing by ternary `compare` function, use a binary function testing whether an element is less than some other element. This apparently makes it easier for the compiler to reason about the code. Benchmark: ``` name before ns/iter after ns/iter diff ns/iter diff % slice::bench::sort_large_ascending 8,969 (8919 MB/s) 7,410 (10796 MB/s) -1,559 -17.38% slice::bench::sort_large_big_ascending 355,640 (3599 MB/s) 359,137 (3564 MB/s) 3,497 0.98% slice::bench::sort_large_big_descending 427,112 (2996 MB/s) 424,721 (3013 MB/s) -2,391 -0.56% slice::bench::sort_large_big_random 2,207,799 (579 MB/s) 2,138,804 (598 MB/s) -68,995 -3.13% slice::bench::sort_large_descending 13,694 (5841 MB/s) 13,514 (5919 MB/s) -180 -1.31% slice::bench::sort_large_mostly_ascending 239,697 (333 MB/s) 203,542 (393 MB/s) -36,155 -15.08% slice::bench::sort_large_mostly_descending 270,102 (296 MB/s) 234,263 (341 MB/s) -35,839 -13.27% slice::bench::sort_large_random 513,406 (155 MB/s) 470,084 (170 MB/s) -43,322 -8.44% slice::bench::sort_large_random_expensive 23,650,321 (3 MB/s) 23,675,098 (3 MB/s) 24,777 0.10% slice::bench::sort_medium_ascending 143 (5594 MB/s) 132 (6060 MB/s) -11 -7.69% slice::bench::sort_medium_descending 197 (4060 MB/s) 188 (4255 MB/s) -9 -4.57% slice::bench::sort_medium_random 3,358 (238 MB/s) 3,271 (244 MB/s) -87 -2.59% slice::bench::sort_small_ascending 32 (2500 MB/s) 32 (2500 MB/s) 0 0.00% slice::bench::sort_small_big_ascending 97 (13195 MB/s) 97 (13195 MB/s) 0 0.00% slice::bench::sort_small_big_descending 247 (5182 MB/s) 249 (5140 MB/s) 2 0.81% slice::bench::sort_small_big_random 502 (2549 MB/s) 498 (2570 MB/s) -4 -0.80% slice::bench::sort_small_descending 55 (1454 MB/s) 61 (1311 MB/s) 6 10.91% slice::bench::sort_small_random 358 (223 MB/s) 356 (224 MB/s) -2 -0.56% ``` --- src/libcollections/slice.rs | 68 ++++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 32 deletions(-) diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs index 11f513ed798e0..2ea953df87357 100644 --- a/src/libcollections/slice.rs +++ b/src/libcollections/slice.rs @@ -98,7 +98,7 @@ #![cfg_attr(test, allow(unused_imports, dead_code))] use alloc::boxed::Box; -use core::cmp::Ordering::{self, Greater}; +use core::cmp::Ordering::{self, Less}; use core::mem::size_of; use core::mem; use core::ptr; @@ -1089,7 +1089,7 @@ impl [T] { pub fn sort(&mut self) where T: Ord { - self.sort_by(|a, b| a.cmp(b)) + merge_sort(self, |a, b| a.lt(b)); } /// Sorts the slice using `f` to extract a key to compare elements by. @@ -1119,7 +1119,7 @@ impl [T] { pub fn sort_by_key(&mut self, mut f: F) where F: FnMut(&T) -> B, B: Ord { - self.sort_by(|a, b| f(a).cmp(&f(b))) + merge_sort(self, |a, b| f(a).lt(&f(b))); } /// Sorts the slice using `compare` to compare elements. @@ -1149,10 +1149,10 @@ impl [T] { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn sort_by(&mut self, compare: F) + pub fn sort_by(&mut self, mut compare: F) where F: FnMut(&T, &T) -> Ordering { - merge_sort(self, compare) + merge_sort(self, |a, b| compare(a, b) == Less); } /// Copies the elements from `src` into `self`. @@ -1355,10 +1355,10 @@ impl ToOwned for [T] { /// Inserts `v[0]` into pre-sorted sequence `v[1..]` so that whole `v[..]` becomes sorted. /// /// This is the integral subroutine of insertion sort. -fn insert_head(v: &mut [T], compare: &mut F) - where F: FnMut(&T, &T) -> Ordering +fn insert_head(v: &mut [T], is_less: &mut F) + where F: FnMut(&T, &T) -> bool { - if v.len() >= 2 && compare(&v[0], &v[1]) == Greater { + if v.len() >= 2 && is_less(&v[1], &v[0]) { unsafe { // There are three ways to implement insertion here: // @@ -1381,12 +1381,12 @@ fn insert_head(v: &mut [T], compare: &mut F) // Intermediate state of the insertion process is always tracked by `hole`, which // serves two purposes: - // 1. Protects integrity of `v` from panics in `compare`. + // 1. Protects integrity of `v` from panics in `is_less`. // 2. Fills the remaining hole in `v` in the end. // // Panic safety: // - // If `compare` panics at any point during the process, `hole` will get dropped and + // If `is_less` panics at any point during the process, `hole` will get dropped and // fill the hole in `v` with `tmp`, thus ensuring that `v` still holds every object it // initially held exactly once. let mut hole = InsertionHole { @@ -1396,7 +1396,7 @@ fn insert_head(v: &mut [T], compare: &mut F) ptr::copy_nonoverlapping(&v[1], &mut v[0], 1); for i in 2..v.len() { - if compare(&tmp.value, &v[i]) != Greater { + if !is_less(&v[i], &tmp.value) { break; } ptr::copy_nonoverlapping(&v[i], &mut v[i - 1], 1); @@ -1432,8 +1432,8 @@ fn insert_head(v: &mut [T], compare: &mut F) /// /// The two slices must be non-empty and `mid` must be in bounds. Buffer `buf` must be long enough /// to hold a copy of the shorter slice. Also, `T` must not be a zero-sized type. -unsafe fn merge(v: &mut [T], mid: usize, buf: *mut T, compare: &mut F) - where F: FnMut(&T, &T) -> Ordering +unsafe fn merge(v: &mut [T], mid: usize, buf: *mut T, is_less: &mut F) + where F: FnMut(&T, &T) -> bool { let len = v.len(); let v = v.as_mut_ptr(); @@ -1449,12 +1449,12 @@ unsafe fn merge(v: &mut [T], mid: usize, buf: *mut T, compare: &mut F) // hole in `v`. // // Intermediate state of the process is always tracked by `hole`, which serves two purposes: - // 1. Protects integrity of `v` from panics in `compare`. + // 1. Protects integrity of `v` from panics in `is_less`. // 2. Fills the remaining hole in `v` if the longer run gets consumed first. // // Panic safety: // - // If `compare` panics at any point during the process, `hole` will get dropped and fill the + // If `is_less` panics at any point during the process, `hole` will get dropped and fill the // hole in `v` with the unconsumed range in `buf`, thus ensuring that `v` still holds every // object it initially held exactly once. let mut hole; @@ -1476,7 +1476,7 @@ unsafe fn merge(v: &mut [T], mid: usize, buf: *mut T, compare: &mut F) while *left < hole.end && right < v_end { // Consume the lesser side. // If equal, prefer the left run to maintain stability. - let to_copy = if compare(&**left, &*right) == Greater { + let to_copy = if is_less(&*right, &**left) { get_and_increment(&mut right) } else { get_and_increment(left) @@ -1500,7 +1500,7 @@ unsafe fn merge(v: &mut [T], mid: usize, buf: *mut T, compare: &mut F) while v < *left && buf < *right { // Consume the greater side. // If equal, prefer the right run to maintain stability. - let to_copy = if compare(&*left.offset(-1), &*right.offset(-1)) == Greater { + let to_copy = if is_less(&*right.offset(-1), &*left.offset(-1)) { decrement_and_get(left) } else { decrement_and_get(right) @@ -1550,8 +1550,8 @@ unsafe fn merge(v: &mut [T], mid: usize, buf: *mut T, compare: &mut F) /// 2. for every `i` in `2..runs.len()`: `runs[i - 2].len > runs[i - 1].len + runs[i].len` /// /// The invariants ensure that the total running time is `O(n log n)` worst-case. -fn merge_sort(v: &mut [T], mut compare: F) - where F: FnMut(&T, &T) -> Ordering +fn merge_sort(v: &mut [T], mut is_less: F) + where F: FnMut(&T, &T) -> bool { // Sorting has no meaningful behavior on zero-sized types. if size_of::() == 0 { @@ -1565,7 +1565,7 @@ fn merge_sort(v: &mut [T], mut compare: F) // // Short runs are extended using insertion sort to span at least `min_run` elements, in order // to improve performance. - let (max_insertion, min_run) = if size_of::() <= 16 { + let (max_insertion, min_run) = if size_of::() <= 2 * mem::size_of::() { (64, 32) } else { (32, 16) @@ -1577,7 +1577,7 @@ fn merge_sort(v: &mut [T], mut compare: F) if len <= max_insertion { if len >= 2 { for i in (0..len-1).rev() { - insert_head(&mut v[i..], &mut compare); + insert_head(&mut v[i..], &mut is_less); } } return; @@ -1585,7 +1585,7 @@ fn merge_sort(v: &mut [T], mut compare: F) // Allocate a buffer to use as scratch memory. We keep the length 0 so we can keep in it // shallow copies of the contents of `v` without risking the dtors running on copies if - // `compare` panics. When merging two sorted runs, this buffer holds a copy of the shorter run, + // `is_less` panics. When merging two sorted runs, this buffer holds a copy of the shorter run, // which will always have length at most `len / 2`. let mut buf = Vec::with_capacity(len / 2); @@ -1600,14 +1600,18 @@ fn merge_sort(v: &mut [T], mut compare: F) let mut start = end - 1; if start > 0 { start -= 1; - if compare(&v[start], &v[start + 1]) == Greater { - while start > 0 && compare(&v[start - 1], &v[start]) == Greater { - start -= 1; - } - v[start..end].reverse(); - } else { - while start > 0 && compare(&v[start - 1], &v[start]) != Greater { - start -= 1; + unsafe { + if is_less(v.get_unchecked(start + 1), v.get_unchecked(start)) { + while start > 0 && is_less(v.get_unchecked(start), + v.get_unchecked(start - 1)) { + start -= 1; + } + v[start..end].reverse(); + } else { + while start > 0 && !is_less(v.get_unchecked(start), + v.get_unchecked(start - 1)) { + start -= 1; + } } } } @@ -1616,7 +1620,7 @@ fn merge_sort(v: &mut [T], mut compare: F) // merge sort on short sequences, so this significantly improves performance. while start > 0 && end - start < min_run { start -= 1; - insert_head(&mut v[start..end], &mut compare); + insert_head(&mut v[start..end], &mut is_less); } // Push this run onto the stack. @@ -1632,7 +1636,7 @@ fn merge_sort(v: &mut [T], mut compare: F) let right = runs[r]; unsafe { merge(&mut v[left.start .. right.start + right.len], left.len, buf.as_mut_ptr(), - &mut compare); + &mut is_less); } runs[r] = Run { start: left.start, From fa457bff264ea62acf56bb9e645b8227ecdc7529 Mon Sep 17 00:00:00 2001 From: Stjepan Glavina Date: Sat, 4 Feb 2017 18:04:26 +0100 Subject: [PATCH 124/137] Minor fix in the *_expensive benchmark Before, the `count` would be copied into the closure and could potentially be optimized way. This change ensures it's borrowed by closure and finally consumed by `test::black_box`. --- src/libcollectionstest/slice.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/libcollectionstest/slice.rs b/src/libcollectionstest/slice.rs index 1b52214dee6ae..b9dec6be7b885 100644 --- a/src/libcollectionstest/slice.rs +++ b/src/libcollectionstest/slice.rs @@ -1429,18 +1429,15 @@ mod bench { fn sort_large_random_expensive(b: &mut Bencher) { let len = 10000; b.iter(|| { + let mut v = gen_random(len); let mut count = 0; - let cmp = move |a: &u64, b: &u64| { + v.sort_by(|a: &u64, b: &u64| { count += 1; if count % 1_000_000_000 == 0 { panic!("should not happen"); } (*a as f64).cos().partial_cmp(&(*b as f64).cos()).unwrap() - }; - - let mut v = gen_random(len); - v.sort_by(cmp); - + }); black_box(count); }); b.bytes = len as u64 * mem::size_of::() as u64; From 65b05541432c1fe7b75fb2dd3b020f933f3b5f4b Mon Sep 17 00:00:00 2001 From: "Zack M. Davis" Date: Thu, 5 Jan 2017 18:55:36 -0800 Subject: [PATCH 125/137] note individual lint name set via lint group attribute in notes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Warning or error messages set via a lint group attribute (e.g. `#[deny(warnings)]`) should still make it clear which individual lint (by name) was triggered, similarly to how we include "on by default" language for default lints. This—and, while we're here, the existing "on by default" language—can be tucked into a note rather than cluttering the main error message. This occasions the slightest of refactorings (we now have to get the diagnostic-builder with the main message first, before matching on the lint source). This is in the matter of #36846. --- src/librustc/lint/context.rs | 53 +++++++++++-------- src/librustc/lint/mod.rs | 2 +- .../imports/rfc-1560-warning-cycle.rs | 1 + src/test/compile-fail/issue-30730.rs | 4 +- src/test/compile-fail/lint-group-style.rs | 20 +++++-- src/test/compile-fail/lint-output-format-2.rs | 11 ++-- src/test/run-pass/path-lookahead.rs | 6 +-- .../proj-outlives-region.stderr | 3 +- .../ui/compare-method/region-unrelated.stderr | 3 +- src/test/ui/span/issue-24690.stderr | 4 ++ src/test/ui/span/multispan-import-lint.stderr | 4 +- 11 files changed, 72 insertions(+), 39 deletions(-) diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 362117d860a5c..62f19412d52f0 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -40,6 +40,7 @@ use std::cmp; use std::default::Default as StdDefault; use std::mem; use std::fmt; +use std::ops::Deref; use syntax::attr; use syntax::ast; use syntax_pos::{MultiSpan, Span}; @@ -446,35 +447,18 @@ pub fn raw_struct_lint<'a, S>(sess: &'a Session, -> DiagnosticBuilder<'a> where S: Into { - let (mut level, source) = lvlsrc; + let (level, source) = lvlsrc; if level == Allow { return sess.diagnostic().struct_dummy(); } let name = lint.name_lower(); let mut def = None; - let msg = match source { - Default => { - format!("{}, #[{}({})] on by default", msg, - level.as_str(), name) - }, - CommandLine => { - format!("{} [-{} {}]", msg, - match level { - Warn => 'W', Deny => 'D', Forbid => 'F', - Allow => bug!() - }, name.replace("_", "-")) - }, - Node(src) => { - def = Some(src); - msg.to_string() - } - }; - // For purposes of printing, we can treat forbid as deny. - if level == Forbid { level = Deny; } + // Except for possible note details, forbid behaves like deny. + let effective_level = if level == Forbid { Deny } else { level }; - let mut err = match (level, span) { + let mut err = match (effective_level, span) { (Warn, Some(sp)) => sess.struct_span_warn(sp, &msg[..]), (Warn, None) => sess.struct_warn(&msg[..]), (Deny, Some(sp)) => sess.struct_span_err(sp, &msg[..]), @@ -482,6 +466,27 @@ pub fn raw_struct_lint<'a, S>(sess: &'a Session, _ => bug!("impossible level in raw_emit_lint"), }; + match source { + Default => { + err.note(&format!("#[{}({})] on by default", level.as_str(), name)); + }, + CommandLine => { + err.note(&format!("[-{} {}]", + match level { + Warn => 'W', Deny => 'D', Forbid => 'F', + Allow => bug!() + }, name.replace("_", "-"))); + }, + Node(lint_attr_name, src) => { + def = Some(src); + if lint_attr_name.as_str().deref() != name { + let level_str = level.as_str(); + err.note(&format!("#[{}({})] implies #[{}({})]", + level_str, lint_attr_name, level_str, name)); + } + } + } + // Check for future incompatibility lints and issue a stronger warning. if let Some(future_incompatible) = lints.future_incompatible(LintId::of(lint)) { let explanation = format!("this was previously accepted by the compiler \ @@ -649,6 +654,8 @@ pub trait LintContext<'tcx>: Sized { } }; + let lint_attr_name = result.expect("lint attribute should be well-formed").0; + for (lint_id, level, span) in v { let (now, now_source) = self.lints().get_level_source(lint_id); if now == Forbid && level != Forbid { @@ -660,7 +667,7 @@ pub trait LintContext<'tcx>: Sized { diag_builder.span_label(span, &format!("overruled by previous forbid")); match now_source { LintSource::Default => &mut diag_builder, - LintSource::Node(forbid_source_span) => { + LintSource::Node(_, forbid_source_span) => { diag_builder.span_label(forbid_source_span, &format!("`forbid` level set here")) }, @@ -672,7 +679,7 @@ pub trait LintContext<'tcx>: Sized { let src = self.lints().get_level_source(lint_id).1; self.level_stack().push((lint_id, (now, src))); pushed += 1; - self.mut_lints().set_level(lint_id, (level, Node(span))); + self.mut_lints().set_level(lint_id, (level, Node(lint_attr_name, span))); } } } diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index d12065ca86e14..9c2a892a5fc7d 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -338,7 +338,7 @@ pub enum LintSource { Default, /// Lint level was set by an attribute. - Node(Span), + Node(ast::Name, Span), /// Lint level was set by a command-line flag. CommandLine, diff --git a/src/test/compile-fail/imports/rfc-1560-warning-cycle.rs b/src/test/compile-fail/imports/rfc-1560-warning-cycle.rs index eb36129799a4e..1d67bf3a1cdda 100644 --- a/src/test/compile-fail/imports/rfc-1560-warning-cycle.rs +++ b/src/test/compile-fail/imports/rfc-1560-warning-cycle.rs @@ -23,6 +23,7 @@ mod bar { //~^ WARN `Foo` is ambiguous //~| WARN hard error in a future release //~| NOTE see issue #38260 + //~| NOTE #[warn(legacy_imports)] on by default } } diff --git a/src/test/compile-fail/issue-30730.rs b/src/test/compile-fail/issue-30730.rs index 82804bb747406..6082740f427d7 100644 --- a/src/test/compile-fail/issue-30730.rs +++ b/src/test/compile-fail/issue-30730.rs @@ -9,5 +9,7 @@ // except according to those terms. #![deny(warnings)] //~ NOTE: lint level defined here -use std::thread; //~ ERROR: unused import +use std::thread; +//~^ ERROR: unused import +//~| NOTE: #[deny(warnings)] implies #[deny(unused_imports)] fn main() {} diff --git a/src/test/compile-fail/lint-group-style.rs b/src/test/compile-fail/lint-group-style.rs index b2e6072c9855c..a8c377034756a 100644 --- a/src/test/compile-fail/lint-group-style.rs +++ b/src/test/compile-fail/lint-group-style.rs @@ -12,7 +12,9 @@ //~^ NOTE lint level defined here #![allow(dead_code)] -fn CamelCase() {} //~ ERROR function `CamelCase` should have a snake case name +fn CamelCase() {} +//~^ ERROR function `CamelCase` should have a snake case name +//~| NOTE #[deny(bad_style)] implies #[deny(non_snake_case)] #[allow(bad_style)] mod test { @@ -22,9 +24,13 @@ mod test { //~^ NOTE lint level defined here //~^^ NOTE lint level defined here mod bad { - fn CamelCase() {} //~ ERROR function `CamelCase` should have a snake case name + fn CamelCase() {} + //~^ ERROR function `CamelCase` should have a snake case name + //~| NOTE #[forbid(bad_style)] implies #[forbid(non_snake_case)] - static bad: isize = 1; //~ ERROR static variable `bad` should have an upper case name + static bad: isize = 1; + //~^ ERROR static variable `bad` should have an upper case name + //~| NOTE #[forbid(bad_style)] implies #[forbid(non_upper_case_globals)] } mod warn { @@ -32,9 +38,13 @@ mod test { //~^ NOTE lint level defined here //~| NOTE lint level defined here - fn CamelCase() {} //~ WARN function `CamelCase` should have a snake case name + fn CamelCase() {} + //~^ WARN function `CamelCase` should have a snake case name + //~| NOTE #[warn(bad_style)] implies #[warn(non_snake_case)] - struct snake_case; //~ WARN type `snake_case` should have a camel case name + struct snake_case; + //~^ WARN type `snake_case` should have a camel case name + //~| NOTE #[warn(bad_style)] implies #[warn(non_camel_case_types)] } } diff --git a/src/test/compile-fail/lint-output-format-2.rs b/src/test/compile-fail/lint-output-format-2.rs index 2f74325d19c7d..8b76bedb003c0 100644 --- a/src/test/compile-fail/lint-output-format-2.rs +++ b/src/test/compile-fail/lint-output-format-2.rs @@ -11,15 +11,20 @@ // compile-flags: -F unused_features // aux-build:lint_output_format.rs -#![feature(foo)] //~ ERROR unused or unknown feature +#![feature(foo)] +//~^ ERROR unused or unknown feature +//~| NOTE [-F unused-features] #![feature(test_feature)] extern crate lint_output_format; use lint_output_format::{foo, bar}; -//~^ WARNING use of deprecated item: text, +//~^ WARNING use of deprecated item: text +//~| NOTE #[warn(deprecated)] on by default fn main() { - let _x = foo(); //~ WARNING #[warn(deprecated)] on by default + let _x = foo(); + //~^ WARNING use of deprecated item: text + //~| NOTE #[warn(deprecated)] on by default let _y = bar(); } diff --git a/src/test/run-pass/path-lookahead.rs b/src/test/run-pass/path-lookahead.rs index 017259af190fc..5c195c8a4c63a 100644 --- a/src/test/run-pass/path-lookahead.rs +++ b/src/test/run-pass/path-lookahead.rs @@ -10,11 +10,11 @@ // Parser test for #37765 -fn with_parens(arg: T) -> String { //~WARN dead_code - return (::to_string(&arg)); //~WARN unused_parens +fn with_parens(arg: T) -> String { //~WARN function is never used: `with_parens` + return (::to_string(&arg)); //~WARN unnecessary parentheses around `return` value } -fn no_parens(arg: T) -> String { //~WARN dead_code +fn no_parens(arg: T) -> String { //~WARN function is never used: `no_parens` return ::to_string(&arg); } diff --git a/src/test/ui/compare-method/proj-outlives-region.stderr b/src/test/ui/compare-method/proj-outlives-region.stderr index 021b571fe793c..2a707c6eb8b10 100644 --- a/src/test/ui/compare-method/proj-outlives-region.stderr +++ b/src/test/ui/compare-method/proj-outlives-region.stderr @@ -1,4 +1,4 @@ -error[E0276]: impl has stricter requirements than trait, #[deny(extra_requirement_in_impl)] on by default +error[E0276]: impl has stricter requirements than trait --> $DIR/proj-outlives-region.rs:22:5 | 17 | fn foo() where T: 'a; @@ -7,6 +7,7 @@ error[E0276]: impl has stricter requirements than trait, #[deny(extra_requiremen 22 | fn foo() where U: 'a { } //~ ERROR E0276 | ^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `U: 'a` | + = note: #[deny(extra_requirement_in_impl)] on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #37166 diff --git a/src/test/ui/compare-method/region-unrelated.stderr b/src/test/ui/compare-method/region-unrelated.stderr index 4df337c525743..9e822bd8b0790 100644 --- a/src/test/ui/compare-method/region-unrelated.stderr +++ b/src/test/ui/compare-method/region-unrelated.stderr @@ -1,4 +1,4 @@ -error[E0276]: impl has stricter requirements than trait, #[deny(extra_requirement_in_impl)] on by default +error[E0276]: impl has stricter requirements than trait --> $DIR/region-unrelated.rs:22:5 | 17 | fn foo() where T: 'a; @@ -7,6 +7,7 @@ error[E0276]: impl has stricter requirements than trait, #[deny(extra_requiremen 22 | fn foo() where V: 'a { } | ^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `V: 'a` | + = note: #[deny(extra_requirement_in_impl)] on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #37166 diff --git a/src/test/ui/span/issue-24690.stderr b/src/test/ui/span/issue-24690.stderr index dbe5e31287e97..623bb4a0d2697 100644 --- a/src/test/ui/span/issue-24690.stderr +++ b/src/test/ui/span/issue-24690.stderr @@ -4,6 +4,7 @@ error: variable `theTwo` should have a snake case name such as `the_two` 19 | let theTwo = 2; | ^^^^^^ | + = note: #[deny(warnings)] implies #[deny(non_snake_case)] note: lint level defined here --> $DIR/issue-24690.rs:16:9 | @@ -15,6 +16,8 @@ error: variable `theOtherTwo` should have a snake case name such as `the_other_t | 20 | let theOtherTwo = 2; | ^^^^^^^^^^^ + | + = note: #[deny(warnings)] implies #[deny(non_snake_case)] error: unused variable: `theOtherTwo` --> $DIR/issue-24690.rs:20:9 @@ -22,6 +25,7 @@ error: unused variable: `theOtherTwo` 20 | let theOtherTwo = 2; | ^^^^^^^^^^^ | + = note: #[deny(warnings)] implies #[deny(unused_variables)] note: lint level defined here --> $DIR/issue-24690.rs:16:9 | diff --git a/src/test/ui/span/multispan-import-lint.stderr b/src/test/ui/span/multispan-import-lint.stderr index b581584eee7e2..4b1ca7f98bbf6 100644 --- a/src/test/ui/span/multispan-import-lint.stderr +++ b/src/test/ui/span/multispan-import-lint.stderr @@ -1,6 +1,8 @@ -warning: unused imports: `Eq`, `Ord`, `PartialEq`, `PartialOrd`, #[warn(unused_imports)] on by default +warning: unused imports: `Eq`, `Ord`, `PartialEq`, `PartialOrd` --> $DIR/multispan-import-lint.rs:11:16 | 11 | use std::cmp::{Eq, Ord, min, PartialEq, PartialOrd}; | ^^ ^^^ ^^^^^^^^^ ^^^^^^^^^^ + | + = note: #[warn(unused_imports)] on by default From 93014467f83435d4721616f9b5e4417fc01623aa Mon Sep 17 00:00:00 2001 From: "Zack M. Davis" Date: Thu, 5 Jan 2017 18:55:43 -0800 Subject: [PATCH 126/137] note lint group set on command line triggering individual lint Previously, the note/message for the source of a lint being the command line unconditionally named the individual lint, even if the actual command specified a lint group (e.g., `-D warnings`); here, we take note of the actual command options so we can be more specific. This remains in the matter of #36846. --- src/librustc/lint/context.rs | 28 +++++++++++++------ src/librustc/lint/mod.rs | 3 +- src/test/compile-fail/lint-output-format-2.rs | 2 +- .../ui/lint/command-line-lint-group-allow.rs | 15 ++++++++++ .../ui/lint/command-line-lint-group-deny.rs | 15 ++++++++++ .../lint/command-line-lint-group-deny.stderr | 10 +++++++ .../ui/lint/command-line-lint-group-forbid.rs | 15 ++++++++++ .../command-line-lint-group-forbid.stderr | 10 +++++++ .../ui/lint/command-line-lint-group-warn.rs | 15 ++++++++++ .../lint/command-line-lint-group-warn.stderr | 8 ++++++ 10 files changed, 110 insertions(+), 11 deletions(-) create mode 100644 src/test/ui/lint/command-line-lint-group-allow.rs create mode 100644 src/test/ui/lint/command-line-lint-group-deny.rs create mode 100644 src/test/ui/lint/command-line-lint-group-deny.stderr create mode 100644 src/test/ui/lint/command-line-lint-group-forbid.rs create mode 100644 src/test/ui/lint/command-line-lint-group-forbid.stderr create mode 100644 src/test/ui/lint/command-line-lint-group-warn.rs create mode 100644 src/test/ui/lint/command-line-lint-group-warn.stderr diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 62f19412d52f0..28600e3ab8eb8 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -43,6 +43,7 @@ use std::fmt; use std::ops::Deref; use syntax::attr; use syntax::ast; +use syntax::symbol::Symbol; use syntax_pos::{MultiSpan, Span}; use errors::{self, Diagnostic, DiagnosticBuilder}; use hir; @@ -300,8 +301,9 @@ impl LintStore { check_lint_name_cmdline(sess, self, &lint_name[..], level); + let lint_flag_val = Symbol::intern(&lint_name); match self.find_lint(&lint_name[..], sess, None) { - Ok(lint_id) => self.set_level(lint_id, (level, CommandLine)), + Ok(lint_id) => self.set_level(lint_id, (level, CommandLine(lint_flag_val))), Err(FindLintError::Removed) => { } Err(_) => { match self.lint_groups.iter().map(|(&x, pair)| (x, pair.0.clone())) @@ -311,7 +313,7 @@ impl LintStore { Some(v) => { v.iter() .map(|lint_id: &LintId| - self.set_level(*lint_id, (level, CommandLine))) + self.set_level(*lint_id, (level, CommandLine(lint_flag_val)))) .collect::>(); } None => { @@ -470,12 +472,20 @@ pub fn raw_struct_lint<'a, S>(sess: &'a Session, Default => { err.note(&format!("#[{}({})] on by default", level.as_str(), name)); }, - CommandLine => { - err.note(&format!("[-{} {}]", - match level { - Warn => 'W', Deny => 'D', Forbid => 'F', - Allow => bug!() - }, name.replace("_", "-"))); + CommandLine(lint_flag_val) => { + let flag = match level { + Warn => "-W", Deny => "-D", Forbid => "-F", + Allow => bug!("earlier conditional return should handle Allow case") + }; + let hyphen_case_lint_name = name.replace("_", "-"); + if lint_flag_val.as_str().deref() == name { + err.note(&format!("requested on the command line with `{} {}`", + flag, hyphen_case_lint_name)); + } else { + let hyphen_case_flag_val = lint_flag_val.as_str().replace("_", "-"); + err.note(&format!("`{} {}` implies `{} {}`", + flag, hyphen_case_flag_val, flag, hyphen_case_lint_name)); + } }, Node(lint_attr_name, src) => { def = Some(src); @@ -671,7 +681,7 @@ pub trait LintContext<'tcx>: Sized { diag_builder.span_label(forbid_source_span, &format!("`forbid` level set here")) }, - LintSource::CommandLine => { + LintSource::CommandLine(_) => { diag_builder.note("`forbid` lint level was set on command line") } }.emit() diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index 9c2a892a5fc7d..e9f603db15d62 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -38,6 +38,7 @@ use std::ascii::AsciiExt; use syntax_pos::Span; use syntax::visit as ast_visit; use syntax::ast; +use syntax::symbol::Symbol; pub use lint::context::{LateContext, EarlyContext, LintContext, LintStore, raw_emit_lint, check_crate, check_ast_crate, gather_attrs, @@ -341,7 +342,7 @@ pub enum LintSource { Node(ast::Name, Span), /// Lint level was set by a command-line flag. - CommandLine, + CommandLine(Symbol), } pub type LevelSource = (Level, LintSource); diff --git a/src/test/compile-fail/lint-output-format-2.rs b/src/test/compile-fail/lint-output-format-2.rs index 8b76bedb003c0..0e68ff752e5a9 100644 --- a/src/test/compile-fail/lint-output-format-2.rs +++ b/src/test/compile-fail/lint-output-format-2.rs @@ -13,7 +13,7 @@ #![feature(foo)] //~^ ERROR unused or unknown feature -//~| NOTE [-F unused-features] +//~| NOTE requested on the command line with `-F unused-features` #![feature(test_feature)] diff --git a/src/test/ui/lint/command-line-lint-group-allow.rs b/src/test/ui/lint/command-line-lint-group-allow.rs new file mode 100644 index 0000000000000..cdb9684933d9b --- /dev/null +++ b/src/test/ui/lint/command-line-lint-group-allow.rs @@ -0,0 +1,15 @@ +// 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. + +// compile-flags: -A bad-style + +fn main() { + let _InappropriateCamelCasing = true; +} diff --git a/src/test/ui/lint/command-line-lint-group-deny.rs b/src/test/ui/lint/command-line-lint-group-deny.rs new file mode 100644 index 0000000000000..1248601c1e44a --- /dev/null +++ b/src/test/ui/lint/command-line-lint-group-deny.rs @@ -0,0 +1,15 @@ +// 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. + +// compile-flags: -D bad-style + +fn main() { + let _InappropriateCamelCasing = true; +} diff --git a/src/test/ui/lint/command-line-lint-group-deny.stderr b/src/test/ui/lint/command-line-lint-group-deny.stderr new file mode 100644 index 0000000000000..eafbf944dea97 --- /dev/null +++ b/src/test/ui/lint/command-line-lint-group-deny.stderr @@ -0,0 +1,10 @@ +error: variable `_InappropriateCamelCasing` should have a snake case name such as `_inappropriate_camel_casing` + --> $DIR/command-line-lint-group-deny.rs:14:9 + | +14 | let _InappropriateCamelCasing = true; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D bad-style` implies `-D non-snake-case` + +error: aborting due to previous error + diff --git a/src/test/ui/lint/command-line-lint-group-forbid.rs b/src/test/ui/lint/command-line-lint-group-forbid.rs new file mode 100644 index 0000000000000..ae16db44864c9 --- /dev/null +++ b/src/test/ui/lint/command-line-lint-group-forbid.rs @@ -0,0 +1,15 @@ +// 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. + +// compile-flags: -F bad-style + +fn main() { + let _InappropriateCamelCasing = true; +} diff --git a/src/test/ui/lint/command-line-lint-group-forbid.stderr b/src/test/ui/lint/command-line-lint-group-forbid.stderr new file mode 100644 index 0000000000000..0cf896060a27f --- /dev/null +++ b/src/test/ui/lint/command-line-lint-group-forbid.stderr @@ -0,0 +1,10 @@ +error: variable `_InappropriateCamelCasing` should have a snake case name such as `_inappropriate_camel_casing` + --> $DIR/command-line-lint-group-forbid.rs:14:9 + | +14 | let _InappropriateCamelCasing = true; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-F bad-style` implies `-F non-snake-case` + +error: aborting due to previous error + diff --git a/src/test/ui/lint/command-line-lint-group-warn.rs b/src/test/ui/lint/command-line-lint-group-warn.rs new file mode 100644 index 0000000000000..7d65c802788bf --- /dev/null +++ b/src/test/ui/lint/command-line-lint-group-warn.rs @@ -0,0 +1,15 @@ +// 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. + +// compile-flags: -W bad-style + +fn main() { + let _InappropriateCamelCasing = true; +} diff --git a/src/test/ui/lint/command-line-lint-group-warn.stderr b/src/test/ui/lint/command-line-lint-group-warn.stderr new file mode 100644 index 0000000000000..4ffbff6cdb7ec --- /dev/null +++ b/src/test/ui/lint/command-line-lint-group-warn.stderr @@ -0,0 +1,8 @@ +warning: variable `_InappropriateCamelCasing` should have a snake case name such as `_inappropriate_camel_casing` + --> $DIR/command-line-lint-group-warn.rs:14:9 + | +14 | let _InappropriateCamelCasing = true; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-W bad-style` implies `-W non-snake-case` + From 778958f25661a41081878ffbb1a589d926d5bd2a Mon Sep 17 00:00:00 2001 From: "Zack M. Davis" Date: Wed, 4 Jan 2017 23:32:09 -0800 Subject: [PATCH 127/137] make lint-group-style test a UI rather than a compile-fail test As suggested by Niko Matsakis in review (https://github.com/rust-lang/rust/pull/38103#discussion_r94460982) regarding the endeavor prompted by #36846. --- src/test/compile-fail/lint-group-style.rs | 51 ----------------- src/test/ui/lint/lint-group-style.rs | 36 ++++++++++++ src/test/ui/lint/lint-group-style.stderr | 67 +++++++++++++++++++++++ 3 files changed, 103 insertions(+), 51 deletions(-) delete mode 100644 src/test/compile-fail/lint-group-style.rs create mode 100644 src/test/ui/lint/lint-group-style.rs create mode 100644 src/test/ui/lint/lint-group-style.stderr diff --git a/src/test/compile-fail/lint-group-style.rs b/src/test/compile-fail/lint-group-style.rs deleted file mode 100644 index a8c377034756a..0000000000000 --- a/src/test/compile-fail/lint-group-style.rs +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2014 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. - -#![deny(bad_style)] -//~^ NOTE lint level defined here -#![allow(dead_code)] - -fn CamelCase() {} -//~^ ERROR function `CamelCase` should have a snake case name -//~| NOTE #[deny(bad_style)] implies #[deny(non_snake_case)] - -#[allow(bad_style)] -mod test { - fn CamelCase() {} - - #[forbid(bad_style)] - //~^ NOTE lint level defined here - //~^^ NOTE lint level defined here - mod bad { - fn CamelCase() {} - //~^ ERROR function `CamelCase` should have a snake case name - //~| NOTE #[forbid(bad_style)] implies #[forbid(non_snake_case)] - - static bad: isize = 1; - //~^ ERROR static variable `bad` should have an upper case name - //~| NOTE #[forbid(bad_style)] implies #[forbid(non_upper_case_globals)] - } - - mod warn { - #![warn(bad_style)] - //~^ NOTE lint level defined here - //~| NOTE lint level defined here - - fn CamelCase() {} - //~^ WARN function `CamelCase` should have a snake case name - //~| NOTE #[warn(bad_style)] implies #[warn(non_snake_case)] - - struct snake_case; - //~^ WARN type `snake_case` should have a camel case name - //~| NOTE #[warn(bad_style)] implies #[warn(non_camel_case_types)] - } -} - -fn main() {} diff --git a/src/test/ui/lint/lint-group-style.rs b/src/test/ui/lint/lint-group-style.rs new file mode 100644 index 0000000000000..2bd760e417a89 --- /dev/null +++ b/src/test/ui/lint/lint-group-style.rs @@ -0,0 +1,36 @@ +// Copyright 2014–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. + +#![deny(bad_style)] +#![allow(dead_code)] + +fn CamelCase() {} + +#[allow(bad_style)] +mod test { + fn CamelCase() {} + + #[forbid(bad_style)] + mod bad { + fn CamelCase() {} + + static bad: isize = 1; + } + + mod warn { + #![warn(bad_style)] + + fn CamelCase() {} + + struct snake_case; + } +} + +fn main() {} diff --git a/src/test/ui/lint/lint-group-style.stderr b/src/test/ui/lint/lint-group-style.stderr new file mode 100644 index 0000000000000..93f6399b22726 --- /dev/null +++ b/src/test/ui/lint/lint-group-style.stderr @@ -0,0 +1,67 @@ +error: function `CamelCase` should have a snake case name such as `camel_case` + --> $DIR/lint-group-style.rs:14:1 + | +14 | fn CamelCase() {} + | ^^^^^^^^^^^^^^^^^ + | + = note: #[deny(bad_style)] implies #[deny(non_snake_case)] +note: lint level defined here + --> $DIR/lint-group-style.rs:11:9 + | +11 | #![deny(bad_style)] + | ^^^^^^^^^ + +error: function `CamelCase` should have a snake case name such as `camel_case` + --> $DIR/lint-group-style.rs:22:9 + | +22 | fn CamelCase() {} + | ^^^^^^^^^^^^^^^^^ + | + = note: #[forbid(bad_style)] implies #[forbid(non_snake_case)] +note: lint level defined here + --> $DIR/lint-group-style.rs:20:14 + | +20 | #[forbid(bad_style)] + | ^^^^^^^^^ + +error: static variable `bad` should have an upper case name such as `BAD` + --> $DIR/lint-group-style.rs:24:9 + | +24 | static bad: isize = 1; + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: #[forbid(bad_style)] implies #[forbid(non_upper_case_globals)] +note: lint level defined here + --> $DIR/lint-group-style.rs:20:14 + | +20 | #[forbid(bad_style)] + | ^^^^^^^^^ + +warning: function `CamelCase` should have a snake case name such as `camel_case` + --> $DIR/lint-group-style.rs:30:9 + | +30 | fn CamelCase() {} + | ^^^^^^^^^^^^^^^^^ + | + = note: #[warn(bad_style)] implies #[warn(non_snake_case)] +note: lint level defined here + --> $DIR/lint-group-style.rs:28:17 + | +28 | #![warn(bad_style)] + | ^^^^^^^^^ + +warning: type `snake_case` should have a camel case name such as `SnakeCase` + --> $DIR/lint-group-style.rs:32:9 + | +32 | struct snake_case; + | ^^^^^^^^^^^^^^^^^^ + | + = note: #[warn(bad_style)] implies #[warn(non_camel_case_types)] +note: lint level defined here + --> $DIR/lint-group-style.rs:28:17 + | +28 | #![warn(bad_style)] + | ^^^^^^^^^ + +error: aborting due to 3 previous errors + From 72af42e8974f521e3fed753feac3d0638ad61025 Mon Sep 17 00:00:00 2001 From: "Zack M. Davis" Date: Thu, 5 Jan 2017 20:01:22 -0800 Subject: [PATCH 128/137] note wording: lint implied by lint group, not lint group implies lint --- src/librustc/lint/context.rs | 8 ++++---- src/test/compile-fail/issue-30730.rs | 2 +- src/test/ui/lint/command-line-lint-group-deny.stderr | 2 +- src/test/ui/lint/command-line-lint-group-forbid.stderr | 2 +- src/test/ui/lint/command-line-lint-group-warn.stderr | 2 +- src/test/ui/lint/lint-group-style.stderr | 10 +++++----- src/test/ui/span/issue-24690.stderr | 6 +++--- 7 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 28600e3ab8eb8..32bc81e947037 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -483,16 +483,16 @@ pub fn raw_struct_lint<'a, S>(sess: &'a Session, flag, hyphen_case_lint_name)); } else { let hyphen_case_flag_val = lint_flag_val.as_str().replace("_", "-"); - err.note(&format!("`{} {}` implies `{} {}`", - flag, hyphen_case_flag_val, flag, hyphen_case_lint_name)); + err.note(&format!("`{} {}` implied by `{} {}`", + flag, hyphen_case_lint_name, flag, hyphen_case_flag_val)); } }, Node(lint_attr_name, src) => { def = Some(src); if lint_attr_name.as_str().deref() != name { let level_str = level.as_str(); - err.note(&format!("#[{}({})] implies #[{}({})]", - level_str, lint_attr_name, level_str, name)); + err.note(&format!("#[{}({})] implied by #[{}({})]", + level_str, name, level_str, lint_attr_name)); } } } diff --git a/src/test/compile-fail/issue-30730.rs b/src/test/compile-fail/issue-30730.rs index 6082740f427d7..086938334c78a 100644 --- a/src/test/compile-fail/issue-30730.rs +++ b/src/test/compile-fail/issue-30730.rs @@ -11,5 +11,5 @@ #![deny(warnings)] //~ NOTE: lint level defined here use std::thread; //~^ ERROR: unused import -//~| NOTE: #[deny(warnings)] implies #[deny(unused_imports)] +//~| NOTE: #[deny(unused_imports)] implied by #[deny(warnings)] fn main() {} diff --git a/src/test/ui/lint/command-line-lint-group-deny.stderr b/src/test/ui/lint/command-line-lint-group-deny.stderr index eafbf944dea97..23fac66cc6c98 100644 --- a/src/test/ui/lint/command-line-lint-group-deny.stderr +++ b/src/test/ui/lint/command-line-lint-group-deny.stderr @@ -4,7 +4,7 @@ error: variable `_InappropriateCamelCasing` should have a snake case name such a 14 | let _InappropriateCamelCasing = true; | ^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `-D bad-style` implies `-D non-snake-case` + = note: `-D non-snake-case` implied by `-D bad-style` error: aborting due to previous error diff --git a/src/test/ui/lint/command-line-lint-group-forbid.stderr b/src/test/ui/lint/command-line-lint-group-forbid.stderr index 0cf896060a27f..0babd7f6fe47a 100644 --- a/src/test/ui/lint/command-line-lint-group-forbid.stderr +++ b/src/test/ui/lint/command-line-lint-group-forbid.stderr @@ -4,7 +4,7 @@ error: variable `_InappropriateCamelCasing` should have a snake case name such a 14 | let _InappropriateCamelCasing = true; | ^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `-F bad-style` implies `-F non-snake-case` + = note: `-F non-snake-case` implied by `-F bad-style` error: aborting due to previous error diff --git a/src/test/ui/lint/command-line-lint-group-warn.stderr b/src/test/ui/lint/command-line-lint-group-warn.stderr index 4ffbff6cdb7ec..998c892c7e349 100644 --- a/src/test/ui/lint/command-line-lint-group-warn.stderr +++ b/src/test/ui/lint/command-line-lint-group-warn.stderr @@ -4,5 +4,5 @@ warning: variable `_InappropriateCamelCasing` should have a snake case name such 14 | let _InappropriateCamelCasing = true; | ^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `-W bad-style` implies `-W non-snake-case` + = note: `-W non-snake-case` implied by `-W bad-style` diff --git a/src/test/ui/lint/lint-group-style.stderr b/src/test/ui/lint/lint-group-style.stderr index 93f6399b22726..9c0f4866af690 100644 --- a/src/test/ui/lint/lint-group-style.stderr +++ b/src/test/ui/lint/lint-group-style.stderr @@ -4,7 +4,7 @@ error: function `CamelCase` should have a snake case name such as `camel_case` 14 | fn CamelCase() {} | ^^^^^^^^^^^^^^^^^ | - = note: #[deny(bad_style)] implies #[deny(non_snake_case)] + = note: #[deny(non_snake_case)] implied by #[deny(bad_style)] note: lint level defined here --> $DIR/lint-group-style.rs:11:9 | @@ -17,7 +17,7 @@ error: function `CamelCase` should have a snake case name such as `camel_case` 22 | fn CamelCase() {} | ^^^^^^^^^^^^^^^^^ | - = note: #[forbid(bad_style)] implies #[forbid(non_snake_case)] + = note: #[forbid(non_snake_case)] implied by #[forbid(bad_style)] note: lint level defined here --> $DIR/lint-group-style.rs:20:14 | @@ -30,7 +30,7 @@ error: static variable `bad` should have an upper case name such as `BAD` 24 | static bad: isize = 1; | ^^^^^^^^^^^^^^^^^^^^^^ | - = note: #[forbid(bad_style)] implies #[forbid(non_upper_case_globals)] + = note: #[forbid(non_upper_case_globals)] implied by #[forbid(bad_style)] note: lint level defined here --> $DIR/lint-group-style.rs:20:14 | @@ -43,7 +43,7 @@ warning: function `CamelCase` should have a snake case name such as `camel_case` 30 | fn CamelCase() {} | ^^^^^^^^^^^^^^^^^ | - = note: #[warn(bad_style)] implies #[warn(non_snake_case)] + = note: #[warn(non_snake_case)] implied by #[warn(bad_style)] note: lint level defined here --> $DIR/lint-group-style.rs:28:17 | @@ -56,7 +56,7 @@ warning: type `snake_case` should have a camel case name such as `SnakeCase` 32 | struct snake_case; | ^^^^^^^^^^^^^^^^^^ | - = note: #[warn(bad_style)] implies #[warn(non_camel_case_types)] + = note: #[warn(non_camel_case_types)] implied by #[warn(bad_style)] note: lint level defined here --> $DIR/lint-group-style.rs:28:17 | diff --git a/src/test/ui/span/issue-24690.stderr b/src/test/ui/span/issue-24690.stderr index 623bb4a0d2697..c4f2616f5945b 100644 --- a/src/test/ui/span/issue-24690.stderr +++ b/src/test/ui/span/issue-24690.stderr @@ -4,7 +4,7 @@ error: variable `theTwo` should have a snake case name such as `the_two` 19 | let theTwo = 2; | ^^^^^^ | - = note: #[deny(warnings)] implies #[deny(non_snake_case)] + = note: #[deny(non_snake_case)] implied by #[deny(warnings)] note: lint level defined here --> $DIR/issue-24690.rs:16:9 | @@ -17,7 +17,7 @@ error: variable `theOtherTwo` should have a snake case name such as `the_other_t 20 | let theOtherTwo = 2; | ^^^^^^^^^^^ | - = note: #[deny(warnings)] implies #[deny(non_snake_case)] + = note: #[deny(non_snake_case)] implied by #[deny(warnings)] error: unused variable: `theOtherTwo` --> $DIR/issue-24690.rs:20:9 @@ -25,7 +25,7 @@ error: unused variable: `theOtherTwo` 20 | let theOtherTwo = 2; | ^^^^^^^^^^^ | - = note: #[deny(warnings)] implies #[deny(unused_variables)] + = note: #[deny(unused_variables)] implied by #[deny(warnings)] note: lint level defined here --> $DIR/issue-24690.rs:16:9 | From a40be0857c7bf48e39f815417b0b5293cd8ed1aa Mon Sep 17 00:00:00 2001 From: Tyler Julian Date: Tue, 10 Jan 2017 19:11:56 -0800 Subject: [PATCH 129/137] libstd/net: Add `peek` APIs to UdpSocket and TcpStream These methods enable socket reads without side-effects. That is, repeated calls to peek() return identical data. This is accomplished by providing the POSIX flag MSG_PEEK to the underlying socket read operations. This also moves the current implementation of recv_from out of the platform-independent sys_common and into respective sys/windows and sys/unix implementations. This allows for more platform-dependent implementations. --- src/liblibc | 2 +- src/libstd/lib.rs | 1 + src/libstd/net/tcp.rs | 54 +++++++++++++++++++ src/libstd/net/udp.rs | 97 +++++++++++++++++++++++++++++++++++ src/libstd/sys/unix/net.rs | 45 ++++++++++++++-- src/libstd/sys/windows/c.rs | 1 + src/libstd/sys/windows/net.rs | 44 +++++++++++++++- src/libstd/sys_common/net.rs | 24 +++++---- 8 files changed, 251 insertions(+), 17 deletions(-) diff --git a/src/liblibc b/src/liblibc index 7d57bdcdbb565..cb7f66732175e 160000 --- a/src/liblibc +++ b/src/liblibc @@ -1 +1 @@ -Subproject commit 7d57bdcdbb56540f37afe5a934ce12d33a6ca7fc +Subproject commit cb7f66732175e6171587ed69656b7aae7dd2e6ec diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 9557c520c5071..3c06409e3b18e 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -275,6 +275,7 @@ #![feature(oom)] #![feature(optin_builtin_traits)] #![feature(panic_unwind)] +#![feature(peek)] #![feature(placement_in_syntax)] #![feature(prelude_import)] #![feature(pub_restricted)] diff --git a/src/libstd/net/tcp.rs b/src/libstd/net/tcp.rs index ed1f08f9c9090..ba6160cc72331 100644 --- a/src/libstd/net/tcp.rs +++ b/src/libstd/net/tcp.rs @@ -296,6 +296,29 @@ impl TcpStream { self.0.write_timeout() } + /// Receives data on the socket from the remote adress to which it is + /// connected, without removing that data from the queue. On success, + /// returns the number of bytes peeked. + /// + /// Successive calls return the same data. This is accomplished by passing + /// `MSG_PEEK` as a flag to the underlying `recv` system call. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(peek)] + /// use std::net::TcpStream; + /// + /// let stream = TcpStream::connect("127.0.0.1:8000") + /// .expect("couldn't bind to address"); + /// let mut buf = [0; 10]; + /// let len = stream.peek(&mut buf).expect("peek failed"); + /// ``` + #[unstable(feature = "peek", issue = "38980")] + pub fn peek(&self, buf: &mut [u8]) -> io::Result { + self.0.peek(buf) + } + /// Sets the value of the `TCP_NODELAY` option on this socket. /// /// If set, this option disables the Nagle algorithm. This means that @@ -1405,4 +1428,35 @@ mod tests { Err(e) => panic!("unexpected error {}", e), } } + + #[test] + fn peek() { + each_ip(&mut |addr| { + let (txdone, rxdone) = channel(); + + let srv = t!(TcpListener::bind(&addr)); + let _t = thread::spawn(move|| { + let mut cl = t!(srv.accept()).0; + cl.write(&[1,3,3,7]).unwrap(); + t!(rxdone.recv()); + }); + + let mut c = t!(TcpStream::connect(&addr)); + let mut b = [0; 10]; + for _ in 1..3 { + let len = c.peek(&mut b).unwrap(); + assert_eq!(len, 4); + } + let len = c.read(&mut b).unwrap(); + assert_eq!(len, 4); + + t!(c.set_nonblocking(true)); + match c.peek(&mut b) { + Ok(_) => panic!("expected error"), + Err(ref e) if e.kind() == ErrorKind::WouldBlock => {} + Err(e) => panic!("unexpected error {}", e), + } + t!(txdone.send(())); + }) + } } diff --git a/src/libstd/net/udp.rs b/src/libstd/net/udp.rs index f8a5ec0b3791e..2f28f475dc88b 100644 --- a/src/libstd/net/udp.rs +++ b/src/libstd/net/udp.rs @@ -83,6 +83,30 @@ impl UdpSocket { self.0.recv_from(buf) } + /// Receives data from the socket, without removing it from the queue. + /// + /// Successive calls return the same data. This is accomplished by passing + /// `MSG_PEEK` as a flag to the underlying `recvfrom` system call. + /// + /// On success, returns the number of bytes peeked and the address from + /// whence the data came. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(peek)] + /// use std::net::UdpSocket; + /// + /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); + /// let mut buf = [0; 10]; + /// let (number_of_bytes, src_addr) = socket.peek_from(&mut buf) + /// .expect("Didn't receive data"); + /// ``` + #[unstable(feature = "peek", issue = "38980")] + pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { + self.0.peek_from(buf) + } + /// Sends data on the socket to the given address. On success, returns the /// number of bytes written. /// @@ -579,6 +603,37 @@ impl UdpSocket { self.0.recv(buf) } + /// Receives data on the socket from the remote adress to which it is + /// connected, without removing that data from the queue. On success, + /// returns the number of bytes peeked. + /// + /// Successive calls return the same data. This is accomplished by passing + /// `MSG_PEEK` as a flag to the underlying `recv` system call. + /// + /// # Errors + /// + /// This method will fail if the socket is not connected. The `connect` method + /// will connect this socket to a remote address. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(peek)] + /// use std::net::UdpSocket; + /// + /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); + /// socket.connect("127.0.0.1:8080").expect("connect function failed"); + /// let mut buf = [0; 10]; + /// match socket.peek(&mut buf) { + /// Ok(received) => println!("received {} bytes", received), + /// Err(e) => println!("peek function failed: {:?}", e), + /// } + /// ``` + #[unstable(feature = "peek", issue = "38980")] + pub fn peek(&self, buf: &mut [u8]) -> io::Result { + self.0.peek(buf) + } + /// Moves this UDP socket into or out of nonblocking mode. /// /// On Unix this corresponds to calling fcntl, and on Windows this @@ -869,6 +924,48 @@ mod tests { assert_eq!(b"hello world", &buf[..]); } + #[test] + fn connect_send_peek_recv() { + each_ip(&mut |addr, _| { + let socket = t!(UdpSocket::bind(&addr)); + t!(socket.connect(addr)); + + t!(socket.send(b"hello world")); + + for _ in 1..3 { + let mut buf = [0; 11]; + let size = t!(socket.peek(&mut buf)); + assert_eq!(b"hello world", &buf[..]); + assert_eq!(size, 11); + } + + let mut buf = [0; 11]; + let size = t!(socket.recv(&mut buf)); + assert_eq!(b"hello world", &buf[..]); + assert_eq!(size, 11); + }) + } + + #[test] + fn peek_from() { + each_ip(&mut |addr, _| { + let socket = t!(UdpSocket::bind(&addr)); + t!(socket.send_to(b"hello world", &addr)); + + for _ in 1..3 { + let mut buf = [0; 11]; + let (size, _) = t!(socket.peek_from(&mut buf)); + assert_eq!(b"hello world", &buf[..]); + assert_eq!(size, 11); + } + + let mut buf = [0; 11]; + let (size, _) = t!(socket.recv_from(&mut buf)); + assert_eq!(b"hello world", &buf[..]); + assert_eq!(size, 11); + }) + } + #[test] fn ttl() { let ttl = 100; diff --git a/src/libstd/sys/unix/net.rs b/src/libstd/sys/unix/net.rs index ad287bbec3889..5efddca110f05 100644 --- a/src/libstd/sys/unix/net.rs +++ b/src/libstd/sys/unix/net.rs @@ -10,12 +10,13 @@ use ffi::CStr; use io; -use libc::{self, c_int, size_t, sockaddr, socklen_t, EAI_SYSTEM}; +use libc::{self, c_int, c_void, size_t, sockaddr, socklen_t, EAI_SYSTEM, MSG_PEEK}; +use mem; use net::{SocketAddr, Shutdown}; use str; use sys::fd::FileDesc; use sys_common::{AsInner, FromInner, IntoInner}; -use sys_common::net::{getsockopt, setsockopt}; +use sys_common::net::{getsockopt, setsockopt, sockaddr_to_addr}; use time::Duration; pub use sys::{cvt, cvt_r}; @@ -155,8 +156,46 @@ impl Socket { self.0.duplicate().map(Socket) } + fn recv_with_flags(&self, buf: &mut [u8], flags: c_int) -> io::Result { + let ret = cvt(unsafe { + libc::recv(self.0.raw(), + buf.as_mut_ptr() as *mut c_void, + buf.len(), + flags) + })?; + Ok(ret as usize) + } + pub fn read(&self, buf: &mut [u8]) -> io::Result { - self.0.read(buf) + self.recv_with_flags(buf, 0) + } + + pub fn peek(&self, buf: &mut [u8]) -> io::Result { + self.recv_with_flags(buf, MSG_PEEK) + } + + fn recv_from_with_flags(&self, buf: &mut [u8], flags: c_int) + -> io::Result<(usize, SocketAddr)> { + let mut storage: libc::sockaddr_storage = unsafe { mem::zeroed() }; + let mut addrlen = mem::size_of_val(&storage) as libc::socklen_t; + + let n = cvt(unsafe { + libc::recvfrom(self.0.raw(), + buf.as_mut_ptr() as *mut c_void, + buf.len(), + flags, + &mut storage as *mut _ as *mut _, + &mut addrlen) + })?; + Ok((n as usize, sockaddr_to_addr(&storage, addrlen as usize)?)) + } + + pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { + self.recv_from_with_flags(buf, 0) + } + + pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { + self.recv_from_with_flags(buf, MSG_PEEK) } pub fn read_to_end(&self, buf: &mut Vec) -> io::Result { diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs index dc7b2fc9a6bab..9f03f5c9717fc 100644 --- a/src/libstd/sys/windows/c.rs +++ b/src/libstd/sys/windows/c.rs @@ -244,6 +244,7 @@ pub const IP_ADD_MEMBERSHIP: c_int = 12; pub const IP_DROP_MEMBERSHIP: c_int = 13; pub const IPV6_ADD_MEMBERSHIP: c_int = 12; pub const IPV6_DROP_MEMBERSHIP: c_int = 13; +pub const MSG_PEEK: c_int = 0x2; #[repr(C)] pub struct ip_mreq { diff --git a/src/libstd/sys/windows/net.rs b/src/libstd/sys/windows/net.rs index aca6994503ff8..adf6210d82e89 100644 --- a/src/libstd/sys/windows/net.rs +++ b/src/libstd/sys/windows/net.rs @@ -147,12 +147,12 @@ impl Socket { Ok(socket) } - pub fn read(&self, buf: &mut [u8]) -> io::Result { + fn recv_with_flags(&self, buf: &mut [u8], flags: c_int) -> io::Result { // On unix when a socket is shut down all further reads return 0, so we // do the same on windows to map a shut down socket to returning EOF. let len = cmp::min(buf.len(), i32::max_value() as usize) as i32; unsafe { - match c::recv(self.0, buf.as_mut_ptr() as *mut c_void, len, 0) { + match c::recv(self.0, buf.as_mut_ptr() as *mut c_void, len, flags) { -1 if c::WSAGetLastError() == c::WSAESHUTDOWN => Ok(0), -1 => Err(last_error()), n => Ok(n as usize) @@ -160,6 +160,46 @@ impl Socket { } } + pub fn read(&self, buf: &mut [u8]) -> io::Result { + self.recv_with_flags(buf, 0) + } + + pub fn peek(&self, buf: &mut [u8]) -> io::Result { + self.recv_with_flags(buf, c::MSG_PEEK) + } + + fn recv_from_with_flags(&self, buf: &mut [u8], flags: c_int) + -> io::Result<(usize, SocketAddr)> { + let mut storage: c::SOCKADDR_STORAGE_LH = unsafe { mem::zeroed() }; + let mut addrlen = mem::size_of_val(&storage) as c::socklen_t; + let len = cmp::min(buf.len(), ::max_value() as usize) as wrlen_t; + + // On unix when a socket is shut down all further reads return 0, so we + // do the same on windows to map a shut down socket to returning EOF. + unsafe { + match c::recvfrom(self.0, + buf.as_mut_ptr() as *mut c_void, + len, + flags, + &mut storage as *mut _ as *mut _, + &mut addrlen) { + -1 if c::WSAGetLastError() == c::WSAESHUTDOWN => { + Ok((0, net::sockaddr_to_addr(&storage, addrlen as usize)?)) + }, + -1 => Err(last_error()), + n => Ok((n as usize, net::sockaddr_to_addr(&storage, addrlen as usize)?)), + } + } + } + + pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { + self.recv_from_with_flags(buf, 0) + } + + pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { + self.recv_from_with_flags(buf, c::MSG_PEEK) + } + pub fn read_to_end(&self, buf: &mut Vec) -> io::Result { let mut me = self; (&mut me).read_to_end(buf) diff --git a/src/libstd/sys_common/net.rs b/src/libstd/sys_common/net.rs index 10ad61f4c800c..3cdeb51194575 100644 --- a/src/libstd/sys_common/net.rs +++ b/src/libstd/sys_common/net.rs @@ -91,7 +91,7 @@ fn sockname(f: F) -> io::Result } } -fn sockaddr_to_addr(storage: &c::sockaddr_storage, +pub fn sockaddr_to_addr(storage: &c::sockaddr_storage, len: usize) -> io::Result { match storage.ss_family as c_int { c::AF_INET => { @@ -222,6 +222,10 @@ impl TcpStream { self.inner.timeout(c::SO_SNDTIMEO) } + pub fn peek(&self, buf: &mut [u8]) -> io::Result { + self.inner.peek(buf) + } + pub fn read(&self, buf: &mut [u8]) -> io::Result { self.inner.read(buf) } @@ -441,17 +445,11 @@ impl UdpSocket { } pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { - let mut storage: c::sockaddr_storage = unsafe { mem::zeroed() }; - let mut addrlen = mem::size_of_val(&storage) as c::socklen_t; - let len = cmp::min(buf.len(), ::max_value() as usize) as wrlen_t; + self.inner.recv_from(buf) + } - let n = cvt(unsafe { - c::recvfrom(*self.inner.as_inner(), - buf.as_mut_ptr() as *mut c_void, - len, 0, - &mut storage as *mut _ as *mut _, &mut addrlen) - })?; - Ok((n as usize, sockaddr_to_addr(&storage, addrlen as usize)?)) + pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { + self.inner.peek_from(buf) } pub fn send_to(&self, buf: &[u8], dst: &SocketAddr) -> io::Result { @@ -578,6 +576,10 @@ impl UdpSocket { self.inner.read(buf) } + pub fn peek(&self, buf: &mut [u8]) -> io::Result { + self.inner.peek(buf) + } + pub fn send(&self, buf: &[u8]) -> io::Result { let len = cmp::min(buf.len(), ::max_value() as usize) as wrlen_t; let ret = cvt(unsafe { From 0477daf9f0788e9ce77149357be9d7209be38fce Mon Sep 17 00:00:00 2001 From: Josh Driver Date: Tue, 24 Jan 2017 01:31:49 +1030 Subject: [PATCH 130/137] Make builtin derives a SyntaxExtension This allows builtin derives to be registered and resolved, just like other derive types. --- src/libsyntax/ext/base.rs | 8 ++++- src/libsyntax/ext/expand.rs | 4 +-- src/libsyntax_ext/deriving/decodable.rs | 1 + src/libsyntax_ext/deriving/encodable.rs | 1 + src/libsyntax_ext/deriving/mod.rs | 42 ++++++++++++------------- src/libsyntax_ext/lib.rs | 2 ++ 6 files changed, 34 insertions(+), 24 deletions(-) diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index edf74e1fe19f1..231e2e6205cf8 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -10,7 +10,7 @@ pub use self::SyntaxExtension::{MultiDecorator, MultiModifier, NormalTT, IdentTT}; -use ast::{self, Attribute, Name, PatKind}; +use ast::{self, Attribute, Name, PatKind, MetaItem}; use attr::HasAttrs; use codemap::{self, CodeMap, ExpnInfo, Spanned, respan}; use syntax_pos::{Span, ExpnId, NO_EXPANSION}; @@ -471,6 +471,9 @@ impl MacResult for DummyResult { } } +pub type BuiltinDeriveFn = + for<'cx> fn(&'cx mut ExtCtxt, Span, &MetaItem, &Annotatable, &mut FnMut(Annotatable)); + /// An enum representing the different kinds of syntax extensions. pub enum SyntaxExtension { /// A syntax extension that is attached to an item and creates new items @@ -508,6 +511,9 @@ pub enum SyntaxExtension { IdentTT(Box, Option, bool), CustomDerive(Box), + + /// An attribute-like procedural macro that derives a builtin trait. + BuiltinDerive(BuiltinDeriveFn), } pub type NamedSyntaxExtension = (Name, SyntaxExtension); diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 226625ebc8e5e..0e5d94e03810f 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -370,7 +370,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let tok_result = mac.expand(self.cx, attr.span, attr_toks, item_toks); self.parse_expansion(tok_result, kind, name, attr.span) } - SyntaxExtension::CustomDerive(_) => { + SyntaxExtension::CustomDerive(..) | SyntaxExtension::BuiltinDerive(..) => { self.cx.span_err(attr.span, &format!("`{}` is a derive mode", name)); kind.dummy(attr.span) } @@ -440,7 +440,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { return kind.dummy(span); } - SyntaxExtension::CustomDerive(..) => { + SyntaxExtension::CustomDerive(..) | SyntaxExtension::BuiltinDerive(..) => { self.cx.span_err(path.span, &format!("`{}` is a derive mode", extname)); return kind.dummy(span); } diff --git a/src/libsyntax_ext/deriving/decodable.rs b/src/libsyntax_ext/deriving/decodable.rs index e2634c60dcaad..6359d642d157c 100644 --- a/src/libsyntax_ext/deriving/decodable.rs +++ b/src/libsyntax_ext/deriving/decodable.rs @@ -35,6 +35,7 @@ pub fn expand_deriving_decodable(cx: &mut ExtCtxt, mitem: &MetaItem, item: &Annotatable, push: &mut FnMut(Annotatable)) { + deriving::warn_if_deprecated(cx, span, "Decodable"); expand_deriving_decodable_imp(cx, span, mitem, item, push, "serialize") } diff --git a/src/libsyntax_ext/deriving/encodable.rs b/src/libsyntax_ext/deriving/encodable.rs index 092738ab8a03d..a276193e81b97 100644 --- a/src/libsyntax_ext/deriving/encodable.rs +++ b/src/libsyntax_ext/deriving/encodable.rs @@ -112,6 +112,7 @@ pub fn expand_deriving_encodable(cx: &mut ExtCtxt, mitem: &MetaItem, item: &Annotatable, push: &mut FnMut(Annotatable)) { + deriving::warn_if_deprecated(cx, span, "Encodable"); expand_deriving_encodable_imp(cx, span, mitem, item, push, "serialize") } diff --git a/src/libsyntax_ext/deriving/mod.rs b/src/libsyntax_ext/deriving/mod.rs index 096f6dfd5d8d8..30d0da588a5df 100644 --- a/src/libsyntax_ext/deriving/mod.rs +++ b/src/libsyntax_ext/deriving/mod.rs @@ -10,10 +10,11 @@ //! The compiler code necessary to implement the `#[derive]` extensions. +use std::rc::Rc; use syntax::ast::{self, MetaItem}; use syntax::attr::HasAttrs; use syntax::codemap; -use syntax::ext::base::{Annotatable, ExtCtxt, SyntaxExtension}; +use syntax::ext::base::{Annotatable, ExtCtxt, SyntaxExtension, Resolver}; use syntax::ext::build::AstBuilder; use syntax::feature_gate; use syntax::ptr::P; @@ -292,7 +293,10 @@ pub fn expand_derive(cx: &mut ExtCtxt, for titem in traits.iter() { let tname = titem.word().unwrap().name(); let name = Symbol::intern(&format!("derive({})", tname)); + let tname_cx = ast::Ident::with_empty_ctxt(titem.name().unwrap()); let mitem = cx.meta_word(titem.span, name); + let path = ast::Path::from_ident(titem.span, tname_cx); + let ext = cx.resolver.resolve_macro(cx.current_expansion.mark, &path, false).unwrap(); let span = Span { expn_id: cx.codemap().record_expansion(codemap::ExpnInfo { @@ -306,11 +310,15 @@ pub fn expand_derive(cx: &mut ExtCtxt, ..titem.span }; - let my_item = Annotatable::Item(item); - expand_builtin(&tname.as_str(), cx, span, &mitem, &my_item, &mut |a| { - items.push(a); - }); - item = my_item.expect_item(); + if let SyntaxExtension::BuiltinDerive(ref func) = *ext { + let my_item = Annotatable::Item(item); + func(cx, span, &mitem, &my_item, &mut |a| { + items.push(a) + }); + item = my_item.expect_item(); + } else { + unreachable!(); + } } items.insert(0, Annotatable::Item(item)); @@ -326,21 +334,13 @@ macro_rules! derive_traits { } } - fn expand_builtin(name: &str, - ecx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Annotatable, - push: &mut FnMut(Annotatable)) { - match name { - $( - $name => { - warn_if_deprecated(ecx, span, $name); - $func(ecx, span, mitem, item, push); - } - )* - _ => panic!("not a builtin derive mode: {}", name), - } + pub fn register_builtin_derives(resolver: &mut Resolver) { + $( + resolver.add_ext( + ast::Ident::with_empty_ctxt(Symbol::intern($name)), + Rc::new(SyntaxExtension::BuiltinDerive($func)) + ); + )* } } } diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs index ebec23d0901a0..e872cfaeacb7b 100644 --- a/src/libsyntax_ext/lib.rs +++ b/src/libsyntax_ext/lib.rs @@ -57,6 +57,8 @@ use syntax::symbol::Symbol; pub fn register_builtins(resolver: &mut syntax::ext::base::Resolver, user_exts: Vec, enable_quotes: bool) { + deriving::register_builtin_derives(resolver); + let mut register = |name, ext| { resolver.add_ext(ast::Ident::with_empty_ctxt(name), Rc::new(ext)); }; From 0a7380d7fcd99ef288ee038fd145da5af41ce84a Mon Sep 17 00:00:00 2001 From: Josh Driver Date: Tue, 24 Jan 2017 08:55:08 +1030 Subject: [PATCH 131/137] Rename CustomDerive to ProcMacroDerive for macros 1.1 --- src/librustc_metadata/creader.rs | 6 +++--- src/librustc_resolve/build_reduced_graph.rs | 2 +- src/libsyntax/ext/base.rs | 6 +++++- src/libsyntax/ext/expand.rs | 4 ++-- src/libsyntax_ext/deriving/custom.rs | 18 +++++++++--------- src/libsyntax_ext/deriving/mod.rs | 4 ++-- src/libsyntax_ext/proc_macro_registrar.rs | 8 ++++---- .../proc-macro/derive-bad.rs | 2 +- .../proc-macro/load-panic.rs | 2 +- .../proc-macro/no-macro-use-attr.rs | 2 +- src/test/compile-fail/no-link.rs | 2 +- src/test/ui/custom-derive/issue-36935.stderr | 2 +- 12 files changed, 31 insertions(+), 27 deletions(-) diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 161331b1728bc..8cb123b54f167 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -577,7 +577,7 @@ impl<'a> CrateLoader<'a> { use proc_macro::TokenStream; use proc_macro::__internal::Registry; use rustc_back::dynamic_lib::DynamicLibrary; - use syntax_ext::deriving::custom::CustomDerive; + use syntax_ext::deriving::custom::ProcMacroDerive; use syntax_ext::proc_macro_impl::AttrProcMacro; let path = match dylib { @@ -609,8 +609,8 @@ impl<'a> CrateLoader<'a> { expand: fn(TokenStream) -> TokenStream, attributes: &[&'static str]) { let attrs = attributes.iter().cloned().map(Symbol::intern).collect(); - let derive = SyntaxExtension::CustomDerive( - Box::new(CustomDerive::new(expand, attrs)) + let derive = SyntaxExtension::ProcMacroDerive( + Box::new(ProcMacroDerive::new(expand, attrs)) ); self.0.push((Symbol::intern(trait_name), Rc::new(derive))); } diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index eb6c7f4bed5de..4679b6be88b6f 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -559,7 +559,7 @@ impl<'a> Resolver<'a> { "an `extern crate` loading macros must be at the crate root"); } else if !self.use_extern_macros && !used && self.session.cstore.dep_kind(module.def_id().unwrap().krate).macros_only() { - let msg = "custom derive crates and `#[no_link]` crates have no effect without \ + let msg = "proc macro crates and `#[no_link]` crates have no effect without \ `#[macro_use]`"; self.session.span_warn(item.span, msg); used = true; // Avoid the normal unused extern crate warning diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 231e2e6205cf8..17b0b97468df8 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -510,7 +510,11 @@ pub enum SyntaxExtension { /// IdentTT(Box, Option, bool), - CustomDerive(Box), + /// An attribute-like procedural macro. TokenStream -> TokenStream. + /// The input is the annotated item. + /// Allows generating code to implement a Trait for a given struct + /// or enum item. + ProcMacroDerive(Box), /// An attribute-like procedural macro that derives a builtin trait. BuiltinDerive(BuiltinDeriveFn), diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 0e5d94e03810f..01a8c215d47aa 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -370,7 +370,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let tok_result = mac.expand(self.cx, attr.span, attr_toks, item_toks); self.parse_expansion(tok_result, kind, name, attr.span) } - SyntaxExtension::CustomDerive(..) | SyntaxExtension::BuiltinDerive(..) => { + SyntaxExtension::ProcMacroDerive(..) | SyntaxExtension::BuiltinDerive(..) => { self.cx.span_err(attr.span, &format!("`{}` is a derive mode", name)); kind.dummy(attr.span) } @@ -440,7 +440,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { return kind.dummy(span); } - SyntaxExtension::CustomDerive(..) | SyntaxExtension::BuiltinDerive(..) => { + SyntaxExtension::ProcMacroDerive(..) | SyntaxExtension::BuiltinDerive(..) => { self.cx.span_err(path.span, &format!("`{}` is a derive mode", extname)); return kind.dummy(span); } diff --git a/src/libsyntax_ext/deriving/custom.rs b/src/libsyntax_ext/deriving/custom.rs index 2ce6fc03f7731..e118ef1ea01f4 100644 --- a/src/libsyntax_ext/deriving/custom.rs +++ b/src/libsyntax_ext/deriving/custom.rs @@ -32,18 +32,18 @@ impl<'a> Visitor<'a> for MarkAttrs<'a> { fn visit_mac(&mut self, _mac: &Mac) {} } -pub struct CustomDerive { +pub struct ProcMacroDerive { inner: fn(TokenStream) -> TokenStream, attrs: Vec, } -impl CustomDerive { - pub fn new(inner: fn(TokenStream) -> TokenStream, attrs: Vec) -> CustomDerive { - CustomDerive { inner: inner, attrs: attrs } +impl ProcMacroDerive { + pub fn new(inner: fn(TokenStream) -> TokenStream, attrs: Vec) -> ProcMacroDerive { + ProcMacroDerive { inner: inner, attrs: attrs } } } -impl MultiItemModifier for CustomDerive { +impl MultiItemModifier for ProcMacroDerive { fn expand(&self, ecx: &mut ExtCtxt, span: Span, @@ -54,7 +54,7 @@ impl MultiItemModifier for CustomDerive { Annotatable::Item(item) => item, Annotatable::ImplItem(_) | Annotatable::TraitItem(_) => { - ecx.span_err(span, "custom derive attributes may only be \ + ecx.span_err(span, "proc_macro_derive attributes may only be \ applied to struct/enum items"); return Vec::new() } @@ -63,7 +63,7 @@ impl MultiItemModifier for CustomDerive { ItemKind::Struct(..) | ItemKind::Enum(..) => {}, _ => { - ecx.span_err(span, "custom derive attributes may only be \ + ecx.span_err(span, "proc_macro_derive attributes may only be \ applied to struct/enum items"); return Vec::new() } @@ -81,7 +81,7 @@ impl MultiItemModifier for CustomDerive { let stream = match res { Ok(stream) => stream, Err(e) => { - let msg = "custom derive attribute panicked"; + let msg = "proc_macro_derive attribute panicked"; let mut err = ecx.struct_span_fatal(span, msg); if let Some(s) = e.downcast_ref::() { err.help(&format!("message: {}", s)); @@ -100,7 +100,7 @@ impl MultiItemModifier for CustomDerive { Ok(new_items) => new_items, Err(_) => { // FIXME: handle this better - let msg = "custom derive produced unparseable tokens"; + let msg = "proc_macro_derive produced unparseable tokens"; ecx.struct_span_fatal(span, msg).emit(); panic!(FatalError); } diff --git a/src/libsyntax_ext/deriving/mod.rs b/src/libsyntax_ext/deriving/mod.rs index 30d0da588a5df..311b8ae41f8b9 100644 --- a/src/libsyntax_ext/deriving/mod.rs +++ b/src/libsyntax_ext/deriving/mod.rs @@ -163,7 +163,7 @@ pub fn expand_derive(cx: &mut ExtCtxt, if is_builtin_trait(tname) || { let derive_mode = ast::Path::from_ident(titem.span, ast::Ident::with_empty_ctxt(tname)); cx.resolver.resolve_macro(cx.current_expansion.mark, &derive_mode, false).map(|ext| { - if let SyntaxExtension::CustomDerive(_) = *ext { true } else { false } + if let SyntaxExtension::ProcMacroDerive(_) = *ext { true } else { false } }).unwrap_or(false) } { return true; @@ -249,7 +249,7 @@ pub fn expand_derive(cx: &mut ExtCtxt, ..mitem.span }; - if let SyntaxExtension::CustomDerive(ref ext) = *ext { + if let SyntaxExtension::ProcMacroDerive(ref ext) = *ext { return ext.expand(cx, span, &mitem, item); } else { unreachable!() diff --git a/src/libsyntax_ext/proc_macro_registrar.rs b/src/libsyntax_ext/proc_macro_registrar.rs index c8af16e9242f0..325f09a83ddab 100644 --- a/src/libsyntax_ext/proc_macro_registrar.rs +++ b/src/libsyntax_ext/proc_macro_registrar.rs @@ -27,7 +27,7 @@ use syntax_pos::{Span, DUMMY_SP}; use deriving; -struct CustomDerive { +struct ProcMacroDerive { trait_name: ast::Name, function_name: Ident, span: Span, @@ -40,7 +40,7 @@ struct AttrProcMacro { } struct CollectProcMacros<'a> { - derives: Vec, + derives: Vec, attr_macros: Vec, in_root: bool, handler: &'a errors::Handler, @@ -176,7 +176,7 @@ impl<'a> CollectProcMacros<'a> { }; if self.in_root && item.vis == ast::Visibility::Public { - self.derives.push(CustomDerive { + self.derives.push(ProcMacroDerive { span: item.span, trait_name: trait_name, function_name: item.ident, @@ -319,7 +319,7 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> { // } // } fn mk_registrar(cx: &mut ExtCtxt, - custom_derives: &[CustomDerive], + custom_derives: &[ProcMacroDerive], custom_attrs: &[AttrProcMacro]) -> P { let eid = cx.codemap().record_expansion(ExpnInfo { call_site: DUMMY_SP, diff --git a/src/test/compile-fail-fulldeps/proc-macro/derive-bad.rs b/src/test/compile-fail-fulldeps/proc-macro/derive-bad.rs index a5359946c09c2..bc4da9fee47ee 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/derive-bad.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/derive-bad.rs @@ -16,7 +16,7 @@ extern crate derive_bad; #[derive( A )] -//~^^ ERROR: custom derive produced unparseable tokens +//~^^ ERROR: proc_macro_derive produced unparseable tokens struct A; fn main() {} diff --git a/src/test/compile-fail-fulldeps/proc-macro/load-panic.rs b/src/test/compile-fail-fulldeps/proc-macro/load-panic.rs index f9906b650fb87..107273d012dd6 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/load-panic.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/load-panic.rs @@ -14,7 +14,7 @@ extern crate derive_panic; #[derive(A)] -//~^ ERROR: custom derive attribute panicked +//~^ ERROR: proc_macro_derive attribute panicked //~| HELP: message: nope! struct Foo; diff --git a/src/test/compile-fail-fulldeps/proc-macro/no-macro-use-attr.rs b/src/test/compile-fail-fulldeps/proc-macro/no-macro-use-attr.rs index f61b8b4073b6f..e47a4aefb5e0b 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/no-macro-use-attr.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/no-macro-use-attr.rs @@ -13,7 +13,7 @@ #![feature(rustc_attrs)] extern crate derive_a; -//~^ WARN custom derive crates and `#[no_link]` crates have no effect without `#[macro_use]` +//~^ WARN proc macro crates and `#[no_link]` crates have no effect without `#[macro_use]` #[rustc_error] fn main() {} //~ ERROR compilation successful diff --git a/src/test/compile-fail/no-link.rs b/src/test/compile-fail/no-link.rs index d8e7411bded2c..f74ff55e2c08e 100644 --- a/src/test/compile-fail/no-link.rs +++ b/src/test/compile-fail/no-link.rs @@ -12,7 +12,7 @@ #[no_link] extern crate empty_struct; -//~^ WARN custom derive crates and `#[no_link]` crates have no effect without `#[macro_use]` +//~^ WARN proc macro crates and `#[no_link]` crates have no effect without `#[macro_use]` fn main() { empty_struct::XEmpty1; //~ ERROR cannot find value `XEmpty1` in module `empty_struct` diff --git a/src/test/ui/custom-derive/issue-36935.stderr b/src/test/ui/custom-derive/issue-36935.stderr index 213366a307d40..ad1382cbc8e4b 100644 --- a/src/test/ui/custom-derive/issue-36935.stderr +++ b/src/test/ui/custom-derive/issue-36935.stderr @@ -1,4 +1,4 @@ -error: custom derive attribute panicked +error: proc_macro_derive attribute panicked --> $DIR/issue-36935.rs:17:15 | 17 | #[derive(Foo, Bar)] From fbdd0388664127c3dd2c3e6a162b597a87ffa7c9 Mon Sep 17 00:00:00 2001 From: Josh Driver Date: Wed, 1 Feb 2017 21:03:09 +1030 Subject: [PATCH 132/137] Move derive macro expansion into the MacroExpander This removes the expand_derives function, and sprinkles the functionality throughout the Invocation Collector, Expander and Resolver. --- src/librustc_resolve/macros.rs | 26 ++ src/libsyntax/ext/base.rs | 10 + src/libsyntax/ext/derive.rs | 218 ++++++++++++++++ src/libsyntax/ext/expand.rs | 110 +++++++- src/libsyntax/lib.rs | 1 + src/libsyntax_ext/deriving/custom.rs | 8 +- src/libsyntax_ext/deriving/decodable.rs | 3 +- src/libsyntax_ext/deriving/encodable.rs | 3 +- src/libsyntax_ext/deriving/mod.rs | 239 +----------------- src/libsyntax_ext/lib.rs | 5 +- .../proc-macro/derive-bad.rs | 2 +- .../proc-macro/load-panic.rs | 2 +- .../deriving-meta-unknown-trait.rs | 2 +- src/test/compile-fail/deriving-primitive.rs | 2 +- src/test/compile-fail/macro-error.rs | 2 +- .../compile-fail/macros-nonfatal-errors.rs | 8 +- src/test/ui/custom-derive/issue-36935.stderr | 2 +- 17 files changed, 378 insertions(+), 265 deletions(-) create mode 100644 src/libsyntax/ext/derive.rs diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 682b3ff834fad..ea3112b2463f8 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -250,6 +250,32 @@ impl<'a> base::Resolver for Resolver<'a> { } result } + + fn resolve_builtin_macro(&mut self, tname: Name) -> Result, Determinacy> { + match self.builtin_macros.get(&tname).cloned() { + Some(binding) => Ok(binding.get_macro(self)), + None => Err(Determinacy::Undetermined), + } + } + + fn resolve_derive_macro(&mut self, scope: Mark, path: &ast::Path, force: bool) + -> Result, Determinacy> { + let ast::Path { span, .. } = *path; + match self.resolve_macro(scope, path, false) { + Ok(ext) => match *ext { + SyntaxExtension::BuiltinDerive(..) | + SyntaxExtension::ProcMacroDerive(..) => Ok(ext), + _ => Err(Determinacy::Determined), + }, + Err(Determinacy::Undetermined) if force => { + let msg = format!("cannot find derive macro `{}` in this scope", path); + let mut err = self.session.struct_span_err(span, &msg); + err.emit(); + Err(Determinacy::Determined) + }, + Err(err) => Err(err), + } + } } impl<'a> Resolver<'a> { diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 17b0b97468df8..9a717b86d091e 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -536,6 +536,9 @@ pub trait Resolver { fn find_attr_invoc(&mut self, attrs: &mut Vec) -> Option; fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, force: bool) -> Result, Determinacy>; + fn resolve_builtin_macro(&mut self, tname: Name) -> Result, Determinacy>; + fn resolve_derive_macro(&mut self, scope: Mark, path: &ast::Path, force: bool) + -> Result, Determinacy>; } #[derive(Copy, Clone, Debug)] @@ -562,6 +565,13 @@ impl Resolver for DummyResolver { -> Result, Determinacy> { Err(Determinacy::Determined) } + fn resolve_builtin_macro(&mut self, _tname: Name) -> Result, Determinacy> { + Err(Determinacy::Determined) + } + fn resolve_derive_macro(&mut self, _scope: Mark, _path: &ast::Path, _force: bool) + -> Result, Determinacy> { + Err(Determinacy::Determined) + } } #[derive(Clone)] diff --git a/src/libsyntax/ext/derive.rs b/src/libsyntax/ext/derive.rs new file mode 100644 index 0000000000000..946448eaaee99 --- /dev/null +++ b/src/libsyntax/ext/derive.rs @@ -0,0 +1,218 @@ +// Copyright 2012-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. + +use ast::Name; +use attr; +use ast::{self, NestedMetaItem}; use ext::base::{ExtCtxt, SyntaxExtension}; +use codemap; +use ext::build::AstBuilder; +use feature_gate; +use symbol::Symbol; +use syntax_pos::Span; + +pub fn derive_attr_trait<'a>(cx: &mut ExtCtxt, attr: &'a ast::Attribute) + -> Option<&'a NestedMetaItem> { + if attr.name() != "derive" { + return None; + } + if attr.value_str().is_some() { + cx.span_err(attr.span, "unexpected value in `derive`"); + return None; + } + + let traits = attr.meta_item_list().unwrap_or(&[]); + + if traits.is_empty() { + cx.span_warn(attr.span, "empty trait list in `derive`"); + return None; + } + + return traits.get(0); +} + +pub fn verify_derive_attrs(cx: &mut ExtCtxt, attrs: &[ast::Attribute]) { + for attr in attrs { + if attr.name() != "derive" { + continue; + } + + if attr.value_str().is_some() { + cx.span_err(attr.span, "unexpected value in `derive`"); + } + + let traits = attr.meta_item_list().unwrap_or(&[]).to_owned(); + + if traits.is_empty() { + cx.span_warn(attr.span, "empty trait list in `derive`"); + attr::mark_used(&attr); + continue; + } + for titem in traits { + if titem.word().is_none() { + cx.span_err(titem.span, "malformed `derive` entry"); + } + } + } +} + +#[derive(PartialEq, Debug, Clone, Copy)] +pub enum DeriveType { + Legacy, + ProcMacro, + Builtin +} + +impl DeriveType { + // Classify a derive trait name by resolving the macro. + pub fn classify(cx: &mut ExtCtxt, tname: Name) -> DeriveType { + let legacy_derive_name = Symbol::intern(&format!("derive_{}", tname)); + + if let Ok(_) = cx.resolver.resolve_builtin_macro(legacy_derive_name) { + return DeriveType::Legacy; + } + + match cx.resolver.resolve_builtin_macro(tname) { + Ok(ext) => match *ext { + SyntaxExtension::BuiltinDerive(..) => DeriveType::Builtin, + _ => DeriveType::ProcMacro, + }, + Err(_) => DeriveType::ProcMacro, + } + } +} + +pub fn get_derive_attr(cx: &mut ExtCtxt, attrs: &mut Vec, + derive_type: DeriveType) -> Option { + for i in 0..attrs.len() { + if attrs[i].name() != "derive" { + continue; + } + + if attrs[i].value_str().is_some() { + continue; + } + + let mut traits = attrs[i].meta_item_list().unwrap_or(&[]).to_owned(); + + // First, weed out malformed #[derive] + traits.retain(|titem| titem.word().is_some()); + + let mut titem = None; + + // See if we can find a matching trait. + for j in 0..traits.len() { + let tname = match traits[j].name() { + Some(tname) => tname, + _ => continue, + }; + + if DeriveType::classify(cx, tname) == derive_type { + titem = Some(traits.remove(j)); + break; + } + } + + // If we find a trait, remove the trait from the attribute. + if let Some(titem) = titem { + if traits.len() == 0 { + attrs.remove(i); + } else { + let derive = Symbol::intern("derive"); + let mitem = cx.meta_list(titem.span, derive, traits); + attrs[i] = cx.attribute(titem.span, mitem); + } + let derive = Symbol::intern("derive"); + let mitem = cx.meta_list(titem.span, derive, vec![titem]); + return Some(cx.attribute(mitem.span, mitem)); + } + } + return None; +} + +fn allow_unstable(cx: &mut ExtCtxt, span: Span, attr_name: &str) -> Span { + Span { + expn_id: cx.codemap().record_expansion(codemap::ExpnInfo { + call_site: span, + callee: codemap::NameAndSpan { + format: codemap::MacroAttribute(Symbol::intern(attr_name)), + span: Some(span), + allow_internal_unstable: true, + }, + }), + ..span + } +} + +pub fn add_derived_markers(cx: &mut ExtCtxt, attrs: &mut Vec) { + if attrs.is_empty() { + return; + } + + let titems = attrs.iter().filter(|a| { + a.name() == "derive" + }).flat_map(|a| { + a.meta_item_list().unwrap_or(&[]).iter() + }).filter_map(|titem| { + titem.name() + }).collect::>(); + + let span = attrs[0].span; + + if !attrs.iter().any(|a| a.name() == "structural_match") && + titems.iter().any(|t| *t == "PartialEq") && titems.iter().any(|t| *t == "Eq") { + let structural_match = Symbol::intern("structural_match"); + let span = allow_unstable(cx, span, "derive(PartialEq, Eq)"); + let meta = cx.meta_word(span, structural_match); + attrs.push(cx.attribute(span, meta)); + } + + if !attrs.iter().any(|a| a.name() == "rustc_copy_clone_marker") && + titems.iter().any(|t| *t == "Copy") && titems.iter().any(|t| *t == "Clone") { + let structural_match = Symbol::intern("rustc_copy_clone_marker"); + let span = allow_unstable(cx, span, "derive(Copy, Clone)"); + let meta = cx.meta_word(span, structural_match); + attrs.push(cx.attribute(span, meta)); + } +} + +pub fn find_derive_attr(cx: &mut ExtCtxt, attrs: &mut Vec) + -> Option { + verify_derive_attrs(cx, attrs); + get_derive_attr(cx, attrs, DeriveType::Legacy).and_then(|a| { + let titem = derive_attr_trait(cx, &a); + titem.and_then(|titem| { + let tword = titem.word().unwrap(); + let tname = tword.name(); + if !cx.ecfg.enable_custom_derive() { + feature_gate::emit_feature_err( + &cx.parse_sess, + "custom_derive", + titem.span, + feature_gate::GateIssue::Language, + feature_gate::EXPLAIN_CUSTOM_DERIVE + ); + None + } else { + let name = Symbol::intern(&format!("derive_{}", tname)); + if !cx.resolver.is_whitelisted_legacy_custom_derive(name) { + cx.span_warn(titem.span, + feature_gate::EXPLAIN_DEPR_CUSTOM_DERIVE); + } + let mitem = cx.meta_word(titem.span, name); + Some(cx.attribute(mitem.span, mitem)) + } + }) + }).or_else(|| { + get_derive_attr(cx, attrs, DeriveType::ProcMacro) + }).or_else(|| { + add_derived_markers(cx, attrs); + get_derive_attr(cx, attrs, DeriveType::Builtin) + }) +} diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 01a8c215d47aa..8e7f8830eafbc 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -8,26 +8,27 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use ast::{Block, Ident, Mac_, PatKind}; +use ast::{self, Block, Ident, Mac_, PatKind}; use ast::{Name, MacStmtStyle, StmtKind, ItemKind}; -use ast; -use ext::hygiene::Mark; -use ext::placeholders::{placeholder, PlaceholderExpander}; use attr::{self, HasAttrs}; use codemap::{ExpnInfo, NameAndSpan, MacroBang, MacroAttribute}; -use syntax_pos::{self, Span, ExpnId}; use config::{is_test_or_bench, StripUnconfigured}; use ext::base::*; +use ext::derive::{find_derive_attr, derive_attr_trait}; +use ext::hygiene::Mark; +use ext::placeholders::{placeholder, PlaceholderExpander}; use feature_gate::{self, Features}; use fold; use fold::*; -use parse::{ParseSess, DirectoryOwnership, PResult, filemap_to_tts}; use parse::parser::Parser; use parse::token; +use parse::{ParseSess, DirectoryOwnership, PResult, filemap_to_tts}; use print::pprust; use ptr::P; use std_inject; +use symbol::Symbol; use symbol::keywords; +use syntax_pos::{self, Span, ExpnId}; use tokenstream::{TokenTree, TokenStream}; use util::small_vector::SmallVector; use visit::Visitor; @@ -166,6 +167,10 @@ pub enum InvocationKind { attr: ast::Attribute, item: Annotatable, }, + Derive { + attr: ast::Attribute, + item: Annotatable, + }, } impl Invocation { @@ -173,6 +178,7 @@ impl Invocation { match self.kind { InvocationKind::Bang { span, .. } => span, InvocationKind::Attr { ref attr, .. } => attr.span, + InvocationKind::Derive { ref attr, .. } => attr.span, } } } @@ -250,6 +256,13 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let path = ast::Path::from_ident(attr.span, ident); self.cx.resolver.resolve_macro(scope, &path, force) } + InvocationKind::Derive { ref attr, .. } => { + let titem = derive_attr_trait(self.cx, &attr).unwrap(); + let tname = titem.name().expect("Expected derive macro name"); + let ident = Ident::with_empty_ctxt(tname); + let path = ast::Path::from_ident(attr.span, ident); + self.cx.resolver.resolve_derive_macro(scope, &path, force) + } }; let ext = match resolution { Ok(ext) => Some(ext), @@ -330,6 +343,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { match invoc.kind { InvocationKind::Bang { .. } => self.expand_bang_invoc(invoc, ext), InvocationKind::Attr { .. } => self.expand_attr_invoc(invoc, ext), + InvocationKind::Derive { .. } => self.expand_derive_invoc(invoc, ext), } } @@ -486,6 +500,71 @@ impl<'a, 'b> MacroExpander<'a, 'b> { }) } + /// Expand a derive invocation. Returns the result of expansion. + fn expand_derive_invoc(&mut self, invoc: Invocation, ext: Rc) -> Expansion { + let Invocation { expansion_kind: kind, .. } = invoc; + let (attr, item) = match invoc.kind { + InvocationKind::Derive { attr, item } => (attr, item), + _ => unreachable!(), + }; + + attr::mark_used(&attr); + let titem = derive_attr_trait(self.cx, &attr).unwrap(); + let tname = ast::Ident::with_empty_ctxt(titem.name().unwrap()); + let name = Symbol::intern(&format!("derive({})", tname)); + let mitem = &attr.value; + + self.cx.bt_push(ExpnInfo { + call_site: attr.span, + callee: NameAndSpan { + format: MacroAttribute(attr.name()), + span: Some(attr.span), + allow_internal_unstable: false, + } + }); + + match *ext { + SyntaxExtension::ProcMacroDerive(ref ext) => { + let span = Span { + expn_id: self.cx.codemap().record_expansion(ExpnInfo { + call_site: mitem.span, + callee: NameAndSpan { + format: MacroAttribute(Symbol::intern(&format!("derive({})", tname))), + span: None, + allow_internal_unstable: false, + }, + }), + ..mitem.span + }; + return kind.expect_from_annotatables(ext.expand(self.cx, span, &mitem, item)); + } + SyntaxExtension::BuiltinDerive(func) => { + let span = Span { + expn_id: self.cx.codemap().record_expansion(ExpnInfo { + call_site: titem.span, + callee: NameAndSpan { + format: MacroAttribute(name), + span: None, + allow_internal_unstable: true, + }, + }), + ..titem.span + }; + let mut items = Vec::new(); + func(self.cx, span, &mitem, &item, &mut |a| { + items.push(a) + }); + items.insert(0, item); + return kind.expect_from_annotatables(items); + } + _ => { + let msg = &format!("macro `{}` may not be used for derive attributes", name); + self.cx.span_err(attr.span, &msg); + kind.dummy(attr.span) + } + } + } + fn parse_expansion(&mut self, toks: TokenStream, kind: ExpansionKind, name: Name, span: Span) -> Expansion { let mut parser = self.cx.new_parser_from_tts(&toks.trees().cloned().collect::>()); @@ -595,16 +674,31 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { fn collect_attr(&mut self, attr: ast::Attribute, item: Annotatable, kind: ExpansionKind) -> Expansion { - self.collect(kind, InvocationKind::Attr { attr: attr, item: item }) + let invoc_kind = if attr.name() == "derive" { + if kind == ExpansionKind::TraitItems || kind == ExpansionKind::ImplItems { + self.cx.span_err(attr.span, "`derive` can be only be applied to items"); + return kind.expect_from_annotatables(::std::iter::once(item)); + } + InvocationKind::Derive { attr: attr, item: item } + } else { + InvocationKind::Attr { attr: attr, item: item } + }; + + self.collect(kind, invoc_kind) } // If `item` is an attr invocation, remove and return the macro attribute. fn classify_item(&mut self, mut item: T) -> (T, Option) { let mut attr = None; + item = item.map_attrs(|mut attrs| { - attr = self.cx.resolver.find_attr_invoc(&mut attrs); + attr = self.cx.resolver.find_attr_invoc(&mut attrs).or_else(|| { + find_derive_attr(self.cx, &mut attrs) + }); + attrs }); + (item, attr) } diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 25be9e91a6ac9..87a03adf6b77c 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -128,6 +128,7 @@ pub mod print { pub mod ext { pub mod base; pub mod build; + pub mod derive; pub mod expand; pub mod placeholders; pub mod hygiene; diff --git a/src/libsyntax_ext/deriving/custom.rs b/src/libsyntax_ext/deriving/custom.rs index e118ef1ea01f4..974e86a574124 100644 --- a/src/libsyntax_ext/deriving/custom.rs +++ b/src/libsyntax_ext/deriving/custom.rs @@ -54,7 +54,7 @@ impl MultiItemModifier for ProcMacroDerive { Annotatable::Item(item) => item, Annotatable::ImplItem(_) | Annotatable::TraitItem(_) => { - ecx.span_err(span, "proc_macro_derive attributes may only be \ + ecx.span_err(span, "proc-macro derives may only be \ applied to struct/enum items"); return Vec::new() } @@ -63,7 +63,7 @@ impl MultiItemModifier for ProcMacroDerive { ItemKind::Struct(..) | ItemKind::Enum(..) => {}, _ => { - ecx.span_err(span, "proc_macro_derive attributes may only be \ + ecx.span_err(span, "proc-macro derives may only be \ applied to struct/enum items"); return Vec::new() } @@ -81,7 +81,7 @@ impl MultiItemModifier for ProcMacroDerive { let stream = match res { Ok(stream) => stream, Err(e) => { - let msg = "proc_macro_derive attribute panicked"; + let msg = "proc-macro derive panicked"; let mut err = ecx.struct_span_fatal(span, msg); if let Some(s) = e.downcast_ref::() { err.help(&format!("message: {}", s)); @@ -100,7 +100,7 @@ impl MultiItemModifier for ProcMacroDerive { Ok(new_items) => new_items, Err(_) => { // FIXME: handle this better - let msg = "proc_macro_derive produced unparseable tokens"; + let msg = "proc-macro derive produced unparseable tokens"; ecx.struct_span_fatal(span, msg).emit(); panic!(FatalError); } diff --git a/src/libsyntax_ext/deriving/decodable.rs b/src/libsyntax_ext/deriving/decodable.rs index 6359d642d157c..498f2348b80f1 100644 --- a/src/libsyntax_ext/deriving/decodable.rs +++ b/src/libsyntax_ext/deriving/decodable.rs @@ -13,6 +13,7 @@ use deriving; use deriving::generic::*; use deriving::generic::ty::*; +use deriving::warn_if_deprecated; use syntax::ast; use syntax::ast::{Expr, MetaItem, Mutability}; @@ -35,7 +36,7 @@ pub fn expand_deriving_decodable(cx: &mut ExtCtxt, mitem: &MetaItem, item: &Annotatable, push: &mut FnMut(Annotatable)) { - deriving::warn_if_deprecated(cx, span, "Decodable"); + warn_if_deprecated(cx, span, "Decodable"); expand_deriving_decodable_imp(cx, span, mitem, item, push, "serialize") } diff --git a/src/libsyntax_ext/deriving/encodable.rs b/src/libsyntax_ext/deriving/encodable.rs index a276193e81b97..9d155c22ad031 100644 --- a/src/libsyntax_ext/deriving/encodable.rs +++ b/src/libsyntax_ext/deriving/encodable.rs @@ -91,6 +91,7 @@ use deriving; use deriving::generic::*; use deriving::generic::ty::*; +use deriving::warn_if_deprecated; use syntax::ast::{Expr, ExprKind, MetaItem, Mutability}; use syntax::ext::base::{Annotatable, ExtCtxt}; @@ -112,7 +113,7 @@ pub fn expand_deriving_encodable(cx: &mut ExtCtxt, mitem: &MetaItem, item: &Annotatable, push: &mut FnMut(Annotatable)) { - deriving::warn_if_deprecated(cx, span, "Encodable"); + warn_if_deprecated(cx, span, "Encodable"); expand_deriving_encodable_imp(cx, span, mitem, item, push, "serialize") } diff --git a/src/libsyntax_ext/deriving/mod.rs b/src/libsyntax_ext/deriving/mod.rs index 311b8ae41f8b9..3bceb02f3d6c5 100644 --- a/src/libsyntax_ext/deriving/mod.rs +++ b/src/libsyntax_ext/deriving/mod.rs @@ -11,12 +11,10 @@ //! The compiler code necessary to implement the `#[derive]` extensions. use std::rc::Rc; -use syntax::ast::{self, MetaItem}; -use syntax::attr::HasAttrs; +use syntax::ast; use syntax::codemap; use syntax::ext::base::{Annotatable, ExtCtxt, SyntaxExtension, Resolver}; use syntax::ext::build::AstBuilder; -use syntax::feature_gate; use syntax::ptr::P; use syntax::symbol::Symbol; use syntax_pos::Span; @@ -90,241 +88,6 @@ fn allow_unstable(cx: &mut ExtCtxt, span: Span, attr_name: &str) -> Span { } } -pub fn expand_derive(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - annotatable: Annotatable) - -> Vec { - debug!("expand_derive: span = {:?}", span); - debug!("expand_derive: mitem = {:?}", mitem); - debug!("expand_derive: annotatable input = {:?}", annotatable); - let mut item = match annotatable { - Annotatable::Item(item) => item, - other => { - cx.span_err(span, "`derive` can only be applied to items"); - return vec![other] - } - }; - - let derive = Symbol::intern("derive"); - let mut derive_attrs = Vec::new(); - item = item.map_attrs(|attrs| { - let partition = attrs.into_iter().partition(|attr| attr.name() == derive); - derive_attrs = partition.0; - partition.1 - }); - - // Expand `#[derive]`s after other attribute macro invocations. - if cx.resolver.find_attr_invoc(&mut item.attrs.clone()).is_some() { - return vec![Annotatable::Item(item.map_attrs(|mut attrs| { - attrs.push(cx.attribute(span, mitem.clone())); - attrs.extend(derive_attrs); - attrs - }))]; - } - - let get_traits = |mitem: &MetaItem, cx: &ExtCtxt| { - if mitem.value_str().is_some() { - cx.span_err(mitem.span, "unexpected value in `derive`"); - } - - let traits = mitem.meta_item_list().unwrap_or(&[]).to_owned(); - if traits.is_empty() { - cx.span_warn(mitem.span, "empty trait list in `derive`"); - } - traits - }; - - let mut traits = get_traits(mitem, cx); - for derive_attr in derive_attrs { - traits.extend(get_traits(&derive_attr.value, cx)); - } - - // First, weed out malformed #[derive] - traits.retain(|titem| { - if titem.word().is_none() { - cx.span_err(titem.span, "malformed `derive` entry"); - false - } else { - true - } - }); - - // Next, check for old-style #[derive(Foo)] - // - // These all get expanded to `#[derive_Foo]` and will get expanded first. If - // we actually add any attributes here then we return to get those expanded - // and then eventually we'll come back to finish off the other derive modes. - let mut new_attributes = Vec::new(); - traits.retain(|titem| { - let tword = titem.word().unwrap(); - let tname = tword.name(); - - if is_builtin_trait(tname) || { - let derive_mode = ast::Path::from_ident(titem.span, ast::Ident::with_empty_ctxt(tname)); - cx.resolver.resolve_macro(cx.current_expansion.mark, &derive_mode, false).map(|ext| { - if let SyntaxExtension::ProcMacroDerive(_) = *ext { true } else { false } - }).unwrap_or(false) - } { - return true; - } - - if !cx.ecfg.enable_custom_derive() { - feature_gate::emit_feature_err(&cx.parse_sess, - "custom_derive", - titem.span, - feature_gate::GateIssue::Language, - feature_gate::EXPLAIN_CUSTOM_DERIVE); - } else { - let name = Symbol::intern(&format!("derive_{}", tname)); - if !cx.resolver.is_whitelisted_legacy_custom_derive(name) { - cx.span_warn(titem.span, feature_gate::EXPLAIN_DEPR_CUSTOM_DERIVE); - } - let mitem = cx.meta_word(titem.span, name); - new_attributes.push(cx.attribute(mitem.span, mitem)); - } - false - }); - if new_attributes.len() > 0 { - item = item.map(|mut i| { - i.attrs.extend(new_attributes); - if traits.len() > 0 { - let list = cx.meta_list(mitem.span, derive, traits); - i.attrs.push(cx.attribute(mitem.span, list)); - } - i - }); - return vec![Annotatable::Item(item)] - } - - // Now check for macros-1.1 style custom #[derive]. - // - // Expand each of them in order given, but *before* we expand any built-in - // derive modes. The logic here is to: - // - // 1. Collect the remaining `#[derive]` annotations into a list. If - // there are any left, attach a `#[derive]` attribute to the item - // that we're currently expanding with the remaining derive modes. - // 2. Manufacture a `#[derive(Foo)]` attribute to pass to the expander. - // 3. Expand the current item we're expanding, getting back a list of - // items that replace it. - // 4. Extend the returned list with the current list of items we've - // collected so far. - // 5. Return everything! - // - // If custom derive extensions end up threading through the `#[derive]` - // attribute, we'll get called again later on to continue expanding - // those modes. - let macros_11_derive = traits.iter() - .cloned() - .enumerate() - .filter(|&(_, ref name)| !is_builtin_trait(name.name().unwrap())) - .next(); - if let Some((i, titem)) = macros_11_derive { - let tname = ast::Ident::with_empty_ctxt(titem.name().unwrap()); - let path = ast::Path::from_ident(titem.span, tname); - let ext = cx.resolver.resolve_macro(cx.current_expansion.mark, &path, false).unwrap(); - - traits.remove(i); - if traits.len() > 0 { - item = item.map(|mut i| { - let list = cx.meta_list(mitem.span, derive, traits); - i.attrs.push(cx.attribute(mitem.span, list)); - i - }); - } - let titem = cx.meta_list_item_word(titem.span, titem.name().unwrap()); - let mitem = cx.meta_list(titem.span, derive, vec![titem]); - let item = Annotatable::Item(item); - - let span = Span { - expn_id: cx.codemap().record_expansion(codemap::ExpnInfo { - call_site: mitem.span, - callee: codemap::NameAndSpan { - format: codemap::MacroAttribute(Symbol::intern(&format!("derive({})", tname))), - span: None, - allow_internal_unstable: false, - }, - }), - ..mitem.span - }; - - if let SyntaxExtension::ProcMacroDerive(ref ext) = *ext { - return ext.expand(cx, span, &mitem, item); - } else { - unreachable!() - } - } - - // Ok, at this point we know that there are no old-style `#[derive_Foo]` nor - // any macros-1.1 style `#[derive(Foo)]`. Expand all built-in traits here. - - // RFC #1445. `#[derive(PartialEq, Eq)]` adds a (trusted) - // `#[structural_match]` attribute. - let (partial_eq, eq) = (Symbol::intern("PartialEq"), Symbol::intern("Eq")); - if traits.iter().any(|t| t.name() == Some(partial_eq)) && - traits.iter().any(|t| t.name() == Some(eq)) { - let structural_match = Symbol::intern("structural_match"); - let span = allow_unstable(cx, span, "derive(PartialEq, Eq)"); - let meta = cx.meta_word(span, structural_match); - item = item.map(|mut i| { - i.attrs.push(cx.attribute(span, meta)); - i - }); - } - - // RFC #1521. `Clone` can assume that `Copy` types' clone implementation is - // the same as the copy implementation. - // - // Add a marker attribute here picked up during #[derive(Clone)] - let (copy, clone) = (Symbol::intern("Copy"), Symbol::intern("Clone")); - if traits.iter().any(|t| t.name() == Some(clone)) && - traits.iter().any(|t| t.name() == Some(copy)) { - let marker = Symbol::intern("rustc_copy_clone_marker"); - let span = allow_unstable(cx, span, "derive(Copy, Clone)"); - let meta = cx.meta_word(span, marker); - item = item.map(|mut i| { - i.attrs.push(cx.attribute(span, meta)); - i - }); - } - - let mut items = Vec::new(); - for titem in traits.iter() { - let tname = titem.word().unwrap().name(); - let name = Symbol::intern(&format!("derive({})", tname)); - let tname_cx = ast::Ident::with_empty_ctxt(titem.name().unwrap()); - let mitem = cx.meta_word(titem.span, name); - let path = ast::Path::from_ident(titem.span, tname_cx); - let ext = cx.resolver.resolve_macro(cx.current_expansion.mark, &path, false).unwrap(); - - let span = Span { - expn_id: cx.codemap().record_expansion(codemap::ExpnInfo { - call_site: titem.span, - callee: codemap::NameAndSpan { - format: codemap::MacroAttribute(name), - span: None, - allow_internal_unstable: true, - }, - }), - ..titem.span - }; - - if let SyntaxExtension::BuiltinDerive(ref func) = *ext { - let my_item = Annotatable::Item(item); - func(cx, span, &mitem, &my_item, &mut |a| { - items.push(a) - }); - item = my_item.expect_item(); - } else { - unreachable!(); - } - } - - items.insert(0, Annotatable::Item(item)); - return items -} - macro_rules! derive_traits { ($( $name:expr => $func:path, )+) => { pub fn is_builtin_trait(name: ast::Name) -> bool { diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs index e872cfaeacb7b..7533171b08556 100644 --- a/src/libsyntax_ext/lib.rs +++ b/src/libsyntax_ext/lib.rs @@ -24,7 +24,6 @@ #![feature(staged_api)] extern crate fmt_macros; -#[macro_use] extern crate log; #[macro_use] extern crate syntax; @@ -51,7 +50,7 @@ pub mod proc_macro_impl; use std::rc::Rc; use syntax::ast; -use syntax::ext::base::{MacroExpanderFn, NormalTT, MultiModifier, NamedSyntaxExtension}; +use syntax::ext::base::{MacroExpanderFn, NormalTT, NamedSyntaxExtension}; use syntax::symbol::Symbol; pub fn register_builtins(resolver: &mut syntax::ext::base::Resolver, @@ -114,8 +113,6 @@ pub fn register_builtins(resolver: &mut syntax::ext::base::Resolver, register(Symbol::intern("format_args"), NormalTT(Box::new(format::expand_format_args), None, true)); - register(Symbol::intern("derive"), MultiModifier(Box::new(deriving::expand_derive))); - for (name, ext) in user_exts { register(name, ext); } diff --git a/src/test/compile-fail-fulldeps/proc-macro/derive-bad.rs b/src/test/compile-fail-fulldeps/proc-macro/derive-bad.rs index bc4da9fee47ee..42fad803bfa68 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/derive-bad.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/derive-bad.rs @@ -16,7 +16,7 @@ extern crate derive_bad; #[derive( A )] -//~^^ ERROR: proc_macro_derive produced unparseable tokens +//~^^ ERROR: proc-macro derive produced unparseable tokens struct A; fn main() {} diff --git a/src/test/compile-fail-fulldeps/proc-macro/load-panic.rs b/src/test/compile-fail-fulldeps/proc-macro/load-panic.rs index 107273d012dd6..c483c048b418f 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/load-panic.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/load-panic.rs @@ -14,7 +14,7 @@ extern crate derive_panic; #[derive(A)] -//~^ ERROR: proc_macro_derive attribute panicked +//~^ ERROR: proc-macro derive panicked //~| HELP: message: nope! struct Foo; diff --git a/src/test/compile-fail/deriving-meta-unknown-trait.rs b/src/test/compile-fail/deriving-meta-unknown-trait.rs index 596cc1e7d5816..d388ece084417 100644 --- a/src/test/compile-fail/deriving-meta-unknown-trait.rs +++ b/src/test/compile-fail/deriving-meta-unknown-trait.rs @@ -11,7 +11,7 @@ // ignore-tidy-linelength #[derive(Eqr)] -//~^ ERROR `#[derive]` for custom traits is not stable enough for use. It is deprecated and will be removed in v1.15 (see issue #29644) +//~^ ERROR cannot find derive macro `Eqr` in this scope struct Foo; pub fn main() {} diff --git a/src/test/compile-fail/deriving-primitive.rs b/src/test/compile-fail/deriving-primitive.rs index be822a173ab58..97a39a46c19a8 100644 --- a/src/test/compile-fail/deriving-primitive.rs +++ b/src/test/compile-fail/deriving-primitive.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#[derive(FromPrimitive)] //~ERROR `#[derive]` for custom traits is not stable +#[derive(FromPrimitive)] //~ERROR cannot find derive macro `FromPrimitive` in this scope enum Foo {} fn main() {} diff --git a/src/test/compile-fail/macro-error.rs b/src/test/compile-fail/macro-error.rs index 4a6dbf014a1ca..f467ba3b1e195 100644 --- a/src/test/compile-fail/macro-error.rs +++ b/src/test/compile-fail/macro-error.rs @@ -16,5 +16,5 @@ fn main() { foo!(0); // Check that we report errors at macro definition, not expansion. let _: cfg!(foo) = (); //~ ERROR non-type macro in type position - derive!(); //~ ERROR `derive` can only be used in attributes + derive!(); //~ ERROR macro undefined: 'derive!' } diff --git a/src/test/compile-fail/macros-nonfatal-errors.rs b/src/test/compile-fail/macros-nonfatal-errors.rs index 723e936212a5b..3f710af8ac9a8 100644 --- a/src/test/compile-fail/macros-nonfatal-errors.rs +++ b/src/test/compile-fail/macros-nonfatal-errors.rs @@ -14,9 +14,11 @@ #![feature(asm)] #![feature(trace_macros, concat_idents)] -#[derive(Default, //~ ERROR - Zero)] //~ ERROR -enum CantDeriveThose {} +#[derive(Zero)] //~ ERROR +struct CantDeriveThis; + +#[derive(Default)] //~ ERROR +enum OrDeriveThis {} fn main() { doesnt_exist!(); //~ ERROR diff --git a/src/test/ui/custom-derive/issue-36935.stderr b/src/test/ui/custom-derive/issue-36935.stderr index ad1382cbc8e4b..9a5e2de14e3b0 100644 --- a/src/test/ui/custom-derive/issue-36935.stderr +++ b/src/test/ui/custom-derive/issue-36935.stderr @@ -1,4 +1,4 @@ -error: proc_macro_derive attribute panicked +error: proc-macro derive panicked --> $DIR/issue-36935.rs:17:15 | 17 | #[derive(Foo, Bar)] From 8e02ad0adab29c018148eaa399ccdfba9c098bb5 Mon Sep 17 00:00:00 2001 From: Sebastian Hahn Date: Wed, 25 Jan 2017 07:13:26 +0100 Subject: [PATCH 133/137] Provide Entry-like API for Option This implements #39288. Thanks to @steveklabnik and @oli-obk for their review comments :) --- src/libcore/option.rs | 70 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 8871e1fa840ef..f4f582495afe8 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -632,6 +632,76 @@ impl Option { } } + ///////////////////////////////////////////////////////////////////////// + // Entry-like operations to insert if None and return a reference + ///////////////////////////////////////////////////////////////////////// + + /// Inserts `v` into the option if it is `None`, then + /// returns a mutable reference to the contained value. + /// + /// # Examples + /// + /// ``` + /// #![feature(option_entry)] + /// + /// let mut x = None; + /// + /// { + /// let y: &mut u32 = x.get_or_insert(5); + /// assert_eq!(y, &5); + /// + /// *y = 7; + /// } + /// + /// assert_eq!(x, Some(7)); + /// ``` + #[inline] + #[unstable(feature = "option_entry", issue = "39288")] + pub fn get_or_insert(&mut self, v: T) -> &mut T { + match *self { + None => *self = Some(v), + _ => (), + } + + match *self { + Some(ref mut v) => v, + _ => unreachable!(), + } + } + + /// Inserts a value computed from `f` into the option if it is `None`, then + /// returns a mutable reference to the contained value. + /// + /// # Examples + /// + /// ``` + /// #![feature(option_entry)] + /// + /// let mut x = None; + /// + /// { + /// let y: &mut u32 = x.get_or_insert_with(|| 5); + /// assert_eq!(y, &5); + /// + /// *y = 7; + /// } + /// + /// assert_eq!(x, Some(7)); + /// ``` + #[inline] + #[unstable(feature = "option_entry", issue = "39288")] + pub fn get_or_insert_with T>(&mut self, f: F) -> &mut T { + match *self { + None => *self = Some(f()), + _ => (), + } + + match *self { + Some(ref mut v) => v, + _ => unreachable!(), + } + } + ///////////////////////////////////////////////////////////////////////// // Misc ///////////////////////////////////////////////////////////////////////// From a201348775081ae24bbd016b089b93906f44e3b7 Mon Sep 17 00:00:00 2001 From: Josh Driver Date: Sun, 5 Feb 2017 12:22:29 +1030 Subject: [PATCH 134/137] Update pretty test for derive attributes Remove attr-variant-data.rs since it relies on quirks in legacy custom derive resolution (undefined derives only print a warning). Add a new test which uses a defined proc macro derive, and tests pretty printing of proc macro derive attributes. --- src/test/pretty/attr-derive.rs | 43 +++++++++++++++++++++ src/test/pretty/attr-variant-data.rs | 51 ------------------------- src/test/pretty/auxiliary/derive-foo.rs | 22 +++++++++++ 3 files changed, 65 insertions(+), 51 deletions(-) create mode 100644 src/test/pretty/attr-derive.rs delete mode 100644 src/test/pretty/attr-variant-data.rs create mode 100644 src/test/pretty/auxiliary/derive-foo.rs diff --git a/src/test/pretty/attr-derive.rs b/src/test/pretty/attr-derive.rs new file mode 100644 index 0000000000000..a1c581a18682c --- /dev/null +++ b/src/test/pretty/attr-derive.rs @@ -0,0 +1,43 @@ +// Copyright 2012 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. + +// aux-build:derive-foo.rs +// ignore-stage1 +// pp-exact +// Testing that both the inner item and next outer item are +// preserved, and that the first outer item parsed in main is not +// accidentally carried over to each inner function + +#[macro_use] +extern crate derive_foo; + +#[derive(Foo)] +struct X; + +#[derive(Foo)] +#[Bar] +struct Y; + +#[derive(Foo)] +struct WithRef { + x: X, + #[Bar] + y: Y, +} + +#[derive(Foo)] +enum Enum { + + #[Bar] + Asdf, + Qwerty, +} + +fn main() { } diff --git a/src/test/pretty/attr-variant-data.rs b/src/test/pretty/attr-variant-data.rs deleted file mode 100644 index 1ffacaa9f5a5d..0000000000000 --- a/src/test/pretty/attr-variant-data.rs +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2012 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. - -// pp-exact -// Testing that both the inner item and next outer item are -// preserved, and that the first outer item parsed in main is not -// accidentally carried over to each inner function - -#![feature(custom_attribute)] -#![feature(custom_derive)] - -#[derive(Serialize, Deserialize)] -struct X; - -#[derive(Serialize, Deserialize)] -struct WithRef<'a, T: 'a> { - #[serde(skip_deserializing)] - t: Option<&'a T>, - #[serde(serialize_with = "ser_x", deserialize_with = "de_x")] - x: X, -} - -#[derive(Serialize, Deserialize)] -enum EnumWith { - Unit, - Newtype( - #[serde(serialize_with = "ser_x", deserialize_with = "de_x")] - X), - Tuple(T, - #[serde(serialize_with = "ser_x", deserialize_with = "de_x")] - X), - Struct { - t: T, - #[serde(serialize_with = "ser_x", deserialize_with = "de_x")] - x: X, - }, -} - -#[derive(Serialize, Deserialize)] -struct Tuple(T, - #[serde(serialize_with = "ser_x", deserialize_with = "de_x")] - X); - -fn main() { } diff --git a/src/test/pretty/auxiliary/derive-foo.rs b/src/test/pretty/auxiliary/derive-foo.rs new file mode 100644 index 0000000000000..bd81d3e5a3b53 --- /dev/null +++ b/src/test/pretty/auxiliary/derive-foo.rs @@ -0,0 +1,22 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(Foo, attributes(Bar))] +pub fn derive(input: TokenStream) -> TokenStream { + "".parse().unwrap() +} From 5e06aeeef0f43653ab93272daf526992db82cc8a Mon Sep 17 00:00:00 2001 From: "Zack M. Davis" Date: Sat, 4 Feb 2017 21:18:35 -0800 Subject: [PATCH 135/137] correct version in which more_struct_aliases was/will be stable The stabilizing commit is 5056a437, which is not in 1.14, but is (at time of writing) on the 1.16 beta branch. --- src/libsyntax/feature_gate.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 970c37045dfc4..cc04727b69808 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -381,7 +381,7 @@ declare_features! ( (accepted, dotdot_in_tuple_patterns, "1.14.0", Some(33627)), (accepted, item_like_imports, "1.14.0", Some(35120)), // Allows using `Self` and associated types in struct expressions and patterns. - (accepted, more_struct_aliases, "1.14.0", Some(37544)), + (accepted, more_struct_aliases, "1.16.0", Some(37544)), ); // (changing above list without updating src/doc/reference.md makes @cmr sad) From 0dbb1e4fee5218b338ed1c8307665342c2b99e4f Mon Sep 17 00:00:00 2001 From: Andrew Cann Date: Sun, 5 Feb 2017 16:41:32 +0800 Subject: [PATCH 136/137] Remove use of ptr::eq --- src/librustc_const_eval/check_match.rs | 31 +++++++++++++++----------- src/librustc_const_eval/lib.rs | 1 - 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs index ce478f1a4504e..f53d451152fbc 100644 --- a/src/librustc_const_eval/check_match.rs +++ b/src/librustc_const_eval/check_match.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::ptr; use _match::{MatchCheckCtxt, Matrix, expand_pattern, is_useful}; use _match::Usefulness::*; use _match::WitnessPreference::*; @@ -274,7 +273,7 @@ fn check_arms<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>, let mut seen = Matrix::empty(); let mut catchall = None; let mut printed_if_let_err = false; - for &(ref pats, guard) in arms { + for (arm_index, &(ref pats, guard)) in arms.iter().enumerate() { for &(pat, hir_pat) in pats { let v = vec![pat]; @@ -305,17 +304,23 @@ fn check_arms<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>, let span = first_pat.0.span; // check which arm we're on. - if ptr::eq(first_arm_pats, pats) { - let mut diagnostic = Diagnostic::new(Level::Warning, - "unreachable pattern"); - diagnostic.set_span(pat.span); - cx.tcx.sess.add_lint_diagnostic(lint::builtin::UNREACHABLE_PATTERNS, - hir_pat.id, diagnostic); - } else { - struct_span_err!(cx.tcx.sess, span, E0165, - "irrefutable while-let pattern") - .span_label(span, &format!("irrefutable pattern")) - .emit(); + match arm_index { + // The arm with the user-specified pattern. + 0 => { + let mut diagnostic = Diagnostic::new(Level::Warning, + "unreachable pattern"); + diagnostic.set_span(pat.span); + cx.tcx.sess.add_lint_diagnostic(lint::builtin::UNREACHABLE_PATTERNS, + hir_pat.id, diagnostic); + }, + // The arm with the wildcard pattern. + 1 => { + struct_span_err!(cx.tcx.sess, span, E0165, + "irrefutable while-let pattern") + .span_label(span, &format!("irrefutable pattern")) + .emit(); + }, + _ => bug!(), } }, diff --git a/src/librustc_const_eval/lib.rs b/src/librustc_const_eval/lib.rs index 7c579f44e79f2..198e49daabc63 100644 --- a/src/librustc_const_eval/lib.rs +++ b/src/librustc_const_eval/lib.rs @@ -30,7 +30,6 @@ #![feature(box_syntax)] #![feature(const_fn)] #![feature(i128_type)] -#![feature(ptr_eq)] extern crate arena; #[macro_use] extern crate syntax; From 7135d0ab944f0bfa5ef4cecfd1dfdd8a79647c53 Mon Sep 17 00:00:00 2001 From: Andrew Cann Date: Sun, 5 Feb 2017 22:29:06 +0800 Subject: [PATCH 137/137] Fix make tidy --- src/librustc_const_eval/check_match.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs index f53d451152fbc..6f33b4fad769f 100644 --- a/src/librustc_const_eval/check_match.rs +++ b/src/librustc_const_eval/check_match.rs @@ -310,8 +310,9 @@ fn check_arms<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>, let mut diagnostic = Diagnostic::new(Level::Warning, "unreachable pattern"); diagnostic.set_span(pat.span); - cx.tcx.sess.add_lint_diagnostic(lint::builtin::UNREACHABLE_PATTERNS, - hir_pat.id, diagnostic); + cx.tcx.sess.add_lint_diagnostic( + lint::builtin::UNREACHABLE_PATTERNS, + hir_pat.id, diagnostic); }, // The arm with the wildcard pattern. 1 => {