From 02ae1e10605dccf29c77f94dbbf916b28d2b7c54 Mon Sep 17 00:00:00 2001 From: Chris Morgan Date: Sun, 8 Jan 2017 16:35:13 +0530 Subject: [PATCH 01/37] 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 02/37] 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 03/37] 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 04/37] 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 05/37] 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 06/37] 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 07/37] 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 62c088c047f4a510bb2f65b550decb5bebff0f7c Mon Sep 17 00:00:00 2001 From: Sergey Pepyakin Date: Fri, 20 Jan 2017 21:18:17 +0300 Subject: [PATCH 08/37] 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 09/37] 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 10/37] 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 bb34856e9d0e480758bdc3afaad60654435d12b3 Mon Sep 17 00:00:00 2001 From: Michael Gattozzi Date: Thu, 26 Jan 2017 01:35:00 -0500 Subject: [PATCH 11/37] 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 9128f6100c9bfe2c2c22d85ccec92f01166f5d25 Mon Sep 17 00:00:00 2001 From: Oliver Middleton Date: Sun, 29 Jan 2017 13:31:47 +0000 Subject: [PATCH 12/37] 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 395f23c9f7c7e1107dce5a05e71b3a9480d4e331 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 2 Feb 2017 16:23:27 +1300 Subject: [PATCH 13/37] 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 89f9767356b24623e6cade93dad3f59ec3288bb7 Mon Sep 17 00:00:00 2001 From: Austin Bonander Date: Wed, 1 Feb 2017 20:11:10 -0800 Subject: [PATCH 14/37] 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 15/37] 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 a0efdf34417b5564a7474e8c2175b9e643640b8f Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Thu, 2 Feb 2017 22:27:15 +0100 Subject: [PATCH 16/37] 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 17/37] 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 18/37] 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 2add6ac14a29d5d828f4da01ee0a09db0f472975 Mon Sep 17 00:00:00 2001 From: Jimmy Cuadra Date: Thu, 2 Feb 2017 17:40:44 -0800 Subject: [PATCH 19/37] 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 681bc5c66cf6f99f7a95ebd5ed38cdd3fb3c4245 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 2 Feb 2017 19:24:20 -0800 Subject: [PATCH 20/37] 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 2cc84df44cca1b6ab4b1f4d01a7680c72d7f20d9 Mon Sep 17 00:00:00 2001 From: Andrew Cann Date: Wed, 11 Jan 2017 15:58:37 +0800 Subject: [PATCH 21/37] 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 22/37] 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 23/37] 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 24/37] 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 25/37] 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 26/37] 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 27/37] 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 7444d07154652c4d7a3e91e645eaa604a8bc4c84 Mon Sep 17 00:00:00 2001 From: Andrew Cann Date: Sat, 4 Feb 2017 14:03:28 +0800 Subject: [PATCH 28/37] 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 29/37] 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 b4ef361a8c7ef75b29bad437ee970c1794793cb1 Mon Sep 17 00:00:00 2001 From: king6cong Date: Sat, 4 Feb 2017 16:44:23 +0800 Subject: [PATCH 30/37] 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 a40be0857c7bf48e39f815417b0b5293cd8ed1aa Mon Sep 17 00:00:00 2001 From: Tyler Julian Date: Tue, 10 Jan 2017 19:11:56 -0800 Subject: [PATCH 31/37] 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 32/37] 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 33/37] 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 34/37] 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 35/37] 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 36/37] 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 37/37] 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)