From 4bcfbc36c672f0f30176a31c5a6e529bebd6fbcc Mon Sep 17 00:00:00 2001 From: Djzin Date: Sun, 12 Mar 2017 13:14:47 +0000 Subject: [PATCH 001/233] speed up mem::swap --- src/libcore/mem.rs | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index f4ce4697d7cf..a7c5d29c5a51 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -109,7 +109,7 @@ pub use intrinsics::transmute; /// [`Clone`][clone]. You need the value's destructor to run only once, /// because a double `free` is undefined behavior. /// -/// An example is the definition of [`mem::swap`][swap] in this module: +/// An example is the (old) definition of [`mem::swap`][swap] in this module: /// /// ``` /// use std::mem; @@ -447,18 +447,15 @@ pub unsafe fn uninitialized() -> T { #[stable(feature = "rust1", since = "1.0.0")] pub fn swap(x: &mut T, y: &mut T) { unsafe { - // Give ourselves some scratch space to work with - let mut t: T = uninitialized(); + let x = x as *mut T as *mut u8; + let y = y as *mut T as *mut u8; - // Perform the swap, `&mut` pointers never alias - ptr::copy_nonoverlapping(&*x, &mut t, 1); - ptr::copy_nonoverlapping(&*y, x, 1); - ptr::copy_nonoverlapping(&t, y, 1); - - // y and t now point to the same thing, but we need to completely - // forget `t` because we do not want to run the destructor for `T` - // on its value, which is still owned somewhere outside this function. - forget(t); + // use an xor-swap as x & y are guaranteed to never alias + for i in 0..size_of::() as isize { + *x.offset(i) ^= *y.offset(i); + *y.offset(i) ^= *x.offset(i); + *x.offset(i) ^= *y.offset(i); + } } } From 85049e508ba6b1502e4d074d051a188c398fabc6 Mon Sep 17 00:00:00 2001 From: Djzin Date: Sun, 12 Mar 2017 14:10:07 +0000 Subject: [PATCH 002/233] avoid recursion --- src/libcore/mem.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index a7c5d29c5a51..748d63362463 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -450,11 +450,14 @@ pub fn swap(x: &mut T, y: &mut T) { let x = x as *mut T as *mut u8; let y = y as *mut T as *mut u8; - // use an xor-swap as x & y are guaranteed to never alias - for i in 0..size_of::() as isize { + // can't use a for loop as the `range` impl calls `mem::swap` recursively + let mut i = 0; + while i < size_of::() as isize { + // use an xor-swap as x & y are guaranteed to never alias *x.offset(i) ^= *y.offset(i); *y.offset(i) ^= *x.offset(i); *x.offset(i) ^= *y.offset(i); + i += 1; } } } From 5702f436aa6258119a32cbff31cc442d73b0d2c0 Mon Sep 17 00:00:00 2001 From: Djzin Date: Sun, 12 Mar 2017 18:32:20 +0000 Subject: [PATCH 003/233] a new approach; ditch xor cuteness and maximize cache locality --- src/libcore/mem.rs | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 748d63362463..e1b9991ccfdf 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -447,17 +447,29 @@ pub unsafe fn uninitialized() -> T { #[stable(feature = "rust1", since = "1.0.0")] pub fn swap(x: &mut T, y: &mut T) { unsafe { + // Give ourselves some scratch space to work with + let mut t: [u8; 16] = mem::uninitialized(); + let x = x as *mut T as *mut u8; let y = y as *mut T as *mut u8; + let t = &mut t as *mut _ as *mut u8; // can't use a for loop as the `range` impl calls `mem::swap` recursively + let len = size_of::() as isize; let mut i = 0; - while i < size_of::() as isize { - // use an xor-swap as x & y are guaranteed to never alias - *x.offset(i) ^= *y.offset(i); - *y.offset(i) ^= *x.offset(i); - *x.offset(i) ^= *y.offset(i); - i += 1; + while i + 16 <= len { + // Perform the swap 16 bytes at a time, `&mut` pointers never alias + ptr::copy_nonoverlapping(x.offset(i), t, 16); + ptr::copy_nonoverlapping(y.offset(i), x.offset(i), 16); + ptr::copy_nonoverlapping(t, y.offset(i), 16); + i += 16; + } + if i < len { + // Swap any remaining bytes + let rem = (len - i) as usize; + ptr::copy_nonoverlapping(x.offset(i), t, rem); + ptr::copy_nonoverlapping(y.offset(i), x.offset(i), rem); + ptr::copy_nonoverlapping(t, y.offset(i), rem); } } } From d1fec0d87a95310fcc1c59d72953ad6be89c78a5 Mon Sep 17 00:00:00 2001 From: Djzin Date: Sun, 12 Mar 2017 18:41:58 +0000 Subject: [PATCH 004/233] fix typo --- src/libcore/mem.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index e1b9991ccfdf..865ff3c6ee4b 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -448,7 +448,7 @@ pub unsafe fn uninitialized() -> T { pub fn swap(x: &mut T, y: &mut T) { unsafe { // Give ourselves some scratch space to work with - let mut t: [u8; 16] = mem::uninitialized(); + let mut t: [u8; 16] = uninitialized(); let x = x as *mut T as *mut u8; let y = y as *mut T as *mut u8; From 1daf58964216dfe1f805cdaff76a91ca90d7523e Mon Sep 17 00:00:00 2001 From: Djzin Date: Mon, 13 Mar 2017 20:03:10 +0000 Subject: [PATCH 005/233] add SWAP_BLOCK_SIZE constant --- src/libcore/mem.rs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 865ff3c6ee4b..9a116e9041f7 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -447,8 +447,10 @@ pub unsafe fn uninitialized() -> T { #[stable(feature = "rust1", since = "1.0.0")] pub fn swap(x: &mut T, y: &mut T) { unsafe { + const SWAP_BLOCK_SIZE: usize = 16; + // Give ourselves some scratch space to work with - let mut t: [u8; 16] = uninitialized(); + let mut t: [u8; SWAP_BLOCK_SIZE] = uninitialized(); let x = x as *mut T as *mut u8; let y = y as *mut T as *mut u8; @@ -457,12 +459,12 @@ pub fn swap(x: &mut T, y: &mut T) { // can't use a for loop as the `range` impl calls `mem::swap` recursively let len = size_of::() as isize; let mut i = 0; - while i + 16 <= len { - // Perform the swap 16 bytes at a time, `&mut` pointers never alias - ptr::copy_nonoverlapping(x.offset(i), t, 16); - ptr::copy_nonoverlapping(y.offset(i), x.offset(i), 16); - ptr::copy_nonoverlapping(t, y.offset(i), 16); - i += 16; + while i + SWAP_BLOCK_SIZE as isize <= len { + // Perform the swap SWAP_BLOCK_SIZE bytes at a time, `&mut` pointers never alias + ptr::copy_nonoverlapping(x.offset(i), t, SWAP_BLOCK_SIZE); + ptr::copy_nonoverlapping(y.offset(i), x.offset(i), SWAP_BLOCK_SIZE); + ptr::copy_nonoverlapping(t, y.offset(i), SWAP_BLOCK_SIZE); + i += SWAP_BLOCK_SIZE as isize; } if i < len { // Swap any remaining bytes From 2816998d1e702a8597c07100856e2483590f3e2a Mon Sep 17 00:00:00 2001 From: Djzin Date: Wed, 15 Mar 2017 06:45:43 +0000 Subject: [PATCH 006/233] use simd blocks --- src/libcore/mem.rs | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 9a116e9041f7..b6838f103c46 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -447,24 +447,34 @@ pub unsafe fn uninitialized() -> T { #[stable(feature = "rust1", since = "1.0.0")] pub fn swap(x: &mut T, y: &mut T) { unsafe { - const SWAP_BLOCK_SIZE: usize = 16; + // The approach here is to utilize simd to swap x & y efficiently. Testing reveals + // that swapping either 32 bytes or 64 bytes at a time is most efficient for intel + // Haswell E processors. LLVM is more able to optimize if we give a struct a + // #[repr(simd)], even if we don't actually use this struct directly. + #[repr(simd)] + struct Block(u64, u64, u64, u64); + let block_size = size_of::(); - // Give ourselves some scratch space to work with - let mut t: [u8; SWAP_BLOCK_SIZE] = uninitialized(); + // Create some uninitialized memory as scratch space + let mut t: Block = uninitialized(); + // Get raw pointers to the bytes of x, y & t for easier manipulation let x = x as *mut T as *mut u8; let y = y as *mut T as *mut u8; let t = &mut t as *mut _ as *mut u8; - // can't use a for loop as the `range` impl calls `mem::swap` recursively + // Loop through x & y, copying them `Block` at a time + // The optimizer should unroll the loop fully for most types + // N.B. We can't use a for loop as the `range` impl calls `mem::swap` recursively let len = size_of::() as isize; let mut i = 0; - while i + SWAP_BLOCK_SIZE as isize <= len { - // Perform the swap SWAP_BLOCK_SIZE bytes at a time, `&mut` pointers never alias - ptr::copy_nonoverlapping(x.offset(i), t, SWAP_BLOCK_SIZE); - ptr::copy_nonoverlapping(y.offset(i), x.offset(i), SWAP_BLOCK_SIZE); - ptr::copy_nonoverlapping(t, y.offset(i), SWAP_BLOCK_SIZE); - i += SWAP_BLOCK_SIZE as isize; + while i + block_size as isize <= len { + // Swap a block of bytes of x & y, using t as a temporary buffer + // This should be optimized into efficient SIMD operations where available + ptr::copy_nonoverlapping(x.offset(i), t, block_size); + ptr::copy_nonoverlapping(y.offset(i), x.offset(i), block_size); + ptr::copy_nonoverlapping(t, y.offset(i), block_size); + i += block_size as isize; } if i < len { // Swap any remaining bytes From f7c641b8b62a36ce23bd000644f19cf8761007b0 Mon Sep 17 00:00:00 2001 From: Irfan Hudda Date: Tue, 21 Mar 2017 22:11:13 +0530 Subject: [PATCH 007/233] Improve documentation of next_power_of_two Clarify overflow behavior of `next_power_of_two`. Related Issue: #18604 --- src/libcore/num/mod.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index f665cfdee77a..487b0dba3c4e 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -2328,7 +2328,7 @@ macro_rules! uint_impl { } /// Returns the smallest power of two greater than or equal to `self`. - /// Unspecified behavior on overflow. + /// More details about overflow behavior can be found in [RFC 560]. /// /// # Examples /// @@ -2338,6 +2338,8 @@ macro_rules! uint_impl { /// assert_eq!(2u8.next_power_of_two(), 2); /// assert_eq!(3u8.next_power_of_two(), 4); /// ``` + /// + /// [RFC 560]: https://github.com/rust-lang/rfcs/blob/master/text/0560-integer-overflow.md #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn next_power_of_two(self) -> Self { From 04e9c20228c38c20c5d4f84328332b2c5c98d5a2 Mon Sep 17 00:00:00 2001 From: Irfan Hudda Date: Wed, 19 Apr 2017 23:59:43 +0530 Subject: [PATCH 008/233] next_power_of_two panic on overflow --- src/libcore/num/mod.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 487b0dba3c4e..15ffe9db8ce6 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -2345,7 +2345,11 @@ macro_rules! uint_impl { pub fn next_power_of_two(self) -> Self { let bits = size_of::() * 8; let one: Self = 1; - one << ((bits - self.wrapping_sub(one).leading_zeros() as usize) % bits) + if self == 0 { + 1 + } else { + one << (bits - self.wrapping_sub(one).leading_zeros() as usize) + } } /// Returns the smallest power of two greater than or equal to `n`. If @@ -2363,7 +2367,9 @@ macro_rules! uint_impl { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn checked_next_power_of_two(self) -> Option { - let npot = self.next_power_of_two(); + let bits = size_of::() * 8; + let one: Self = 1; + let npot = one << ((bits - self.wrapping_sub(one).leading_zeros() as usize) % bits); if npot >= self { Some(npot) } else { From f7bd370818b003f57e47a1894ff0d791ad23628d Mon Sep 17 00:00:00 2001 From: Irfan Hudda Date: Thu, 20 Apr 2017 19:51:38 +0530 Subject: [PATCH 009/233] remove redundant wrapping_sub --- src/libcore/num/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 15ffe9db8ce6..bef7a20cd7f3 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -2348,7 +2348,7 @@ macro_rules! uint_impl { if self == 0 { 1 } else { - one << (bits - self.wrapping_sub(one).leading_zeros() as usize) + one << (bits - (self - one).leading_zeros() as usize) } } From c6ca81aa921415a33e1c8f32e0c53a2c5eb6b485 Mon Sep 17 00:00:00 2001 From: Djzin Date: Mon, 24 Apr 2017 07:40:11 +0100 Subject: [PATCH 010/233] change wording --- src/libcore/mem.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index b6838f103c46..e51976c4845e 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -109,7 +109,7 @@ pub use intrinsics::transmute; /// [`Clone`][clone]. You need the value's destructor to run only once, /// because a double `free` is undefined behavior. /// -/// An example is the (old) definition of [`mem::swap`][swap] in this module: +/// An example is a possible implementation of [`mem::swap`][swap]: /// /// ``` /// use std::mem; From 8f9caff988954ab19f4a242d905aa6092a03bddd Mon Sep 17 00:00:00 2001 From: Irfan Hudda Date: Fri, 28 Apr 2017 21:50:02 +0530 Subject: [PATCH 011/233] Add helper functions for `next_power_of_two` and `checked_next_power_of_two` --- src/libcore/num/mod.rs | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index bef7a20cd7f3..0c7832168bb9 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -2327,6 +2327,18 @@ macro_rules! uint_impl { (self.wrapping_sub(1)) & self == 0 && !(self == 0) } + fn round_up_to_one_less_than_a_power_of_two(self) -> Self { + let bits = size_of::() as u32 * 8; + let z = self.leading_zeros(); + (if z == bits { 0 as Self } else { !0 }).wrapping_shr(z) + } + + fn one_less_than_next_power_of_two(self) -> Self { + self.wrapping_sub(1) + .round_up_to_one_less_than_a_power_of_two() + .wrapping_add(if self == 0 { 1 } else { 0 }) + } + /// Returns the smallest power of two greater than or equal to `self`. /// More details about overflow behavior can be found in [RFC 560]. /// @@ -2343,13 +2355,7 @@ macro_rules! uint_impl { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn next_power_of_two(self) -> Self { - let bits = size_of::() * 8; - let one: Self = 1; - if self == 0 { - 1 - } else { - one << (bits - (self - one).leading_zeros() as usize) - } + self.one_less_than_next_power_of_two() + 1 } /// Returns the smallest power of two greater than or equal to `n`. If @@ -2367,9 +2373,7 @@ macro_rules! uint_impl { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn checked_next_power_of_two(self) -> Option { - let bits = size_of::() * 8; - let one: Self = 1; - let npot = one << ((bits - self.wrapping_sub(one).leading_zeros() as usize) % bits); + let npot = self.one_less_than_next_power_of_two().wrapping_add(1); if npot >= self { Some(npot) } else { From 67684a399c2020495075b2e6c848850e7a8d60e9 Mon Sep 17 00:00:00 2001 From: Irfan Hudda Date: Sat, 29 Apr 2017 00:06:54 +0530 Subject: [PATCH 012/233] Add comment about overflow behavior for next_power_of_two --- src/libcore/num/mod.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 0c7832168bb9..8c4a6e871e12 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -2340,6 +2340,9 @@ macro_rules! uint_impl { } /// Returns the smallest power of two greater than or equal to `self`. + /// When return value overflows, it panics in debug mode and return + /// value is wrapped in release mode. + /// /// More details about overflow behavior can be found in [RFC 560]. /// /// # Examples From ed24829985cd01ae7ab980d785b6dff2e8332868 Mon Sep 17 00:00:00 2001 From: Irfan Hudda Date: Sat, 29 Apr 2017 01:51:54 +0530 Subject: [PATCH 013/233] Simplify `checked_next_power_of_two` function --- src/libcore/num/mod.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 8c4a6e871e12..cc1f9ca79a15 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -2376,12 +2376,7 @@ macro_rules! uint_impl { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn checked_next_power_of_two(self) -> Option { - let npot = self.one_less_than_next_power_of_two().wrapping_add(1); - if npot >= self { - Some(npot) - } else { - None - } + self.one_less_than_next_power_of_two().checked_add(1) } } } From 42754ce710a777b38402b12728daf54d68ea2b50 Mon Sep 17 00:00:00 2001 From: whitequark Date: Mon, 13 Feb 2017 09:57:50 +0000 Subject: [PATCH 014/233] Add profiling support, through the rustc -Z profile flag. When -Z profile is passed, the GCDAProfiling LLVM pass is added to the pipeline, which uses debug information to instrument the IR. After compiling with -Z profile, the $(OUT_DIR)/$(CRATE_NAME).gcno file is created, containing initial profiling information. After running the program built, the $(OUT_DIR)/$(CRATE_NAME).gcda file is created, containing branch counters. The created *.gcno and *.gcda files can be processed using the "llvm-cov gcov" and "lcov" tools. The profiling data LLVM generates does not faithfully follow the GCC's format for *.gcno and *.gcda files, and so it will probably not work with other tools (such as gcov itself) that consume these files. --- configure | 1 + src/Cargo.lock | 9 +++ src/bootstrap/check.rs | 4 ++ src/bootstrap/config.rs | 4 ++ src/bootstrap/config.toml.example | 3 + src/bootstrap/lib.rs | 3 + src/doc/unstable-book/src/SUMMARY.md | 3 + .../src/compiler-flags/profile.md | 5 ++ .../src/language-features/profiler-runtime.md | 5 ++ .../library-features/profiler-runtime-lib.md | 5 ++ src/libprofiler_builtins/Cargo.toml | 18 ++++++ src/libprofiler_builtins/build.rs | 56 +++++++++++++++++++ src/libprofiler_builtins/lib.rs | 20 +++++++ src/librustc/middle/cstore.rs | 2 + src/librustc/session/config.rs | 2 + src/librustc_driver/driver.rs | 8 ++- src/librustc_llvm/ffi.rs | 4 ++ src/librustc_metadata/creader.rs | 28 ++++++++++ src/librustc_metadata/cstore.rs | 5 ++ src/librustc_metadata/cstore_impl.rs | 4 ++ src/librustc_trans/back/link.rs | 3 + src/librustc_trans/back/write.rs | 4 ++ src/librustc_trans/base.rs | 8 ++- src/librustc_trans/context.rs | 11 +++- src/librustc_trans/debuginfo/metadata.rs | 40 ++++++++++++- src/librustc_trans/debuginfo/mod.rs | 2 + src/libstd/Cargo.toml | 2 + src/libsyntax/feature_gate.rs | 11 ++++ src/rustllvm/RustWrapper.cpp | 4 ++ .../feature-gate-profiler-runtime.rs | 13 +++++ src/test/run-make/profile/Makefile | 7 +++ src/test/run-make/profile/test.rs | 11 ++++ 32 files changed, 296 insertions(+), 9 deletions(-) create mode 100644 src/doc/unstable-book/src/compiler-flags/profile.md create mode 100644 src/doc/unstable-book/src/language-features/profiler-runtime.md create mode 100644 src/doc/unstable-book/src/library-features/profiler-runtime-lib.md create mode 100644 src/libprofiler_builtins/Cargo.toml create mode 100644 src/libprofiler_builtins/build.rs create mode 100644 src/libprofiler_builtins/lib.rs create mode 100644 src/test/compile-fail/feature-gate-profiler-runtime.rs create mode 100644 src/test/run-make/profile/Makefile create mode 100644 src/test/run-make/profile/test.rs diff --git a/configure b/configure index c5ecc2236894..ced7377a2364 100755 --- a/configure +++ b/configure @@ -452,6 +452,7 @@ opt vendor 0 "enable usage of vendored Rust crates" opt sanitizers 0 "build the sanitizer runtimes (asan, lsan, msan, tsan)" opt dist-src 1 "when building tarballs enables building a source tarball" opt cargo-openssl-static 0 "static openssl in cargo" +opt profiler 0 "build the profiler runtime" # Optimization and debugging options. These may be overridden by the release channel, etc. opt_nosave optimize 1 "build optimized rust code" diff --git a/src/Cargo.lock b/src/Cargo.lock index 21b167f6d427..696ba153c9a6 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -355,6 +355,14 @@ dependencies = [ "syntax_pos 0.0.0", ] +[[package]] +name = "profiler_builtins" +version = "0.0.0" +dependencies = [ + "core 0.0.0", + "gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "pulldown-cmark" version = "0.0.8" @@ -833,6 +841,7 @@ dependencies = [ "libc 0.0.0", "panic_abort 0.0.0", "panic_unwind 0.0.0", + "profiler_builtins 0.0.0", "rand 0.0.0", "rustc_asan 0.0.0", "rustc_lsan 0.0.0", diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index d7457e088694..47b1e06a5ff8 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -268,6 +268,10 @@ pub fn compiletest(build: &Build, cmd.env("SANITIZER_SUPPORT", "1"); } + if build.config.profiler { + cmd.env("PROFILER_SUPPORT", "1"); + } + cmd.arg("--adb-path").arg("adb"); cmd.arg("--adb-test-dir").arg(ADB_TEST_DIR); if target.contains("android") { diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 34fbc33d981a..8133a869c250 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -50,6 +50,7 @@ pub struct Config { pub full_bootstrap: bool, pub extended: bool, pub sanitizers: bool, + pub profiler: bool, // llvm codegen options pub llvm_assertions: bool, @@ -158,6 +159,7 @@ struct Build { extended: Option, verbose: Option, sanitizers: Option, + profiler: Option, openssl_static: Option, } @@ -311,6 +313,7 @@ impl Config { set(&mut config.extended, build.extended); set(&mut config.verbose, build.verbose); set(&mut config.sanitizers, build.sanitizers); + set(&mut config.profiler, build.profiler); set(&mut config.openssl_static, build.openssl_static); if let Some(ref install) = toml.install { @@ -462,6 +465,7 @@ impl Config { ("FULL_BOOTSTRAP", self.full_bootstrap), ("EXTENDED", self.extended), ("SANITIZERS", self.sanitizers), + ("PROFILER", self.profiler), ("DIST_SRC", self.rust_dist_src), ("CARGO_OPENSSL_STATIC", self.openssl_static), } diff --git a/src/bootstrap/config.toml.example b/src/bootstrap/config.toml.example index 0309eca0e5de..93997027dbb8 100644 --- a/src/bootstrap/config.toml.example +++ b/src/bootstrap/config.toml.example @@ -147,6 +147,9 @@ # Build the sanitizer runtimes #sanitizers = false +# Build the profiler runtime +#profiler = false + # Indicates whether the OpenSSL linked into Cargo will be statically linked or # not. If static linkage is specified then the build system will download a # known-good version of OpenSSL, compile it, and link it to Cargo. diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 017d4015134d..b0c0033fbe72 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -667,6 +667,9 @@ impl Build { if self.config.backtrace { features.push_str(" backtrace"); } + if self.config.profiler { + features.push_str(" profiler"); + } return features } diff --git a/src/doc/unstable-book/src/SUMMARY.md b/src/doc/unstable-book/src/SUMMARY.md index 0d0485dc872d..27ee688a84fc 100644 --- a/src/doc/unstable-book/src/SUMMARY.md +++ b/src/doc/unstable-book/src/SUMMARY.md @@ -2,6 +2,7 @@ - [Compiler flags](compiler-flags.md) - [linker_flavor](compiler-flags/linker-flavor.md) + - [profile](compiler-flags/profile.md) - [remap_path_prefix](compiler-flags/remap-path-prefix.md) - [Language features](language-features.md) - [abi_msp430_interrupt](language-features/abi-msp430-interrupt.md) @@ -71,6 +72,7 @@ - [plugin_registrar](language-features/plugin-registrar.md) - [prelude_import](language-features/prelude-import.md) - [proc_macro](language-features/proc-macro.md) + - [profiler_runtime](language-features/profiler-runtime.md) - [quote](language-features/quote.md) - [relaxed_adts](language-features/relaxed-adts.md) - [repr_align](language-features/repr-align.md) @@ -180,6 +182,7 @@ - [print](library-features/print.md) - [proc_macro_internals](library-features/proc-macro-internals.md) - [process_try_wait](library-features/process-try-wait.md) + - [profiler_runtime_lib](library-features/sanitizer-runtime-lib.md) - [question_mark_carrier](library-features/question-mark-carrier.md) - [rand](library-features/rand.md) - [range_contains](library-features/range-contains.md) diff --git a/src/doc/unstable-book/src/compiler-flags/profile.md b/src/doc/unstable-book/src/compiler-flags/profile.md new file mode 100644 index 000000000000..f9634c55c96e --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/profile.md @@ -0,0 +1,5 @@ +# `profile` + +The tracking issue for this feature is: None + +------------------------ diff --git a/src/doc/unstable-book/src/language-features/profiler-runtime.md b/src/doc/unstable-book/src/language-features/profiler-runtime.md new file mode 100644 index 000000000000..a9879c8d5a65 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/profiler-runtime.md @@ -0,0 +1,5 @@ +# `profiler_runtime` + +The tracking issue for this feature is: None. + +------------------------ diff --git a/src/doc/unstable-book/src/library-features/profiler-runtime-lib.md b/src/doc/unstable-book/src/library-features/profiler-runtime-lib.md new file mode 100644 index 000000000000..a01f1e73ab40 --- /dev/null +++ b/src/doc/unstable-book/src/library-features/profiler-runtime-lib.md @@ -0,0 +1,5 @@ +# `profiler_runtime_lib` + +This feature is internal to the Rust compiler and is not intended for general use. + +------------------------ diff --git a/src/libprofiler_builtins/Cargo.toml b/src/libprofiler_builtins/Cargo.toml new file mode 100644 index 000000000000..dbbc168e7ea3 --- /dev/null +++ b/src/libprofiler_builtins/Cargo.toml @@ -0,0 +1,18 @@ +[package] +authors = ["The Rust Project Developers"] +build = "build.rs" +name = "profiler_builtins" +version = "0.0.0" + +[lib] +name = "profiler_builtins" +path = "lib.rs" +test = false +bench = false +doc = false + +[dependencies] +core = { path = "../libcore" } + +[build-dependencies] +gcc = "0.3.27" diff --git a/src/libprofiler_builtins/build.rs b/src/libprofiler_builtins/build.rs new file mode 100644 index 000000000000..a9685ca7e1aa --- /dev/null +++ b/src/libprofiler_builtins/build.rs @@ -0,0 +1,56 @@ +// 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. + +//! Compiles the profiler part of the `compiler-rt` library. +//! +//! See the build.rs for libcompiler_builtins crate for details. + +extern crate gcc; + +use std::env; +use std::path::Path; + +fn main() { + let target = env::var("TARGET").expect("TARGET was not set"); + let cfg = &mut gcc::Config::new(); + + if target.contains("msvc") { + // Don't pull in extra libraries on MSVC + cfg.flag("/Zl"); + } else { + // Turn off various features of gcc and such, mostly copying + // compiler-rt's build system already + cfg.flag("-fno-builtin"); + cfg.flag("-fvisibility=hidden"); + cfg.flag("-fomit-frame-pointer"); + cfg.flag("-ffreestanding"); + cfg.define("VISIBILITY_HIDDEN", None); + } + + let profile_sources = &["GCDAProfiling.c", + "InstrProfiling.c", + "InstrProfilingBuffer.c", + "InstrProfilingFile.c", + "InstrProfilingMerge.c", + "InstrProfilingMergeFile.c", + "InstrProfilingPlatformDarwin.c", + "InstrProfilingPlatformLinux.c", + "InstrProfilingPlatformOther.c", + "InstrProfilingRuntime.cc", + "InstrProfilingUtil.c", + "InstrProfilingValue.c", + "InstrProfilingWriter.c"]; + + for src in profile_sources { + cfg.file(Path::new("../compiler-rt/lib/profile").join(src)); + } + + cfg.compile("libprofiler-rt.a"); +} diff --git a/src/libprofiler_builtins/lib.rs b/src/libprofiler_builtins/lib.rs new file mode 100644 index 000000000000..087cc444185b --- /dev/null +++ b/src/libprofiler_builtins/lib.rs @@ -0,0 +1,20 @@ +// 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. + +#![no_std] +#![cfg_attr(not(stage0), feature(profiler_runtime))] +#![cfg_attr(not(stage0), profiler_runtime)] +#![unstable(feature = "profiler_runtime_lib", + reason = "internal implementation detail of rustc right now", + issue = "0")] +#![crate_name = "profiler_builtins"] +#![crate_type = "rlib"] +#![allow(unused_features)] +#![feature(staged_api)] diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 0b43e65ddbf8..23d670b0f8a8 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -220,6 +220,7 @@ pub trait CrateStore { fn is_panic_runtime(&self, cnum: CrateNum) -> bool; fn is_compiler_builtins(&self, cnum: CrateNum) -> bool; fn is_sanitizer_runtime(&self, cnum: CrateNum) -> bool; + fn is_profiler_runtime(&self, cnum: CrateNum) -> bool; fn panic_strategy(&self, cnum: CrateNum) -> PanicStrategy; fn extern_crate(&self, cnum: CrateNum) -> Option; /// The name of the crate as it is referred to in source code of the current @@ -356,6 +357,7 @@ impl CrateStore for DummyCrateStore { fn is_allocator(&self, cnum: CrateNum) -> bool { bug!("is_allocator") } fn is_panic_runtime(&self, cnum: CrateNum) -> bool { bug!("is_panic_runtime") } fn is_compiler_builtins(&self, cnum: CrateNum) -> bool { bug!("is_compiler_builtins") } + fn is_profiler_runtime(&self, cnum: CrateNum) -> bool { bug!("is_profiler_runtime") } fn is_sanitizer_runtime(&self, cnum: CrateNum) -> bool { bug!("is_sanitizer_runtime") } fn panic_strategy(&self, cnum: CrateNum) -> PanicStrategy { bug!("panic_strategy") diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 0bb4cd69e0cd..bf46a7bef2f9 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1025,6 +1025,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "add a source pattern to the file path remapping config"), remap_path_prefix_to: Vec = (vec![], parse_string_push, [TRACKED], "add a mapping target to the file path remapping config"), + profile: bool = (false, parse_bool, [TRACKED], + "insert profiling code"), } pub fn default_lib_output() -> CrateType { diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index dab2a0758a21..900eb127711b 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -203,7 +203,8 @@ pub fn compile_input(sess: &Session, println!("Pre-trans"); tcx.print_debug_stats(); } - let trans = phase_4_translate_to_llvm(tcx, analysis, &incremental_hashes_map); + let trans = phase_4_translate_to_llvm(tcx, analysis, &incremental_hashes_map, + &outputs); if log_enabled!(::log::LogLevel::Info) { println!("Post-trans"); @@ -1029,7 +1030,8 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, /// be discarded. pub fn phase_4_translate_to_llvm<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, analysis: ty::CrateAnalysis, - incremental_hashes_map: &IncrementalHashesMap) + incremental_hashes_map: &IncrementalHashesMap, + output_filenames: &OutputFilenames) -> trans::CrateTranslation { let time_passes = tcx.sess.time_passes(); @@ -1077,7 +1079,7 @@ pub fn phase_4_translate_to_llvm<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let translation = time(time_passes, "translation", - move || trans::trans_crate(tcx, analysis, &incremental_hashes_map)); + move || trans::trans_crate(tcx, analysis, &incremental_hashes_map, output_filenames)); time(time_passes, "assert dep graph", diff --git a/src/librustc_llvm/ffi.rs b/src/librustc_llvm/ffi.rs index 402166cc13fd..a70e6e3cf13f 100644 --- a/src/librustc_llvm/ffi.rs +++ b/src/librustc_llvm/ffi.rs @@ -587,7 +587,9 @@ extern "C" { pub fn LLVMIsUndef(Val: ValueRef) -> Bool; // Operations on metadata + pub fn LLVMMDStringInContext(C: ContextRef, Str: *const c_char, SLen: c_uint) -> ValueRef; pub fn LLVMMDNodeInContext(C: ContextRef, Vals: *const ValueRef, Count: c_uint) -> ValueRef; + pub fn LLVMAddNamedMetadataOperand(M: ModuleRef, Name: *const c_char, Val: ValueRef); // Operations on scalar constants pub fn LLVMConstInt(IntTy: TypeRef, N: c_ulonglong, SignExtend: Bool) -> ValueRef; @@ -1328,6 +1330,8 @@ extern "C" { pub fn LLVMRustAddModuleFlag(M: ModuleRef, name: *const c_char, value: u32); + pub fn LLVMRustMetadataAsValue(C: ContextRef, MD: MetadataRef) -> ValueRef; + pub fn LLVMRustDIBuilderCreate(M: ModuleRef) -> DIBuilderRef; pub fn LLVMRustDIBuilderDispose(Builder: DIBuilderRef); diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 966e814e3379..b4aad1abcd1d 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -870,6 +870,33 @@ impl<'a> CrateLoader<'a> { } } + fn inject_profiler_runtime(&mut self) { + if self.sess.opts.debugging_opts.profile { + let mut uses_std = false; + self.cstore.iter_crate_data(|_, data| { + if data.name == "std" { + uses_std = true; + } + }); + + if uses_std { + info!("loading profiler"); + + let symbol = Symbol::intern("profiler_builtins"); + let dep_kind = DepKind::Implicit; + let (_, data) = + self.resolve_crate(&None, symbol, symbol, None, DUMMY_SP, + PathKind::Crate, dep_kind); + + // Sanity check the loaded crate to ensure it is indeed a profiler runtime + if !data.is_profiler_runtime() { + self.sess.err(&format!("the crate `profiler_builtins` is not \ + a profiler runtime")); + } + } + } + } + fn inject_allocator_crate(&mut self) { // Make sure that we actually need an allocator, if none of our // dependencies need one then we definitely don't! @@ -1071,6 +1098,7 @@ impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> { // inject the sanitizer runtime before the allocator runtime because all // sanitizers force the use of the `alloc_system` allocator self.inject_sanitizer_runtime(); + self.inject_profiler_runtime(); self.inject_allocator_crate(); self.inject_panic_runtime(krate); diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs index 72ad1d75a561..577400d95bee 100644 --- a/src/librustc_metadata/cstore.rs +++ b/src/librustc_metadata/cstore.rs @@ -308,6 +308,11 @@ impl CrateMetadata { attr::contains_name(&attrs, "sanitizer_runtime") } + pub fn is_profiler_runtime(&self) -> bool { + let attrs = self.get_item_attrs(CRATE_DEF_INDEX); + attr::contains_name(&attrs, "profiler_runtime") + } + pub fn is_no_builtins(&self) -> bool { let attrs = self.get_item_attrs(CRATE_DEF_INDEX); attr::contains_name(&attrs, "no_builtins") diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 36b993aad69b..d11dbe3e8b85 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -275,6 +275,10 @@ impl CrateStore for cstore::CStore { self.get_crate_data(cnum).is_sanitizer_runtime() } + fn is_profiler_runtime(&self, cnum: CrateNum) -> bool { + self.get_crate_data(cnum).is_profiler_runtime() + } + fn panic_strategy(&self, cnum: CrateNum) -> PanicStrategy { self.get_crate_data(cnum).panic_strategy() } diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index e42e69d2a76e..7c53ea92581c 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -1074,6 +1074,9 @@ fn add_upstream_rust_crates(cmd: &mut Linker, // symbols from the dylib. let src = sess.cstore.used_crate_source(cnum); match data[cnum.as_usize() - 1] { + _ if sess.cstore.is_profiler_runtime(cnum) => { + add_static_crate(cmd, sess, tmpdir, crate_type, cnum); + } _ if sess.cstore.is_sanitizer_runtime(cnum) => { link_sanitizer_runtime(cmd, sess, tmpdir, cnum); } diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index ccb3f7ac882a..26f7488b18ea 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -699,6 +699,10 @@ pub fn run_passes(sess: &Session, } } + if sess.opts.debugging_opts.profile { + modules_config.passes.push("insert-gcov-profiling".to_owned()) + } + modules_config.opt_level = Some(get_llvm_opt_level(sess.opts.optimize)); modules_config.opt_size = Some(get_llvm_opt_size(sess.opts.optimize)); diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 56ff5ebb069e..34f1db0e42fc 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -42,7 +42,7 @@ use rustc::dep_graph::AssertDepGraphSafe; use rustc::middle::cstore::LinkMeta; use rustc::hir::map as hir_map; use rustc::util::common::time; -use session::config::{self, NoDebugInfo}; +use session::config::{self, NoDebugInfo, OutputFilenames}; use rustc_incremental::IncrementalHashesMap; use session::{self, DataTypeKind, Session}; use abi; @@ -1053,7 +1053,8 @@ pub fn find_exported_symbols(tcx: TyCtxt, reachable: &NodeSet) -> NodeSet { pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, analysis: ty::CrateAnalysis, - incremental_hashes_map: &IncrementalHashesMap) + incremental_hashes_map: &IncrementalHashesMap, + output_filenames: &OutputFilenames) -> CrateTranslation { // Be careful with this krate: obviously it gives access to the // entire contents of the krate. So if you push any subtasks of @@ -1070,7 +1071,8 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let shared_ccx = SharedCrateContext::new(tcx, exported_symbols, - check_overflow); + check_overflow, + output_filenames); // Translate the metadata. let (metadata_llcx, metadata_llmod, metadata) = time(tcx.sess.time_passes(), "write metadata", || { diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs index 90cda2f5cad3..dfc961555518 100644 --- a/src/librustc_trans/context.rs +++ b/src/librustc_trans/context.rs @@ -27,6 +27,7 @@ use rustc::ty::subst::Substs; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::layout::{LayoutTyper, TyLayout}; use session::config::NoDebugInfo; +use session::config::OutputFilenames; use session::Session; use session::config; use util::nodemap::{NodeSet, DefIdMap, FxHashMap}; @@ -83,6 +84,8 @@ pub struct SharedCrateContext<'a, 'tcx: 'a> { check_overflow: bool, use_dll_storage_attrs: bool, + + output_filenames: &'a OutputFilenames, } /// The local portion of a `CrateContext`. There is one `LocalCrateContext` @@ -266,7 +269,8 @@ pub unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (Cont impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> { pub fn new(tcx: TyCtxt<'b, 'tcx, 'tcx>, exported_symbols: NodeSet, - check_overflow: bool) + check_overflow: bool, + output_filenames: &'b OutputFilenames) -> SharedCrateContext<'b, 'tcx> { // An interesting part of Windows which MSVC forces our hand on (and // apparently MinGW didn't) is the usage of `dllimport` and `dllexport` @@ -319,6 +323,7 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> { tcx: tcx, check_overflow: check_overflow, use_dll_storage_attrs: use_dll_storage_attrs, + output_filenames: output_filenames, } } @@ -353,6 +358,10 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> { pub fn use_dll_storage_attrs(&self) -> bool { self.use_dll_storage_attrs } + + pub fn output_filenames(&self) -> &OutputFilenames { + self.output_filenames + } } impl<'a, 'tcx> LocalCrateContext<'a, 'tcx> { diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs index 188f8ee33663..310c07662b3e 100644 --- a/src/librustc_trans/debuginfo/metadata.rs +++ b/src/librustc_trans/debuginfo/metadata.rs @@ -39,10 +39,12 @@ use rustc::ty::{self, AdtKind, Ty}; use rustc::ty::layout::{self, LayoutTyper}; use session::config; use util::nodemap::FxHashMap; +use rustc::util::common::path2cstr; use libc::{c_uint, c_longlong}; use std::ffi::CString; use std::ptr; +use std::path::Path; use syntax::ast; use syntax::symbol::{Interner, InternedString, Symbol}; use syntax_pos::{self, Span}; @@ -788,7 +790,7 @@ pub fn compile_unit_metadata(scc: &SharedCrateContext, let file_metadata = llvm::LLVMRustDIBuilderCreateFile( debug_context.builder, compile_unit_name, work_dir.as_ptr()); - return llvm::LLVMRustDIBuilderCreateCompileUnit( + let unit_metadata = llvm::LLVMRustDIBuilderCreateCompileUnit( debug_context.builder, DW_LANG_RUST, file_metadata, @@ -796,12 +798,46 @@ pub fn compile_unit_metadata(scc: &SharedCrateContext, sess.opts.optimize != config::OptLevel::No, flags.as_ptr() as *const _, 0, - split_name.as_ptr() as *const _) + split_name.as_ptr() as *const _); + + let cu_desc_metadata = llvm::LLVMRustMetadataAsValue(debug_context.llcontext, + unit_metadata); + + let gcov_cu_info = [ + // Ideally we would be using the three-element form of !llvm.gcov metadata, + // which allows us to specify gcno/gcda files explicitly, but that's only + // available in LLVM 3.9+; so we rely on LLVM chopping off the extension + // and replacing it with gcno/gcda, instead. + path_to_mdstring(debug_context.llcontext, + &scc.output_filenames().with_extension("gcno")), + // path_to_mdstring(debug_context.llcontext, + // &scc.output_filenames().with_extension("gcda")), + cu_desc_metadata, + ]; + let gcov_metadata = llvm::LLVMMDNodeInContext(debug_context.llcontext, + gcov_cu_info.as_ptr(), + gcov_cu_info.len() as c_uint); + + let llvm_gcov_ident = CString::new("llvm.gcov").unwrap(); + llvm::LLVMAddNamedMetadataOperand(debug_context.llmod, + llvm_gcov_ident.as_ptr(), + gcov_metadata); + + return unit_metadata; }; fn fallback_path(scc: &SharedCrateContext) -> CString { CString::new(scc.tcx().crate_name(LOCAL_CRATE).to_string()).unwrap() } + + fn path_to_mdstring(llcx: llvm::ContextRef, path: &Path) -> llvm::ValueRef { + let path_str = path2cstr(path); + unsafe { + llvm::LLVMMDStringInContext(llcx, + path_str.as_ptr(), + path_str.as_bytes().len() as c_uint) + } + } } struct MetadataCreationResult { diff --git a/src/librustc_trans/debuginfo/mod.rs b/src/librustc_trans/debuginfo/mod.rs index ebe42a2b9082..b78cb4071e5a 100644 --- a/src/librustc_trans/debuginfo/mod.rs +++ b/src/librustc_trans/debuginfo/mod.rs @@ -67,6 +67,7 @@ const DW_TAG_arg_variable: c_uint = 0x101; /// A context object for maintaining all state needed by the debuginfo module. pub struct CrateDebugContext<'tcx> { llcontext: ContextRef, + llmod: ModuleRef, builder: DIBuilderRef, created_files: RefCell>, created_enum_disr_types: RefCell>, @@ -87,6 +88,7 @@ impl<'tcx> CrateDebugContext<'tcx> { let llcontext = unsafe { llvm::LLVMGetModuleContext(llmod) }; CrateDebugContext { llcontext: llcontext, + llmod: llmod, builder: builder, created_files: RefCell::new(FxHashMap()), created_enum_disr_types: RefCell::new(FxHashMap()), diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index 717892be2aba..f268214e5d16 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -20,6 +20,7 @@ core = { path = "../libcore" } libc = { path = "../rustc/libc_shim" } rand = { path = "../librand" } compiler_builtins = { path = "../libcompiler_builtins" } +profiler_builtins = { path = "../libprofiler_builtins", optional = true } std_unicode = { path = "../libstd_unicode" } unwind = { path = "../libunwind" } @@ -43,3 +44,4 @@ debug-jemalloc = ["alloc_jemalloc/debug"] jemalloc = ["alloc_jemalloc"] force_alloc_system = [] panic-unwind = ["panic_unwind"] +profiler = ["profiler_builtins"] diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index b6a2c983fd4d..9101cf7e98bf 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -331,6 +331,10 @@ declare_features! ( // rustc internal (active, sanitizer_runtime, "1.17.0", None), + // Used to identify crates that contain the profiler runtime + // rustc internal + (active, profiler_runtime, "1.18.0", None), + // `extern "x86-interrupt" fn()` (active, abi_x86_interrupt, "1.17.0", Some(40180)), @@ -693,6 +697,13 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG identify crates that contain the runtime of a \ sanitizer and will never be stable", cfg_fn!(sanitizer_runtime))), + ("profiler_runtime", Whitelisted, Gated(Stability::Unstable, + "profiler_runtime", + "the `#[profiler_runtime]` attribute is used to \ + identify the `profiler_builtins` crate which \ + contains the profiler runtime and will never be \ + stable", + cfg_fn!(profiler_runtime))), ("allow_internal_unstable", Normal, Gated(Stability::Unstable, "allow_internal_unstable", diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index c24867224ea8..0a485632bb3d 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -466,6 +466,10 @@ extern "C" void LLVMRustAddModuleFlag(LLVMModuleRef M, const char *Name, unwrap(M)->addModuleFlag(Module::Warning, Name, Value); } +extern "C" void LLVMRustMetadataAsValue(LLVMContextRef C, LLVMRustMetadataRef MD) { + wrap(MetadataAsValue::get(*unwrap(C), unwrap(MD))); +} + extern "C" LLVMRustDIBuilderRef LLVMRustDIBuilderCreate(LLVMModuleRef M) { return new DIBuilder(*unwrap(M)); } diff --git a/src/test/compile-fail/feature-gate-profiler-runtime.rs b/src/test/compile-fail/feature-gate-profiler-runtime.rs new file mode 100644 index 000000000000..c6b2cb2eb077 --- /dev/null +++ b/src/test/compile-fail/feature-gate-profiler-runtime.rs @@ -0,0 +1,13 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![profiler_runtime] //~ ERROR the `#[profiler_runtime]` attribute is + +fn main() {} diff --git a/src/test/run-make/profile/Makefile b/src/test/run-make/profile/Makefile new file mode 100644 index 000000000000..94a2a30869b5 --- /dev/null +++ b/src/test/run-make/profile/Makefile @@ -0,0 +1,7 @@ +-include ../tools.mk + +all: + $(RUSTC) -g -Z profile test.rs + $(call RUN,test) || exit 1 + [ -e "$(TMPDIR)/test.gcno" ] || (echo "No .gcno file"; exit 1) + [ -e "$(TMPDIR)/test.gcda" ] || (echo "No .gcda file"; exit 1) diff --git a/src/test/run-make/profile/test.rs b/src/test/run-make/profile/test.rs new file mode 100644 index 000000000000..046d27a9f0fe --- /dev/null +++ b/src/test/run-make/profile/test.rs @@ -0,0 +1,11 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() {} From 165f3668d602c4eaa02125cf86fb8d12719cb441 Mon Sep 17 00:00:00 2001 From: Djzin Date: Sun, 7 May 2017 20:26:19 +0100 Subject: [PATCH 015/233] optimize out stack alignment for sizes < 32 --- src/libcore/mem.rs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index e51976c4845e..2dc1f0e04bcc 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -453,15 +453,13 @@ pub fn swap(x: &mut T, y: &mut T) { // #[repr(simd)], even if we don't actually use this struct directly. #[repr(simd)] struct Block(u64, u64, u64, u64); + struct UnalignedBlock(u64, u64, u64, u64); + let block_size = size_of::(); - // Create some uninitialized memory as scratch space - let mut t: Block = uninitialized(); - - // Get raw pointers to the bytes of x, y & t for easier manipulation + // Get raw pointers to the bytes of x & y for easier manipulation let x = x as *mut T as *mut u8; let y = y as *mut T as *mut u8; - let t = &mut t as *mut _ as *mut u8; // Loop through x & y, copying them `Block` at a time // The optimizer should unroll the loop fully for most types @@ -469,6 +467,12 @@ pub fn swap(x: &mut T, y: &mut T) { let len = size_of::() as isize; let mut i = 0; while i + block_size as isize <= len { + // Create some uninitialized memory as scratch space + // Moving the declaration of `t` here avoids aligning the stack when + // this loop is unused + let mut t: Block = uninitialized(); + let t = &mut t as *mut _ as *mut u8; + // Swap a block of bytes of x & y, using t as a temporary buffer // This should be optimized into efficient SIMD operations where available ptr::copy_nonoverlapping(x.offset(i), t, block_size); @@ -478,6 +482,9 @@ pub fn swap(x: &mut T, y: &mut T) { } if i < len { // Swap any remaining bytes + let mut t: UnalignedBlock = uninitialized(); + let t = &mut t as *mut _ as *mut u8; + let rem = (len - i) as usize; ptr::copy_nonoverlapping(x.offset(i), t, rem); ptr::copy_nonoverlapping(y.offset(i), x.offset(i), rem); From ca2fa97b6ca858a1c7748d117f5ed096b185380a Mon Sep 17 00:00:00 2001 From: Djzin Date: Sun, 7 May 2017 20:29:39 +0100 Subject: [PATCH 016/233] improve wording --- src/libcore/mem.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 2dc1f0e04bcc..5fb30a9abfec 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -468,8 +468,7 @@ pub fn swap(x: &mut T, y: &mut T) { let mut i = 0; while i + block_size as isize <= len { // Create some uninitialized memory as scratch space - // Moving the declaration of `t` here avoids aligning the stack when - // this loop is unused + // Decaring `t` here avoids aligning the stack when this loop is unused let mut t: Block = uninitialized(); let t = &mut t as *mut _ as *mut u8; From fcc970aca5d3e169c6a837c34f62b3e6e0ed74d1 Mon Sep 17 00:00:00 2001 From: Djzin Date: Sun, 7 May 2017 21:56:14 +0100 Subject: [PATCH 017/233] fix nit --- src/libcore/mem.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 5fb30a9abfec..87206152a0d2 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -468,7 +468,7 @@ pub fn swap(x: &mut T, y: &mut T) { let mut i = 0; while i + block_size as isize <= len { // Create some uninitialized memory as scratch space - // Decaring `t` here avoids aligning the stack when this loop is unused + // Declaring `t` here avoids aligning the stack when this loop is unused let mut t: Block = uninitialized(); let t = &mut t as *mut _ as *mut u8; From 93219a262706447c52f3f20819e5caa7b2e2e3a2 Mon Sep 17 00:00:00 2001 From: Irfan Hudda Date: Tue, 23 May 2017 23:04:23 +0530 Subject: [PATCH 018/233] Add comments to explain helper functions --- src/libcore/num/mod.rs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index cc1f9ca79a15..8fd21d77dc31 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -2327,12 +2327,22 @@ macro_rules! uint_impl { (self.wrapping_sub(1)) & self == 0 && !(self == 0) } + // Returns one less than next greater power of two. + // (For 8u8 next greater power of two is 16u8 and for 6u8 it is 8u8) + // + // 8u8.round_up_to_one_less_than_a_power_of_two() == 15 + // 6u8.round_up_to_one_less_than_a_power_of_two() == 7 fn round_up_to_one_less_than_a_power_of_two(self) -> Self { let bits = size_of::() as u32 * 8; let z = self.leading_zeros(); (if z == bits { 0 as Self } else { !0 }).wrapping_shr(z) } + // Returns one less than next power of two. + // (For 8u8 next power of two is 8u8 and for 6u8 it is 8u8) + // + // 8u8.one_less_than_next_power_of_two() == 7 + // 6u8.one_less_than_next_power_of_two() == 7 fn one_less_than_next_power_of_two(self) -> Self { self.wrapping_sub(1) .round_up_to_one_less_than_a_power_of_two() @@ -2340,10 +2350,10 @@ macro_rules! uint_impl { } /// Returns the smallest power of two greater than or equal to `self`. - /// When return value overflows, it panics in debug mode and return - /// value is wrapped in release mode. /// - /// More details about overflow behavior can be found in [RFC 560]. + /// When return value overflows (i.e. `self > (1 << (N-1))` for type + /// `uN`), it panics in debug mode and return value is wrapped to 0 in + /// release mode (the only situation in which method can return 0). /// /// # Examples /// @@ -2353,8 +2363,6 @@ macro_rules! uint_impl { /// assert_eq!(2u8.next_power_of_two(), 2); /// assert_eq!(3u8.next_power_of_two(), 4); /// ``` - /// - /// [RFC 560]: https://github.com/rust-lang/rfcs/blob/master/text/0560-integer-overflow.md #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn next_power_of_two(self) -> Self { From c6307a2fa55c3d62c06b85b349257a8194093442 Mon Sep 17 00:00:00 2001 From: Djzin Date: Sat, 27 May 2017 14:29:41 +0100 Subject: [PATCH 019/233] copy tail bytes better for aligned types --- src/libcore/mem.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 87206152a0d2..2975d2e28dd3 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -479,6 +479,27 @@ pub fn swap(x: &mut T, y: &mut T) { ptr::copy_nonoverlapping(t, y.offset(i), block_size); i += block_size as isize; } + + // Swap remaining bytes 8 at a time if x & y are properly aligned + if align_of::() % 8 == 0 { + while i + 8 <= len as isize { + let t = *(x.offset(i) as *mut u64); + *(x.offset(i) as *mut u64) = *(y.offset(i) as *mut u64); + *(y.offset(i) as *mut u64) = t; + i += 8; + } + } + + // Swap remaining bytes 4 at a time if x & y are properly aligned + if align_of::() % 4 == 0 { + while i + 4 <= len as isize { + let t = *(x.offset(i) as *mut u32); + *(x.offset(i) as *mut u32) = *(y.offset(i) as *mut u32); + *(y.offset(i) as *mut u32) = t; + i += 4; + } + } + if i < len { // Swap any remaining bytes let mut t: UnalignedBlock = uninitialized(); From d4d3f53468cb392cb9b80278a232857ad8d68992 Mon Sep 17 00:00:00 2001 From: Djzin Date: Sat, 27 May 2017 16:39:51 +0100 Subject: [PATCH 020/233] better respect alignment for copying tail --- src/libcore/mem.rs | 62 +++++++++++++++++++++++++++------------------- 1 file changed, 37 insertions(+), 25 deletions(-) diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 64034b05fde9..a2154e7fc69e 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -532,35 +532,47 @@ pub fn swap(x: &mut T, y: &mut T) { i += block_size as isize; } - // Swap remaining bytes 8 at a time if x & y are properly aligned - if align_of::() % 8 == 0 { - while i + 8 <= len as isize { - let t = *(x.offset(i) as *mut u64); - *(x.offset(i) as *mut u64) = *(y.offset(i) as *mut u64); - *(y.offset(i) as *mut u64) = t; - i += 8; - } - } - - // Swap remaining bytes 4 at a time if x & y are properly aligned - if align_of::() % 4 == 0 { - while i + 4 <= len as isize { - let t = *(x.offset(i) as *mut u32); - *(x.offset(i) as *mut u32) = *(y.offset(i) as *mut u32); - *(y.offset(i) as *mut u32) = t; - i += 4; - } - } if i < len { - // Swap any remaining bytes + // Swap any remaining bytes, using aligned types to copy + // where appropriate (this information is lost by conversion + // to *mut u8, so restore it manually here) let mut t: UnalignedBlock = uninitialized(); - let t = &mut t as *mut _ as *mut u8; - let rem = (len - i) as usize; - ptr::copy_nonoverlapping(x.offset(i), t, rem); - ptr::copy_nonoverlapping(y.offset(i), x.offset(i), rem); - ptr::copy_nonoverlapping(t, y.offset(i), rem); + + if align_of::() % 8 == 0 && len % 8 == 0 { + let t = &mut t as *mut _ as *mut u64; + let x = x.offset(i) as *mut u64; + let y = y.offset(i) as *mut u64; + + ptr::copy_nonoverlapping(x, t, rem / 8); + ptr::copy_nonoverlapping(y, x, rem / 8); + ptr::copy_nonoverlapping(t, y, rem / 8); + } else if align_of::() % 4 == 0 && len % 4 == 0 { + let t = &mut t as *mut _ as *mut u32; + let x = x.offset(i) as *mut u32; + let y = y.offset(i) as *mut u32; + + ptr::copy_nonoverlapping(x, t, rem / 4); + ptr::copy_nonoverlapping(y, x, rem / 4); + ptr::copy_nonoverlapping(t, y, rem / 4); + } else if align_of::() % 2 == 0 && len % 2 == 0 { + let t = &mut t as *mut _ as *mut u16; + let x = x.offset(i) as *mut u16; + let y = y.offset(i) as *mut u16; + + ptr::copy_nonoverlapping(x, t, rem / 2); + ptr::copy_nonoverlapping(y, x, rem / 2); + ptr::copy_nonoverlapping(t, y, rem / 2); + } else { + let t = &mut t as *mut _ as *mut u8; + let x = x.offset(i); + let y = y.offset(i); + + ptr::copy_nonoverlapping(x, t, rem); + ptr::copy_nonoverlapping(y, x, rem); + ptr::copy_nonoverlapping(t, y, rem); + } } } } From ac33d2cbfbe103cb9dda7cc31eda85fcd8ca039d Mon Sep 17 00:00:00 2001 From: gentoo90 Date: Sun, 28 May 2017 12:08:40 +0300 Subject: [PATCH 021/233] Fix GDB pretty-printer for tuples Names of children should not be the same, because GDB uses them to distinguish the children. --- src/etc/gdb_rust_pretty_printing.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/etc/gdb_rust_pretty_printing.py b/src/etc/gdb_rust_pretty_printing.py index afac8d6bbaef..e617435f54f4 100755 --- a/src/etc/gdb_rust_pretty_printing.py +++ b/src/etc/gdb_rust_pretty_printing.py @@ -186,10 +186,10 @@ class RustStructPrinter(object): cs = [] wrapped_value = self.__val.get_wrapped_value() - for field in self.__val.type.get_fields(): + for number, field in enumerate(self.__val.type.get_fields()): field_value = wrapped_value[field.name] if self.__is_tuple_like: - cs.append(("", field_value)) + cs.append((str(number), field_value)) else: cs.append((field.name, field_value)) From 8a973dfa24b676e6e50b6c6bbb1cdce17499a2f7 Mon Sep 17 00:00:00 2001 From: Djzin Date: Sun, 28 May 2017 15:39:47 +0100 Subject: [PATCH 022/233] restore old behaviour for sizes < 128 --- src/libcore/mem.rs | 71 +++++++++++++++++++++------------------------- 1 file changed, 32 insertions(+), 39 deletions(-) diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index a2154e7fc69e..93ec54b17390 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -499,6 +499,24 @@ pub unsafe fn uninitialized() -> T { #[stable(feature = "rust1", since = "1.0.0")] pub fn swap(x: &mut T, y: &mut T) { unsafe { + let len = size_of::(); + + if len < 128 { + // Give ourselves some scratch space to work with + let mut t: T = uninitialized(); + + // Perform the swap, `&mut` pointers never alias + ptr::copy_nonoverlapping(&*x, &mut t, 1); + ptr::copy_nonoverlapping(&*y, x, 1); + ptr::copy_nonoverlapping(&t, y, 1); + + // y and t now point to the same thing, but we need to completely + // forget `t` because we do not want to run the destructor for `T` + // on its value, which is still owned somewhere outside this function. + forget(t); + return; + } + // The approach here is to utilize simd to swap x & y efficiently. Testing reveals // that swapping either 32 bytes or 64 bytes at a time is most efficient for intel // Haswell E processors. LLVM is more able to optimize if we give a struct a @@ -516,20 +534,21 @@ pub fn swap(x: &mut T, y: &mut T) { // Loop through x & y, copying them `Block` at a time // The optimizer should unroll the loop fully for most types // N.B. We can't use a for loop as the `range` impl calls `mem::swap` recursively - let len = size_of::() as isize; let mut i = 0; - while i + block_size as isize <= len { + while i + block_size <= len { // Create some uninitialized memory as scratch space // Declaring `t` here avoids aligning the stack when this loop is unused let mut t: Block = uninitialized(); let t = &mut t as *mut _ as *mut u8; + let x = x.offset(i as isize); + let y = y.offset(i as isize); // Swap a block of bytes of x & y, using t as a temporary buffer // This should be optimized into efficient SIMD operations where available - ptr::copy_nonoverlapping(x.offset(i), t, block_size); - ptr::copy_nonoverlapping(y.offset(i), x.offset(i), block_size); - ptr::copy_nonoverlapping(t, y.offset(i), block_size); - i += block_size as isize; + ptr::copy_nonoverlapping(x, t, block_size); + ptr::copy_nonoverlapping(y, x, block_size); + ptr::copy_nonoverlapping(t, y, block_size); + i += block_size; } @@ -538,41 +557,15 @@ pub fn swap(x: &mut T, y: &mut T) { // where appropriate (this information is lost by conversion // to *mut u8, so restore it manually here) let mut t: UnalignedBlock = uninitialized(); - let rem = (len - i) as usize; + let rem = len - i; - if align_of::() % 8 == 0 && len % 8 == 0 { - let t = &mut t as *mut _ as *mut u64; - let x = x.offset(i) as *mut u64; - let y = y.offset(i) as *mut u64; + let t = &mut t as *mut _ as *mut u8; + let x = x.offset(i as isize); + let y = y.offset(i as isize); - ptr::copy_nonoverlapping(x, t, rem / 8); - ptr::copy_nonoverlapping(y, x, rem / 8); - ptr::copy_nonoverlapping(t, y, rem / 8); - } else if align_of::() % 4 == 0 && len % 4 == 0 { - let t = &mut t as *mut _ as *mut u32; - let x = x.offset(i) as *mut u32; - let y = y.offset(i) as *mut u32; - - ptr::copy_nonoverlapping(x, t, rem / 4); - ptr::copy_nonoverlapping(y, x, rem / 4); - ptr::copy_nonoverlapping(t, y, rem / 4); - } else if align_of::() % 2 == 0 && len % 2 == 0 { - let t = &mut t as *mut _ as *mut u16; - let x = x.offset(i) as *mut u16; - let y = y.offset(i) as *mut u16; - - ptr::copy_nonoverlapping(x, t, rem / 2); - ptr::copy_nonoverlapping(y, x, rem / 2); - ptr::copy_nonoverlapping(t, y, rem / 2); - } else { - let t = &mut t as *mut _ as *mut u8; - let x = x.offset(i); - let y = y.offset(i); - - ptr::copy_nonoverlapping(x, t, rem); - ptr::copy_nonoverlapping(y, x, rem); - ptr::copy_nonoverlapping(t, y, rem); - } + ptr::copy_nonoverlapping(x, t, rem); + ptr::copy_nonoverlapping(y, x, rem); + ptr::copy_nonoverlapping(t, y, rem); } } } From b795b7b43b5812a07b8fa7ed022b2f0f012a4950 Mon Sep 17 00:00:00 2001 From: Djzin Date: Sun, 28 May 2017 18:10:12 +0100 Subject: [PATCH 023/233] restore old behaviour --- src/libcore/mem.rs | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 93ec54b17390..91b348fb5d67 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -499,24 +499,6 @@ pub unsafe fn uninitialized() -> T { #[stable(feature = "rust1", since = "1.0.0")] pub fn swap(x: &mut T, y: &mut T) { unsafe { - let len = size_of::(); - - if len < 128 { - // Give ourselves some scratch space to work with - let mut t: T = uninitialized(); - - // Perform the swap, `&mut` pointers never alias - ptr::copy_nonoverlapping(&*x, &mut t, 1); - ptr::copy_nonoverlapping(&*y, x, 1); - ptr::copy_nonoverlapping(&t, y, 1); - - // y and t now point to the same thing, but we need to completely - // forget `t` because we do not want to run the destructor for `T` - // on its value, which is still owned somewhere outside this function. - forget(t); - return; - } - // The approach here is to utilize simd to swap x & y efficiently. Testing reveals // that swapping either 32 bytes or 64 bytes at a time is most efficient for intel // Haswell E processors. LLVM is more able to optimize if we give a struct a @@ -534,6 +516,7 @@ pub fn swap(x: &mut T, y: &mut T) { // Loop through x & y, copying them `Block` at a time // The optimizer should unroll the loop fully for most types // N.B. We can't use a for loop as the `range` impl calls `mem::swap` recursively + let len = size_of::(); let mut i = 0; while i + block_size <= len { // Create some uninitialized memory as scratch space From 167e4b09d1688a0b4ac9b260a84bacdc926e0230 Mon Sep 17 00:00:00 2001 From: gentoo90 Date: Tue, 30 May 2017 11:14:25 +0300 Subject: [PATCH 024/233] Fix 'invalid literal for int()' exception in pretty-printers Some pointers values include additional info, so they can't be parsed with int(). --- src/etc/gdb_rust_pretty_printing.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/etc/gdb_rust_pretty_printing.py b/src/etc/gdb_rust_pretty_printing.py index e617435f54f4..2ad16b50d3f8 100755 --- a/src/etc/gdb_rust_pretty_printing.py +++ b/src/etc/gdb_rust_pretty_printing.py @@ -78,7 +78,8 @@ class GdbValue(rustpp.Value): def as_integer(self): if self.gdb_val.type.code == gdb.TYPE_CODE_PTR: - return int(str(self.gdb_val), 0) + as_str = str(self.gdb_val).split()[0] + return int(as_str, 0) return int(self.gdb_val) def get_wrapped_value(self): From 10977bcf6cb278895313045b048851bef019272d Mon Sep 17 00:00:00 2001 From: gentoo90 Date: Tue, 30 May 2017 23:42:35 +0300 Subject: [PATCH 025/233] Fix 'invalid literal for int()' exception with unicode in pretty-printers str() can't handle unicode strings --- src/etc/gdb_rust_pretty_printing.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/etc/gdb_rust_pretty_printing.py b/src/etc/gdb_rust_pretty_printing.py index 2ad16b50d3f8..aa1d00eaaab6 100755 --- a/src/etc/gdb_rust_pretty_printing.py +++ b/src/etc/gdb_rust_pretty_printing.py @@ -78,7 +78,7 @@ class GdbValue(rustpp.Value): def as_integer(self): if self.gdb_val.type.code == gdb.TYPE_CODE_PTR: - as_str = str(self.gdb_val).split()[0] + as_str = unicode(self.gdb_val).split()[0] return int(as_str, 0) return int(self.gdb_val) From 18fadb61c4aab3d1b2fc49ac7d7fea85b3914fb3 Mon Sep 17 00:00:00 2001 From: Irfan Hudda Date: Wed, 31 May 2017 22:25:15 +0530 Subject: [PATCH 026/233] Simplify helper functions Based on @scottmcm 's suggestion --- src/libcore/num/mod.rs | 28 +++++++++++++--------------- src/libstd/num.rs | 5 ++++- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 8fd21d77dc31..e5a8cfdd9a1d 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -15,7 +15,6 @@ use convert::TryFrom; use fmt; use intrinsics; -use mem::size_of; use str::FromStr; /// Provides intentionally-wrapped arithmetic on `T`. @@ -2327,26 +2326,25 @@ macro_rules! uint_impl { (self.wrapping_sub(1)) & self == 0 && !(self == 0) } - // Returns one less than next greater power of two. - // (For 8u8 next greater power of two is 16u8 and for 6u8 it is 8u8) - // - // 8u8.round_up_to_one_less_than_a_power_of_two() == 15 - // 6u8.round_up_to_one_less_than_a_power_of_two() == 7 - fn round_up_to_one_less_than_a_power_of_two(self) -> Self { - let bits = size_of::() as u32 * 8; - let z = self.leading_zeros(); - (if z == bits { 0 as Self } else { !0 }).wrapping_shr(z) - } - // Returns one less than next power of two. // (For 8u8 next power of two is 8u8 and for 6u8 it is 8u8) // // 8u8.one_less_than_next_power_of_two() == 7 // 6u8.one_less_than_next_power_of_two() == 7 + // + // This method cannot overflow, as in the `next_power_of_two` + // overflow cases it instead ends up returning the maximum value + // of the type, and can return 0 for 0. fn one_less_than_next_power_of_two(self) -> Self { - self.wrapping_sub(1) - .round_up_to_one_less_than_a_power_of_two() - .wrapping_add(if self == 0 { 1 } else { 0 }) + if self <= 1 { return 0; } + + // Because `p > 0`, it cannot consist entirely of leading zeros. + // That means the shift is always in-bounds, and some processors + // (such as intel pre-haswell) have more efficient ctlz + // intrinsics when the argument is non-zero. + let p = self - 1; + let z = p.leading_zeros(); + <$SelfT>::max_value() >> z } /// Returns the smallest power of two greater than or equal to `self`. diff --git a/src/libstd/num.rs b/src/libstd/num.rs index 5f83d077a136..894a6e6796ca 100644 --- a/src/libstd/num.rs +++ b/src/libstd/num.rs @@ -176,7 +176,10 @@ mod tests { fn $test_name() { #![test] assert_eq!((0 as $T).checked_next_power_of_two(), Some(1)); - assert!(($T::MAX / 2).checked_next_power_of_two().is_some()); + let smax = $T::MAX >> 1; + assert_eq!(smax.checked_next_power_of_two(), Some(smax+1)); + assert_eq!((smax + 1).checked_next_power_of_two(), Some(smax + 1)); + assert_eq!((smax + 2).checked_next_power_of_two(), None); assert_eq!(($T::MAX - 1).checked_next_power_of_two(), None); assert_eq!($T::MAX.checked_next_power_of_two(), None); let mut next_power = 1; From c7ef85ca0eb09acad16d2f969e69737308290309 Mon Sep 17 00:00:00 2001 From: gentoo90 Date: Thu, 1 Jun 2017 21:26:09 +0300 Subject: [PATCH 027/233] Add test for 'invalid literal for int()' exception in gdb pretty-printers --- src/test/debuginfo/pretty-std.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/test/debuginfo/pretty-std.rs b/src/test/debuginfo/pretty-std.rs index 153f0c8271fc..a1a2cd67bb33 100644 --- a/src/test/debuginfo/pretty-std.rs +++ b/src/test/debuginfo/pretty-std.rs @@ -38,6 +38,9 @@ // gdbg-check:$6 = None // gdbr-check:$6 = core::option::Option::None +// gdb-command: print some_string +// gdbr-check:$7 = Some = {"IAMA optional string!"} + // === LLDB TESTS ================================================================================== @@ -82,6 +85,8 @@ fn main() { let some = Some(8i16); let none: Option = None; + let some_string = Some("IAMA optional string!".to_owned()); + zzz(); // #break } From c1f687b73fc76808d8f4555d6f77b7f64e554fa9 Mon Sep 17 00:00:00 2001 From: gentoo90 Date: Fri, 2 Jun 2017 16:18:00 +0300 Subject: [PATCH 028/233] Add GDB pretty-printer for OsString --- src/etc/debugger_pretty_printers_common.py | 9 +++++++++ src/etc/gdb_rust_pretty_printing.py | 18 ++++++++++++++++++ src/test/debuginfo/pretty-std.rs | 12 ++++++++++-- 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/etc/debugger_pretty_printers_common.py b/src/etc/debugger_pretty_printers_common.py index 5e3ff5246a92..7eb008a05f61 100644 --- a/src/etc/debugger_pretty_printers_common.py +++ b/src/etc/debugger_pretty_printers_common.py @@ -46,6 +46,7 @@ TYPE_KIND_CSTYLE_ENUM = 14 TYPE_KIND_PTR = 15 TYPE_KIND_FIXED_SIZE_VEC = 16 TYPE_KIND_REGULAR_UNION = 17 +TYPE_KIND_OS_STRING = 18 ENCODED_ENUM_PREFIX = "RUST$ENCODED$ENUM$" ENUM_DISR_FIELD_NAME = "RUST$ENUM$DISR" @@ -64,6 +65,9 @@ STD_VEC_FIELD_NAMES = [STD_VEC_FIELD_NAME_BUF, # std::String related constants STD_STRING_FIELD_NAMES = ["vec"] +# std::ffi::OsString related constants +OS_STRING_FIELD_NAMES = ["inner"] + class Type(object): """ @@ -162,6 +166,11 @@ class Type(object): self.__conforms_to_field_layout(STD_STRING_FIELD_NAMES)): return TYPE_KIND_STD_STRING + # OS STRING + if (unqualified_type_name == "OsString" and + self.__conforms_to_field_layout(OS_STRING_FIELD_NAMES)): + return TYPE_KIND_OS_STRING + # ENUM VARIANTS if fields[0].name == ENUM_DISR_FIELD_NAME: if field_count == 1: diff --git a/src/etc/gdb_rust_pretty_printing.py b/src/etc/gdb_rust_pretty_printing.py index aa1d00eaaab6..d2bc7dd53df7 100755 --- a/src/etc/gdb_rust_pretty_printing.py +++ b/src/etc/gdb_rust_pretty_printing.py @@ -125,6 +125,9 @@ def rust_pretty_printer_lookup_function(gdb_val): if type_kind == rustpp.TYPE_KIND_STD_STRING: return RustStdStringPrinter(val) + if type_kind == rustpp.TYPE_KIND_OS_STRING: + return RustOsStringPrinter(val) + if type_kind == rustpp.TYPE_KIND_TUPLE: return RustStructPrinter(val, omit_first_field = False, @@ -269,6 +272,21 @@ class RustStdStringPrinter(object): length=length) +class RustOsStringPrinter(object): + def __init__(self, val): + self.__val = val + + def to_string(self): + buf = self.__val.get_child_at_index(0) + vec = buf.get_child_at_index(0) + if vec.type.get_unqualified_type_name() == "Wtf8Buf": + vec = vec.get_child_at_index(0) + + (length, data_ptr, cap) = rustpp.extract_length_ptr_and_cap_from_std_vec( + vec) + return '"%s"' % data_ptr.get_wrapped_value().string(length=length) + + class RustCStyleVariantPrinter(object): def __init__(self, val): assert val.type.get_dwarf_type_kind() == rustpp.DWARF_TYPE_CODE_ENUM diff --git a/src/test/debuginfo/pretty-std.rs b/src/test/debuginfo/pretty-std.rs index a1a2cd67bb33..88a3c76b8581 100644 --- a/src/test/debuginfo/pretty-std.rs +++ b/src/test/debuginfo/pretty-std.rs @@ -38,8 +38,11 @@ // gdbg-check:$6 = None // gdbr-check:$6 = core::option::Option::None -// gdb-command: print some_string -// gdbr-check:$7 = Some = {"IAMA optional string!"} +// gdbr-command: print os_string +// gdbr-check:$7 = "IAMA OS string 😃" + +// gdbr-command: print some_string +// gdbr-check:$8 = Some = {"IAMA optional string!"} // === LLDB TESTS ================================================================================== @@ -66,6 +69,8 @@ #![allow(unused_variables)] +use std::ffi::OsString; + fn main() { @@ -81,6 +86,9 @@ fn main() { // String let string = "IAMA string!".to_string(); + // OsString + let os_string = OsString::from("IAMA OS string \u{1F603}"); + // Option let some = Some(8i16); let none: Option = None; From fdb2837bd90ea3a7209cfe56a8f99b37b4f6b373 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Fri, 2 Jun 2017 10:59:19 -0700 Subject: [PATCH 029/233] Vec is pronounced 'vec' --- src/libcollections/vec.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 3ef8438bc0bd..2de27725e956 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -9,7 +9,7 @@ // except according to those terms. //! A contiguous growable array type with heap-allocated contents, written -//! `Vec` but pronounced 'vector.' +//! `Vec`. //! //! Vectors have `O(1)` indexing, amortized `O(1)` push (to the end) and //! `O(1)` pop (from the end). From b9f9c7710320ed1973ece7973d5918a09767a7e7 Mon Sep 17 00:00:00 2001 From: gentoo90 Date: Fri, 2 Jun 2017 21:18:45 +0300 Subject: [PATCH 030/233] Add separate GDB pretty-printer for empty structs Use a class without children() method for printing empty structs. Presence of this method makes GDB's variable objects interface act like if the struct had children. --- src/etc/gdb_rust_pretty_printing.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/etc/gdb_rust_pretty_printing.py b/src/etc/gdb_rust_pretty_printing.py index d2bc7dd53df7..aab15d9ed1e3 100755 --- a/src/etc/gdb_rust_pretty_printing.py +++ b/src/etc/gdb_rust_pretty_printing.py @@ -100,8 +100,10 @@ def rust_pretty_printer_lookup_function(gdb_val): val = GdbValue(gdb_val) type_kind = val.type.get_type_kind() - if (type_kind == rustpp.TYPE_KIND_REGULAR_STRUCT or - type_kind == rustpp.TYPE_KIND_EMPTY): + if type_kind == rustpp.TYPE_KIND_EMPTY: + return RustEmptyPrinter(val) + + if type_kind == rustpp.TYPE_KIND_REGULAR_STRUCT: return RustStructPrinter(val, omit_first_field = False, omit_type_name = False, @@ -174,6 +176,14 @@ def rust_pretty_printer_lookup_function(gdb_val): #=------------------------------------------------------------------------------ # Pretty Printer Classes #=------------------------------------------------------------------------------ +class RustEmptyPrinter(object): + def __init__(self, val): + self.__val = val + + def to_string(self): + return self.__val.type.get_unqualified_type_name() + + class RustStructPrinter(object): def __init__(self, val, omit_first_field, omit_type_name, is_tuple_like): self.__val = val From 8d9df99fbbefd4e394c932309c1453b5a92d93b3 Mon Sep 17 00:00:00 2001 From: Ulysse Carion Date: Sat, 3 Jun 2017 21:30:13 -0700 Subject: [PATCH 031/233] Explicate what "Rc" and "Arc" stand for. --- src/liballoc/arc.rs | 3 ++- src/liballoc/rc.rs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs index 5faf4dcccaf9..81e97334e3c9 100644 --- a/src/liballoc/arc.rs +++ b/src/liballoc/arc.rs @@ -42,7 +42,8 @@ use heap::deallocate; /// necessarily) at _exactly_ `MAX_REFCOUNT + 1` references. const MAX_REFCOUNT: usize = (isize::MAX) as usize; -/// A thread-safe reference-counting pointer. +/// A thread-safe reference-counting pointer. "Arc" stands for "Atomically +/// Reference Counted". /// /// The type `Arc` provides shared ownership of a value of type `T`, /// allocated in the heap. Invoking [`clone`][clone] on `Arc` produces diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 33951b911dd5..d5d003ed5bb2 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -10,7 +10,8 @@ #![allow(deprecated)] -//! Single-threaded reference-counting pointers. +//! Single-threaded reference-counting pointers. "Rc" stands for "Reference +//! Counted". //! //! The type [`Rc`][`Rc`] provides shared ownership of a value of type `T`, //! allocated in the heap. Invoking [`clone`][clone] on [`Rc`] produces a new From 18612b21d05ce0021f9ef995592b158e181ffd90 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sun, 4 Jun 2017 01:47:21 -0700 Subject: [PATCH 032/233] Delegate str:Index(Mut) to SliceIndex Move any extra logic that the former had into the latter, so they're consistent. --- src/libcore/str/mod.rs | 55 ++++++++++++++---------------------------- 1 file changed, 18 insertions(+), 37 deletions(-) diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 547a4899c711..76a5d0c0b50b 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -1617,12 +1617,7 @@ mod traits { #[inline] fn index(&self, index: ops::RangeTo) -> &str { - // is_char_boundary checks that the index is in [0, .len()] - if self.is_char_boundary(index.end) { - unsafe { self.slice_unchecked(0, index.end) } - } else { - super::slice_error_fail(self, 0, index.end) - } + index.index(self) } } @@ -1636,12 +1631,7 @@ mod traits { impl ops::IndexMut> for str { #[inline] fn index_mut(&mut self, index: ops::RangeTo) -> &mut str { - // is_char_boundary checks that the index is in [0, .len()] - if self.is_char_boundary(index.end) { - unsafe { self.slice_mut_unchecked(0, index.end) } - } else { - super::slice_error_fail(self, 0, index.end) - } + index.index_mut(self) } } @@ -1657,12 +1647,7 @@ mod traits { #[inline] fn index(&self, index: ops::RangeFrom) -> &str { - // is_char_boundary checks that the index is in [0, .len()] - if self.is_char_boundary(index.start) { - unsafe { self.slice_unchecked(index.start, self.len()) } - } else { - super::slice_error_fail(self, index.start, self.len()) - } + index.index(self) } } @@ -1676,13 +1661,7 @@ mod traits { impl ops::IndexMut> for str { #[inline] fn index_mut(&mut self, index: ops::RangeFrom) -> &mut str { - // is_char_boundary checks that the index is in [0, .len()] - if self.is_char_boundary(index.start) { - let len = self.len(); - unsafe { self.slice_mut_unchecked(index.start, len) } - } else { - super::slice_error_fail(self, index.start, self.len()) - } + index.index_mut(self) } } @@ -1724,9 +1703,7 @@ mod traits { #[inline] fn index(&self, index: ops::RangeInclusive) -> &str { - assert!(index.end != usize::max_value(), - "attempted to index str up to maximum usize"); - self.index(index.start .. index.end+1) + index.index(self) } } @@ -1738,9 +1715,7 @@ mod traits { #[inline] fn index(&self, index: ops::RangeToInclusive) -> &str { - assert!(index.end != usize::max_value(), - "attempted to index str up to maximum usize"); - self.index(.. index.end+1) + index.index(self) } } @@ -1750,9 +1725,7 @@ mod traits { impl ops::IndexMut> for str { #[inline] fn index_mut(&mut self, index: ops::RangeInclusive) -> &mut str { - assert!(index.end != usize::max_value(), - "attempted to index str up to maximum usize"); - self.index_mut(index.start .. index.end+1) + index.index_mut(self) } } #[unstable(feature = "inclusive_range", @@ -1761,9 +1734,7 @@ mod traits { impl ops::IndexMut> for str { #[inline] fn index_mut(&mut self, index: ops::RangeToInclusive) -> &mut str { - assert!(index.end != usize::max_value(), - "attempted to index str up to maximum usize"); - self.index_mut(.. index.end+1) + index.index_mut(self) } } @@ -1886,6 +1857,7 @@ mod traits { } #[inline] fn index_mut(self, slice: &mut str) -> &mut Self::Output { + // is_char_boundary checks that the index is in [0, .len()] if slice.is_char_boundary(self.end) { unsafe { self.get_unchecked_mut(slice) } } else { @@ -1932,6 +1904,7 @@ mod traits { } #[inline] fn index_mut(self, slice: &mut str) -> &mut Self::Output { + // is_char_boundary checks that the index is in [0, .len()] if slice.is_char_boundary(self.start) { unsafe { self.get_unchecked_mut(slice) } } else { @@ -1961,10 +1934,14 @@ mod traits { } #[inline] fn index(self, slice: &str) -> &Self::Output { + assert!(self.end != usize::max_value(), + "attempted to index str up to maximum usize"); (self.start..self.end+1).index(slice) } #[inline] fn index_mut(self, slice: &mut str) -> &mut Self::Output { + assert!(self.end != usize::max_value(), + "attempted to index str up to maximum usize"); (self.start..self.end+1).index_mut(slice) } } @@ -2002,11 +1979,15 @@ mod traits { } #[inline] fn index(self, slice: &str) -> &Self::Output { + assert!(self.end != usize::max_value(), + "attempted to index str up to maximum usize"); let end = self.end + 1; self.get(slice).unwrap_or_else(|| super::slice_error_fail(slice, 0, end)) } #[inline] fn index_mut(self, slice: &mut str) -> &mut Self::Output { + assert!(self.end != usize::max_value(), + "attempted to index str up to maximum usize"); if slice.is_char_boundary(self.end) { unsafe { self.get_unchecked_mut(slice) } } else { From 60524c55e9150892913272737b77bbcc2fd29a02 Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Sun, 4 Jun 2017 17:12:47 +0100 Subject: [PATCH 033/233] Stop checking uses_std --- src/librustc_metadata/creader.rs | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 5d1462c502ae..45633e995502 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -908,27 +908,18 @@ impl<'a> CrateLoader<'a> { fn inject_profiler_runtime(&mut self) { if self.sess.opts.debugging_opts.profile { - let mut uses_std = false; - self.cstore.iter_crate_data(|_, data| { - if data.name == "std" { - uses_std = true; - } - }); + info!("loading profiler"); - if uses_std { - info!("loading profiler"); + let symbol = Symbol::intern("profiler_builtins"); + let dep_kind = DepKind::Implicit; + let (_, data) = + self.resolve_crate(&None, symbol, symbol, None, DUMMY_SP, + PathKind::Crate, dep_kind); - let symbol = Symbol::intern("profiler_builtins"); - let dep_kind = DepKind::Implicit; - let (_, data) = - self.resolve_crate(&None, symbol, symbol, None, DUMMY_SP, - PathKind::Crate, dep_kind); - - // Sanity check the loaded crate to ensure it is indeed a profiler runtime - if !data.is_profiler_runtime(&self.sess.dep_graph) { - self.sess.err(&format!("the crate `profiler_builtins` is not \ - a profiler runtime")); - } + // Sanity check the loaded crate to ensure it is indeed a profiler runtime + if !data.is_profiler_runtime(&self.sess.dep_graph) { + self.sess.err(&format!("the crate `profiler_builtins` is not \ + a profiler runtime")); } } } From a1ca5f689fbb36ab6f691446390ec80a90a0556a Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Sun, 4 Jun 2017 17:50:25 +0100 Subject: [PATCH 034/233] Add llvm.gcov metadata only if profiler is enabled --- src/librustc_trans/debuginfo/metadata.rs | 42 +++++++++++++----------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs index d9b99e0eb683..32fd2bac85f4 100644 --- a/src/librustc_trans/debuginfo/metadata.rs +++ b/src/librustc_trans/debuginfo/metadata.rs @@ -806,28 +806,30 @@ pub fn compile_unit_metadata(scc: &SharedCrateContext, 0, split_name.as_ptr() as *const _); - let cu_desc_metadata = llvm::LLVMRustMetadataAsValue(debug_context.llcontext, - unit_metadata); + if sess.opts.debugging_opts.profile { + let cu_desc_metadata = llvm::LLVMRustMetadataAsValue(debug_context.llcontext, + unit_metadata); - let gcov_cu_info = [ - // Ideally we would be using the three-element form of !llvm.gcov metadata, - // which allows us to specify gcno/gcda files explicitly, but that's only - // available in LLVM 3.9+; so we rely on LLVM chopping off the extension - // and replacing it with gcno/gcda, instead. - path_to_mdstring(debug_context.llcontext, - &scc.output_filenames().with_extension("gcno")), - // path_to_mdstring(debug_context.llcontext, - // &scc.output_filenames().with_extension("gcda")), - cu_desc_metadata, - ]; - let gcov_metadata = llvm::LLVMMDNodeInContext(debug_context.llcontext, - gcov_cu_info.as_ptr(), - gcov_cu_info.len() as c_uint); + let gcov_cu_info = [ + // Ideally we would be using the three-element form of !llvm.gcov metadata, + // which allows us to specify gcno/gcda files explicitly, but that's only + // available in LLVM 3.9+; so we rely on LLVM chopping off the extension + // and replacing it with gcno/gcda, instead. + path_to_mdstring(debug_context.llcontext, + &scc.output_filenames().with_extension("gcno")), + // path_to_mdstring(debug_context.llcontext, + // &scc.output_filenames().with_extension("gcda")), + cu_desc_metadata, + ]; + let gcov_metadata = llvm::LLVMMDNodeInContext(debug_context.llcontext, + gcov_cu_info.as_ptr(), + gcov_cu_info.len() as c_uint); - let llvm_gcov_ident = CString::new("llvm.gcov").unwrap(); - llvm::LLVMAddNamedMetadataOperand(debug_context.llmod, - llvm_gcov_ident.as_ptr(), - gcov_metadata); + let llvm_gcov_ident = CString::new("llvm.gcov").unwrap(); + llvm::LLVMAddNamedMetadataOperand(debug_context.llmod, + llvm_gcov_ident.as_ptr(), + gcov_metadata); + } return unit_metadata; }; From 0b0a5ac032d121f89bae2e9906d70be771e39887 Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Sun, 4 Jun 2017 19:05:03 +0100 Subject: [PATCH 035/233] Run profiler test only if built with profiler support --- src/test/run-make/profile/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/run-make/profile/Makefile b/src/test/run-make/profile/Makefile index 94a2a30869b5..7300bfc95536 100644 --- a/src/test/run-make/profile/Makefile +++ b/src/test/run-make/profile/Makefile @@ -1,7 +1,9 @@ -include ../tools.mk all: +ifeq ($(PROFILER_SUPPORT),1) $(RUSTC) -g -Z profile test.rs $(call RUN,test) || exit 1 [ -e "$(TMPDIR)/test.gcno" ] || (echo "No .gcno file"; exit 1) [ -e "$(TMPDIR)/test.gcda" ] || (echo "No .gcda file"; exit 1) +endif From 808a08a363591abf754fafd93ec3f44c686486ec Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sun, 4 Jun 2017 11:08:25 -0700 Subject: [PATCH 036/233] Add overflow checking for str::get with inclusive ranges Fixes #42401 --- src/libcollections/tests/lib.rs | 1 + src/libcollections/tests/str.rs | 42 +++++++++++++++++++++++++++++++++ src/libcore/str/mod.rs | 16 +++++++++---- 3 files changed, 55 insertions(+), 4 deletions(-) diff --git a/src/libcollections/tests/lib.rs b/src/libcollections/tests/lib.rs index 8af8786994e4..f64a549a05d4 100644 --- a/src/libcollections/tests/lib.rs +++ b/src/libcollections/tests/lib.rs @@ -22,6 +22,7 @@ #![feature(rand)] #![feature(slice_rotate)] #![feature(splice)] +#![feature(str_checked_slicing)] #![feature(str_escape)] #![feature(test)] #![feature(unboxed_closures)] diff --git a/src/libcollections/tests/str.rs b/src/libcollections/tests/str.rs index c9b7104fec4f..9d8ca38b20e4 100644 --- a/src/libcollections/tests/str.rs +++ b/src/libcollections/tests/str.rs @@ -358,6 +358,48 @@ fn test_slice_fail() { &"中华Việt Nam"[0..2]; } +#[test] +#[should_panic] +fn test_str_slice_rangetoinclusive_max_panics() { + &"hello"[...usize::max_value()]; +} + +#[test] +#[should_panic] +fn test_str_slice_rangeinclusive_max_panics() { + &"hello"[1...usize::max_value()]; +} + +#[test] +#[should_panic] +fn test_str_slicemut_rangetoinclusive_max_panics() { + let mut s = "hello".to_owned(); + let s: &mut str = &mut s; + &mut s[...usize::max_value()]; +} + +#[test] +#[should_panic] +fn test_str_slicemut_rangeinclusive_max_panics() { + let mut s = "hello".to_owned(); + let s: &mut str = &mut s; + &mut s[1...usize::max_value()]; +} + +#[test] +fn test_str_get_maxinclusive() { + let mut s = "hello".to_owned(); + { + let s: &str = &s; + assert_eq!(s.get(...usize::max_value()), None); + assert_eq!(s.get(1...usize::max_value()), None); + } + { + let s: &mut str = &mut s; + assert_eq!(s.get(...usize::max_value()), None); + assert_eq!(s.get(1...usize::max_value()), None); + } +} #[test] fn test_is_char_boundary() { diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 76a5d0c0b50b..34aca592b1e9 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -1918,11 +1918,19 @@ mod traits { type Output = str; #[inline] fn get(self, slice: &str) -> Option<&Self::Output> { - (self.start..self.end+1).get(slice) + if let Some(end) = self.end.checked_add(1) { + (self.start..end).get(slice) + } else { + None + } } #[inline] fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> { - (self.start..self.end+1).get_mut(slice) + if let Some(end) = self.end.checked_add(1) { + (self.start..end).get_mut(slice) + } else { + None + } } #[inline] unsafe fn get_unchecked(self, slice: &str) -> &Self::Output { @@ -1953,7 +1961,7 @@ mod traits { type Output = str; #[inline] fn get(self, slice: &str) -> Option<&Self::Output> { - if slice.is_char_boundary(self.end + 1) { + if self.end < usize::max_value() && slice.is_char_boundary(self.end + 1) { Some(unsafe { self.get_unchecked(slice) }) } else { None @@ -1961,7 +1969,7 @@ mod traits { } #[inline] fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> { - if slice.is_char_boundary(self.end + 1) { + if self.end < usize::max_value() && slice.is_char_boundary(self.end + 1) { Some(unsafe { self.get_unchecked_mut(slice) }) } else { None From 8b7826ffb9b7fad61591421f58c1ddc3a2bdaf6e Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Sun, 4 Jun 2017 19:53:42 +0100 Subject: [PATCH 037/233] Use the three-element variant of the 'llvm.gcov' metadata --- src/librustc_trans/debuginfo/metadata.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs index 32fd2bac85f4..95ceec610eaa 100644 --- a/src/librustc_trans/debuginfo/metadata.rs +++ b/src/librustc_trans/debuginfo/metadata.rs @@ -811,14 +811,10 @@ pub fn compile_unit_metadata(scc: &SharedCrateContext, unit_metadata); let gcov_cu_info = [ - // Ideally we would be using the three-element form of !llvm.gcov metadata, - // which allows us to specify gcno/gcda files explicitly, but that's only - // available in LLVM 3.9+; so we rely on LLVM chopping off the extension - // and replacing it with gcno/gcda, instead. path_to_mdstring(debug_context.llcontext, &scc.output_filenames().with_extension("gcno")), - // path_to_mdstring(debug_context.llcontext, - // &scc.output_filenames().with_extension("gcda")), + path_to_mdstring(debug_context.llcontext, + &scc.output_filenames().with_extension("gcda")), cu_desc_metadata, ]; let gcov_metadata = llvm::LLVMMDNodeInContext(debug_context.llcontext, From 9d188e680e5558af2842231e6c32a676afc0086b Mon Sep 17 00:00:00 2001 From: Tommy Ip Date: Mon, 5 Jun 2017 11:14:48 +0100 Subject: [PATCH 038/233] Better closure error message Use tracked data introduced in #42196 to provide a better closure error message by showing why a closure implements `FnOnce`. ``` error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce` --> $DIR/issue_26046.rs:4:19 | 4 | let closure = move || { | ___________________^ 5 | | vec 6 | | }; | |_____^ | note: closure is `FnOnce` because it moves the variable `vec` out of its environment --> $DIR/issue_26046.rs:5:9 | 5 | vec | ^^^ error: aborting due to previous error(s) ``` Fixes #26046 --- src/librustc/traits/error_reporting.rs | 32 ++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 049d5e488c94..e29e4786671b 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -29,7 +29,7 @@ use hir::{self, intravisit, Local, Pat, Body}; use hir::intravisit::{Visitor, NestedVisitorMap}; use hir::map::NodeExpr; use hir::def_id::DefId; -use infer::{self, InferCtxt}; +use infer::{self, InferCtxt, InferTables, InferTablesRef}; use infer::type_variable::TypeVariableOrigin; use rustc::lint::builtin::EXTRA_REQUIREMENT_IN_IMPL; use std::fmt; @@ -640,16 +640,38 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { ty::Predicate::ClosureKind(closure_def_id, kind) => { let found_kind = self.closure_kind(closure_def_id).unwrap(); let closure_span = self.tcx.hir.span_if_local(closure_def_id).unwrap(); + let node_id = self.tcx.hir.as_local_node_id(closure_def_id).unwrap(); let mut err = struct_span_err!( self.tcx.sess, closure_span, E0525, "expected a closure that implements the `{}` trait, \ but this closure only implements `{}`", kind, found_kind); - err.span_note( - obligation.cause.span, - &format!("the requirement to implement \ - `{}` derives from here", kind)); + + let infer_tables = match self.tables { + InferTables::Interned(tables) => + Some(InferTablesRef::Interned(tables)), + InferTables::InProgress(tables) => + Some(InferTablesRef::InProgress(tables.borrow())), + InferTables::Missing => None, + }; + + if let Some(tables) = infer_tables { + if let Some(&(ty::ClosureKind::FnOnce, Some((span, name)))) = + tables.closure_kinds.get(&node_id) + { + err.span_note( + span, + &format!("closure is `FnOnce` because it moves the \ + variable `{}` out of its environment", name)); + } + } else { + err.span_note( + obligation.cause.span, + &format!("the requirement to implement `{}` \ + derives from here", kind)); + } + err.emit(); return; } From 9cbb5f9a245f859c94d90acebef02adbc4a807e3 Mon Sep 17 00:00:00 2001 From: Tommy Ip Date: Mon, 5 Jun 2017 11:35:17 +0100 Subject: [PATCH 039/233] Add ui tests for issue 26046 --- src/test/ui/issue-26046.rs | 21 +++++++++++++++++++++ src/test/ui/issue-26046.stderr | 17 +++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 src/test/ui/issue-26046.rs create mode 100644 src/test/ui/issue-26046.stderr diff --git a/src/test/ui/issue-26046.rs b/src/test/ui/issue-26046.rs new file mode 100644 index 000000000000..de06de530c6c --- /dev/null +++ b/src/test/ui/issue-26046.rs @@ -0,0 +1,21 @@ +// 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. + +fn get_closure() -> Box Vec> { + let vec = vec![1u8, 2u8]; + + let closure = move || { + vec + }; + + Box::new(closure) +} + +fn main() {} diff --git a/src/test/ui/issue-26046.stderr b/src/test/ui/issue-26046.stderr new file mode 100644 index 000000000000..fa3681dc01fa --- /dev/null +++ b/src/test/ui/issue-26046.stderr @@ -0,0 +1,17 @@ +error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce` + --> $DIR/issue-26046.rs:14:19 + | +14 | let closure = move || { + | ___________________^ +15 | | vec +16 | | }; + | |_____^ + | +note: closure is `FnOnce` because it moves the variable `vec` out of its environment + --> $DIR/issue-26046.rs:15:9 + | +15 | vec + | ^^^ + +error: aborting due to previous error(s) + From 1af0cb165065ebca5296a7b5841ebec9bfb40476 Mon Sep 17 00:00:00 2001 From: Ulysse Carion Date: Mon, 5 Jun 2017 12:07:54 -0700 Subject: [PATCH 040/233] Use single quotes, and doc the Rc struct itself. --- src/liballoc/arc.rs | 4 ++-- src/liballoc/rc.rs | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs index 81e97334e3c9..5ed41f6ffe62 100644 --- a/src/liballoc/arc.rs +++ b/src/liballoc/arc.rs @@ -42,8 +42,8 @@ use heap::deallocate; /// necessarily) at _exactly_ `MAX_REFCOUNT + 1` references. const MAX_REFCOUNT: usize = (isize::MAX) as usize; -/// A thread-safe reference-counting pointer. "Arc" stands for "Atomically -/// Reference Counted". +/// A thread-safe reference-counting pointer. 'Arc' stands for 'Atomically +/// Reference Counted'. /// /// The type `Arc` provides shared ownership of a value of type `T`, /// allocated in the heap. Invoking [`clone`][clone] on `Arc` produces diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index d5d003ed5bb2..1f3388ad2c28 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -10,8 +10,8 @@ #![allow(deprecated)] -//! Single-threaded reference-counting pointers. "Rc" stands for "Reference -//! Counted". +//! Single-threaded reference-counting pointers. 'Rc' stands for 'Reference +//! Counted'. //! //! The type [`Rc`][`Rc`] provides shared ownership of a value of type `T`, //! allocated in the heap. Invoking [`clone`][clone] on [`Rc`] produces a new @@ -267,7 +267,8 @@ struct RcBox { value: T, } -/// A single-threaded reference-counting pointer. +/// A single-threaded reference-counting pointer. 'Rc' stands for 'Reference +/// Counted'. /// /// See the [module-level documentation](./index.html) for more details. /// From 26ad8d4ad304a4aaaeab4bbc51ed5cbd733d13ba Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Mon, 5 Jun 2017 23:56:59 +0100 Subject: [PATCH 041/233] Enable profiler on all builders --- src/ci/run.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ci/run.sh b/src/ci/run.sh index 549e804603c0..7885a5b22434 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -32,6 +32,7 @@ RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --disable-manage-submodules" RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-locked-deps" RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-cargo-openssl-static" RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-llvm-clean-rebuild" +RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-profiling" if [ "$DIST_SRC" = "" ]; then RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --disable-dist-src" From 84d1626e517346e2a603788b8026c17e754f4144 Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Tue, 6 Jun 2017 00:39:07 +0100 Subject: [PATCH 042/233] Add basic documentation for the profile feature --- .../unstable-book/src/compiler-flags/profile.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/doc/unstable-book/src/compiler-flags/profile.md b/src/doc/unstable-book/src/compiler-flags/profile.md index f9634c55c96e..1c4ae5207ff5 100644 --- a/src/doc/unstable-book/src/compiler-flags/profile.md +++ b/src/doc/unstable-book/src/compiler-flags/profile.md @@ -3,3 +3,19 @@ The tracking issue for this feature is: None ------------------------ + +This feature allows the generation of code coverage reports. + +Set the compiler flags `-Ccodegen-units=1 -Clink-dead-code -Cpasses=insert-gcov-profiling -Zno-landing-pads` to enable gcov profiling. + +For example: +```Bash +cargo new testgcov --bin +cd testgcov +export RUSTFLAGS="-Ccodegen-units=1 -Clink-dead-code -Cpasses=insert-gcov-profiling -Zno-landing-pads" +cargo build +cargo run +``` + +Once you've built and run your program, files with the `gcno` (after build) and `gcda` (after execution) extensions will be created. +You can parse them with [llvm-cov gcov](http://llvm.org/docs/CommandGuide/llvm-cov.html#llvm-cov-gcov) or [grcov](https://github.com/marco-c/grcov). From 13b3c34e4bf38ad6e6f0453ab84029faf5dd5058 Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Tue, 6 Jun 2017 00:42:09 +0100 Subject: [PATCH 043/233] Spell profiler option correctly... --- src/ci/run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ci/run.sh b/src/ci/run.sh index 7885a5b22434..763d6684463c 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -32,7 +32,7 @@ RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --disable-manage-submodules" RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-locked-deps" RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-cargo-openssl-static" RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-llvm-clean-rebuild" -RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-profiling" +RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-profiler" if [ "$DIST_SRC" = "" ]; then RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --disable-dist-src" From 4db8c9f0baef0a5851f6c777d8ce31274bf8c10b Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Mon, 5 Jun 2017 23:42:13 -0400 Subject: [PATCH 044/233] Add doc example for `CString::into_raw`. --- src/libstd/ffi/c_str.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index 1167c39dba8e..a1ce02b58305 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -288,6 +288,26 @@ impl CString { /// Failure to call [`from_raw`] will lead to a memory leak. /// /// [`from_raw`]: #method.from_raw + /// + /// # Examples + /// + /// ``` + /// use std::ffi::CString; + /// + /// let c_string = CString::new("foo").unwrap(); + /// + /// let ptr = c_string.into_raw(); + /// + /// unsafe { + /// assert_eq!(b'f', *ptr as u8); + /// assert_eq!(b'o', *ptr.offset(1) as u8); + /// assert_eq!(b'o', *ptr.offset(2) as u8); + /// assert_eq!(b'\0', *ptr.offset(3) as u8); + /// + /// // retake pointer to free memory + /// let _ = CString::from_raw(ptr); + /// } + /// ``` #[stable(feature = "cstr_memory", since = "1.4.0")] pub fn into_raw(self) -> *mut c_char { Box::into_raw(self.into_inner()) as *mut c_char From 3ec1f61accd0386d6923102bd2da30fef4603c47 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Mon, 5 Jun 2017 23:46:44 -0400 Subject: [PATCH 045/233] Add doc example for `CString::into_bytes`. --- src/libstd/ffi/c_str.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index a1ce02b58305..0e8d72c5f3be 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -331,6 +331,16 @@ impl CString { /// /// The returned buffer does **not** contain the trailing nul separator and /// it is guaranteed to not have any interior nul bytes. + /// + /// # Examples + /// + /// ``` + /// use std::ffi::CString; + /// + /// let c_string = CString::new("foo").unwrap(); + /// let bytes = c_string.into_bytes(); + /// assert_eq!(bytes, vec![b'f', b'o', b'o']); + /// ``` #[stable(feature = "cstring_into", since = "1.7.0")] pub fn into_bytes(self) -> Vec { let mut vec = self.into_inner().into_vec(); From 815c12a7657cfc68c7058f83d9c30ff7607c17b2 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Mon, 5 Jun 2017 23:48:13 -0400 Subject: [PATCH 046/233] Add doc example for `CString::into_bytes_with_nul`. --- src/libstd/ffi/c_str.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index 0e8d72c5f3be..81563a590644 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -353,6 +353,16 @@ impl CString { /// includes the trailing nul byte. /// /// [`into_bytes`]: #method.into_bytes + /// + /// # Examples + /// + /// ``` + /// use std::ffi::CString; + /// + /// let c_string = CString::new("foo").unwrap(); + /// let bytes = c_string.into_bytes_with_nul(); + /// assert_eq!(bytes, vec![b'f', b'o', b'o', b'\0']); + /// ``` #[stable(feature = "cstring_into", since = "1.7.0")] pub fn into_bytes_with_nul(self) -> Vec { self.into_inner().into_vec() From ae4832d48acc563a55e23190e03f75e9e3336293 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Mon, 5 Jun 2017 23:49:52 -0400 Subject: [PATCH 047/233] Add doc example for `CString::as_bytes_with_nul`. --- src/libstd/ffi/c_str.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index 81563a590644..21e4779fc3a2 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -381,6 +381,16 @@ impl CString { /// includes the trailing nul byte. /// /// [`as_bytes`]: #method.as_bytes + /// + /// # Examples + /// + /// ``` + /// use std::ffi::CString; + /// + /// let c_string = CString::new("foo").unwrap(); + /// let bytes = c_string.as_bytes_with_nul(); + /// assert_eq!(bytes, &[b'f', b'o', b'o', b'\0']); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn as_bytes_with_nul(&self) -> &[u8] { &self.inner From 06f63f5edb887aaff70a475de904103119d022e3 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Mon, 5 Jun 2017 23:50:49 -0400 Subject: [PATCH 048/233] Add doc example for `CString::as_bytes`. --- src/libstd/ffi/c_str.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index 21e4779fc3a2..2d78f0511d6d 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -372,6 +372,16 @@ impl CString { /// /// The returned slice does **not** contain the trailing nul separator and /// it is guaranteed to not have any interior nul bytes. + /// + /// # Examples + /// + /// ``` + /// use std::ffi::CString; + /// + /// let c_string = CString::new("foo").unwrap(); + /// let bytes = c_string.as_bytes(); + /// assert_eq!(bytes, &[b'f', b'o', b'o']); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn as_bytes(&self) -> &[u8] { &self.inner[..self.inner.len() - 1] From 94c808c1d3fbf6f73b2bfdb8d6fbcad1d260fe64 Mon Sep 17 00:00:00 2001 From: Tommy Ip Date: Tue, 6 Jun 2017 09:06:56 +0100 Subject: [PATCH 049/233] Update closure errors to emit context for FnMut It now handles both FnMut and FnOnce case. --- src/librustc/traits/error_reporting.rs | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index e29e4786671b..73753382a7cd 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -657,13 +657,18 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { }; if let Some(tables) = infer_tables { - if let Some(&(ty::ClosureKind::FnOnce, Some((span, name)))) = - tables.closure_kinds.get(&node_id) - { - err.span_note( - span, - &format!("closure is `FnOnce` because it moves the \ - variable `{}` out of its environment", name)); + match tables.closure_kinds.get(&node_id) { + Some(&(ty::ClosureKind::FnOnce, Some((span, name)))) => { + err.span_note(span, &format!( + "closure is `FnOnce` because it moves the \ + variable `{}` out of its environment", name)); + }, + Some(&(ty::ClosureKind::FnMut, Some((span, name)))) => { + err.span_note(span, &format!( + "closure is `FnMut` because it mutates the \ + variable `{}` here", name)); + }, + _ => {} } } else { err.span_note( From 2c282b8e5d0b592f72e9fd3c6038c8e2e80d6055 Mon Sep 17 00:00:00 2001 From: Tommy Ip Date: Tue, 6 Jun 2017 09:17:06 +0100 Subject: [PATCH 050/233] Add additional ui tests for issue 26046 This tests the FnMut case. --- src/test/ui/issue-26046-fn-mut.rs | 21 +++++++++++++++++++++ src/test/ui/issue-26046-fn-mut.stderr | 17 +++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 src/test/ui/issue-26046-fn-mut.rs create mode 100644 src/test/ui/issue-26046-fn-mut.stderr diff --git a/src/test/ui/issue-26046-fn-mut.rs b/src/test/ui/issue-26046-fn-mut.rs new file mode 100644 index 000000000000..5ed7ace5437d --- /dev/null +++ b/src/test/ui/issue-26046-fn-mut.rs @@ -0,0 +1,21 @@ +// 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. + +fn foo() -> Box { + let num = 5; + + let closure = || { + num += 1; + }; + + Box::new(closure) +} + +fn main() {} diff --git a/src/test/ui/issue-26046-fn-mut.stderr b/src/test/ui/issue-26046-fn-mut.stderr new file mode 100644 index 000000000000..4dd33ef8a0e1 --- /dev/null +++ b/src/test/ui/issue-26046-fn-mut.stderr @@ -0,0 +1,17 @@ +error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnMut` + --> $DIR/issue-26046-fn-mut.rs:14:19 + | +14 | let closure = || { + | ___________________^ +15 | | num += 1; +16 | | }; + | |_____^ + | +note: closure is `FnMut` because it mutates the variable `num` here + --> $DIR/issue-26046-fn-mut.rs:15:9 + | +15 | num += 1; + | ^^^ + +error: aborting due to previous error(s) + From b1b6490c5d60b0c5d0166407db9b57e39fc3e3a4 Mon Sep 17 00:00:00 2001 From: Tommy Ip Date: Tue, 6 Jun 2017 09:29:06 +0100 Subject: [PATCH 051/233] Group closure context ui tests --- src/test/ui/{ => closure_context}/issue-26046-fn-mut.rs | 0 src/test/ui/{ => closure_context}/issue-26046-fn-mut.stderr | 0 .../issue-26046-fn-once.rs} | 0 .../issue-26046-fn-once.stderr} | 4 ++-- .../ui/{fn_once-moved.rs => closure_context/issue-42065.rs} | 0 .../issue-42065.stderr} | 4 ++-- 6 files changed, 4 insertions(+), 4 deletions(-) rename src/test/ui/{ => closure_context}/issue-26046-fn-mut.rs (100%) rename src/test/ui/{ => closure_context}/issue-26046-fn-mut.stderr (100%) rename src/test/ui/{issue-26046.rs => closure_context/issue-26046-fn-once.rs} (100%) rename src/test/ui/{issue-26046.stderr => closure_context/issue-26046-fn-once.stderr} (83%) rename src/test/ui/{fn_once-moved.rs => closure_context/issue-42065.rs} (100%) rename src/test/ui/{fn_once-moved.stderr => closure_context/issue-42065.stderr} (86%) diff --git a/src/test/ui/issue-26046-fn-mut.rs b/src/test/ui/closure_context/issue-26046-fn-mut.rs similarity index 100% rename from src/test/ui/issue-26046-fn-mut.rs rename to src/test/ui/closure_context/issue-26046-fn-mut.rs diff --git a/src/test/ui/issue-26046-fn-mut.stderr b/src/test/ui/closure_context/issue-26046-fn-mut.stderr similarity index 100% rename from src/test/ui/issue-26046-fn-mut.stderr rename to src/test/ui/closure_context/issue-26046-fn-mut.stderr diff --git a/src/test/ui/issue-26046.rs b/src/test/ui/closure_context/issue-26046-fn-once.rs similarity index 100% rename from src/test/ui/issue-26046.rs rename to src/test/ui/closure_context/issue-26046-fn-once.rs diff --git a/src/test/ui/issue-26046.stderr b/src/test/ui/closure_context/issue-26046-fn-once.stderr similarity index 83% rename from src/test/ui/issue-26046.stderr rename to src/test/ui/closure_context/issue-26046-fn-once.stderr index fa3681dc01fa..4a7aae87439f 100644 --- a/src/test/ui/issue-26046.stderr +++ b/src/test/ui/closure_context/issue-26046-fn-once.stderr @@ -1,5 +1,5 @@ error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce` - --> $DIR/issue-26046.rs:14:19 + --> $DIR/issue-26046-fn-once.rs:14:19 | 14 | let closure = move || { | ___________________^ @@ -8,7 +8,7 @@ error[E0525]: expected a closure that implements the `Fn` trait, but this closur | |_____^ | note: closure is `FnOnce` because it moves the variable `vec` out of its environment - --> $DIR/issue-26046.rs:15:9 + --> $DIR/issue-26046-fn-once.rs:15:9 | 15 | vec | ^^^ diff --git a/src/test/ui/fn_once-moved.rs b/src/test/ui/closure_context/issue-42065.rs similarity index 100% rename from src/test/ui/fn_once-moved.rs rename to src/test/ui/closure_context/issue-42065.rs diff --git a/src/test/ui/fn_once-moved.stderr b/src/test/ui/closure_context/issue-42065.stderr similarity index 86% rename from src/test/ui/fn_once-moved.stderr rename to src/test/ui/closure_context/issue-42065.stderr index 27b7d91d1d4b..5bbd372adb6c 100644 --- a/src/test/ui/fn_once-moved.stderr +++ b/src/test/ui/closure_context/issue-42065.stderr @@ -1,5 +1,5 @@ error[E0382]: use of moved value: `debug_dump_dict` - --> $DIR/fn_once-moved.rs:21:5 + --> $DIR/issue-42065.rs:21:5 | 20 | debug_dump_dict(); | --------------- value moved here @@ -7,7 +7,7 @@ error[E0382]: use of moved value: `debug_dump_dict` | ^^^^^^^^^^^^^^^ value used here after move | note: closure cannot be invoked more than once because it moves the variable `dict` out of its environment - --> $DIR/fn_once-moved.rs:16:29 + --> $DIR/issue-42065.rs:16:29 | 16 | for (key, value) in dict { | ^^^^ From 95c6fc49441d5387c5495da4eb7b40537c218c1a Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Tue, 6 Jun 2017 11:10:34 +0100 Subject: [PATCH 052/233] Suggest 'profile' flag --- src/doc/unstable-book/src/compiler-flags/profile.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/unstable-book/src/compiler-flags/profile.md b/src/doc/unstable-book/src/compiler-flags/profile.md index 1c4ae5207ff5..3b4f34e67c53 100644 --- a/src/doc/unstable-book/src/compiler-flags/profile.md +++ b/src/doc/unstable-book/src/compiler-flags/profile.md @@ -6,13 +6,13 @@ The tracking issue for this feature is: None This feature allows the generation of code coverage reports. -Set the compiler flags `-Ccodegen-units=1 -Clink-dead-code -Cpasses=insert-gcov-profiling -Zno-landing-pads` to enable gcov profiling. +Set the `-Zprofile` compiler flag in order to enable gcov profiling. For example: ```Bash cargo new testgcov --bin cd testgcov -export RUSTFLAGS="-Ccodegen-units=1 -Clink-dead-code -Cpasses=insert-gcov-profiling -Zno-landing-pads" +export RUSTFLAGS="-Zprofile" cargo build cargo run ``` From b6e8635fefebd80647ecd2463f0c90df79c81ca4 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Fri, 2 Jun 2017 15:45:56 +0200 Subject: [PATCH 053/233] ICH: Make StableHashingContext work with any TyCtxt, not just the global one. --- src/librustc/ich/caching_codemap_view.rs | 4 +- src/librustc/ich/hcx.rs | 74 +++++++------- src/librustc/ich/impls_hir.rs | 99 ++++++++++--------- src/librustc/ich/impls_mir.rs | 78 ++++++++------- src/librustc/ich/impls_syntax.rs | 40 ++++---- src/librustc/ich/impls_ty.rs | 94 ++++++++++-------- src/librustc/macros.rs | 16 +-- src/librustc/mir/cache.rs | 4 +- src/librustc/ty/mod.rs | 8 +- src/librustc_incremental/calculate_svh/mod.rs | 4 +- src/librustc_metadata/isolated_encoder.rs | 12 +-- src/librustc_metadata/schema.rs | 14 +-- 12 files changed, 239 insertions(+), 208 deletions(-) diff --git a/src/librustc/ich/caching_codemap_view.rs b/src/librustc/ich/caching_codemap_view.rs index 9aecd8ad8360..bf47b9bb9d43 100644 --- a/src/librustc/ich/caching_codemap_view.rs +++ b/src/librustc/ich/caching_codemap_view.rs @@ -29,8 +29,8 @@ pub struct CachingCodemapView<'tcx> { time_stamp: usize, } -impl<'tcx> CachingCodemapView<'tcx> { - pub fn new<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> CachingCodemapView<'tcx> { +impl<'gcx> CachingCodemapView<'gcx> { + pub fn new<'a, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> CachingCodemapView<'gcx> { let codemap = tcx.sess.codemap(); let files = codemap.files(); let first_file = files[0].clone(); diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs index a83554889418..2784a7bd024f 100644 --- a/src/librustc/ich/hcx.rs +++ b/src/librustc/ich/hcx.rs @@ -33,9 +33,9 @@ use rustc_data_structures::accumulate_vec::AccumulateVec; /// enough information to transform DefIds and HirIds into stable DefPaths (i.e. /// a reference to the TyCtxt) and it holds a few caches for speeding up various /// things (e.g. each DefId/DefPath is only hashed once). -pub struct StableHashingContext<'a, 'tcx: 'a> { - tcx: ty::TyCtxt<'a, 'tcx, 'tcx>, - codemap: CachingCodemapView<'tcx>, +pub struct StableHashingContext<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { + tcx: ty::TyCtxt<'a, 'gcx, 'tcx>, + codemap: CachingCodemapView<'gcx>, hash_spans: bool, hash_bodies: bool, overflow_checks_enabled: bool, @@ -51,9 +51,9 @@ pub enum NodeIdHashingMode { HashTraitsInScope, } -impl<'a, 'tcx: 'a> StableHashingContext<'a, 'tcx> { +impl<'a, 'gcx, 'tcx> StableHashingContext<'a, 'gcx, 'tcx> { - pub fn new(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>) -> Self { + pub fn new(tcx: ty::TyCtxt<'a, 'gcx, 'tcx>) -> Self { let hash_spans_initial = tcx.sess.opts.debuginfo != NoDebugInfo; let check_overflow_initial = tcx.sess.overflow_checks(); @@ -111,7 +111,7 @@ impl<'a, 'tcx: 'a> StableHashingContext<'a, 'tcx> { } #[inline] - pub fn tcx(&self) -> ty::TyCtxt<'a, 'tcx, 'tcx> { + pub fn tcx(&self) -> ty::TyCtxt<'a, 'gcx, 'tcx> { self.tcx } @@ -131,7 +131,7 @@ impl<'a, 'tcx: 'a> StableHashingContext<'a, 'tcx> { } #[inline] - pub fn codemap(&mut self) -> &mut CachingCodemapView<'tcx> { + pub fn codemap(&mut self) -> &mut CachingCodemapView<'gcx> { &mut self.codemap } @@ -195,9 +195,9 @@ impl<'a, 'tcx: 'a> StableHashingContext<'a, 'tcx> { } -impl<'a, 'tcx> HashStable> for ast::NodeId { +impl<'a, 'gcx, 'tcx> HashStable> for ast::NodeId { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { match hcx.node_id_hashing_mode { NodeIdHashingMode::Ignore => { @@ -230,7 +230,7 @@ impl<'a, 'tcx> HashStable> for ast::NodeId { } } -impl<'a, 'tcx> HashStable> for Span { +impl<'a, 'gcx, 'tcx> HashStable> for Span { // Hash a span in a stable way. We can't directly hash the span's BytePos // fields (that would be similar to hashing pointers, since those are just @@ -242,7 +242,7 @@ impl<'a, 'tcx> HashStable> for Span { // Also, hashing filenames is expensive so we avoid doing it twice when the // span starts and ends in the same file, which is almost always the case. fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { use syntax_pos::Pos; @@ -305,15 +305,16 @@ impl<'a, 'tcx> HashStable> for Span { } } -pub fn hash_stable_hashmap<'a, 'tcx, K, V, R, SK, F, W>(hcx: &mut StableHashingContext<'a, 'tcx>, - hasher: &mut StableHasher, - map: &HashMap, - extract_stable_key: F) +pub fn hash_stable_hashmap<'a, 'gcx, 'tcx, K, V, R, SK, F, W>( + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, + hasher: &mut StableHasher, + map: &HashMap, + extract_stable_key: F) where K: Eq + std_hash::Hash, - V: HashStable>, + V: HashStable>, R: std_hash::BuildHasher, - SK: HashStable> + Ord + Clone, - F: Fn(&mut StableHashingContext<'a, 'tcx>, &K) -> SK, + SK: HashStable> + Ord + Clone, + F: Fn(&mut StableHashingContext<'a, 'gcx, 'tcx>, &K) -> SK, W: StableHasherResult, { let mut keys: Vec<_> = map.keys() @@ -327,14 +328,15 @@ pub fn hash_stable_hashmap<'a, 'tcx, K, V, R, SK, F, W>(hcx: &mut StableHashingC } } -pub fn hash_stable_hashset<'a, 'tcx, K, R, SK, F, W>(hcx: &mut StableHashingContext<'a, 'tcx>, - hasher: &mut StableHasher, - set: &HashSet, - extract_stable_key: F) +pub fn hash_stable_hashset<'a, 'tcx, 'gcx, K, R, SK, F, W>( + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, + hasher: &mut StableHasher, + set: &HashSet, + extract_stable_key: F) where K: Eq + std_hash::Hash, R: std_hash::BuildHasher, - SK: HashStable> + Ord + Clone, - F: Fn(&mut StableHashingContext<'a, 'tcx>, &K) -> SK, + SK: HashStable> + Ord + Clone, + F: Fn(&mut StableHashingContext<'a, 'gcx, 'tcx>, &K) -> SK, W: StableHasherResult, { let mut keys: Vec<_> = set.iter() @@ -344,10 +346,11 @@ pub fn hash_stable_hashset<'a, 'tcx, K, R, SK, F, W>(hcx: &mut StableHashingCont keys.hash_stable(hcx, hasher); } -pub fn hash_stable_nodemap<'a, 'tcx, V, W>(hcx: &mut StableHashingContext<'a, 'tcx>, - hasher: &mut StableHasher, - map: &NodeMap) - where V: HashStable>, +pub fn hash_stable_nodemap<'a, 'tcx, 'gcx, V, W>( + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, + hasher: &mut StableHasher, + map: &NodeMap) + where V: HashStable>, W: StableHasherResult, { hash_stable_hashmap(hcx, hasher, map, |hcx, node_id| { @@ -356,14 +359,15 @@ pub fn hash_stable_nodemap<'a, 'tcx, V, W>(hcx: &mut StableHashingContext<'a, 't } -pub fn hash_stable_btreemap<'a, 'tcx, K, V, SK, F, W>(hcx: &mut StableHashingContext<'a, 'tcx>, - hasher: &mut StableHasher, - map: &BTreeMap, - extract_stable_key: F) +pub fn hash_stable_btreemap<'a, 'tcx, 'gcx, K, V, SK, F, W>( + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, + hasher: &mut StableHasher, + map: &BTreeMap, + extract_stable_key: F) where K: Eq + Ord, - V: HashStable>, - SK: HashStable> + Ord + Clone, - F: Fn(&mut StableHashingContext<'a, 'tcx>, &K) -> SK, + V: HashStable>, + SK: HashStable> + Ord + Clone, + F: Fn(&mut StableHashingContext<'a, 'gcx, 'tcx>, &K) -> SK, W: StableHasherResult, { let mut keys: Vec<_> = map.keys() diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index c582cac67e22..678ec797a86b 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -21,20 +21,20 @@ use syntax::ast; use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult}; -impl<'a, 'tcx> HashStable> for DefId { +impl<'a, 'gcx, 'tcx> HashStable> for DefId { #[inline] fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { hcx.def_path_hash(*self).hash_stable(hcx, hasher); } } -impl<'a, 'tcx> HashStable> for hir::HirId { +impl<'a, 'gcx, 'tcx> HashStable> for hir::HirId { #[inline] fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { let hir::HirId { owner, @@ -55,9 +55,9 @@ impl_stable_hash_for!(tuple_struct hir::ItemLocalId { index }); // want to pick up on a reference changing its target, so we hash the NodeIds // in "DefPath Mode". -impl<'a, 'tcx> HashStable> for hir::ItemId { +impl<'a, 'gcx, 'tcx> HashStable> for hir::ItemId { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { let hir::ItemId { id @@ -69,9 +69,9 @@ impl<'a, 'tcx> HashStable> for hir::ItemId { } } -impl<'a, 'tcx> HashStable> for hir::TraitItemId { +impl<'a, 'gcx, 'tcx> HashStable> for hir::TraitItemId { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { let hir::TraitItemId { node_id @@ -83,9 +83,9 @@ impl<'a, 'tcx> HashStable> for hir::TraitItemId { } } -impl<'a, 'tcx> HashStable> for hir::ImplItemId { +impl<'a, 'gcx, 'tcx> HashStable> for hir::ImplItemId { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { let hir::ImplItemId { node_id @@ -215,9 +215,9 @@ impl_stable_hash_for!(struct hir::TypeBinding { span }); -impl<'a, 'tcx> HashStable> for hir::Ty { +impl<'a, 'gcx, 'tcx> HashStable> for hir::Ty { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { let node_id_hashing_mode = match self.node { hir::TySlice(..) | @@ -299,9 +299,9 @@ impl_stable_hash_for!(enum hir::FunctionRetTy { Return(t) }); -impl<'a, 'tcx> HashStable> for hir::TraitRef { +impl<'a, 'gcx, 'tcx> HashStable> for hir::TraitRef { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { let hir::TraitRef { ref path, @@ -338,9 +338,9 @@ impl_stable_hash_for!(struct hir::MacroDef { }); -impl<'a, 'tcx> HashStable> for hir::Block { +impl<'a, 'gcx, 'tcx> HashStable> for hir::Block { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { let hir::Block { ref stmts, @@ -386,9 +386,9 @@ impl<'a, 'tcx> HashStable> for hir::Block { } } -impl<'a, 'tcx> HashStable> for hir::Pat { +impl<'a, 'gcx, 'tcx> HashStable> for hir::Pat { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { let node_id_hashing_mode = match self.node { hir::PatKind::Wild | @@ -529,9 +529,9 @@ impl_stable_hash_for!(enum hir::UnsafeSource { UserProvided }); -impl<'a, 'tcx> HashStable> for hir::Expr { +impl<'a, 'gcx, 'tcx> HashStable> for hir::Expr { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { hcx.while_hashing_hir_bodies(true, |hcx| { let hir::Expr { @@ -652,9 +652,9 @@ impl_stable_hash_for!(enum hir::LoopSource { ForLoop }); -impl<'a, 'tcx> HashStable> for hir::MatchSource { +impl<'a, 'gcx, 'tcx> HashStable> for hir::MatchSource { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { use hir::MatchSource; @@ -703,9 +703,9 @@ impl_stable_hash_for!(enum hir::ScopeTarget { Loop(loop_id_result) }); -impl<'a, 'tcx> HashStable> for ast::Ident { +impl<'a, 'gcx, 'tcx> HashStable> for ast::Ident { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { let ast::Ident { ref name, @@ -716,9 +716,9 @@ impl<'a, 'tcx> HashStable> for ast::Ident { } } -impl<'a, 'tcx> HashStable> for hir::TraitItem { +impl<'a, 'gcx, 'tcx> HashStable> for hir::TraitItem { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { let hir::TraitItem { id, @@ -749,9 +749,9 @@ impl_stable_hash_for!(enum hir::TraitItemKind { Type(bounds, rhs) }); -impl<'a, 'tcx> HashStable> for hir::ImplItem { +impl<'a, 'gcx, 'tcx> HashStable> for hir::ImplItem { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { let hir::ImplItem { id, @@ -781,9 +781,9 @@ impl_stable_hash_for!(enum hir::ImplItemKind { Type(t) }); -impl<'a, 'tcx> HashStable> for hir::Visibility { +impl<'a, 'gcx, 'tcx> HashStable> for hir::Visibility { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(hcx, hasher); match *self { @@ -802,9 +802,9 @@ impl<'a, 'tcx> HashStable> for hir::Visibility { } } -impl<'a, 'tcx> HashStable> for hir::Defaultness { +impl<'a, 'gcx, 'tcx> HashStable> for hir::Defaultness { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(hcx, hasher); match *self { @@ -823,9 +823,9 @@ impl_stable_hash_for!(enum hir::ImplPolarity { Negative }); -impl<'a, 'tcx> HashStable> for hir::Mod { +impl<'a, 'gcx, 'tcx> HashStable> for hir::Mod { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { let hir::Mod { inner, @@ -878,9 +878,9 @@ impl_stable_hash_for!(enum hir::VariantData { Unit(id) }); -impl<'a, 'tcx> HashStable> for hir::Item { +impl<'a, 'gcx, 'tcx> HashStable> for hir::Item { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { let node_id_hashing_mode = match self.node { hir::ItemExternCrate(..) | @@ -961,9 +961,10 @@ impl_stable_hash_for!(struct hir::ImplItemRef { defaultness }); -impl<'a, 'tcx> HashStable> for hir::AssociatedItemKind { +impl<'a, 'gcx, 'tcx> HashStable> +for hir::AssociatedItemKind { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(hcx, hasher); match *self { @@ -1008,9 +1009,9 @@ impl_stable_hash_for!(struct hir::Body { value }); -impl<'a, 'tcx> HashStable> for hir::BodyId { +impl<'a, 'gcx, 'tcx> HashStable> for hir::BodyId { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { if hcx.hash_bodies() { hcx.tcx().hir.body(*self).hash_stable(hcx, hasher); @@ -1024,9 +1025,9 @@ impl_stable_hash_for!(struct hir::InlineAsmOutput { is_indirect }); -impl<'a, 'tcx> HashStable> for hir::GlobalAsm { +impl<'a, 'gcx, 'tcx> HashStable> for hir::GlobalAsm { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { let hir::GlobalAsm { asm, @@ -1037,9 +1038,9 @@ impl<'a, 'tcx> HashStable> for hir::GlobalAsm { } } -impl<'a, 'tcx> HashStable> for hir::InlineAsm { +impl<'a, 'gcx, 'tcx> HashStable> for hir::InlineAsm { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { let hir::InlineAsm { asm, @@ -1114,10 +1115,11 @@ impl_stable_hash_for!(enum hir::Constness { NotConst }); -impl<'a, 'tcx> HashStable> for hir::def_id::DefIndex { +impl<'a, 'gcx, 'tcx> HashStable> +for hir::def_id::DefIndex { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { DefId::local(*self).hash_stable(hcx, hasher); } @@ -1129,9 +1131,10 @@ impl_stable_hash_for!(struct hir::def::Export { span }); -impl<'a, 'tcx> HashStable> for ::middle::lang_items::LangItem { +impl<'a, 'gcx, 'tcx> HashStable> +for ::middle::lang_items::LangItem { fn hash_stable(&self, - _: &mut StableHashingContext<'a, 'tcx>, + _: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { ::std::hash::Hash::hash(self, hasher); } diff --git a/src/librustc/ich/impls_mir.rs b/src/librustc/ich/impls_mir.rs index edaeb596fe58..ae2bea3027d4 100644 --- a/src/librustc/ich/impls_mir.rs +++ b/src/librustc/ich/impls_mir.rs @@ -32,10 +32,11 @@ impl_stable_hash_for!(struct mir::LocalDecl<'tcx> { impl_stable_hash_for!(struct mir::UpvarDecl { debug_name, by_ref }); impl_stable_hash_for!(struct mir::BasicBlockData<'tcx> { statements, terminator, is_cleanup }); -impl<'a, 'tcx> HashStable> for mir::Terminator<'tcx> { +impl<'a, 'gcx, 'tcx> HashStable> +for mir::Terminator<'tcx> { #[inline] fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { let mir::Terminator { ref kind, @@ -72,59 +73,61 @@ impl<'a, 'tcx> HashStable> for mir::Terminator<'t } -impl<'a, 'tcx> HashStable> for mir::Local { +impl<'a, 'gcx, 'tcx> HashStable> for mir::Local { #[inline] fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { use rustc_data_structures::indexed_vec::Idx; self.index().hash_stable(hcx, hasher); } } -impl<'a, 'tcx> HashStable> for mir::BasicBlock { +impl<'a, 'gcx, 'tcx> HashStable> for mir::BasicBlock { #[inline] fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { use rustc_data_structures::indexed_vec::Idx; self.index().hash_stable(hcx, hasher); } } -impl<'a, 'tcx> HashStable> for mir::Field { +impl<'a, 'gcx, 'tcx> HashStable> for mir::Field { #[inline] fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { use rustc_data_structures::indexed_vec::Idx; self.index().hash_stable(hcx, hasher); } } -impl<'a, 'tcx> HashStable> for mir::VisibilityScope { +impl<'a, 'gcx, 'tcx> HashStable> +for mir::VisibilityScope { #[inline] fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { use rustc_data_structures::indexed_vec::Idx; self.index().hash_stable(hcx, hasher); } } -impl<'a, 'tcx> HashStable> for mir::Promoted { +impl<'a, 'gcx, 'tcx> HashStable> for mir::Promoted { #[inline] fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { use rustc_data_structures::indexed_vec::Idx; self.index().hash_stable(hcx, hasher); } } -impl<'a, 'tcx> HashStable> for mir::TerminatorKind<'tcx> { +impl<'a, 'gcx, 'tcx> HashStable> +for mir::TerminatorKind<'tcx> { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(hcx, hasher); @@ -182,9 +185,10 @@ impl<'a, 'tcx> HashStable> for mir::TerminatorKin } } -impl<'a, 'tcx> HashStable> for mir::AssertMessage<'tcx> { +impl<'a, 'gcx, 'tcx> HashStable> +for mir::AssertMessage<'tcx> { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(hcx, hasher); @@ -202,9 +206,10 @@ impl<'a, 'tcx> HashStable> for mir::AssertMessage impl_stable_hash_for!(struct mir::Statement<'tcx> { source_info, kind }); -impl<'a, 'tcx> HashStable> for mir::StatementKind<'tcx> { +impl<'a, 'gcx, 'tcx> HashStable> +for mir::StatementKind<'tcx> { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(hcx, hasher); @@ -231,9 +236,9 @@ impl<'a, 'tcx> HashStable> for mir::StatementKind } } -impl<'a, 'tcx> HashStable> for mir::Lvalue<'tcx> { +impl<'a, 'gcx, 'tcx> HashStable> for mir::Lvalue<'tcx> { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(hcx, hasher); match *self { @@ -250,12 +255,13 @@ impl<'a, 'tcx> HashStable> for mir::Lvalue<'tcx> } } -impl<'a, 'tcx, B, V> HashStable> for mir::Projection<'tcx, B, V> - where B: HashStable>, - V: HashStable> +impl<'a, 'gcx, 'tcx, B, V> HashStable> +for mir::Projection<'tcx, B, V> + where B: HashStable>, + V: HashStable> { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { let mir::Projection { ref base, @@ -267,11 +273,12 @@ impl<'a, 'tcx, B, V> HashStable> for mir::Project } } -impl<'a, 'tcx, V> HashStable> for mir::ProjectionElem<'tcx, V> - where V: HashStable> +impl<'a, 'gcx, 'tcx, V> HashStable> +for mir::ProjectionElem<'tcx, V> + where V: HashStable> { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(hcx, hasher); match *self { @@ -302,9 +309,9 @@ impl<'a, 'tcx, V> HashStable> for mir::Projection impl_stable_hash_for!(struct mir::VisibilityScopeData { span, parent_scope }); -impl<'a, 'tcx> HashStable> for mir::Operand<'tcx> { +impl<'a, 'gcx, 'tcx> HashStable> for mir::Operand<'tcx> { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(hcx, hasher); @@ -319,9 +326,9 @@ impl<'a, 'tcx> HashStable> for mir::Operand<'tcx> } } -impl<'a, 'tcx> HashStable> for mir::Rvalue<'tcx> { +impl<'a, 'gcx, 'tcx> HashStable> for mir::Rvalue<'tcx> { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(hcx, hasher); @@ -379,9 +386,10 @@ impl_stable_hash_for!(enum mir::CastKind { Unsize }); -impl<'a, 'tcx> HashStable> for mir::AggregateKind<'tcx> { +impl<'a, 'gcx, 'tcx> HashStable> +for mir::AggregateKind<'tcx> { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(hcx, hasher); match *self { @@ -435,9 +443,9 @@ impl_stable_hash_for!(enum mir::NullOp { impl_stable_hash_for!(struct mir::Constant<'tcx> { span, ty, literal }); -impl<'a, 'tcx> HashStable> for mir::Literal<'tcx> { +impl<'a, 'gcx, 'tcx> HashStable> for mir::Literal<'tcx> { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(hcx, hasher); match *self { diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs index f6ad97445e8b..995f797df2fb 100644 --- a/src/librustc/ich/impls_syntax.rs +++ b/src/librustc/ich/impls_syntax.rs @@ -27,20 +27,21 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult}; use rustc_data_structures::accumulate_vec::AccumulateVec; -impl<'a, 'tcx> HashStable> for ::syntax::symbol::InternedString { +impl<'a, 'gcx, 'tcx> HashStable> +for ::syntax::symbol::InternedString { #[inline] fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { let s: &str = &**self; s.hash_stable(hcx, hasher); } } -impl<'a, 'tcx> HashStable> for ast::Name { +impl<'a, 'gcx, 'tcx> HashStable> for ast::Name { #[inline] fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { self.as_str().hash_stable(hcx, hasher); } @@ -82,9 +83,10 @@ impl_stable_hash_for!(enum ::syntax::abi::Abi { impl_stable_hash_for!(struct ::syntax::attr::Deprecation { since, note }); impl_stable_hash_for!(struct ::syntax::attr::Stability { level, feature, rustc_depr }); -impl<'a, 'tcx> HashStable> for ::syntax::attr::StabilityLevel { +impl<'a, 'gcx, 'tcx> HashStable> +for ::syntax::attr::StabilityLevel { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(hcx, hasher); match *self { @@ -135,9 +137,9 @@ impl_stable_hash_for!(struct ::syntax::ast::Lifetime { id, span, ident }); impl_stable_hash_for!(enum ::syntax::ast::StrStyle { Cooked, Raw(pounds) }); impl_stable_hash_for!(enum ::syntax::ast::AttrStyle { Outer, Inner }); -impl<'a, 'tcx> HashStable> for [ast::Attribute] { +impl<'a, 'gcx, 'tcx> HashStable> for [ast::Attribute] { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { // Some attributes are always ignored during hashing. let filtered: AccumulateVec<[&ast::Attribute; 8]> = self @@ -155,9 +157,9 @@ impl<'a, 'tcx> HashStable> for [ast::Attribute] { } } -impl<'a, 'tcx> HashStable> for ast::Attribute { +impl<'a, 'gcx, 'tcx> HashStable> for ast::Attribute { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { // Make sure that these have been filtered out. debug_assert!(self.name().map(|name| !hcx.is_ignored_attr(name)).unwrap_or(true)); @@ -184,9 +186,10 @@ impl<'a, 'tcx> HashStable> for ast::Attribute { } } -impl<'a, 'tcx> HashStable> for tokenstream::TokenTree { +impl<'a, 'gcx, 'tcx> HashStable> +for tokenstream::TokenTree { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(hcx, hasher); match *self { @@ -205,9 +208,10 @@ impl<'a, 'tcx> HashStable> for tokenstream::Token } } -impl<'a, 'tcx> HashStable> for tokenstream::TokenStream { +impl<'a, 'gcx, 'tcx> HashStable> +for tokenstream::TokenStream { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { for sub_tt in self.trees() { sub_tt.hash_stable(hcx, hasher); @@ -215,8 +219,8 @@ impl<'a, 'tcx> HashStable> for tokenstream::Token } } -fn hash_token<'a, 'tcx, W: StableHasherResult>(token: &token::Token, - hcx: &mut StableHashingContext<'a, 'tcx>, +fn hash_token<'a, 'gcx, 'tcx, W: StableHasherResult>(token: &token::Token, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher, error_reporting_span: Span) { mem::discriminant(token).hash_stable(hcx, hasher); @@ -322,9 +326,9 @@ impl_stable_hash_for!(enum ::syntax::ast::MetaItemKind { NameValue(lit) }); -impl<'a, 'tcx> HashStable> for FileMap { +impl<'a, 'gcx, 'tcx> HashStable> for FileMap { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { let FileMap { ref name, diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index a362dc31ff18..4e78d79ef873 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -19,27 +19,30 @@ use std::mem; use syntax_pos::symbol::InternedString; use ty; -impl<'a, 'tcx, T> HashStable> for &'tcx ty::Slice - where T: HashStable> { +impl<'a, 'gcx, 'tcx, T> HashStable> +for &'tcx ty::Slice + where T: HashStable> { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { (&self[..]).hash_stable(hcx, hasher); } } -impl<'a, 'tcx> HashStable> for ty::subst::Kind<'tcx> { +impl<'a, 'gcx, 'tcx> HashStable> +for ty::subst::Kind<'tcx> { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { self.as_type().hash_stable(hcx, hasher); self.as_region().hash_stable(hcx, hasher); } } -impl<'a, 'tcx> HashStable> for ty::RegionKind { +impl<'a, 'gcx, 'tcx> HashStable> +for ty::RegionKind { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(hcx, hasher); match *self { @@ -72,9 +75,10 @@ impl<'a, 'tcx> HashStable> for ty::RegionKind { } } -impl<'a, 'tcx> HashStable> for ty::adjustment::AutoBorrow<'tcx> { +impl<'a, 'gcx, 'tcx> HashStable> +for ty::adjustment::AutoBorrow<'tcx> { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(hcx, hasher); match *self { @@ -89,9 +93,10 @@ impl<'a, 'tcx> HashStable> for ty::adjustment::Au } } -impl<'a, 'tcx> HashStable> for ty::adjustment::Adjust<'tcx> { +impl<'a, 'gcx, 'tcx> HashStable> +for ty::adjustment::Adjust<'tcx> { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(hcx, hasher); match *self { @@ -122,9 +127,10 @@ impl_stable_hash_for!(enum ty::BorrowKind { MutBorrow }); -impl<'a, 'tcx> HashStable> for ty::UpvarCapture<'tcx> { +impl<'a, 'gcx, 'tcx> HashStable> +for ty::UpvarCapture<'tcx> { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(hcx, hasher); match *self { @@ -143,11 +149,11 @@ impl_stable_hash_for!(struct ty::FnSig<'tcx> { abi }); -impl<'a, 'tcx, T> HashStable> for ty::Binder - where T: HashStable> + ty::fold::TypeFoldable<'tcx> +impl<'a, 'gcx, 'tcx, T> HashStable> for ty::Binder + where T: HashStable> + ty::fold::TypeFoldable<'tcx> { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { hcx.tcx().anonymize_late_bound_regions(self).0.hash_stable(hcx, hasher); } @@ -166,12 +172,13 @@ impl_stable_hash_for!(struct ty::TraitPredicate<'tcx> { trait_ref }); impl_stable_hash_for!(tuple_struct ty::EquatePredicate<'tcx> { t1, t2 }); impl_stable_hash_for!(struct ty::SubtypePredicate<'tcx> { a_is_expected, a, b }); -impl<'a, 'tcx, A, B> HashStable> for ty::OutlivesPredicate - where A: HashStable>, - B: HashStable>, +impl<'a, 'gcx, 'tcx, A, B> HashStable> +for ty::OutlivesPredicate + where A: HashStable>, + B: HashStable>, { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { let ty::OutlivesPredicate(ref a, ref b) = *self; a.hash_stable(hcx, hasher); @@ -183,9 +190,9 @@ impl_stable_hash_for!(struct ty::ProjectionPredicate<'tcx> { projection_ty, ty } impl_stable_hash_for!(struct ty::ProjectionTy<'tcx> { trait_ref, item_def_id }); -impl<'a, 'tcx> HashStable> for ty::Predicate<'tcx> { +impl<'a, 'gcx, 'tcx> HashStable> for ty::Predicate<'tcx> { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(hcx, hasher); match *self { @@ -221,9 +228,9 @@ impl<'a, 'tcx> HashStable> for ty::Predicate<'tcx } } -impl<'a, 'tcx> HashStable> for ty::AdtFlags { +impl<'a, 'gcx, 'tcx> HashStable> for ty::AdtFlags { fn hash_stable(&self, - _: &mut StableHashingContext<'a, 'tcx>, + _: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { std_hash::Hash::hash(self, hasher); } @@ -248,10 +255,10 @@ impl_stable_hash_for!(struct ty::FieldDef { vis }); -impl<'a, 'tcx> HashStable> +impl<'a, 'gcx, 'tcx> HashStable> for ::middle::const_val::ConstVal<'tcx> { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { use middle::const_val::ConstVal; @@ -324,9 +331,9 @@ impl_stable_hash_for!(enum ty::adjustment::CustomCoerceUnsized { Struct(index) }); -impl<'a, 'tcx> HashStable> for ty::Generics { +impl<'a, 'gcx, 'tcx> HashStable> for ty::Generics { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { let ty::Generics { parent, @@ -350,9 +357,10 @@ impl<'a, 'tcx> HashStable> for ty::Generics { } } -impl<'a, 'tcx> HashStable> for ty::RegionParameterDef { +impl<'a, 'gcx, 'tcx> HashStable> +for ty::RegionParameterDef { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { let ty::RegionParameterDef { name, @@ -379,12 +387,12 @@ impl_stable_hash_for!(struct ty::TypeParameterDef { }); -impl<'a, 'tcx, T> HashStable> +impl<'a, 'gcx, 'tcx, T> HashStable> for ::middle::resolve_lifetime::Set1 - where T: HashStable> + where T: HashStable> { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { use middle::resolve_lifetime::Set1; @@ -427,10 +435,11 @@ impl_stable_hash_for!(enum ty::cast::CastKind { FnPtrAddrCast }); -impl<'a, 'tcx> HashStable> for ::middle::region::CodeExtent +impl<'a, 'gcx, 'tcx> HashStable> +for ::middle::region::CodeExtent { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { use middle::region::CodeExtent; @@ -472,10 +481,11 @@ impl_stable_hash_for!(enum ty::BoundRegion { BrEnv }); -impl<'a, 'tcx> HashStable> for ty::TypeVariants<'tcx> +impl<'a, 'gcx, 'tcx> HashStable> +for ty::TypeVariants<'tcx> { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { use ty::TypeVariants::*; @@ -563,10 +573,11 @@ impl_stable_hash_for!(struct ty::TypeAndMut<'tcx> { mutbl }); -impl<'a, 'tcx> HashStable> for ty::ExistentialPredicate<'tcx> +impl<'a, 'gcx, 'tcx> HashStable> +for ty::ExistentialPredicate<'tcx> { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(hcx, hasher); match *self { @@ -595,9 +606,10 @@ impl_stable_hash_for!(struct ty::ExistentialProjection<'tcx> { }); -impl<'a, 'tcx> HashStable> for ty::TypeckTables<'tcx> { +impl<'a, 'gcx, 'tcx> HashStable> +for ty::TypeckTables<'tcx> { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { let ty::TypeckTables { ref type_dependent_defs, diff --git a/src/librustc/macros.rs b/src/librustc/macros.rs index c18e585f7955..f814f941b06f 100644 --- a/src/librustc/macros.rs +++ b/src/librustc/macros.rs @@ -73,10 +73,10 @@ macro_rules! __impl_stable_hash_field { #[macro_export] macro_rules! impl_stable_hash_for { (enum $enum_name:path { $( $variant:ident $( ( $($arg:ident),* ) )* ),* }) => { - impl<'a, 'tcx> ::rustc_data_structures::stable_hasher::HashStable<$crate::ich::StableHashingContext<'a, 'tcx>> for $enum_name { + impl<'a, 'gcx, 'tcx> ::rustc_data_structures::stable_hasher::HashStable<$crate::ich::StableHashingContext<'a, 'gcx, 'tcx>> for $enum_name { #[inline] fn hash_stable(&self, - __ctx: &mut $crate::ich::StableHashingContext<'a, 'tcx>, + __ctx: &mut $crate::ich::StableHashingContext<'a, 'gcx, 'tcx>, __hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher) { use $enum_name::*; ::std::mem::discriminant(self).hash_stable(__ctx, __hasher); @@ -92,10 +92,10 @@ macro_rules! impl_stable_hash_for { } }; (struct $struct_name:path { $($field:ident),* }) => { - impl<'a, 'tcx> ::rustc_data_structures::stable_hasher::HashStable<$crate::ich::StableHashingContext<'a, 'tcx>> for $struct_name { + impl<'a, 'gcx, 'tcx> ::rustc_data_structures::stable_hasher::HashStable<$crate::ich::StableHashingContext<'a, 'gcx, 'tcx>> for $struct_name { #[inline] fn hash_stable(&self, - __ctx: &mut $crate::ich::StableHashingContext<'a, 'tcx>, + __ctx: &mut $crate::ich::StableHashingContext<'a, 'gcx, 'tcx>, __hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher) { let $struct_name { $(ref $field),* @@ -106,10 +106,10 @@ macro_rules! impl_stable_hash_for { } }; (tuple_struct $struct_name:path { $($field:ident),* }) => { - impl<'a, 'tcx> ::rustc_data_structures::stable_hasher::HashStable<$crate::ich::StableHashingContext<'a, 'tcx>> for $struct_name { + impl<'a, 'gcx, 'tcx> ::rustc_data_structures::stable_hasher::HashStable<$crate::ich::StableHashingContext<'a, 'gcx, 'tcx>> for $struct_name { #[inline] fn hash_stable(&self, - __ctx: &mut $crate::ich::StableHashingContext<'a, 'tcx>, + __ctx: &mut $crate::ich::StableHashingContext<'a, 'gcx, 'tcx>, __hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher) { let $struct_name ( $(ref $field),* @@ -125,11 +125,11 @@ macro_rules! impl_stable_hash_for { macro_rules! impl_stable_hash_for_spanned { ($T:path) => ( - impl<'a, 'tcx> HashStable> for ::syntax::codemap::Spanned<$T> + impl<'a, 'gcx, 'tcx> HashStable> for ::syntax::codemap::Spanned<$T> { #[inline] fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { self.node.hash_stable(hcx, hasher); self.span.hash_stable(hcx, hasher); diff --git a/src/librustc/mir/cache.rs b/src/librustc/mir/cache.rs index 799686ceca4a..73c702fedb81 100644 --- a/src/librustc/mir/cache.rs +++ b/src/librustc/mir/cache.rs @@ -35,9 +35,9 @@ impl serialize::Decodable for Cache { } } -impl<'a, 'tcx> HashStable> for Cache { +impl<'a, 'gcx, 'tcx> HashStable> for Cache { fn hash_stable(&self, - _: &mut StableHashingContext<'a, 'tcx>, + _: &mut StableHashingContext<'a, 'gcx, 'tcx>, _: &mut StableHasher) { // do nothing } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 653021119aab..afa2da3d561b 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -465,9 +465,9 @@ impl<'tcx> Hash for TyS<'tcx> { } } -impl<'a, 'tcx> HashStable> for ty::TyS<'tcx> { +impl<'a, 'gcx, 'tcx> HashStable> for ty::TyS<'tcx> { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { let ty::TyS { ref sty, @@ -1318,9 +1318,9 @@ impl<'tcx> serialize::UseSpecializedEncodable for &'tcx AdtDef { impl<'tcx> serialize::UseSpecializedDecodable for &'tcx AdtDef {} -impl<'a, 'tcx> HashStable> for AdtDef { +impl<'a, 'gcx, 'tcx> HashStable> for AdtDef { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { let ty::AdtDef { did, diff --git a/src/librustc_incremental/calculate_svh/mod.rs b/src/librustc_incremental/calculate_svh/mod.rs index be4d610a8955..7831ae3092f4 100644 --- a/src/librustc_incremental/calculate_svh/mod.rs +++ b/src/librustc_incremental/calculate_svh/mod.rs @@ -94,7 +94,7 @@ impl<'a> ::std::ops::Index<&'a DepNode> for IncrementalHashesMap { } struct ComputeItemHashesVisitor<'a, 'tcx: 'a> { - hcx: StableHashingContext<'a, 'tcx>, + hcx: StableHashingContext<'a, 'tcx, 'tcx>, hashes: IncrementalHashesMap, } @@ -103,7 +103,7 @@ impl<'a, 'tcx: 'a> ComputeItemHashesVisitor<'a, 'tcx> { dep_node: DepNode, hash_bodies: bool, item_like: T) - where T: HashStable> + where T: HashStable> { if !hash_bodies && !self.hcx.tcx().sess.opts.build_dep_graph() { // If we just need the hashes in order to compute the SVH, we don't diff --git a/src/librustc_metadata/isolated_encoder.rs b/src/librustc_metadata/isolated_encoder.rs index ed1680fbfaee..c4116489357a 100644 --- a/src/librustc_metadata/isolated_encoder.rs +++ b/src/librustc_metadata/isolated_encoder.rs @@ -23,7 +23,7 @@ use rustc_serialize::Encodable; pub struct IsolatedEncoder<'a, 'b: 'a, 'tcx: 'b> { pub tcx: TyCtxt<'b, 'tcx, 'tcx>, ecx: &'a mut EncodeContext<'b, 'tcx>, - hcx: Option<(StableHashingContext<'b, 'tcx>, StableHasher)>, + hcx: Option<(StableHashingContext<'b, 'tcx, 'tcx>, StableHasher)>, } impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { @@ -61,7 +61,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { } pub fn lazy(&mut self, value: &T) -> Lazy - where T: Encodable + HashStable> + where T: Encodable + HashStable> { if let Some((ref mut hcx, ref mut hasher)) = self.hcx { value.hash_stable(hcx, hasher); @@ -72,7 +72,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { pub fn lazy_seq(&mut self, iter: I) -> LazySeq where I: IntoIterator, - T: Encodable + HashStable> + T: Encodable + HashStable> { if let Some((ref mut hcx, ref mut hasher)) = self.hcx { let iter = iter.into_iter(); @@ -111,7 +111,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { pub fn lazy_seq_ref<'x, I, T>(&mut self, iter: I) -> LazySeq where I: IntoIterator, - T: 'x + Encodable + HashStable> + T: 'x + Encodable + HashStable> { if let Some((ref mut hcx, ref mut hasher)) = self.hcx { let iter = iter.into_iter(); @@ -149,7 +149,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { } pub fn lazy_seq_from_slice(&mut self, slice: &[T]) -> LazySeq - where T: Encodable + HashStable> + where T: Encodable + HashStable> { if let Some((ref mut hcx, ref mut hasher)) = self.hcx { slice.hash_stable(hcx, hasher); @@ -159,7 +159,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { } pub fn lazy_seq_ref_from_slice(&mut self, slice: &[&T]) -> LazySeq - where T: Encodable + HashStable> + where T: Encodable + HashStable> { if let Some((ref mut hcx, ref mut hasher)) = self.hcx { slice.hash_stable(hcx, hasher); diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index 2ffe7cc02aaa..9180f9100ad7 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -221,11 +221,11 @@ impl Tracked { } } -impl<'a, 'tcx, T> HashStable> for Tracked - where T: HashStable> +impl<'a, 'gcx, 'tcx, T> HashStable> for Tracked + where T: HashStable> { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { let Tracked { ref state @@ -277,9 +277,9 @@ pub struct TraitImpls { pub impls: LazySeq, } -impl<'a, 'tcx> HashStable> for TraitImpls { +impl<'a, 'gcx, 'tcx> HashStable> for TraitImpls { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { let TraitImpls { trait_id: (krate, def_index), @@ -359,9 +359,9 @@ pub enum EntryKind<'tcx> { AssociatedConst(AssociatedContainer, u8), } -impl<'a, 'tcx> HashStable> for EntryKind<'tcx> { +impl<'a, 'gcx, 'tcx> HashStable> for EntryKind<'tcx> { fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(hcx, hasher); match *self { From 7fc84907dc39bf36050ec0dfd57f82079f09d993 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Fri, 2 Jun 2017 17:34:24 +0200 Subject: [PATCH 054/233] ICH: Add some HashStable implementations. --- src/librustc/ich/impls_hir.rs | 15 ++++++++++- src/librustc_data_structures/stable_hasher.rs | 26 +++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index 678ec797a86b..7f7a545df960 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -12,7 +12,7 @@ //! types in no particular order. use hir; -use hir::def_id::DefId; +use hir::def_id::{DefId, CrateNum, CRATE_DEF_INDEX}; use ich::{StableHashingContext, NodeIdHashingMode}; use std::mem; @@ -46,6 +46,19 @@ impl<'a, 'gcx, 'tcx> HashStable> for hir::H } } + +impl<'a, 'gcx, 'tcx> HashStable> for CrateNum { + #[inline] + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, + hasher: &mut StableHasher) { + hcx.def_path_hash(DefId { + krate: *self, + index: CRATE_DEF_INDEX + }).hash_stable(hcx, hasher); + } +} + impl_stable_hash_for!(tuple_struct hir::ItemLocalId { index }); // The following implementations of HashStable for ItemId, TraitItemId, and diff --git a/src/librustc_data_structures/stable_hasher.rs b/src/librustc_data_structures/stable_hasher.rs index 635b95d861da..634d3041bf4a 100644 --- a/src/librustc_data_structures/stable_hasher.rs +++ b/src/librustc_data_structures/stable_hasher.rs @@ -244,6 +244,14 @@ impl HashStable for f64 { } } +impl, CTX> HashStable for (T1,) { + fn hash_stable(&self, + ctx: &mut CTX, + hasher: &mut StableHasher) { + self.0.hash_stable(ctx, hasher); + } +} + impl, T2: HashStable, CTX> HashStable for (T1, T2) { fn hash_stable(&self, ctx: &mut CTX, @@ -273,6 +281,24 @@ impl, CTX> HashStable for Vec { } } +impl, CTX> HashStable for ::std::rc::Rc { + #[inline] + fn hash_stable(&self, + ctx: &mut CTX, + hasher: &mut StableHasher) { + (**self).hash_stable(ctx, hasher); + } +} + +impl, CTX> HashStable for ::std::sync::Arc { + #[inline] + fn hash_stable(&self, + ctx: &mut CTX, + hasher: &mut StableHasher) { + (**self).hash_stable(ctx, hasher); + } +} + impl HashStable for str { #[inline] fn hash_stable(&self, From 12e5b699a493e3d67698a9a42c82f686684c32af Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Tue, 6 Jun 2017 15:09:21 +0200 Subject: [PATCH 055/233] incr.comp.: Make WorkProductId opaque so we don't accidentally rely on being able to reconstruct obj-file names from one. --- src/librustc/dep_graph/dep_node.rs | 17 ++++++++++++++--- src/librustc/dep_graph/graph.rs | 15 +++++++-------- src/librustc_incremental/persist/data.rs | 3 +-- src/librustc_incremental/persist/load.rs | 7 +++---- .../persist/work_product.rs | 3 +-- src/librustc_trans/partitioning.rs | 5 ++--- 6 files changed, 28 insertions(+), 22 deletions(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 85a02953a910..1a0f89a1e536 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -9,8 +9,10 @@ // except according to those terms. use hir::def_id::CrateNum; +use ich::Fingerprint; +use rustc_data_structures::stable_hasher::StableHasher; use std::fmt::Debug; -use std::sync::Arc; +use std::hash::Hash; macro_rules! try_opt { ($e:expr) => ( @@ -56,7 +58,7 @@ pub enum DepNode { /// Represents some artifact that we save to disk. Note that these /// do not have a def-id as part of their identifier. - WorkProduct(Arc), + WorkProduct(WorkProductId), // Represents different phases in the compiler. RegionMaps(D), @@ -318,7 +320,16 @@ impl DepNode { /// the need to be mapped or unmapped. (This ensures we can serialize /// them even in the absence of a tcx.) #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] -pub struct WorkProductId(pub String); +pub struct WorkProductId(pub Fingerprint); + +impl WorkProductId { + pub fn from_cgu_name(cgu_name: &str) -> WorkProductId { + let mut hasher = StableHasher::new(); + cgu_name.len().hash(&mut hasher); + cgu_name.hash(&mut hasher); + WorkProductId(hasher.finish()) + } +} #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] pub enum GlobalMetaDataKind { diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index 18eb4e5d0ad7..dc482b0d6ac8 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -13,7 +13,6 @@ use rustc_data_structures::fx::FxHashMap; use session::config::OutputType; use std::cell::{Ref, RefCell}; use std::rc::Rc; -use std::sync::Arc; use super::dep_node::{DepNode, WorkProductId}; use super::query::DepGraphQuery; @@ -35,10 +34,10 @@ struct DepGraphData { /// things available to us. If we find that they are not dirty, we /// load the path to the file storing those work-products here into /// this map. We can later look for and extract that data. - previous_work_products: RefCell, WorkProduct>>, + previous_work_products: RefCell>, /// Work-products that we generate in this run. - work_products: RefCell, WorkProduct>>, + work_products: RefCell>, } impl DepGraph { @@ -120,7 +119,7 @@ impl DepGraph { /// Indicates that a previous work product exists for `v`. This is /// invoked during initial start-up based on what nodes are clean /// (and what files exist in the incr. directory). - pub fn insert_previous_work_product(&self, v: &Arc, data: WorkProduct) { + pub fn insert_previous_work_product(&self, v: &WorkProductId, data: WorkProduct) { debug!("insert_previous_work_product({:?}, {:?})", v, data); self.data.previous_work_products.borrow_mut() .insert(v.clone(), data); @@ -129,7 +128,7 @@ impl DepGraph { /// Indicates that we created the given work-product in this run /// for `v`. This record will be preserved and loaded in the next /// run. - pub fn insert_work_product(&self, v: &Arc, data: WorkProduct) { + pub fn insert_work_product(&self, v: &WorkProductId, data: WorkProduct) { debug!("insert_work_product({:?}, {:?})", v, data); self.data.work_products.borrow_mut() .insert(v.clone(), data); @@ -137,7 +136,7 @@ impl DepGraph { /// Check whether a previous work product exists for `v` and, if /// so, return the path that leads to it. Used to skip doing work. - pub fn previous_work_product(&self, v: &Arc) -> Option { + pub fn previous_work_product(&self, v: &WorkProductId) -> Option { self.data.previous_work_products.borrow() .get(v) .cloned() @@ -145,13 +144,13 @@ impl DepGraph { /// Access the map of work-products created during this run. Only /// used during saving of the dep-graph. - pub fn work_products(&self) -> Ref, WorkProduct>> { + pub fn work_products(&self) -> Ref> { self.data.work_products.borrow() } /// Access the map of work-products created during the cached run. Only /// used during saving of the dep-graph. - pub fn previous_work_products(&self) -> Ref, WorkProduct>> { + pub fn previous_work_products(&self) -> Ref> { self.data.previous_work_products.borrow() } } diff --git a/src/librustc_incremental/persist/data.rs b/src/librustc_incremental/persist/data.rs index 682a7051a1e9..4669bb866d41 100644 --- a/src/librustc_incremental/persist/data.rs +++ b/src/librustc_incremental/persist/data.rs @@ -15,7 +15,6 @@ use rustc::hir::def_id::DefIndex; use rustc::hir::map::DefPathHash; use rustc::ich::Fingerprint; use rustc::middle::cstore::EncodedMetadataHash; -use std::sync::Arc; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::indexed_vec::{IndexVec, Idx}; @@ -98,7 +97,7 @@ pub struct SerializedHash { #[derive(Debug, RustcEncodable, RustcDecodable)] pub struct SerializedWorkProduct { /// node that produced the work-product - pub id: Arc, + pub id: WorkProductId, /// work-product data itself pub work_product: WorkProduct, diff --git a/src/librustc_incremental/persist/load.rs b/src/librustc_incremental/persist/load.rs index b30a1f4d3254..f2ecf4c74e78 100644 --- a/src/librustc_incremental/persist/load.rs +++ b/src/librustc_incremental/persist/load.rs @@ -22,7 +22,6 @@ use rustc_serialize::Decodable as RustcDecodable; use rustc_serialize::opaque::Decoder; use std::default::Default; use std::path::{Path}; -use std::sync::Arc; use IncrementalHashesMap; use super::data::*; @@ -327,7 +326,7 @@ fn transitive_dirty_nodes(edge_map: &FxHashMap, Vec(tcx: TyCtxt<'a, 'tcx, 'tcx>, work_products: Vec, - clean_work_products: &FxHashSet>) { + clean_work_products: &FxHashSet) { debug!("reconcile_work_products({:?})", work_products); for swp in work_products { if !clean_work_products.contains(&swp.id) { @@ -424,8 +423,8 @@ fn process_edges<'a, 'tcx, 'edges>( target: &'edges DepNode, edges: &'edges FxHashMap, Vec>>, dirty_raw_nodes: &DirtyNodes, - clean_work_products: &mut FxHashSet>, - dirty_work_products: &mut FxHashSet>, + clean_work_products: &mut FxHashSet, + dirty_work_products: &mut FxHashSet, extra_edges: &mut Vec<(&'edges DepNode, &'edges DepNode)>) { // If the target is dirty, skip the edge. If this is an edge diff --git a/src/librustc_incremental/persist/work_product.rs b/src/librustc_incremental/persist/work_product.rs index 0e9f90615401..16ab10ab4bbb 100644 --- a/src/librustc_incremental/persist/work_product.rs +++ b/src/librustc_incremental/persist/work_product.rs @@ -16,7 +16,6 @@ use rustc::session::Session; use rustc::session::config::OutputType; use rustc::util::fs::link_or_copy; use std::path::PathBuf; -use std::sync::Arc; use std::fs as std_fs; pub fn save_trans_partition(sess: &Session, @@ -30,7 +29,7 @@ pub fn save_trans_partition(sess: &Session, if sess.opts.incremental.is_none() { return; } - let work_product_id = Arc::new(WorkProductId(cgu_name.to_string())); + let work_product_id = WorkProductId::from_cgu_name(cgu_name); let saved_files: Option> = files.iter() diff --git a/src/librustc_trans/partitioning.rs b/src/librustc_trans/partitioning.rs index 2fe463e92a8a..df8984e6d247 100644 --- a/src/librustc_trans/partitioning.rs +++ b/src/librustc_trans/partitioning.rs @@ -114,7 +114,6 @@ use rustc::ty::{self, TyCtxt}; use rustc::ty::item_path::characteristic_def_id_of_type; use rustc_incremental::IchHasher; use std::hash::Hash; -use std::sync::Arc; use syntax::ast::NodeId; use syntax::symbol::{Symbol, InternedString}; use trans_item::{TransItem, InstantiationMode}; @@ -164,8 +163,8 @@ impl<'tcx> CodegenUnit<'tcx> { &self.items } - pub fn work_product_id(&self) -> Arc { - Arc::new(WorkProductId(self.name().to_string())) + pub fn work_product_id(&self) -> WorkProductId { + WorkProductId::from_cgu_name(self.name()) } pub fn work_product_dep_node(&self) -> DepNode { From 4c908a9d37d1ed173e4226c3b71e9f05b7260c39 Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Tue, 6 Jun 2017 18:09:33 +0100 Subject: [PATCH 056/233] Enable profiler selectively on some builders --- .travis.yml | 6 +++--- appveyor.yml | 8 +++++--- src/ci/docker/dist-i686-linux/Dockerfile | 3 ++- src/ci/docker/dist-x86_64-linux/Dockerfile | 3 ++- src/ci/docker/x86_64-gnu/Dockerfile | 2 +- src/ci/run.sh | 1 - 6 files changed, 13 insertions(+), 10 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9ef759b3f80a..cf7134f873a5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -54,7 +54,7 @@ matrix: # version that we're using, 8.2, cannot compile LLVM for OSX 10.7. - env: > RUST_CHECK_TARGET=check - RUST_CONFIGURE_ARGS="--build=x86_64-apple-darwin --enable-sanitizers" + RUST_CONFIGURE_ARGS="--build=x86_64-apple-darwin --enable-sanitizers --enable-profiler" SRC=. RUSTC_RETRY_LINKER_ON_SEGFAULT=1 SCCACHE_ERROR_LOG=/tmp/sccache.log @@ -87,7 +87,7 @@ matrix: # OSX 10.7 and `xcode7` is the latest Xcode able to compile LLVM for 10.7. - env: > RUST_CHECK_TARGET=dist - RUST_CONFIGURE_ARGS="--build=i686-apple-darwin --enable-extended" + RUST_CONFIGURE_ARGS="--build=i686-apple-darwin --enable-extended --enable-profiler" SRC=. DEPLOY=1 RUSTC_RETRY_LINKER_ON_SEGFAULT=1 @@ -101,7 +101,7 @@ matrix: - *osx_install_sccache - env: > RUST_CHECK_TARGET=dist - RUST_CONFIGURE_ARGS="--target=aarch64-apple-ios,armv7-apple-ios,armv7s-apple-ios,i386-apple-ios,x86_64-apple-ios --enable-extended --enable-sanitizers" + RUST_CONFIGURE_ARGS="--target=aarch64-apple-ios,armv7-apple-ios,armv7s-apple-ios,i386-apple-ios,x86_64-apple-ios --enable-extended --enable-sanitizers --enable-profiler" SRC=. DEPLOY=1 RUSTC_RETRY_LINKER_ON_SEGFAULT=1 diff --git a/appveyor.yml b/appveyor.yml index 96de1d90f25e..d4f805de5de3 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -7,7 +7,7 @@ environment: matrix: # 32/64 bit MSVC tests - MSYS_BITS: 64 - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler SCRIPT: python x.py test - MSYS_BITS: 32 RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc --target=i586-pc-windows-msvc @@ -48,16 +48,18 @@ environment: - RUST_CONFIGURE_ARGS: > --build=x86_64-pc-windows-msvc --enable-extended + --enable-profiler SCRIPT: python x.py dist DEPLOY: 1 - RUST_CONFIGURE_ARGS: > --build=i686-pc-windows-msvc --target=i586-pc-windows-msvc --enable-extended + --enable-profiler SCRIPT: python x.py dist DEPLOY: 1 - MSYS_BITS: 32 - RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu --enable-extended + RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu --enable-extended --enable-profiler SCRIPT: python x.py dist MINGW_URL: https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z @@ -65,7 +67,7 @@ environment: DEPLOY: 1 - MSYS_BITS: 64 SCRIPT: python x.py dist - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu --enable-extended + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu --enable-extended --enable-profiler MINGW_URL: https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z MINGW_DIR: mingw64 diff --git a/src/ci/docker/dist-i686-linux/Dockerfile b/src/ci/docker/dist-i686-linux/Dockerfile index a3c08e93ed15..9145e9dfc8d1 100644 --- a/src/ci/docker/dist-i686-linux/Dockerfile +++ b/src/ci/docker/dist-i686-linux/Dockerfile @@ -90,7 +90,8 @@ ENV HOSTS=i686-unknown-linux-gnu ENV RUST_CONFIGURE_ARGS \ --host=$HOSTS \ --enable-extended \ - --enable-sanitizers + --enable-sanitizers \ + --enable-profiler ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS # This is the only builder which will create source tarballs diff --git a/src/ci/docker/dist-x86_64-linux/Dockerfile b/src/ci/docker/dist-x86_64-linux/Dockerfile index e2e42836dcda..78b62839a35d 100644 --- a/src/ci/docker/dist-x86_64-linux/Dockerfile +++ b/src/ci/docker/dist-x86_64-linux/Dockerfile @@ -90,7 +90,8 @@ ENV HOSTS=x86_64-unknown-linux-gnu ENV RUST_CONFIGURE_ARGS \ --host=$HOSTS \ --enable-extended \ - --enable-sanitizers + --enable-sanitizers \ + --enable-profiler ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS # This is the only builder which will create source tarballs diff --git a/src/ci/docker/x86_64-gnu/Dockerfile b/src/ci/docker/x86_64-gnu/Dockerfile index de85e1ff36af..0bbbded57f27 100644 --- a/src/ci/docker/x86_64-gnu/Dockerfile +++ b/src/ci/docker/x86_64-gnu/Dockerfile @@ -22,5 +22,5 @@ RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-ini rm dumb-init_*.deb ENTRYPOINT ["/usr/bin/dumb-init", "--"] -ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu --enable-sanitizers +ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu --enable-sanitizers --enable-profiler ENV SCRIPT python2.7 ../x.py test diff --git a/src/ci/run.sh b/src/ci/run.sh index 763d6684463c..549e804603c0 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -32,7 +32,6 @@ RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --disable-manage-submodules" RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-locked-deps" RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-cargo-openssl-static" RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-llvm-clean-rebuild" -RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-profiler" if [ "$DIST_SRC" = "" ]; then RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --disable-dist-src" From c1c2cd23765bf7dbaa41a99ae6f8f763ed6852b4 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Tue, 6 Jun 2017 22:43:59 +0300 Subject: [PATCH 057/233] Statements do not have types. --- src/librustc_typeck/check/mod.rs | 39 ++++++-------------------- src/librustc_typeck/check/writeback.rs | 5 ---- 2 files changed, 9 insertions(+), 35 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index c3bce8048796..04469dcaf2bd 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -120,7 +120,7 @@ use syntax::feature_gate::{GateIssue, emit_feature_err}; use syntax::ptr::P; use syntax::symbol::{Symbol, InternedString, keywords}; use syntax::util::lev_distance::find_best_match_for_name; -use syntax_pos::{self, BytePos, Span, DUMMY_SP}; +use syntax_pos::{self, BytePos, Span}; use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; use rustc::hir::itemlikevisit::ItemLikeVisitor; @@ -1901,14 +1901,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { value) } - pub fn write_nil(&self, node_id: ast::NodeId) { - self.write_ty(node_id, self.tcx.mk_nil()); - } - - pub fn write_error(&self, node_id: ast::NodeId) { - self.write_ty(node_id, self.tcx.types.err); - } - pub fn require_type_meets(&self, ty: Ty<'tcx>, span: Span, @@ -4020,11 +4012,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { pub fn check_stmt(&self, stmt: &'gcx hir::Stmt) { // Don't do all the complex logic below for DeclItem. match stmt.node { - hir::StmtDecl(ref decl, id) => { + hir::StmtDecl(ref decl, _) => { match decl.node { hir::DeclLocal(_) => {} hir::DeclItem(_) => { - self.write_nil(id); return; } } @@ -4040,34 +4031,22 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.diverges.set(Diverges::Maybe); self.has_errors.set(false); - let (node_id, _span) = match stmt.node { - hir::StmtDecl(ref decl, id) => { - let span = match decl.node { + match stmt.node { + hir::StmtDecl(ref decl, _) => { + match decl.node { hir::DeclLocal(ref l) => { self.check_decl_local(&l); - l.span } - hir::DeclItem(_) => {/* ignore for now */ - DUMMY_SP - } - }; - (id, span) + hir::DeclItem(_) => {/* ignore for now */} + } } - hir::StmtExpr(ref expr, id) => { + hir::StmtExpr(ref expr, _) => { // Check with expected type of () self.check_expr_has_type(&expr, self.tcx.mk_nil()); - (id, expr.span) } - hir::StmtSemi(ref expr, id) => { + hir::StmtSemi(ref expr, _) => { self.check_expr(&expr); - (id, expr.span) } - }; - - if self.has_errors.get() { - self.write_error(node_id); - } else { - self.write_nil(node_id); } // Combine the diverging and has_error flags. diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 012fde16d875..4af262bcb78d 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -155,11 +155,6 @@ impl<'cx, 'gcx, 'tcx> Visitor<'gcx> for WritebackCx<'cx, 'gcx, 'tcx> { NestedVisitorMap::None } - fn visit_stmt(&mut self, s: &'gcx hir::Stmt) { - self.visit_node_id(s.span, s.node.id()); - intravisit::walk_stmt(self, s); - } - fn visit_expr(&mut self, e: &'gcx hir::Expr) { self.fix_scalar_builtin_expr(e); From bc7eb3bd3af6e9108733d2bb9432381abf1cc278 Mon Sep 17 00:00:00 2001 From: gaurikholkar Date: Thu, 1 Jun 2017 15:46:26 +0530 Subject: [PATCH 058/233] Changing error message for interior mutability, adding ui test --- src/librustc_mir/diagnostics.rs | 8 ++++---- src/librustc_mir/transform/qualify_consts.rs | 2 +- src/libstd/panic.rs | 2 +- .../compile-fail/issue-17718-const-borrow.rs | 6 +++--- .../interior-mutability/interior-mutability.rs | 16 ++++++++++++++++ .../interior-mutability.stderr | 14 ++++++++++++++ 6 files changed, 39 insertions(+), 9 deletions(-) create mode 100644 src/test/ui/interior-mutability/interior-mutability.rs create mode 100644 src/test/ui/interior-mutability/interior-mutability.stderr diff --git a/src/librustc_mir/diagnostics.rs b/src/librustc_mir/diagnostics.rs index bb07081fe433..0edd5d44b606 100644 --- a/src/librustc_mir/diagnostics.rs +++ b/src/librustc_mir/diagnostics.rs @@ -309,8 +309,8 @@ use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT}; const A: AtomicUsize = ATOMIC_USIZE_INIT; static B: &'static AtomicUsize = &A; -// error: cannot borrow a constant which contains interior mutability, create a -// static instead +// error: cannot borrow a constant which may contain interior mutability, +// create a static instead ``` A `const` represents a constant value that should never change. If one takes @@ -338,8 +338,8 @@ use std::cell::Cell; const A: Cell = Cell::new(1); const B: &'static Cell = &A; -// error: cannot borrow a constant which contains interior mutability, create -// a static instead +// error: cannot borrow a constant which may contain interior mutability, +// create a static instead // or: struct C { a: Cell } diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index ef88e813a50c..793cffdec89e 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -663,7 +663,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { self.add(Qualif::NOT_CONST); if self.mode != Mode::Fn { span_err!(self.tcx.sess, self.span, E0492, - "cannot borrow a constant which contains \ + "cannot borrow a constant which may contain \ interior mutability, create a static instead"); } } diff --git a/src/libstd/panic.rs b/src/libstd/panic.rs index f99634ecac23..58356bc43eeb 100644 --- a/src/libstd/panic.rs +++ b/src/libstd/panic.rs @@ -112,7 +112,7 @@ pub trait UnwindSafe {} /// This is a "helper marker trait" used to provide impl blocks for the /// `UnwindSafe` trait, for more information see that documentation. #[stable(feature = "catch_unwind", since = "1.9.0")] -#[rustc_on_unimplemented = "the type {Self} contains interior mutability \ +#[rustc_on_unimplemented = "the type {Self} may contain interior mutability \ and a reference may not be safely transferrable \ across a catch_unwind boundary"] pub trait RefUnwindSafe {} diff --git a/src/test/compile-fail/issue-17718-const-borrow.rs b/src/test/compile-fail/issue-17718-const-borrow.rs index ec6d1141c1a0..327b69468229 100644 --- a/src/test/compile-fail/issue-17718-const-borrow.rs +++ b/src/test/compile-fail/issue-17718-const-borrow.rs @@ -14,13 +14,13 @@ use std::cell::UnsafeCell; const A: UnsafeCell = UnsafeCell::new(1); const B: &'static UnsafeCell = &A; -//~^ ERROR: cannot borrow a constant which contains interior mutability +//~^ ERROR: cannot borrow a constant which may contain interior mutability struct C { a: UnsafeCell } const D: C = C { a: UnsafeCell::new(1) }; const E: &'static UnsafeCell = &D.a; -//~^ ERROR: cannot borrow a constant which contains interior mutability +//~^ ERROR: cannot borrow a constant which may contain interior mutability const F: &'static C = &D; -//~^ ERROR: cannot borrow a constant which contains interior mutability +//~^ ERROR: cannot borrow a constant which may contain interior mutability fn main() {} diff --git a/src/test/ui/interior-mutability/interior-mutability.rs b/src/test/ui/interior-mutability/interior-mutability.rs new file mode 100644 index 000000000000..60d85d1b3b78 --- /dev/null +++ b/src/test/ui/interior-mutability/interior-mutability.rs @@ -0,0 +1,16 @@ +// 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. + +use std::cell::Cell; +use std::panic::catch_unwind; +fn main() { + let mut x = Cell::new(22); + catch_unwind(|| { x.set(23); }); +} diff --git a/src/test/ui/interior-mutability/interior-mutability.stderr b/src/test/ui/interior-mutability/interior-mutability.stderr new file mode 100644 index 000000000000..a9535f1c8303 --- /dev/null +++ b/src/test/ui/interior-mutability/interior-mutability.stderr @@ -0,0 +1,14 @@ +error[E0277]: the trait bound `std::cell::UnsafeCell: std::panic::RefUnwindSafe` is not satisfied in `std::cell::Cell` + --> $DIR/interior-mutability.rs:15:5 + | +15 | catch_unwind(|| { x.set(23); }); + | ^^^^^^^^^^^^ the type std::cell::UnsafeCell may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary + | + = help: within `std::cell::Cell`, the trait `std::panic::RefUnwindSafe` is not implemented for `std::cell::UnsafeCell` + = note: required because it appears within the type `std::cell::Cell` + = note: required because of the requirements on the impl of `std::panic::UnwindSafe` for `&std::cell::Cell` + = note: required because it appears within the type `[closure@$DIR/interior-mutability.rs:15:18: 15:35 x:&std::cell::Cell]` + = note: required by `std::panic::catch_unwind` + +error: aborting due to previous error(s) + From e37cfc7dd29aeea001d006e7dbd1a53556f9f1de Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 6 Jun 2017 14:26:56 -0700 Subject: [PATCH 059/233] bootstrap: improve 'build --help' by explaining what exactly the last example does --- src/bootstrap/flags.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index f100baa5d2ca..3a265b2f3bbb 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -198,7 +198,11 @@ Arguments: For a quick build with a usable compile, you can pass: - ./x.py build --stage 1 src/libtest"); + ./x.py build --stage 1 src/libtest + + This will first build everything once (like --stage 0 without further + arguments would), and then use the compiler built in stage 0 to build + src/libtest and its dependencies."); } "test" => { subcommand_help.push_str("\n From e8689c7de71f822dca891099a94c9377c36e46b2 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Mon, 5 Jun 2017 19:07:43 -0700 Subject: [PATCH 060/233] Fix setting PATH during linkage on windows-gnu --- src/librustc_trans/back/link.rs | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index ee92a4b4a2df..e57cbb1c9101 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -141,17 +141,20 @@ pub fn build_link_meta(incremental_hashes_map: &IncrementalHashesMap) -> LinkMet return r; } -// The third parameter is for an env vars, used to set up the path for MSVC -// to find its DLLs +// The third parameter is for env vars, used on windows to set up the +// path for MSVC to find its DLLs, and gcc to find its bundled +// toolchain pub fn get_linker(sess: &Session) -> (String, Command, Vec<(OsString, OsString)>) { + let envs = vec![("PATH".into(), command_path(sess))]; + if let Some(ref linker) = sess.opts.cg.linker { - (linker.clone(), Command::new(linker), vec![]) + (linker.clone(), Command::new(linker), envs) } else if sess.target.target.options.is_like_msvc { let (cmd, envs) = msvc_link_exe_cmd(sess); ("link.exe".to_string(), cmd, envs) } else { - (sess.target.target.options.linker.clone(), - Command::new(&sess.target.target.options.linker), vec![]) + let linker = &sess.target.target.options.linker; + (linker.clone(), Command::new(&linker), envs) } } @@ -182,7 +185,7 @@ pub fn get_ar_prog(sess: &Session) -> String { }) } -fn command_path(sess: &Session, extra: Option) -> OsString { +fn command_path(sess: &Session) -> OsString { // The compiler's sysroot often has some bundled tools, so add it to the // PATH for the child. let mut new_path = sess.host_filesearch(PathKind::All) @@ -190,7 +193,6 @@ fn command_path(sess: &Session, extra: Option) -> OsString { if let Some(path) = env::var_os("PATH") { new_path.extend(env::split_paths(&path)); } - new_path.extend(extra); env::join_paths(new_path).unwrap() } @@ -451,7 +453,7 @@ fn archive_config<'a>(sess: &'a Session, src: input.map(|p| p.to_path_buf()), lib_search_paths: archive_search_paths(sess), ar_prog: get_ar_prog(sess), - command_path: command_path(sess, None), + command_path: command_path(sess), } } @@ -727,7 +729,7 @@ fn link_natively(sess: &Session, // The invocations of cc share some flags across platforms let (pname, mut cmd, envs) = get_linker(sess); - // This will set PATH on MSVC + // This will set PATH on windows cmd.envs(envs); let root = sess.target_filesearch(PathKind::Native).get_lib_path(); From 2cadc32b66e135eeb9ac22d433cd931b021792a5 Mon Sep 17 00:00:00 2001 From: Nick Whitney Date: Tue, 6 Jun 2017 01:31:46 -0400 Subject: [PATCH 061/233] Add max and min default fns to Ord trait Pursuant to issue #25663, this commit adds the max and min functions to the Ord trait, enabling items that implement Ord to use UFCS (ex. 1.max(2)) instead of the longer std::cmp::max(1,2) format. --- src/doc/unstable-book/src/SUMMARY.md | 1 + .../src/library-features/ord-max-min.md | 7 ++++ src/libcore/cmp.rs | 36 +++++++++++++++++++ src/libcore/tests/cmp.rs | 10 ++++++ src/libcore/tests/lib.rs | 1 + 5 files changed, 55 insertions(+) create mode 100644 src/doc/unstable-book/src/library-features/ord-max-min.md diff --git a/src/doc/unstable-book/src/SUMMARY.md b/src/doc/unstable-book/src/SUMMARY.md index 2b3ef338fad5..b278b5dbb2ca 100644 --- a/src/doc/unstable-book/src/SUMMARY.md +++ b/src/doc/unstable-book/src/SUMMARY.md @@ -165,6 +165,7 @@ - [n16](library-features/n16.md) - [never_type_impls](library-features/never-type-impls.md) - [nonzero](library-features/nonzero.md) + - [ord_max_min](library-features/ord-max-min.md) - [offset_to](library-features/offset-to.md) - [once_poison](library-features/once-poison.md) - [oom](library-features/oom.md) diff --git a/src/doc/unstable-book/src/library-features/ord-max-min.md b/src/doc/unstable-book/src/library-features/ord-max-min.md new file mode 100644 index 000000000000..564cd1ac30b2 --- /dev/null +++ b/src/doc/unstable-book/src/library-features/ord-max-min.md @@ -0,0 +1,7 @@ +# `ord-max-min` + +The tracking issue for this feature is: [#25663] + +[#25663]: https://github.com/rust-lang/rust/issues/25663 + +------------------------ diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index 661cf73c7f30..4c50b11e7050 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -443,6 +443,42 @@ pub trait Ord: Eq + PartialOrd { /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn cmp(&self, other: &Self) -> Ordering; + + /// Compares and returns the maximum of two values. + /// + /// Returns the second argument if the comparison determines them to be equal. + /// + /// # Examples + /// + /// ``` + /// #![feature(ord_max_min)] + /// + /// assert_eq!(2, 1.max(2)); + /// assert_eq!(2, 2.max(2)); + /// ``` + #[unstable(feature = "ord_max_min", issue = "25663")] + fn max(self, other: Self) -> Self + where Self: Sized { + if other >= self { other } else { self } + } + + /// Compares and returns the minimum of two values. + /// + /// Returns the first argument if the comparison determines them to be equal. + /// + /// # Examples + /// + /// ``` + /// #![feature(ord_max_min)] + /// + /// assert_eq!(1, 1.min(2)); + /// assert_eq!(2, 2.min(2)); + /// ``` + #[unstable(feature = "ord_max_min", issue = "25663")] + fn min(self, other: Self) -> Self + where Self: Sized { + if self <= other { self } else { other } + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/tests/cmp.rs b/src/libcore/tests/cmp.rs index e3c65ad8b33c..8c5179f59932 100644 --- a/src/libcore/tests/cmp.rs +++ b/src/libcore/tests/cmp.rs @@ -28,6 +28,16 @@ fn test_mut_int_totalord() { assert_eq!((&mut 12).cmp(&&mut -5), Greater); } +#[test] +fn test_ord_max_min() { + assert_eq!(1.max(2), 2); + assert_eq!(2.max(1), 2); + assert_eq!(1.min(2), 1); + assert_eq!(2.min(1), 1); + assert_eq!(1.max(1), 1); + assert_eq!(1.min(1), 1); +} + #[test] fn test_ordering_reverse() { assert_eq!(Less.reverse(), Greater); diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index 505e51fa80b3..77a9307f43ec 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -26,6 +26,7 @@ #![feature(iter_rfind)] #![feature(libc)] #![feature(nonzero)] +#![feature(ord_max_min)] #![feature(rand)] #![feature(raw)] #![feature(sip_hash_13)] From a32ffc679702e3ae307c7fc20873c9e970a8894c Mon Sep 17 00:00:00 2001 From: Nick Whitney Date: Tue, 6 Jun 2017 23:00:09 -0400 Subject: [PATCH 062/233] Alias std::cmp::max/min to Ord::max/min --- src/libcore/cmp.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index 4c50b11e7050..6f35d0417f18 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -714,6 +714,8 @@ pub trait PartialOrd: PartialEq { /// /// Returns the first argument if the comparison determines them to be equal. /// +/// Internally uses an alias to `Ord::min`. +/// /// # Examples /// /// ``` @@ -725,13 +727,15 @@ pub trait PartialOrd: PartialEq { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn min(v1: T, v2: T) -> T { - if v1 <= v2 { v1 } else { v2 } + v1.min(v2) } /// Compares and returns the maximum of two values. /// /// Returns the second argument if the comparison determines them to be equal. /// +/// Internally uses an alias to `Ord::max`. +/// /// # Examples /// /// ``` @@ -743,7 +747,7 @@ pub fn min(v1: T, v2: T) -> T { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn max(v1: T, v2: T) -> T { - if v2 >= v1 { v2 } else { v1 } + v1.max(v2) } // Implementation of PartialEq, Eq, PartialOrd and Ord for primitive types From ab72611d8f664684dbd5dd2efe6fd7edff53ee5d Mon Sep 17 00:00:00 2001 From: Masaki Hara Date: Sun, 4 Jun 2017 14:10:14 +0900 Subject: [PATCH 063/233] Replace some matches with try. --- src/librustc_resolve/macros.rs | 5 +---- src/libsyntax/parse/parser.rs | 5 +---- src/libsyntax/ptr.rs | 5 +---- 3 files changed, 3 insertions(+), 12 deletions(-) diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index a950a9a23e47..60c07eda4d5c 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -285,10 +285,7 @@ impl<'a> base::Resolver for Resolver<'a> { -> Result>, Determinacy> { let def = match invoc.kind { InvocationKind::Attr { attr: None, .. } => return Ok(None), - _ => match self.resolve_invoc_to_def(invoc, scope, force) { - Ok(def) => def, - Err(determinacy) => return Err(determinacy), - }, + _ => self.resolve_invoc_to_def(invoc, scope, force)?, }; self.macro_defs.insert(invoc.expansion_data.mark, def.def_id()); diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index d9cb2b4ab7db..1e156ed07b0c 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1249,10 +1249,7 @@ impl<'a> Parser<'a> { let mac = respan(lo.to(self.prev_span), Mac_ { path: pth, tts: tts }); (keywords::Invalid.ident(), ast::TraitItemKind::Macro(mac)) } else { - let (constness, unsafety, abi) = match self.parse_fn_front_matter() { - Ok(cua) => cua, - Err(e) => return Err(e), - }; + let (constness, unsafety, abi) = self.parse_fn_front_matter()?; let ident = self.parse_ident()?; let mut generics = self.parse_generics()?; diff --git a/src/libsyntax/ptr.rs b/src/libsyntax/ptr.rs index 15111bbba0a9..d51ff9860ac8 100644 --- a/src/libsyntax/ptr.rs +++ b/src/libsyntax/ptr.rs @@ -211,10 +211,7 @@ impl Encodable for P<[T]> { impl Decodable for P<[T]> { fn decode(d: &mut D) -> Result, D::Error> { - Ok(P::from_vec(match Decodable::decode(d) { - Ok(t) => t, - Err(e) => return Err(e) - })) + Ok(P::from_vec(Decodable::decode(d)?)) } } From 0fb8414f147ced57e49630ea31be5a585f728c04 Mon Sep 17 00:00:00 2001 From: Henri Sivonen Date: Wed, 7 Jun 2017 11:17:16 +0300 Subject: [PATCH 064/233] Change `llvm.neon.*` to `llvm.arm.neon.*` in the mapping for platform intrinsics This avoids linker errors when using platform intrinsics on 32-bit ARM with NEON. Fixes rust-lang-nursery/simd#10. --- src/etc/platform-intrinsics/arm.json | 2 +- src/librustc_platform_intrinsics/arm.rs | 780 ++++++++++++------------ 2 files changed, 391 insertions(+), 391 deletions(-) diff --git a/src/etc/platform-intrinsics/arm.json b/src/etc/platform-intrinsics/arm.json index 39e49e239f34..d008320713c3 100644 --- a/src/etc/platform-intrinsics/arm.json +++ b/src/etc/platform-intrinsics/arm.json @@ -1,7 +1,7 @@ { "platform": "arm_v", "intrinsic_prefix": "", - "llvm_prefix": "llvm.neon.v", + "llvm_prefix": "llvm.arm.neon.v", "number_info": { "signed": { "kind": "s", diff --git a/src/librustc_platform_intrinsics/arm.rs b/src/librustc_platform_intrinsics/arm.rs index 834528aaaa31..59ac5ccc53f5 100644 --- a/src/librustc_platform_intrinsics/arm.rs +++ b/src/librustc_platform_intrinsics/arm.rs @@ -25,232 +25,232 @@ pub fn find(name: &str) -> Option { "hadd_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x8, &::I8x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vhadds.v8i8") + definition: Named("llvm.arm.neon.vhadds.v8i8") }, "hadd_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x8, &::U8x8]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vhaddu.v8i8") + definition: Named("llvm.arm.neon.vhaddu.v8i8") }, "hadd_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x4, &::I16x4]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vhadds.v4i16") + definition: Named("llvm.arm.neon.vhadds.v4i16") }, "hadd_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x4, &::U16x4]; &INPUTS }, output: &::U16x4, - definition: Named("llvm.neon.vhaddu.v4i16") + definition: Named("llvm.arm.neon.vhaddu.v4i16") }, "hadd_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x2, &::I32x2]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vhadds.v2i32") + definition: Named("llvm.arm.neon.vhadds.v2i32") }, "hadd_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x2, &::U32x2]; &INPUTS }, output: &::U32x2, - definition: Named("llvm.neon.vhaddu.v2i32") + definition: Named("llvm.arm.neon.vhaddu.v2i32") }, "haddq_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x16, &::I8x16]; &INPUTS }, output: &::I8x16, - definition: Named("llvm.neon.vhadds.v16i8") + definition: Named("llvm.arm.neon.vhadds.v16i8") }, "haddq_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x16, &::U8x16]; &INPUTS }, output: &::U8x16, - definition: Named("llvm.neon.vhaddu.v16i8") + definition: Named("llvm.arm.neon.vhaddu.v16i8") }, "haddq_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::I16x8]; &INPUTS }, output: &::I16x8, - definition: Named("llvm.neon.vhadds.v8i16") + definition: Named("llvm.arm.neon.vhadds.v8i16") }, "haddq_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x8, &::U16x8]; &INPUTS }, output: &::U16x8, - definition: Named("llvm.neon.vhaddu.v8i16") + definition: Named("llvm.arm.neon.vhaddu.v8i16") }, "haddq_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::I32x4]; &INPUTS }, output: &::I32x4, - definition: Named("llvm.neon.vhadds.v4i32") + definition: Named("llvm.arm.neon.vhadds.v4i32") }, "haddq_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::U32x4]; &INPUTS }, output: &::U32x4, - definition: Named("llvm.neon.vhaddu.v4i32") + definition: Named("llvm.arm.neon.vhaddu.v4i32") }, "rhadd_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x8, &::I8x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vrhadds.v8i8") + definition: Named("llvm.arm.neon.vrhadds.v8i8") }, "rhadd_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x8, &::U8x8]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vrhaddu.v8i8") + definition: Named("llvm.arm.neon.vrhaddu.v8i8") }, "rhadd_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x4, &::I16x4]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vrhadds.v4i16") + definition: Named("llvm.arm.neon.vrhadds.v4i16") }, "rhadd_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x4, &::U16x4]; &INPUTS }, output: &::U16x4, - definition: Named("llvm.neon.vrhaddu.v4i16") + definition: Named("llvm.arm.neon.vrhaddu.v4i16") }, "rhadd_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x2, &::I32x2]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vrhadds.v2i32") + definition: Named("llvm.arm.neon.vrhadds.v2i32") }, "rhadd_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x2, &::U32x2]; &INPUTS }, output: &::U32x2, - definition: Named("llvm.neon.vrhaddu.v2i32") + definition: Named("llvm.arm.neon.vrhaddu.v2i32") }, "rhaddq_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x16, &::I8x16]; &INPUTS }, output: &::I8x16, - definition: Named("llvm.neon.vrhadds.v16i8") + definition: Named("llvm.arm.neon.vrhadds.v16i8") }, "rhaddq_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x16, &::U8x16]; &INPUTS }, output: &::U8x16, - definition: Named("llvm.neon.vrhaddu.v16i8") + definition: Named("llvm.arm.neon.vrhaddu.v16i8") }, "rhaddq_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::I16x8]; &INPUTS }, output: &::I16x8, - definition: Named("llvm.neon.vrhadds.v8i16") + definition: Named("llvm.arm.neon.vrhadds.v8i16") }, "rhaddq_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x8, &::U16x8]; &INPUTS }, output: &::U16x8, - definition: Named("llvm.neon.vrhaddu.v8i16") + definition: Named("llvm.arm.neon.vrhaddu.v8i16") }, "rhaddq_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::I32x4]; &INPUTS }, output: &::I32x4, - definition: Named("llvm.neon.vrhadds.v4i32") + definition: Named("llvm.arm.neon.vrhadds.v4i32") }, "rhaddq_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::U32x4]; &INPUTS }, output: &::U32x4, - definition: Named("llvm.neon.vrhaddu.v4i32") + definition: Named("llvm.arm.neon.vrhaddu.v4i32") }, "qadd_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x8, &::I8x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vqadds.v8i8") + definition: Named("llvm.arm.neon.vqadds.v8i8") }, "qadd_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x8, &::U8x8]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vqaddu.v8i8") + definition: Named("llvm.arm.neon.vqaddu.v8i8") }, "qadd_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x4, &::I16x4]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vqadds.v4i16") + definition: Named("llvm.arm.neon.vqadds.v4i16") }, "qadd_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x4, &::U16x4]; &INPUTS }, output: &::U16x4, - definition: Named("llvm.neon.vqaddu.v4i16") + definition: Named("llvm.arm.neon.vqaddu.v4i16") }, "qadd_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x2, &::I32x2]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vqadds.v2i32") + definition: Named("llvm.arm.neon.vqadds.v2i32") }, "qadd_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x2, &::U32x2]; &INPUTS }, output: &::U32x2, - definition: Named("llvm.neon.vqaddu.v2i32") + definition: Named("llvm.arm.neon.vqaddu.v2i32") }, "qadd_s64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I64x1, &::I64x1]; &INPUTS }, output: &::I64x1, - definition: Named("llvm.neon.vqadds.v1i64") + definition: Named("llvm.arm.neon.vqadds.v1i64") }, "qadd_u64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U64x1, &::U64x1]; &INPUTS }, output: &::U64x1, - definition: Named("llvm.neon.vqaddu.v1i64") + definition: Named("llvm.arm.neon.vqaddu.v1i64") }, "qaddq_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x16, &::I8x16]; &INPUTS }, output: &::I8x16, - definition: Named("llvm.neon.vqadds.v16i8") + definition: Named("llvm.arm.neon.vqadds.v16i8") }, "qaddq_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x16, &::U8x16]; &INPUTS }, output: &::U8x16, - definition: Named("llvm.neon.vqaddu.v16i8") + definition: Named("llvm.arm.neon.vqaddu.v16i8") }, "qaddq_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::I16x8]; &INPUTS }, output: &::I16x8, - definition: Named("llvm.neon.vqadds.v8i16") + definition: Named("llvm.arm.neon.vqadds.v8i16") }, "qaddq_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x8, &::U16x8]; &INPUTS }, output: &::U16x8, - definition: Named("llvm.neon.vqaddu.v8i16") + definition: Named("llvm.arm.neon.vqaddu.v8i16") }, "qaddq_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::I32x4]; &INPUTS }, output: &::I32x4, - definition: Named("llvm.neon.vqadds.v4i32") + definition: Named("llvm.arm.neon.vqadds.v4i32") }, "qaddq_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::U32x4]; &INPUTS }, output: &::U32x4, - definition: Named("llvm.neon.vqaddu.v4i32") + definition: Named("llvm.arm.neon.vqaddu.v4i32") }, "qaddq_s64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I64x2, &::I64x2]; &INPUTS }, output: &::I64x2, - definition: Named("llvm.neon.vqadds.v2i64") + definition: Named("llvm.arm.neon.vqadds.v2i64") }, "qaddq_u64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U64x2, &::U64x2]; &INPUTS }, output: &::U64x2, - definition: Named("llvm.neon.vqaddu.v2i64") + definition: Named("llvm.arm.neon.vqaddu.v2i64") }, "raddhn_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::I16x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vraddhn.v8i8") + definition: Named("llvm.arm.neon.vraddhn.v8i8") }, "raddhn_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x8, &::U16x8]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vraddhn.v8i8") + definition: Named("llvm.arm.neon.vraddhn.v8i8") }, "raddhn_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::I32x4]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vraddhn.v4i16") + definition: Named("llvm.arm.neon.vraddhn.v4i16") }, "raddhn_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::U32x4]; &INPUTS }, output: &::U16x4, - definition: Named("llvm.neon.vraddhn.v4i16") + definition: Named("llvm.arm.neon.vraddhn.v4i16") }, "raddhn_s64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I64x2, &::I64x2]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vraddhn.v2i32") + definition: Named("llvm.arm.neon.vraddhn.v2i32") }, "raddhn_u64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U64x2, &::U64x2]; &INPUTS }, output: &::U32x2, - definition: Named("llvm.neon.vraddhn.v2i32") + definition: Named("llvm.arm.neon.vraddhn.v2i32") }, "fma_f32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::F32x2, &::F32x2]; &INPUTS }, @@ -265,1122 +265,1122 @@ pub fn find(name: &str) -> Option { "qdmulh_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x4, &::I16x4]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vsqdmulh.v4i16") + definition: Named("llvm.arm.neon.vsqdmulh.v4i16") }, "qdmulh_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x2, &::I32x2]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vsqdmulh.v2i32") + definition: Named("llvm.arm.neon.vsqdmulh.v2i32") }, "qdmulhq_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::I16x8]; &INPUTS }, output: &::I16x8, - definition: Named("llvm.neon.vsqdmulh.v8i16") + definition: Named("llvm.arm.neon.vsqdmulh.v8i16") }, "qdmulhq_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::I32x4]; &INPUTS }, output: &::I32x4, - definition: Named("llvm.neon.vsqdmulh.v4i32") + definition: Named("llvm.arm.neon.vsqdmulh.v4i32") }, "qrdmulh_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x4, &::I16x4]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vsqrdmulh.v4i16") + definition: Named("llvm.arm.neon.vsqrdmulh.v4i16") }, "qrdmulh_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x2, &::I32x2]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vsqrdmulh.v2i32") + definition: Named("llvm.arm.neon.vsqrdmulh.v2i32") }, "qrdmulhq_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::I16x8]; &INPUTS }, output: &::I16x8, - definition: Named("llvm.neon.vsqrdmulh.v8i16") + definition: Named("llvm.arm.neon.vsqrdmulh.v8i16") }, "qrdmulhq_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::I32x4]; &INPUTS }, output: &::I32x4, - definition: Named("llvm.neon.vsqrdmulh.v4i32") + definition: Named("llvm.arm.neon.vsqrdmulh.v4i32") }, "mull_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x8, &::I8x8]; &INPUTS }, output: &::I16x8, - definition: Named("llvm.neon.vmulls.v8i16") + definition: Named("llvm.arm.neon.vmulls.v8i16") }, "mull_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x8, &::U8x8]; &INPUTS }, output: &::U16x8, - definition: Named("llvm.neon.vmullu.v8i16") + definition: Named("llvm.arm.neon.vmullu.v8i16") }, "mull_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x4, &::I16x4]; &INPUTS }, output: &::I32x4, - definition: Named("llvm.neon.vmulls.v4i32") + definition: Named("llvm.arm.neon.vmulls.v4i32") }, "mull_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x4, &::U16x4]; &INPUTS }, output: &::U32x4, - definition: Named("llvm.neon.vmullu.v4i32") + definition: Named("llvm.arm.neon.vmullu.v4i32") }, "mull_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x2, &::I32x2]; &INPUTS }, output: &::I64x2, - definition: Named("llvm.neon.vmulls.v2i64") + definition: Named("llvm.arm.neon.vmulls.v2i64") }, "mull_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x2, &::U32x2]; &INPUTS }, output: &::U64x2, - definition: Named("llvm.neon.vmullu.v2i64") + definition: Named("llvm.arm.neon.vmullu.v2i64") }, "qdmullq_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x8, &::I8x8]; &INPUTS }, output: &::I16x8, - definition: Named("llvm.neon.vsqdmull.v8i16") + definition: Named("llvm.arm.neon.vsqdmull.v8i16") }, "qdmullq_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x4, &::I16x4]; &INPUTS }, output: &::I32x4, - definition: Named("llvm.neon.vsqdmull.v4i32") + definition: Named("llvm.arm.neon.vsqdmull.v4i32") }, "hsub_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x8, &::I8x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vhsubs.v8i8") + definition: Named("llvm.arm.neon.vhsubs.v8i8") }, "hsub_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x8, &::U8x8]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vhsubu.v8i8") + definition: Named("llvm.arm.neon.vhsubu.v8i8") }, "hsub_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x4, &::I16x4]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vhsubs.v4i16") + definition: Named("llvm.arm.neon.vhsubs.v4i16") }, "hsub_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x4, &::U16x4]; &INPUTS }, output: &::U16x4, - definition: Named("llvm.neon.vhsubu.v4i16") + definition: Named("llvm.arm.neon.vhsubu.v4i16") }, "hsub_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x2, &::I32x2]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vhsubs.v2i32") + definition: Named("llvm.arm.neon.vhsubs.v2i32") }, "hsub_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x2, &::U32x2]; &INPUTS }, output: &::U32x2, - definition: Named("llvm.neon.vhsubu.v2i32") + definition: Named("llvm.arm.neon.vhsubu.v2i32") }, "hsubq_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x16, &::I8x16]; &INPUTS }, output: &::I8x16, - definition: Named("llvm.neon.vhsubs.v16i8") + definition: Named("llvm.arm.neon.vhsubs.v16i8") }, "hsubq_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x16, &::U8x16]; &INPUTS }, output: &::U8x16, - definition: Named("llvm.neon.vhsubu.v16i8") + definition: Named("llvm.arm.neon.vhsubu.v16i8") }, "hsubq_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::I16x8]; &INPUTS }, output: &::I16x8, - definition: Named("llvm.neon.vhsubs.v8i16") + definition: Named("llvm.arm.neon.vhsubs.v8i16") }, "hsubq_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x8, &::U16x8]; &INPUTS }, output: &::U16x8, - definition: Named("llvm.neon.vhsubu.v8i16") + definition: Named("llvm.arm.neon.vhsubu.v8i16") }, "hsubq_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::I32x4]; &INPUTS }, output: &::I32x4, - definition: Named("llvm.neon.vhsubs.v4i32") + definition: Named("llvm.arm.neon.vhsubs.v4i32") }, "hsubq_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::U32x4]; &INPUTS }, output: &::U32x4, - definition: Named("llvm.neon.vhsubu.v4i32") + definition: Named("llvm.arm.neon.vhsubu.v4i32") }, "qsub_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x8, &::I8x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vqsubs.v8i8") + definition: Named("llvm.arm.neon.vqsubs.v8i8") }, "qsub_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x8, &::U8x8]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vqsubu.v8i8") + definition: Named("llvm.arm.neon.vqsubu.v8i8") }, "qsub_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x4, &::I16x4]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vqsubs.v4i16") + definition: Named("llvm.arm.neon.vqsubs.v4i16") }, "qsub_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x4, &::U16x4]; &INPUTS }, output: &::U16x4, - definition: Named("llvm.neon.vqsubu.v4i16") + definition: Named("llvm.arm.neon.vqsubu.v4i16") }, "qsub_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x2, &::I32x2]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vqsubs.v2i32") + definition: Named("llvm.arm.neon.vqsubs.v2i32") }, "qsub_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x2, &::U32x2]; &INPUTS }, output: &::U32x2, - definition: Named("llvm.neon.vqsubu.v2i32") + definition: Named("llvm.arm.neon.vqsubu.v2i32") }, "qsub_s64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I64x1, &::I64x1]; &INPUTS }, output: &::I64x1, - definition: Named("llvm.neon.vqsubs.v1i64") + definition: Named("llvm.arm.neon.vqsubs.v1i64") }, "qsub_u64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U64x1, &::U64x1]; &INPUTS }, output: &::U64x1, - definition: Named("llvm.neon.vqsubu.v1i64") + definition: Named("llvm.arm.neon.vqsubu.v1i64") }, "qsubq_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x16, &::I8x16]; &INPUTS }, output: &::I8x16, - definition: Named("llvm.neon.vqsubs.v16i8") + definition: Named("llvm.arm.neon.vqsubs.v16i8") }, "qsubq_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x16, &::U8x16]; &INPUTS }, output: &::U8x16, - definition: Named("llvm.neon.vqsubu.v16i8") + definition: Named("llvm.arm.neon.vqsubu.v16i8") }, "qsubq_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::I16x8]; &INPUTS }, output: &::I16x8, - definition: Named("llvm.neon.vqsubs.v8i16") + definition: Named("llvm.arm.neon.vqsubs.v8i16") }, "qsubq_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x8, &::U16x8]; &INPUTS }, output: &::U16x8, - definition: Named("llvm.neon.vqsubu.v8i16") + definition: Named("llvm.arm.neon.vqsubu.v8i16") }, "qsubq_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::I32x4]; &INPUTS }, output: &::I32x4, - definition: Named("llvm.neon.vqsubs.v4i32") + definition: Named("llvm.arm.neon.vqsubs.v4i32") }, "qsubq_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::U32x4]; &INPUTS }, output: &::U32x4, - definition: Named("llvm.neon.vqsubu.v4i32") + definition: Named("llvm.arm.neon.vqsubu.v4i32") }, "qsubq_s64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I64x2, &::I64x2]; &INPUTS }, output: &::I64x2, - definition: Named("llvm.neon.vqsubs.v2i64") + definition: Named("llvm.arm.neon.vqsubs.v2i64") }, "qsubq_u64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U64x2, &::U64x2]; &INPUTS }, output: &::U64x2, - definition: Named("llvm.neon.vqsubu.v2i64") + definition: Named("llvm.arm.neon.vqsubu.v2i64") }, "rsubhn_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::I16x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vrsubhn.v8i8") + definition: Named("llvm.arm.neon.vrsubhn.v8i8") }, "rsubhn_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x8, &::U16x8]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vrsubhn.v8i8") + definition: Named("llvm.arm.neon.vrsubhn.v8i8") }, "rsubhn_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::I32x4]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vrsubhn.v4i16") + definition: Named("llvm.arm.neon.vrsubhn.v4i16") }, "rsubhn_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::U32x4]; &INPUTS }, output: &::U16x4, - definition: Named("llvm.neon.vrsubhn.v4i16") + definition: Named("llvm.arm.neon.vrsubhn.v4i16") }, "rsubhn_s64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I64x2, &::I64x2]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vrsubhn.v2i32") + definition: Named("llvm.arm.neon.vrsubhn.v2i32") }, "rsubhn_u64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U64x2, &::U64x2]; &INPUTS }, output: &::U32x2, - definition: Named("llvm.neon.vrsubhn.v2i32") + definition: Named("llvm.arm.neon.vrsubhn.v2i32") }, "abd_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x8, &::I8x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vabds.v8i8") + definition: Named("llvm.arm.neon.vabds.v8i8") }, "abd_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x8, &::U8x8]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vabdu.v8i8") + definition: Named("llvm.arm.neon.vabdu.v8i8") }, "abd_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x4, &::I16x4]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vabds.v4i16") + definition: Named("llvm.arm.neon.vabds.v4i16") }, "abd_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x4, &::U16x4]; &INPUTS }, output: &::U16x4, - definition: Named("llvm.neon.vabdu.v4i16") + definition: Named("llvm.arm.neon.vabdu.v4i16") }, "abd_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x2, &::I32x2]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vabds.v2i32") + definition: Named("llvm.arm.neon.vabds.v2i32") }, "abd_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x2, &::U32x2]; &INPUTS }, output: &::U32x2, - definition: Named("llvm.neon.vabdu.v2i32") + definition: Named("llvm.arm.neon.vabdu.v2i32") }, "abd_f32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::F32x2, &::F32x2]; &INPUTS }, output: &::F32x2, - definition: Named("llvm.neon.vabdf.v2f32") + definition: Named("llvm.arm.neon.vabdf.v2f32") }, "abdq_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x16, &::I8x16]; &INPUTS }, output: &::I8x16, - definition: Named("llvm.neon.vabds.v16i8") + definition: Named("llvm.arm.neon.vabds.v16i8") }, "abdq_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x16, &::U8x16]; &INPUTS }, output: &::U8x16, - definition: Named("llvm.neon.vabdu.v16i8") + definition: Named("llvm.arm.neon.vabdu.v16i8") }, "abdq_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::I16x8]; &INPUTS }, output: &::I16x8, - definition: Named("llvm.neon.vabds.v8i16") + definition: Named("llvm.arm.neon.vabds.v8i16") }, "abdq_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x8, &::U16x8]; &INPUTS }, output: &::U16x8, - definition: Named("llvm.neon.vabdu.v8i16") + definition: Named("llvm.arm.neon.vabdu.v8i16") }, "abdq_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::I32x4]; &INPUTS }, output: &::I32x4, - definition: Named("llvm.neon.vabds.v4i32") + definition: Named("llvm.arm.neon.vabds.v4i32") }, "abdq_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::U32x4]; &INPUTS }, output: &::U32x4, - definition: Named("llvm.neon.vabdu.v4i32") + definition: Named("llvm.arm.neon.vabdu.v4i32") }, "abdq_f32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::F32x4, &::F32x4]; &INPUTS }, output: &::F32x4, - definition: Named("llvm.neon.vabdf.v4f32") + definition: Named("llvm.arm.neon.vabdf.v4f32") }, "max_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x8, &::I8x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vmaxs.v8i8") + definition: Named("llvm.arm.neon.vmaxs.v8i8") }, "max_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x8, &::U8x8]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vmaxu.v8i8") + definition: Named("llvm.arm.neon.vmaxu.v8i8") }, "max_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x4, &::I16x4]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vmaxs.v4i16") + definition: Named("llvm.arm.neon.vmaxs.v4i16") }, "max_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x4, &::U16x4]; &INPUTS }, output: &::U16x4, - definition: Named("llvm.neon.vmaxu.v4i16") + definition: Named("llvm.arm.neon.vmaxu.v4i16") }, "max_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x2, &::I32x2]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vmaxs.v2i32") + definition: Named("llvm.arm.neon.vmaxs.v2i32") }, "max_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x2, &::U32x2]; &INPUTS }, output: &::U32x2, - definition: Named("llvm.neon.vmaxu.v2i32") + definition: Named("llvm.arm.neon.vmaxu.v2i32") }, "max_f32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::F32x2, &::F32x2]; &INPUTS }, output: &::F32x2, - definition: Named("llvm.neon.vmaxf.v2f32") + definition: Named("llvm.arm.neon.vmaxf.v2f32") }, "maxq_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x16, &::I8x16]; &INPUTS }, output: &::I8x16, - definition: Named("llvm.neon.vmaxs.v16i8") + definition: Named("llvm.arm.neon.vmaxs.v16i8") }, "maxq_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x16, &::U8x16]; &INPUTS }, output: &::U8x16, - definition: Named("llvm.neon.vmaxu.v16i8") + definition: Named("llvm.arm.neon.vmaxu.v16i8") }, "maxq_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::I16x8]; &INPUTS }, output: &::I16x8, - definition: Named("llvm.neon.vmaxs.v8i16") + definition: Named("llvm.arm.neon.vmaxs.v8i16") }, "maxq_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x8, &::U16x8]; &INPUTS }, output: &::U16x8, - definition: Named("llvm.neon.vmaxu.v8i16") + definition: Named("llvm.arm.neon.vmaxu.v8i16") }, "maxq_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::I32x4]; &INPUTS }, output: &::I32x4, - definition: Named("llvm.neon.vmaxs.v4i32") + definition: Named("llvm.arm.neon.vmaxs.v4i32") }, "maxq_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::U32x4]; &INPUTS }, output: &::U32x4, - definition: Named("llvm.neon.vmaxu.v4i32") + definition: Named("llvm.arm.neon.vmaxu.v4i32") }, "maxq_f32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::F32x4, &::F32x4]; &INPUTS }, output: &::F32x4, - definition: Named("llvm.neon.vmaxf.v4f32") + definition: Named("llvm.arm.neon.vmaxf.v4f32") }, "min_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x8, &::I8x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vmins.v8i8") + definition: Named("llvm.arm.neon.vmins.v8i8") }, "min_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x8, &::U8x8]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vminu.v8i8") + definition: Named("llvm.arm.neon.vminu.v8i8") }, "min_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x4, &::I16x4]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vmins.v4i16") + definition: Named("llvm.arm.neon.vmins.v4i16") }, "min_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x4, &::U16x4]; &INPUTS }, output: &::U16x4, - definition: Named("llvm.neon.vminu.v4i16") + definition: Named("llvm.arm.neon.vminu.v4i16") }, "min_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x2, &::I32x2]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vmins.v2i32") + definition: Named("llvm.arm.neon.vmins.v2i32") }, "min_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x2, &::U32x2]; &INPUTS }, output: &::U32x2, - definition: Named("llvm.neon.vminu.v2i32") + definition: Named("llvm.arm.neon.vminu.v2i32") }, "min_f32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::F32x2, &::F32x2]; &INPUTS }, output: &::F32x2, - definition: Named("llvm.neon.vminf.v2f32") + definition: Named("llvm.arm.neon.vminf.v2f32") }, "minq_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x16, &::I8x16]; &INPUTS }, output: &::I8x16, - definition: Named("llvm.neon.vmins.v16i8") + definition: Named("llvm.arm.neon.vmins.v16i8") }, "minq_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x16, &::U8x16]; &INPUTS }, output: &::U8x16, - definition: Named("llvm.neon.vminu.v16i8") + definition: Named("llvm.arm.neon.vminu.v16i8") }, "minq_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::I16x8]; &INPUTS }, output: &::I16x8, - definition: Named("llvm.neon.vmins.v8i16") + definition: Named("llvm.arm.neon.vmins.v8i16") }, "minq_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x8, &::U16x8]; &INPUTS }, output: &::U16x8, - definition: Named("llvm.neon.vminu.v8i16") + definition: Named("llvm.arm.neon.vminu.v8i16") }, "minq_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::I32x4]; &INPUTS }, output: &::I32x4, - definition: Named("llvm.neon.vmins.v4i32") + definition: Named("llvm.arm.neon.vmins.v4i32") }, "minq_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::U32x4]; &INPUTS }, output: &::U32x4, - definition: Named("llvm.neon.vminu.v4i32") + definition: Named("llvm.arm.neon.vminu.v4i32") }, "minq_f32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::F32x4, &::F32x4]; &INPUTS }, output: &::F32x4, - definition: Named("llvm.neon.vminf.v4f32") + definition: Named("llvm.arm.neon.vminf.v4f32") }, "shl_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x8, &::I8x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vshls.v8i8") + definition: Named("llvm.arm.neon.vshls.v8i8") }, "shl_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x8, &::I8x8]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vshlu.v8i8") + definition: Named("llvm.arm.neon.vshlu.v8i8") }, "shl_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x4, &::I16x4]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vshls.v4i16") + definition: Named("llvm.arm.neon.vshls.v4i16") }, "shl_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x4, &::I16x4]; &INPUTS }, output: &::U16x4, - definition: Named("llvm.neon.vshlu.v4i16") + definition: Named("llvm.arm.neon.vshlu.v4i16") }, "shl_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x2, &::I32x2]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vshls.v2i32") + definition: Named("llvm.arm.neon.vshls.v2i32") }, "shl_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x2, &::I32x2]; &INPUTS }, output: &::U32x2, - definition: Named("llvm.neon.vshlu.v2i32") + definition: Named("llvm.arm.neon.vshlu.v2i32") }, "shl_s64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I64x1, &::I64x1]; &INPUTS }, output: &::I64x1, - definition: Named("llvm.neon.vshls.v1i64") + definition: Named("llvm.arm.neon.vshls.v1i64") }, "shl_u64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U64x1, &::I64x1]; &INPUTS }, output: &::U64x1, - definition: Named("llvm.neon.vshlu.v1i64") + definition: Named("llvm.arm.neon.vshlu.v1i64") }, "shlq_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x16, &::I8x16]; &INPUTS }, output: &::I8x16, - definition: Named("llvm.neon.vshls.v16i8") + definition: Named("llvm.arm.neon.vshls.v16i8") }, "shlq_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x16, &::I8x16]; &INPUTS }, output: &::U8x16, - definition: Named("llvm.neon.vshlu.v16i8") + definition: Named("llvm.arm.neon.vshlu.v16i8") }, "shlq_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::I16x8]; &INPUTS }, output: &::I16x8, - definition: Named("llvm.neon.vshls.v8i16") + definition: Named("llvm.arm.neon.vshls.v8i16") }, "shlq_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x8, &::I16x8]; &INPUTS }, output: &::U16x8, - definition: Named("llvm.neon.vshlu.v8i16") + definition: Named("llvm.arm.neon.vshlu.v8i16") }, "shlq_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::I32x4]; &INPUTS }, output: &::I32x4, - definition: Named("llvm.neon.vshls.v4i32") + definition: Named("llvm.arm.neon.vshls.v4i32") }, "shlq_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::I32x4]; &INPUTS }, output: &::U32x4, - definition: Named("llvm.neon.vshlu.v4i32") + definition: Named("llvm.arm.neon.vshlu.v4i32") }, "shlq_s64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I64x2, &::I64x2]; &INPUTS }, output: &::I64x2, - definition: Named("llvm.neon.vshls.v2i64") + definition: Named("llvm.arm.neon.vshls.v2i64") }, "shlq_u64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U64x2, &::I64x2]; &INPUTS }, output: &::U64x2, - definition: Named("llvm.neon.vshlu.v2i64") + definition: Named("llvm.arm.neon.vshlu.v2i64") }, "qshl_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x8, &::I8x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vqshls.v8i8") + definition: Named("llvm.arm.neon.vqshls.v8i8") }, "qshl_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x8, &::I8x8]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vqshlu.v8i8") + definition: Named("llvm.arm.neon.vqshlu.v8i8") }, "qshl_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x4, &::I16x4]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vqshls.v4i16") + definition: Named("llvm.arm.neon.vqshls.v4i16") }, "qshl_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x4, &::I16x4]; &INPUTS }, output: &::U16x4, - definition: Named("llvm.neon.vqshlu.v4i16") + definition: Named("llvm.arm.neon.vqshlu.v4i16") }, "qshl_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x2, &::I32x2]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vqshls.v2i32") + definition: Named("llvm.arm.neon.vqshls.v2i32") }, "qshl_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x2, &::I32x2]; &INPUTS }, output: &::U32x2, - definition: Named("llvm.neon.vqshlu.v2i32") + definition: Named("llvm.arm.neon.vqshlu.v2i32") }, "qshl_s64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I64x1, &::I64x1]; &INPUTS }, output: &::I64x1, - definition: Named("llvm.neon.vqshls.v1i64") + definition: Named("llvm.arm.neon.vqshls.v1i64") }, "qshl_u64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U64x1, &::I64x1]; &INPUTS }, output: &::U64x1, - definition: Named("llvm.neon.vqshlu.v1i64") + definition: Named("llvm.arm.neon.vqshlu.v1i64") }, "qshlq_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x16, &::I8x16]; &INPUTS }, output: &::I8x16, - definition: Named("llvm.neon.vqshls.v16i8") + definition: Named("llvm.arm.neon.vqshls.v16i8") }, "qshlq_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x16, &::I8x16]; &INPUTS }, output: &::U8x16, - definition: Named("llvm.neon.vqshlu.v16i8") + definition: Named("llvm.arm.neon.vqshlu.v16i8") }, "qshlq_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::I16x8]; &INPUTS }, output: &::I16x8, - definition: Named("llvm.neon.vqshls.v8i16") + definition: Named("llvm.arm.neon.vqshls.v8i16") }, "qshlq_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x8, &::I16x8]; &INPUTS }, output: &::U16x8, - definition: Named("llvm.neon.vqshlu.v8i16") + definition: Named("llvm.arm.neon.vqshlu.v8i16") }, "qshlq_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::I32x4]; &INPUTS }, output: &::I32x4, - definition: Named("llvm.neon.vqshls.v4i32") + definition: Named("llvm.arm.neon.vqshls.v4i32") }, "qshlq_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::I32x4]; &INPUTS }, output: &::U32x4, - definition: Named("llvm.neon.vqshlu.v4i32") + definition: Named("llvm.arm.neon.vqshlu.v4i32") }, "qshlq_s64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I64x2, &::I64x2]; &INPUTS }, output: &::I64x2, - definition: Named("llvm.neon.vqshls.v2i64") + definition: Named("llvm.arm.neon.vqshls.v2i64") }, "qshlq_u64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U64x2, &::I64x2]; &INPUTS }, output: &::U64x2, - definition: Named("llvm.neon.vqshlu.v2i64") + definition: Named("llvm.arm.neon.vqshlu.v2i64") }, "rshl_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x8, &::I8x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vrshls.v8i8") + definition: Named("llvm.arm.neon.vrshls.v8i8") }, "rshl_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x8, &::I8x8]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vrshlu.v8i8") + definition: Named("llvm.arm.neon.vrshlu.v8i8") }, "rshl_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x4, &::I16x4]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vrshls.v4i16") + definition: Named("llvm.arm.neon.vrshls.v4i16") }, "rshl_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x4, &::I16x4]; &INPUTS }, output: &::U16x4, - definition: Named("llvm.neon.vrshlu.v4i16") + definition: Named("llvm.arm.neon.vrshlu.v4i16") }, "rshl_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x2, &::I32x2]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vrshls.v2i32") + definition: Named("llvm.arm.neon.vrshls.v2i32") }, "rshl_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x2, &::I32x2]; &INPUTS }, output: &::U32x2, - definition: Named("llvm.neon.vrshlu.v2i32") + definition: Named("llvm.arm.neon.vrshlu.v2i32") }, "rshl_s64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I64x1, &::I64x1]; &INPUTS }, output: &::I64x1, - definition: Named("llvm.neon.vrshls.v1i64") + definition: Named("llvm.arm.neon.vrshls.v1i64") }, "rshl_u64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U64x1, &::I64x1]; &INPUTS }, output: &::U64x1, - definition: Named("llvm.neon.vrshlu.v1i64") + definition: Named("llvm.arm.neon.vrshlu.v1i64") }, "rshlq_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x16, &::I8x16]; &INPUTS }, output: &::I8x16, - definition: Named("llvm.neon.vrshls.v16i8") + definition: Named("llvm.arm.neon.vrshls.v16i8") }, "rshlq_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x16, &::I8x16]; &INPUTS }, output: &::U8x16, - definition: Named("llvm.neon.vrshlu.v16i8") + definition: Named("llvm.arm.neon.vrshlu.v16i8") }, "rshlq_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::I16x8]; &INPUTS }, output: &::I16x8, - definition: Named("llvm.neon.vrshls.v8i16") + definition: Named("llvm.arm.neon.vrshls.v8i16") }, "rshlq_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x8, &::I16x8]; &INPUTS }, output: &::U16x8, - definition: Named("llvm.neon.vrshlu.v8i16") + definition: Named("llvm.arm.neon.vrshlu.v8i16") }, "rshlq_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::I32x4]; &INPUTS }, output: &::I32x4, - definition: Named("llvm.neon.vrshls.v4i32") + definition: Named("llvm.arm.neon.vrshls.v4i32") }, "rshlq_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::I32x4]; &INPUTS }, output: &::U32x4, - definition: Named("llvm.neon.vrshlu.v4i32") + definition: Named("llvm.arm.neon.vrshlu.v4i32") }, "rshlq_s64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I64x2, &::I64x2]; &INPUTS }, output: &::I64x2, - definition: Named("llvm.neon.vrshls.v2i64") + definition: Named("llvm.arm.neon.vrshls.v2i64") }, "rshlq_u64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U64x2, &::I64x2]; &INPUTS }, output: &::U64x2, - definition: Named("llvm.neon.vrshlu.v2i64") + definition: Named("llvm.arm.neon.vrshlu.v2i64") }, "qrshl_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x8, &::I8x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vqrshls.v8i8") + definition: Named("llvm.arm.neon.vqrshls.v8i8") }, "qrshl_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x8, &::I8x8]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vqrshlu.v8i8") + definition: Named("llvm.arm.neon.vqrshlu.v8i8") }, "qrshl_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x4, &::I16x4]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vqrshls.v4i16") + definition: Named("llvm.arm.neon.vqrshls.v4i16") }, "qrshl_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x4, &::I16x4]; &INPUTS }, output: &::U16x4, - definition: Named("llvm.neon.vqrshlu.v4i16") + definition: Named("llvm.arm.neon.vqrshlu.v4i16") }, "qrshl_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x2, &::I32x2]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vqrshls.v2i32") + definition: Named("llvm.arm.neon.vqrshls.v2i32") }, "qrshl_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x2, &::I32x2]; &INPUTS }, output: &::U32x2, - definition: Named("llvm.neon.vqrshlu.v2i32") + definition: Named("llvm.arm.neon.vqrshlu.v2i32") }, "qrshl_s64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I64x1, &::I64x1]; &INPUTS }, output: &::I64x1, - definition: Named("llvm.neon.vqrshls.v1i64") + definition: Named("llvm.arm.neon.vqrshls.v1i64") }, "qrshl_u64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U64x1, &::I64x1]; &INPUTS }, output: &::U64x1, - definition: Named("llvm.neon.vqrshlu.v1i64") + definition: Named("llvm.arm.neon.vqrshlu.v1i64") }, "qrshlq_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x16, &::I8x16]; &INPUTS }, output: &::I8x16, - definition: Named("llvm.neon.vqrshls.v16i8") + definition: Named("llvm.arm.neon.vqrshls.v16i8") }, "qrshlq_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x16, &::I8x16]; &INPUTS }, output: &::U8x16, - definition: Named("llvm.neon.vqrshlu.v16i8") + definition: Named("llvm.arm.neon.vqrshlu.v16i8") }, "qrshlq_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::I16x8]; &INPUTS }, output: &::I16x8, - definition: Named("llvm.neon.vqrshls.v8i16") + definition: Named("llvm.arm.neon.vqrshls.v8i16") }, "qrshlq_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x8, &::I16x8]; &INPUTS }, output: &::U16x8, - definition: Named("llvm.neon.vqrshlu.v8i16") + definition: Named("llvm.arm.neon.vqrshlu.v8i16") }, "qrshlq_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::I32x4]; &INPUTS }, output: &::I32x4, - definition: Named("llvm.neon.vqrshls.v4i32") + definition: Named("llvm.arm.neon.vqrshls.v4i32") }, "qrshlq_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::I32x4]; &INPUTS }, output: &::U32x4, - definition: Named("llvm.neon.vqrshlu.v4i32") + definition: Named("llvm.arm.neon.vqrshlu.v4i32") }, "qrshlq_s64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I64x2, &::I64x2]; &INPUTS }, output: &::I64x2, - definition: Named("llvm.neon.vqrshls.v2i64") + definition: Named("llvm.arm.neon.vqrshls.v2i64") }, "qrshlq_u64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U64x2, &::I64x2]; &INPUTS }, output: &::U64x2, - definition: Named("llvm.neon.vqrshlu.v2i64") + definition: Named("llvm.arm.neon.vqrshlu.v2i64") }, "qshrun_n_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::U32]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vsqshrun.v8i8") + definition: Named("llvm.arm.neon.vsqshrun.v8i8") }, "qshrun_n_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::U32]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vsqshrun.v4i16") + definition: Named("llvm.arm.neon.vsqshrun.v4i16") }, "qshrun_n_s64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I64x2, &::U32]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vsqshrun.v2i32") + definition: Named("llvm.arm.neon.vsqshrun.v2i32") }, "qrshrun_n_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::U32]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vsqrshrun.v8i8") + definition: Named("llvm.arm.neon.vsqrshrun.v8i8") }, "qrshrun_n_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::U32]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vsqrshrun.v4i16") + definition: Named("llvm.arm.neon.vsqrshrun.v4i16") }, "qrshrun_n_s64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I64x2, &::U32]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vsqrshrun.v2i32") + definition: Named("llvm.arm.neon.vsqrshrun.v2i32") }, "qshrn_n_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::U32]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vqshrns.v8i8") + definition: Named("llvm.arm.neon.vqshrns.v8i8") }, "qshrn_n_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x8, &::U32]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vqshrnu.v8i8") + definition: Named("llvm.arm.neon.vqshrnu.v8i8") }, "qshrn_n_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::U32]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vqshrns.v4i16") + definition: Named("llvm.arm.neon.vqshrns.v4i16") }, "qshrn_n_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::U32]; &INPUTS }, output: &::U16x4, - definition: Named("llvm.neon.vqshrnu.v4i16") + definition: Named("llvm.arm.neon.vqshrnu.v4i16") }, "qshrn_n_s64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I64x2, &::U32]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vqshrns.v2i32") + definition: Named("llvm.arm.neon.vqshrns.v2i32") }, "qshrn_n_u64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U64x2, &::U32]; &INPUTS }, output: &::U32x2, - definition: Named("llvm.neon.vqshrnu.v2i32") + definition: Named("llvm.arm.neon.vqshrnu.v2i32") }, "rshrn_n_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::U32]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vrshrn.v8i8") + definition: Named("llvm.arm.neon.vrshrn.v8i8") }, "rshrn_n_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x8, &::U32]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vrshrn.v8i8") + definition: Named("llvm.arm.neon.vrshrn.v8i8") }, "rshrn_n_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::U32]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vrshrn.v4i16") + definition: Named("llvm.arm.neon.vrshrn.v4i16") }, "rshrn_n_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::U32]; &INPUTS }, output: &::U16x4, - definition: Named("llvm.neon.vrshrn.v4i16") + definition: Named("llvm.arm.neon.vrshrn.v4i16") }, "rshrn_n_s64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I64x2, &::U32]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vrshrn.v2i32") + definition: Named("llvm.arm.neon.vrshrn.v2i32") }, "rshrn_n_u64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U64x2, &::U32]; &INPUTS }, output: &::U32x2, - definition: Named("llvm.neon.vrshrn.v2i32") + definition: Named("llvm.arm.neon.vrshrn.v2i32") }, "qrshrn_n_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::U32]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vqrshrns.v8i8") + definition: Named("llvm.arm.neon.vqrshrns.v8i8") }, "qrshrn_n_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x8, &::U32]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vqrshrnu.v8i8") + definition: Named("llvm.arm.neon.vqrshrnu.v8i8") }, "qrshrn_n_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::U32]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vqrshrns.v4i16") + definition: Named("llvm.arm.neon.vqrshrns.v4i16") }, "qrshrn_n_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::U32]; &INPUTS }, output: &::U16x4, - definition: Named("llvm.neon.vqrshrnu.v4i16") + definition: Named("llvm.arm.neon.vqrshrnu.v4i16") }, "qrshrn_n_s64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I64x2, &::U32]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vqrshrns.v2i32") + definition: Named("llvm.arm.neon.vqrshrns.v2i32") }, "qrshrn_n_u64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U64x2, &::U32]; &INPUTS }, output: &::U32x2, - definition: Named("llvm.neon.vqrshrnu.v2i32") + definition: Named("llvm.arm.neon.vqrshrnu.v2i32") }, "sri_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x8, &::I8x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vvsri.v8i8") + definition: Named("llvm.arm.neon.vvsri.v8i8") }, "sri_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x8, &::U8x8]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vvsri.v8i8") + definition: Named("llvm.arm.neon.vvsri.v8i8") }, "sri_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x4, &::I16x4]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vvsri.v4i16") + definition: Named("llvm.arm.neon.vvsri.v4i16") }, "sri_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x4, &::U16x4]; &INPUTS }, output: &::U16x4, - definition: Named("llvm.neon.vvsri.v4i16") + definition: Named("llvm.arm.neon.vvsri.v4i16") }, "sri_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x2, &::I32x2]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vvsri.v2i32") + definition: Named("llvm.arm.neon.vvsri.v2i32") }, "sri_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x2, &::U32x2]; &INPUTS }, output: &::U32x2, - definition: Named("llvm.neon.vvsri.v2i32") + definition: Named("llvm.arm.neon.vvsri.v2i32") }, "sri_s64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I64x1, &::I64x1]; &INPUTS }, output: &::I64x1, - definition: Named("llvm.neon.vvsri.v1i64") + definition: Named("llvm.arm.neon.vvsri.v1i64") }, "sri_u64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U64x1, &::U64x1]; &INPUTS }, output: &::U64x1, - definition: Named("llvm.neon.vvsri.v1i64") + definition: Named("llvm.arm.neon.vvsri.v1i64") }, "sriq_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x16, &::I8x16]; &INPUTS }, output: &::I8x16, - definition: Named("llvm.neon.vvsri.v16i8") + definition: Named("llvm.arm.neon.vvsri.v16i8") }, "sriq_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x16, &::U8x16]; &INPUTS }, output: &::U8x16, - definition: Named("llvm.neon.vvsri.v16i8") + definition: Named("llvm.arm.neon.vvsri.v16i8") }, "sriq_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::I16x8]; &INPUTS }, output: &::I16x8, - definition: Named("llvm.neon.vvsri.v8i16") + definition: Named("llvm.arm.neon.vvsri.v8i16") }, "sriq_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x8, &::U16x8]; &INPUTS }, output: &::U16x8, - definition: Named("llvm.neon.vvsri.v8i16") + definition: Named("llvm.arm.neon.vvsri.v8i16") }, "sriq_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::I32x4]; &INPUTS }, output: &::I32x4, - definition: Named("llvm.neon.vvsri.v4i32") + definition: Named("llvm.arm.neon.vvsri.v4i32") }, "sriq_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::U32x4]; &INPUTS }, output: &::U32x4, - definition: Named("llvm.neon.vvsri.v4i32") + definition: Named("llvm.arm.neon.vvsri.v4i32") }, "sriq_s64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I64x2, &::I64x2]; &INPUTS }, output: &::I64x2, - definition: Named("llvm.neon.vvsri.v2i64") + definition: Named("llvm.arm.neon.vvsri.v2i64") }, "sriq_u64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U64x2, &::U64x2]; &INPUTS }, output: &::U64x2, - definition: Named("llvm.neon.vvsri.v2i64") + definition: Named("llvm.arm.neon.vvsri.v2i64") }, "sli_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x8, &::I8x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vvsli.v8i8") + definition: Named("llvm.arm.neon.vvsli.v8i8") }, "sli_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x8, &::U8x8]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vvsli.v8i8") + definition: Named("llvm.arm.neon.vvsli.v8i8") }, "sli_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x4, &::I16x4]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vvsli.v4i16") + definition: Named("llvm.arm.neon.vvsli.v4i16") }, "sli_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x4, &::U16x4]; &INPUTS }, output: &::U16x4, - definition: Named("llvm.neon.vvsli.v4i16") + definition: Named("llvm.arm.neon.vvsli.v4i16") }, "sli_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x2, &::I32x2]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vvsli.v2i32") + definition: Named("llvm.arm.neon.vvsli.v2i32") }, "sli_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x2, &::U32x2]; &INPUTS }, output: &::U32x2, - definition: Named("llvm.neon.vvsli.v2i32") + definition: Named("llvm.arm.neon.vvsli.v2i32") }, "sli_s64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I64x1, &::I64x1]; &INPUTS }, output: &::I64x1, - definition: Named("llvm.neon.vvsli.v1i64") + definition: Named("llvm.arm.neon.vvsli.v1i64") }, "sli_u64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U64x1, &::U64x1]; &INPUTS }, output: &::U64x1, - definition: Named("llvm.neon.vvsli.v1i64") + definition: Named("llvm.arm.neon.vvsli.v1i64") }, "sliq_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x16, &::I8x16]; &INPUTS }, output: &::I8x16, - definition: Named("llvm.neon.vvsli.v16i8") + definition: Named("llvm.arm.neon.vvsli.v16i8") }, "sliq_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x16, &::U8x16]; &INPUTS }, output: &::U8x16, - definition: Named("llvm.neon.vvsli.v16i8") + definition: Named("llvm.arm.neon.vvsli.v16i8") }, "sliq_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::I16x8]; &INPUTS }, output: &::I16x8, - definition: Named("llvm.neon.vvsli.v8i16") + definition: Named("llvm.arm.neon.vvsli.v8i16") }, "sliq_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x8, &::U16x8]; &INPUTS }, output: &::U16x8, - definition: Named("llvm.neon.vvsli.v8i16") + definition: Named("llvm.arm.neon.vvsli.v8i16") }, "sliq_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::I32x4]; &INPUTS }, output: &::I32x4, - definition: Named("llvm.neon.vvsli.v4i32") + definition: Named("llvm.arm.neon.vvsli.v4i32") }, "sliq_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::U32x4]; &INPUTS }, output: &::U32x4, - definition: Named("llvm.neon.vvsli.v4i32") + definition: Named("llvm.arm.neon.vvsli.v4i32") }, "sliq_s64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I64x2, &::I64x2]; &INPUTS }, output: &::I64x2, - definition: Named("llvm.neon.vvsli.v2i64") + definition: Named("llvm.arm.neon.vvsli.v2i64") }, "sliq_u64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U64x2, &::U64x2]; &INPUTS }, output: &::U64x2, - definition: Named("llvm.neon.vvsli.v2i64") + definition: Named("llvm.arm.neon.vvsli.v2i64") }, "vqmovn_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I16x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vqxtns.v8i8") + definition: Named("llvm.arm.neon.vqxtns.v8i8") }, "vqmovn_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::U16x8]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vqxtnu.v8i8") + definition: Named("llvm.arm.neon.vqxtnu.v8i8") }, "vqmovn_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I32x4]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vqxtns.v4i16") + definition: Named("llvm.arm.neon.vqxtns.v4i16") }, "vqmovn_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::U32x4]; &INPUTS }, output: &::U16x4, - definition: Named("llvm.neon.vqxtnu.v4i16") + definition: Named("llvm.arm.neon.vqxtnu.v4i16") }, "vqmovn_s64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I64x2]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vqxtns.v2i32") + definition: Named("llvm.arm.neon.vqxtns.v2i32") }, "vqmovn_u64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::U64x2]; &INPUTS }, output: &::U32x2, - definition: Named("llvm.neon.vqxtnu.v2i32") + definition: Named("llvm.arm.neon.vqxtnu.v2i32") }, "abs_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I8x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vabs.v8i8") + definition: Named("llvm.arm.neon.vabs.v8i8") }, "abs_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I16x4]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vabs.v4i16") + definition: Named("llvm.arm.neon.vabs.v4i16") }, "abs_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I32x2]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vabs.v2i32") + definition: Named("llvm.arm.neon.vabs.v2i32") }, "absq_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I8x16]; &INPUTS }, output: &::I8x16, - definition: Named("llvm.neon.vabs.v16i8") + definition: Named("llvm.arm.neon.vabs.v16i8") }, "absq_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I16x8]; &INPUTS }, output: &::I16x8, - definition: Named("llvm.neon.vabs.v8i16") + definition: Named("llvm.arm.neon.vabs.v8i16") }, "absq_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I32x4]; &INPUTS }, output: &::I32x4, - definition: Named("llvm.neon.vabs.v4i32") + definition: Named("llvm.arm.neon.vabs.v4i32") }, "abs_f32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::F32x2]; &INPUTS }, @@ -1395,62 +1395,62 @@ pub fn find(name: &str) -> Option { "qabs_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I8x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vsqabs.v8i8") + definition: Named("llvm.arm.neon.vsqabs.v8i8") }, "qabs_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I16x4]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vsqabs.v4i16") + definition: Named("llvm.arm.neon.vsqabs.v4i16") }, "qabs_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I32x2]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vsqabs.v2i32") + definition: Named("llvm.arm.neon.vsqabs.v2i32") }, "qabsq_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I8x16]; &INPUTS }, output: &::I8x16, - definition: Named("llvm.neon.vsqabs.v16i8") + definition: Named("llvm.arm.neon.vsqabs.v16i8") }, "qabsq_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I16x8]; &INPUTS }, output: &::I16x8, - definition: Named("llvm.neon.vsqabs.v8i16") + definition: Named("llvm.arm.neon.vsqabs.v8i16") }, "qabsq_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I32x4]; &INPUTS }, output: &::I32x4, - definition: Named("llvm.neon.vsqabs.v4i32") + definition: Named("llvm.arm.neon.vsqabs.v4i32") }, "qneg_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I8x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vsqneg.v8i8") + definition: Named("llvm.arm.neon.vsqneg.v8i8") }, "qneg_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I16x4]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vsqneg.v4i16") + definition: Named("llvm.arm.neon.vsqneg.v4i16") }, "qneg_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I32x2]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vsqneg.v2i32") + definition: Named("llvm.arm.neon.vsqneg.v2i32") }, "qnegq_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I8x16]; &INPUTS }, output: &::I8x16, - definition: Named("llvm.neon.vsqneg.v16i8") + definition: Named("llvm.arm.neon.vsqneg.v16i8") }, "qnegq_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I16x8]; &INPUTS }, output: &::I16x8, - definition: Named("llvm.neon.vsqneg.v8i16") + definition: Named("llvm.arm.neon.vsqneg.v8i16") }, "qnegq_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I32x4]; &INPUTS }, output: &::I32x4, - definition: Named("llvm.neon.vsqneg.v4i32") + definition: Named("llvm.arm.neon.vsqneg.v4i32") }, "clz_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I8x8]; &INPUTS }, @@ -1515,62 +1515,62 @@ pub fn find(name: &str) -> Option { "cls_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I8x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vcls.v8i8") + definition: Named("llvm.arm.neon.vcls.v8i8") }, "cls_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::U8x8]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vcls.v8i8") + definition: Named("llvm.arm.neon.vcls.v8i8") }, "cls_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I16x4]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vcls.v4i16") + definition: Named("llvm.arm.neon.vcls.v4i16") }, "cls_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::U16x4]; &INPUTS }, output: &::U16x4, - definition: Named("llvm.neon.vcls.v4i16") + definition: Named("llvm.arm.neon.vcls.v4i16") }, "cls_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I32x2]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vcls.v2i32") + definition: Named("llvm.arm.neon.vcls.v2i32") }, "cls_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::U32x2]; &INPUTS }, output: &::U32x2, - definition: Named("llvm.neon.vcls.v2i32") + definition: Named("llvm.arm.neon.vcls.v2i32") }, "clsq_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I8x16]; &INPUTS }, output: &::I8x16, - definition: Named("llvm.neon.vcls.v16i8") + definition: Named("llvm.arm.neon.vcls.v16i8") }, "clsq_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::U8x16]; &INPUTS }, output: &::U8x16, - definition: Named("llvm.neon.vcls.v16i8") + definition: Named("llvm.arm.neon.vcls.v16i8") }, "clsq_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I16x8]; &INPUTS }, output: &::I16x8, - definition: Named("llvm.neon.vcls.v8i16") + definition: Named("llvm.arm.neon.vcls.v8i16") }, "clsq_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::U16x8]; &INPUTS }, output: &::U16x8, - definition: Named("llvm.neon.vcls.v8i16") + definition: Named("llvm.arm.neon.vcls.v8i16") }, "clsq_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I32x4]; &INPUTS }, output: &::I32x4, - definition: Named("llvm.neon.vcls.v4i32") + definition: Named("llvm.arm.neon.vcls.v4i32") }, "clsq_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::U32x4]; &INPUTS }, output: &::U32x4, - definition: Named("llvm.neon.vcls.v4i32") + definition: Named("llvm.arm.neon.vcls.v4i32") }, "cnt_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I8x8]; &INPUTS }, @@ -1595,32 +1595,32 @@ pub fn find(name: &str) -> Option { "recpe_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::U32x2]; &INPUTS }, output: &::U32x2, - definition: Named("llvm.neon.vrecpe.v2i32") + definition: Named("llvm.arm.neon.vrecpe.v2i32") }, "recpe_f32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::F32x2]; &INPUTS }, output: &::F32x2, - definition: Named("llvm.neon.vrecpe.v2f32") + definition: Named("llvm.arm.neon.vrecpe.v2f32") }, "recpeq_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::U32x4]; &INPUTS }, output: &::U32x4, - definition: Named("llvm.neon.vrecpe.v4i32") + definition: Named("llvm.arm.neon.vrecpe.v4i32") }, "recpeq_f32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::F32x4]; &INPUTS }, output: &::F32x4, - definition: Named("llvm.neon.vrecpe.v4f32") + definition: Named("llvm.arm.neon.vrecpe.v4f32") }, "recps_f32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::F32x2, &::F32x2]; &INPUTS }, output: &::F32x2, - definition: Named("llvm.neon.vfrecps.v2f32") + definition: Named("llvm.arm.neon.vfrecps.v2f32") }, "recpsq_f32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::F32x4, &::F32x4]; &INPUTS }, output: &::F32x4, - definition: Named("llvm.neon.vfrecps.v4f32") + definition: Named("llvm.arm.neon.vfrecps.v4f32") }, "sqrt_f32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::F32x2]; &INPUTS }, @@ -1635,452 +1635,452 @@ pub fn find(name: &str) -> Option { "rsqrte_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::U32x2]; &INPUTS }, output: &::U32x2, - definition: Named("llvm.neon.vrsqrte.v2i32") + definition: Named("llvm.arm.neon.vrsqrte.v2i32") }, "rsqrte_f32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::F32x2]; &INPUTS }, output: &::F32x2, - definition: Named("llvm.neon.vrsqrte.v2f32") + definition: Named("llvm.arm.neon.vrsqrte.v2f32") }, "rsqrteq_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::U32x4]; &INPUTS }, output: &::U32x4, - definition: Named("llvm.neon.vrsqrte.v4i32") + definition: Named("llvm.arm.neon.vrsqrte.v4i32") }, "rsqrteq_f32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::F32x4]; &INPUTS }, output: &::F32x4, - definition: Named("llvm.neon.vrsqrte.v4f32") + definition: Named("llvm.arm.neon.vrsqrte.v4f32") }, "rsqrts_f32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::F32x2, &::F32x2]; &INPUTS }, output: &::F32x2, - definition: Named("llvm.neon.vrsqrts.v2f32") + definition: Named("llvm.arm.neon.vrsqrts.v2f32") }, "rsqrtsq_f32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::F32x4, &::F32x4]; &INPUTS }, output: &::F32x4, - definition: Named("llvm.neon.vrsqrts.v4f32") + definition: Named("llvm.arm.neon.vrsqrts.v4f32") }, "bsl_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x8, &::I8x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vbsl.v8i8") + definition: Named("llvm.arm.neon.vbsl.v8i8") }, "bsl_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x8, &::U8x8]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vbsl.v8i8") + definition: Named("llvm.arm.neon.vbsl.v8i8") }, "bsl_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x4, &::I16x4]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vbsl.v4i16") + definition: Named("llvm.arm.neon.vbsl.v4i16") }, "bsl_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x4, &::U16x4]; &INPUTS }, output: &::U16x4, - definition: Named("llvm.neon.vbsl.v4i16") + definition: Named("llvm.arm.neon.vbsl.v4i16") }, "bsl_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x2, &::I32x2]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vbsl.v2i32") + definition: Named("llvm.arm.neon.vbsl.v2i32") }, "bsl_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x2, &::U32x2]; &INPUTS }, output: &::U32x2, - definition: Named("llvm.neon.vbsl.v2i32") + definition: Named("llvm.arm.neon.vbsl.v2i32") }, "bsl_s64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U64x1, &::I64x1]; &INPUTS }, output: &::I64x1, - definition: Named("llvm.neon.vbsl.v1i64") + definition: Named("llvm.arm.neon.vbsl.v1i64") }, "bsl_u64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U64x1, &::U64x1]; &INPUTS }, output: &::U64x1, - definition: Named("llvm.neon.vbsl.v1i64") + definition: Named("llvm.arm.neon.vbsl.v1i64") }, "bslq_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x16, &::I8x16]; &INPUTS }, output: &::I8x16, - definition: Named("llvm.neon.vbsl.v16i8") + definition: Named("llvm.arm.neon.vbsl.v16i8") }, "bslq_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x16, &::U8x16]; &INPUTS }, output: &::U8x16, - definition: Named("llvm.neon.vbsl.v16i8") + definition: Named("llvm.arm.neon.vbsl.v16i8") }, "bslq_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x8, &::I16x8]; &INPUTS }, output: &::I16x8, - definition: Named("llvm.neon.vbsl.v8i16") + definition: Named("llvm.arm.neon.vbsl.v8i16") }, "bslq_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x8, &::U16x8]; &INPUTS }, output: &::U16x8, - definition: Named("llvm.neon.vbsl.v8i16") + definition: Named("llvm.arm.neon.vbsl.v8i16") }, "bslq_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::I32x4]; &INPUTS }, output: &::I32x4, - definition: Named("llvm.neon.vbsl.v4i32") + definition: Named("llvm.arm.neon.vbsl.v4i32") }, "bslq_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::U32x4]; &INPUTS }, output: &::U32x4, - definition: Named("llvm.neon.vbsl.v4i32") + definition: Named("llvm.arm.neon.vbsl.v4i32") }, "bslq_s64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U64x2, &::I64x2]; &INPUTS }, output: &::I64x2, - definition: Named("llvm.neon.vbsl.v2i64") + definition: Named("llvm.arm.neon.vbsl.v2i64") }, "bslq_u64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U64x2, &::U64x2]; &INPUTS }, output: &::U64x2, - definition: Named("llvm.neon.vbsl.v2i64") + definition: Named("llvm.arm.neon.vbsl.v2i64") }, "padd_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x8, &::I8x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vpadd.v8i8") + definition: Named("llvm.arm.neon.vpadd.v8i8") }, "padd_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x8, &::U8x8]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vpadd.v8i8") + definition: Named("llvm.arm.neon.vpadd.v8i8") }, "padd_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x4, &::I16x4]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vpadd.v4i16") + definition: Named("llvm.arm.neon.vpadd.v4i16") }, "padd_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x4, &::U16x4]; &INPUTS }, output: &::U16x4, - definition: Named("llvm.neon.vpadd.v4i16") + definition: Named("llvm.arm.neon.vpadd.v4i16") }, "padd_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x2, &::I32x2]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vpadd.v2i32") + definition: Named("llvm.arm.neon.vpadd.v2i32") }, "padd_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x2, &::U32x2]; &INPUTS }, output: &::U32x2, - definition: Named("llvm.neon.vpadd.v2i32") + definition: Named("llvm.arm.neon.vpadd.v2i32") }, "padd_f32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::F32x2, &::F32x2]; &INPUTS }, output: &::F32x2, - definition: Named("llvm.neon.vpadd.v2f32") + definition: Named("llvm.arm.neon.vpadd.v2f32") }, "paddl_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I8x8]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vpaddls.v4i16.v8i8") + definition: Named("llvm.arm.neon.vpaddls.v4i16.v8i8") }, "paddl_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::U8x8]; &INPUTS }, output: &::U16x4, - definition: Named("llvm.neon.vpaddlu.v4i16.v8i8") + definition: Named("llvm.arm.neon.vpaddlu.v4i16.v8i8") }, "paddl_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I16x4]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vpaddls.v2i32.v4i16") + definition: Named("llvm.arm.neon.vpaddls.v2i32.v4i16") }, "paddl_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::U16x4]; &INPUTS }, output: &::U32x2, - definition: Named("llvm.neon.vpaddlu.v2i32.v4i16") + definition: Named("llvm.arm.neon.vpaddlu.v2i32.v4i16") }, "paddl_s64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I32x2]; &INPUTS }, output: &::I64x1, - definition: Named("llvm.neon.vpaddls.v1i64.v2i32") + definition: Named("llvm.arm.neon.vpaddls.v1i64.v2i32") }, "paddl_u64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::U32x2]; &INPUTS }, output: &::U64x1, - definition: Named("llvm.neon.vpaddlu.v1i64.v2i32") + definition: Named("llvm.arm.neon.vpaddlu.v1i64.v2i32") }, "paddlq_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I8x16]; &INPUTS }, output: &::I16x8, - definition: Named("llvm.neon.vpaddls.v8i16.v16i8") + definition: Named("llvm.arm.neon.vpaddls.v8i16.v16i8") }, "paddlq_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::U8x16]; &INPUTS }, output: &::U16x8, - definition: Named("llvm.neon.vpaddlu.v8i16.v16i8") + definition: Named("llvm.arm.neon.vpaddlu.v8i16.v16i8") }, "paddlq_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I16x8]; &INPUTS }, output: &::I32x4, - definition: Named("llvm.neon.vpaddls.v4i32.v8i16") + definition: Named("llvm.arm.neon.vpaddls.v4i32.v8i16") }, "paddlq_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::U16x8]; &INPUTS }, output: &::U32x4, - definition: Named("llvm.neon.vpaddlu.v4i32.v8i16") + definition: Named("llvm.arm.neon.vpaddlu.v4i32.v8i16") }, "paddlq_s64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::I32x4]; &INPUTS }, output: &::I64x2, - definition: Named("llvm.neon.vpaddls.v2i64.v4i32") + definition: Named("llvm.arm.neon.vpaddls.v2i64.v4i32") }, "paddlq_u64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 1] = [&::U32x4]; &INPUTS }, output: &::U64x2, - definition: Named("llvm.neon.vpaddlu.v2i64.v4i32") + definition: Named("llvm.arm.neon.vpaddlu.v2i64.v4i32") }, "padal_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x4, &::I8x8]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vpadals.v4i16.v4i16") + definition: Named("llvm.arm.neon.vpadals.v4i16.v4i16") }, "padal_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x4, &::U8x8]; &INPUTS }, output: &::U16x4, - definition: Named("llvm.neon.vpadalu.v4i16.v4i16") + definition: Named("llvm.arm.neon.vpadalu.v4i16.v4i16") }, "padal_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x2, &::I16x4]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vpadals.v2i32.v2i32") + definition: Named("llvm.arm.neon.vpadals.v2i32.v2i32") }, "padal_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x2, &::U16x4]; &INPUTS }, output: &::U32x2, - definition: Named("llvm.neon.vpadalu.v2i32.v2i32") + definition: Named("llvm.arm.neon.vpadalu.v2i32.v2i32") }, "padal_s64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I64x1, &::I32x2]; &INPUTS }, output: &::I64x1, - definition: Named("llvm.neon.vpadals.v1i64.v1i64") + definition: Named("llvm.arm.neon.vpadals.v1i64.v1i64") }, "padal_u64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U64x1, &::U32x2]; &INPUTS }, output: &::U64x1, - definition: Named("llvm.neon.vpadalu.v1i64.v1i64") + definition: Named("llvm.arm.neon.vpadalu.v1i64.v1i64") }, "padalq_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::I8x16]; &INPUTS }, output: &::I16x8, - definition: Named("llvm.neon.vpadals.v8i16.v8i16") + definition: Named("llvm.arm.neon.vpadals.v8i16.v8i16") }, "padalq_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x8, &::U8x16]; &INPUTS }, output: &::U16x8, - definition: Named("llvm.neon.vpadalu.v8i16.v8i16") + definition: Named("llvm.arm.neon.vpadalu.v8i16.v8i16") }, "padalq_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::I16x8]; &INPUTS }, output: &::I32x4, - definition: Named("llvm.neon.vpadals.v4i32.v4i32") + definition: Named("llvm.arm.neon.vpadals.v4i32.v4i32") }, "padalq_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::U16x8]; &INPUTS }, output: &::U32x4, - definition: Named("llvm.neon.vpadalu.v4i32.v4i32") + definition: Named("llvm.arm.neon.vpadalu.v4i32.v4i32") }, "padalq_s64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I64x2, &::I32x4]; &INPUTS }, output: &::I64x2, - definition: Named("llvm.neon.vpadals.v2i64.v2i64") + definition: Named("llvm.arm.neon.vpadals.v2i64.v2i64") }, "padalq_u64" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U64x2, &::U32x4]; &INPUTS }, output: &::U64x2, - definition: Named("llvm.neon.vpadalu.v2i64.v2i64") + definition: Named("llvm.arm.neon.vpadalu.v2i64.v2i64") }, "pmax_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x8, &::I8x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vpmaxs.v8i8") + definition: Named("llvm.arm.neon.vpmaxs.v8i8") }, "pmax_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x8, &::U8x8]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vpmaxu.v8i8") + definition: Named("llvm.arm.neon.vpmaxu.v8i8") }, "pmax_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x4, &::I16x4]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vpmaxs.v4i16") + definition: Named("llvm.arm.neon.vpmaxs.v4i16") }, "pmax_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x4, &::U16x4]; &INPUTS }, output: &::U16x4, - definition: Named("llvm.neon.vpmaxu.v4i16") + definition: Named("llvm.arm.neon.vpmaxu.v4i16") }, "pmax_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x2, &::I32x2]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vpmaxs.v2i32") + definition: Named("llvm.arm.neon.vpmaxs.v2i32") }, "pmax_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x2, &::U32x2]; &INPUTS }, output: &::U32x2, - definition: Named("llvm.neon.vpmaxu.v2i32") + definition: Named("llvm.arm.neon.vpmaxu.v2i32") }, "pmax_f32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::F32x2, &::F32x2]; &INPUTS }, output: &::F32x2, - definition: Named("llvm.neon.vpmaxf.v2f32") + definition: Named("llvm.arm.neon.vpmaxf.v2f32") }, "pmin_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x8, &::I8x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vpmins.v8i8") + definition: Named("llvm.arm.neon.vpmins.v8i8") }, "pmin_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x8, &::U8x8]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vpminu.v8i8") + definition: Named("llvm.arm.neon.vpminu.v8i8") }, "pmin_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x4, &::I16x4]; &INPUTS }, output: &::I16x4, - definition: Named("llvm.neon.vpmins.v4i16") + definition: Named("llvm.arm.neon.vpmins.v4i16") }, "pmin_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x4, &::U16x4]; &INPUTS }, output: &::U16x4, - definition: Named("llvm.neon.vpminu.v4i16") + definition: Named("llvm.arm.neon.vpminu.v4i16") }, "pmin_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x2, &::I32x2]; &INPUTS }, output: &::I32x2, - definition: Named("llvm.neon.vpmins.v2i32") + definition: Named("llvm.arm.neon.vpmins.v2i32") }, "pmin_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x2, &::U32x2]; &INPUTS }, output: &::U32x2, - definition: Named("llvm.neon.vpminu.v2i32") + definition: Named("llvm.arm.neon.vpminu.v2i32") }, "pmin_f32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::F32x2, &::F32x2]; &INPUTS }, output: &::F32x2, - definition: Named("llvm.neon.vpminf.v2f32") + definition: Named("llvm.arm.neon.vpminf.v2f32") }, "pminq_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x16, &::I8x16]; &INPUTS }, output: &::I8x16, - definition: Named("llvm.neon.vpmins.v16i8") + definition: Named("llvm.arm.neon.vpmins.v16i8") }, "pminq_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x16, &::U8x16]; &INPUTS }, output: &::U8x16, - definition: Named("llvm.neon.vpminu.v16i8") + definition: Named("llvm.arm.neon.vpminu.v16i8") }, "pminq_s16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::I16x8]; &INPUTS }, output: &::I16x8, - definition: Named("llvm.neon.vpmins.v8i16") + definition: Named("llvm.arm.neon.vpmins.v8i16") }, "pminq_u16" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U16x8, &::U16x8]; &INPUTS }, output: &::U16x8, - definition: Named("llvm.neon.vpminu.v8i16") + definition: Named("llvm.arm.neon.vpminu.v8i16") }, "pminq_s32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::I32x4]; &INPUTS }, output: &::I32x4, - definition: Named("llvm.neon.vpmins.v4i32") + definition: Named("llvm.arm.neon.vpmins.v4i32") }, "pminq_u32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::U32x4]; &INPUTS }, output: &::U32x4, - definition: Named("llvm.neon.vpminu.v4i32") + definition: Named("llvm.arm.neon.vpminu.v4i32") }, "pminq_f32" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::F32x4, &::F32x4]; &INPUTS }, output: &::F32x4, - definition: Named("llvm.neon.vpminf.v4f32") + definition: Named("llvm.arm.neon.vpminf.v4f32") }, "tbl1_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::I8x8, &::U8x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vtbl1") + definition: Named("llvm.arm.neon.vtbl1") }, "tbl1_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [&::U8x8, &::U8x8]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vtbl1") + definition: Named("llvm.arm.neon.vtbl1") }, "tbx1_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 3] = [&::I8x8, &::I8x8, &::U8x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vtbx1") + definition: Named("llvm.arm.neon.vtbx1") }, "tbx1_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 3] = [&::U8x8, &::U8x8, &::U8x8]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vtbx1") + definition: Named("llvm.arm.neon.vtbx1") }, "tbl2_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [{ static AGG: Type = Type::Aggregate(true, { static PARTS: [&'static Type; 2] = [&::I8x8, &::I8x8]; &PARTS }); &AGG }, &::U8x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vtbl2") + definition: Named("llvm.arm.neon.vtbl2") }, "tbl2_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [{ static AGG: Type = Type::Aggregate(true, { static PARTS: [&'static Type; 2] = [&::U8x8, &::U8x8]; &PARTS }); &AGG }, &::U8x8]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vtbl2") + definition: Named("llvm.arm.neon.vtbl2") }, "tbx2_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [{ static AGG: Type = Type::Aggregate(true, { static PARTS: [&'static Type; 2] = [&::I8x8, &::I8x8]; &PARTS }); &AGG }, &::U8x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vtbx2") + definition: Named("llvm.arm.neon.vtbx2") }, "tbx2_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [{ static AGG: Type = Type::Aggregate(true, { static PARTS: [&'static Type; 2] = [&::U8x8, &::U8x8]; &PARTS }); &AGG }, &::U8x8]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vtbx2") + definition: Named("llvm.arm.neon.vtbx2") }, "tbl3_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [{ static AGG: Type = Type::Aggregate(true, { static PARTS: [&'static Type; 3] = [&::I8x8, &::I8x8, &::I8x8]; &PARTS }); &AGG }, &::U8x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vtbl3") + definition: Named("llvm.arm.neon.vtbl3") }, "tbl3_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [{ static AGG: Type = Type::Aggregate(true, { static PARTS: [&'static Type; 3] = [&::U8x8, &::U8x8, &::U8x8]; &PARTS }); &AGG }, &::U8x8]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vtbl3") + definition: Named("llvm.arm.neon.vtbl3") }, "tbx3_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 3] = [&::I8x8, { static AGG: Type = Type::Aggregate(true, { static PARTS: [&'static Type; 3] = [&::I8x8, &::I8x8, &::I8x8]; &PARTS }); &AGG }, &::U8x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vtbx3") + definition: Named("llvm.arm.neon.vtbx3") }, "tbx3_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 3] = [&::U8x8, { static AGG: Type = Type::Aggregate(true, { static PARTS: [&'static Type; 3] = [&::U8x8, &::U8x8, &::U8x8]; &PARTS }); &AGG }, &::U8x8]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vtbx3") + definition: Named("llvm.arm.neon.vtbx3") }, "tbl4_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [{ static AGG: Type = Type::Aggregate(true, { static PARTS: [&'static Type; 4] = [&::I8x8, &::I8x8, &::I8x8, &::I8x8]; &PARTS }); &AGG }, &::U8x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vtbl4") + definition: Named("llvm.arm.neon.vtbl4") }, "tbl4_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 2] = [{ static AGG: Type = Type::Aggregate(true, { static PARTS: [&'static Type; 4] = [&::U8x8, &::U8x8, &::U8x8, &::U8x8]; &PARTS }); &AGG }, &::U8x8]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vtbl4") + definition: Named("llvm.arm.neon.vtbl4") }, "tbx4_s8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 3] = [&::I8x8, { static AGG: Type = Type::Aggregate(true, { static PARTS: [&'static Type; 4] = [&::I8x8, &::I8x8, &::I8x8, &::I8x8]; &PARTS }); &AGG }, &::U8x8]; &INPUTS }, output: &::I8x8, - definition: Named("llvm.neon.vtbx4") + definition: Named("llvm.arm.neon.vtbx4") }, "tbx4_u8" => Intrinsic { inputs: { static INPUTS: [&'static Type; 3] = [&::U8x8, { static AGG: Type = Type::Aggregate(true, { static PARTS: [&'static Type; 4] = [&::U8x8, &::U8x8, &::U8x8, &::U8x8]; &PARTS }); &AGG }, &::U8x8]; &INPUTS }, output: &::U8x8, - definition: Named("llvm.neon.vtbx4") + definition: Named("llvm.arm.neon.vtbx4") }, _ => return None, }) From 980a5b0529a94d68c1ab37170f810e7cf73996d8 Mon Sep 17 00:00:00 2001 From: gaurikholkar Date: Wed, 7 Jun 2017 02:22:21 -0700 Subject: [PATCH 065/233] indentation fixes --- src/librustc_mir/diagnostics.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_mir/diagnostics.rs b/src/librustc_mir/diagnostics.rs index 0edd5d44b606..6f3db0b388de 100644 --- a/src/librustc_mir/diagnostics.rs +++ b/src/librustc_mir/diagnostics.rs @@ -309,7 +309,7 @@ use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT}; const A: AtomicUsize = ATOMIC_USIZE_INIT; static B: &'static AtomicUsize = &A; -// error: cannot borrow a constant which may contain interior mutability, +// error: cannot borrow a constant which may contain interior mutability, // create a static instead ``` @@ -338,7 +338,7 @@ use std::cell::Cell; const A: Cell = Cell::new(1); const B: &'static Cell = &A; -// error: cannot borrow a constant which may contain interior mutability, +// error: cannot borrow a constant which may contain interior mutability, // create a static instead // or: From 8b36d3308effcc013c9c4aea9d83fa1d8bd540c1 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Wed, 7 Jun 2017 10:45:20 +0200 Subject: [PATCH 066/233] Allocate DefIndices for global crate metadata. This allows for treating global crate metadata the same as regular metadata with regard to incr. comp. --- src/librustc/dep_graph/dep_node.rs | 17 ---- src/librustc/dep_graph/mod.rs | 1 - src/librustc/hir/map/definitions.rs | 118 ++++++++++++++++++++--- src/librustc/middle/cstore.rs | 8 +- src/librustc/ty/item_path.rs | 3 +- src/librustc_incremental/persist/data.rs | 4 - src/librustc_incremental/persist/hash.rs | 37 ++----- src/librustc_incremental/persist/save.rs | 6 +- src/librustc_metadata/creader.rs | 8 +- src/librustc_metadata/cstore.rs | 11 +-- src/librustc_metadata/cstore_impl.rs | 4 +- src/librustc_metadata/decoder.rs | 19 ++-- src/librustc_metadata/encoder.rs | 40 +++++--- src/librustc_metadata/index_builder.rs | 2 +- 14 files changed, 159 insertions(+), 119 deletions(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 1a0f89a1e536..1571cf344ede 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -53,9 +53,6 @@ pub enum DepNode { /// in an extern crate. MetaData(D), - /// Represents some piece of metadata global to its crate. - GlobalMetaData(D, GlobalMetaDataKind), - /// Represents some artifact that we save to disk. Note that these /// do not have a def-id as part of their identifier. WorkProduct(WorkProductId), @@ -309,7 +306,6 @@ impl DepNode { ItemBodyNestedBodies(ref d) => op(d).map(ItemBodyNestedBodies), ConstIsRvaluePromotableToStatic(ref d) => op(d).map(ConstIsRvaluePromotableToStatic), IsMirAvailable(ref d) => op(d).map(IsMirAvailable), - GlobalMetaData(ref d, kind) => op(d).map(|d| GlobalMetaData(d, kind)), } } } @@ -330,16 +326,3 @@ impl WorkProductId { WorkProductId(hasher.finish()) } } - -#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] -pub enum GlobalMetaDataKind { - Krate, - CrateDeps, - DylibDependencyFormats, - LangItems, - LangItemsMissing, - NativeLibraries, - CodeMap, - Impls, - ExportedSymbols, -} diff --git a/src/librustc/dep_graph/mod.rs b/src/librustc/dep_graph/mod.rs index 822b61df7a48..809bed939f54 100644 --- a/src/librustc/dep_graph/mod.rs +++ b/src/librustc/dep_graph/mod.rs @@ -22,7 +22,6 @@ mod thread; pub use self::dep_tracking_map::{DepTrackingMap, DepTrackingMapConfig}; pub use self::dep_node::DepNode; pub use self::dep_node::WorkProductId; -pub use self::dep_node::GlobalMetaDataKind; pub use self::graph::DepGraph; pub use self::graph::WorkProduct; pub use self::query::DepGraphQuery; diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index ced0f351c9ee..ae43035f3b2e 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -15,7 +15,8 @@ //! expressions) that are mostly just leftovers. use hir; -use hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE, DefIndexAddressSpace}; +use hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE, DefIndexAddressSpace, + CRATE_DEF_INDEX}; use ich::Fingerprint; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::indexed_vec::IndexVec; @@ -396,6 +397,11 @@ pub enum DefPathData { ImplTrait, /// A `typeof` type node. Typeof, + + /// GlobalMetaData identifies a piece of crate metadata that is global to + /// a whole crate (as opposed to just one item). GlobalMetaData components + /// are only supposed to show up right below the crate root. + GlobalMetaData(Ident) } #[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug, @@ -427,8 +433,8 @@ impl Definitions { /// Get the number of definitions. pub fn def_index_counts_lo_hi(&self) -> (usize, usize) { - (self.def_index_to_node[DefIndexAddressSpace::Low.index()].len(), - self.def_index_to_node[DefIndexAddressSpace::High.index()].len()) + (self.table.index_to_key[DefIndexAddressSpace::Low.index()].len(), + self.table.index_to_key[DefIndexAddressSpace::High.index()].len()) } pub fn def_key(&self, index: DefIndex) -> DefKey { @@ -469,7 +475,12 @@ impl Definitions { if def_id.krate == LOCAL_CRATE { let space_index = def_id.index.address_space().index(); let array_index = def_id.index.as_array_index(); - Some(self.def_index_to_node[space_index][array_index]) + let node_id = self.def_index_to_node[space_index][array_index]; + if node_id != ast::DUMMY_NODE_ID { + Some(node_id) + } else { + None + } } else { None } @@ -498,12 +509,16 @@ impl Definitions { // Create the definition. let address_space = super::ITEM_LIKE_SPACE; - let index = self.table.allocate(key, def_path_hash, address_space); + let root_index = self.table.allocate(key, def_path_hash, address_space); + assert_eq!(root_index, CRATE_DEF_INDEX); assert!(self.def_index_to_node[address_space.index()].is_empty()); self.def_index_to_node[address_space.index()].push(ast::CRATE_NODE_ID); - self.node_to_def_index.insert(ast::CRATE_NODE_ID, index); + self.node_to_def_index.insert(ast::CRATE_NODE_ID, root_index); - index + // Allocate some other DefIndices that always must exist. + GlobalMetaDataKind::allocate_def_indices(self); + + root_index } /// Add a definition with a parent definition. @@ -550,13 +565,19 @@ impl Definitions { assert_eq!(index.as_array_index(), self.def_index_to_node[address_space.index()].len()); self.def_index_to_node[address_space.index()].push(node_id); + + // Some things for which we allocate DefIndices don't correspond to + // anything in the AST, so they don't have a NodeId. For these cases + // we don't need a mapping from NodeId to DefIndex. + if node_id != ast::DUMMY_NODE_ID { + debug!("create_def_with_parent: def_index_to_node[{:?} <-> {:?}", index, node_id); + self.node_to_def_index.insert(node_id, index); + } + if expansion.is_modern() { self.expansions.insert(index, expansion); } - debug!("create_def_with_parent: def_index_to_node[{:?} <-> {:?}", index, node_id); - self.node_to_def_index.insert(node_id, index); - index } @@ -594,7 +615,8 @@ impl DefPathData { LifetimeDef(ident) | EnumVariant(ident) | Binding(ident) | - Field(ident) => Some(ident), + Field(ident) | + GlobalMetaData(ident) => Some(ident), Impl | CrateRoot | @@ -622,7 +644,8 @@ impl DefPathData { LifetimeDef(ident) | EnumVariant(ident) | Binding(ident) | - Field(ident) => { + Field(ident) | + GlobalMetaData(ident) => { return ident.name.as_str(); } @@ -667,3 +690,74 @@ impl ::std::hash::Hash for DefPathData { } } } + + +// We define the GlobalMetaDataKind enum with this macro because we want to +// make sure that we exhaustively iterate over all variants when registering +// the corresponding DefIndices in the DefTable. +macro_rules! define_global_metadata_kind { + (pub enum GlobalMetaDataKind { + $($variant:ident),* + }) => ( + #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, + RustcEncodable, RustcDecodable)] + pub enum GlobalMetaDataKind { + $($variant),* + } + + impl GlobalMetaDataKind { + fn allocate_def_indices(definitions: &mut Definitions) { + $({ + let instance = GlobalMetaDataKind::$variant; + definitions.create_def_with_parent( + CRATE_DEF_INDEX, + ast::DUMMY_NODE_ID, + DefPathData::GlobalMetaData(instance.ident()), + DefIndexAddressSpace::High, + Mark::root() + ); + + // Make sure calling def_index does not crash. + instance.def_index(&definitions.table); + })* + } + + pub fn def_index(&self, def_path_table: &DefPathTable) -> DefIndex { + let def_key = DefKey { + parent: Some(CRATE_DEF_INDEX), + disambiguated_data: DisambiguatedDefPathData { + data: DefPathData::GlobalMetaData(self.ident()), + disambiguator: 0, + } + }; + + def_path_table.key_to_index[&def_key] + } + + fn ident(&self) -> Ident { + + let string = match *self { + $( + GlobalMetaDataKind::$variant => { + concat!("{{GlobalMetaData::", stringify!($variant), "}}") + } + )* + }; + + Ident::from_str(string) + } + } + ) +} + +define_global_metadata_kind!(pub enum GlobalMetaDataKind { + Krate, + CrateDeps, + DylibDependencyFormats, + LangItems, + LangItemsMissing, + NativeLibraries, + CodeMap, + Impls, + ExportedSymbols +}); diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 71b066c6688b..57b8c7f8c16b 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -23,7 +23,6 @@ // probably get a better home if someone can find one. use hir::def; -use dep_graph::DepNode; use hir::def_id::{CrateNum, DefId, DefIndex}; use hir::map as hir_map; use hir::map::definitions::{Definitions, DefKey, DisambiguatedDefPathData, @@ -190,15 +189,14 @@ pub struct EncodedMetadataHash { /// upstream crate. #[derive(Debug, RustcEncodable, RustcDecodable, Clone)] pub struct EncodedMetadataHashes { - pub entry_hashes: Vec, - pub global_hashes: Vec<(DepNode<()>, ich::Fingerprint)>, + // Stable content hashes for things in crate metadata, indexed by DefIndex. + pub hashes: Vec, } impl EncodedMetadataHashes { pub fn new() -> EncodedMetadataHashes { EncodedMetadataHashes { - entry_hashes: Vec::new(), - global_hashes: Vec::new(), + hashes: Vec::new(), } } } diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index 78536b53ba87..503177e437be 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -197,7 +197,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { data @ DefPathData::ClosureExpr | data @ DefPathData::Binding(..) | data @ DefPathData::ImplTrait | - data @ DefPathData::Typeof => { + data @ DefPathData::Typeof | + data @ DefPathData::GlobalMetaData(..) => { let parent_def_id = self.parent_def_id(def_id).unwrap(); self.push_item_path(buffer, parent_def_id); buffer.push(&data.as_interned_str()); diff --git a/src/librustc_incremental/persist/data.rs b/src/librustc_incremental/persist/data.rs index 4669bb866d41..96b7de94daf6 100644 --- a/src/librustc_incremental/persist/data.rs +++ b/src/librustc_incremental/persist/data.rs @@ -126,10 +126,6 @@ pub struct SerializedMetadataHashes { /// (matching the one found in this structure). pub entry_hashes: Vec, - /// This map contains fingerprints that are not specific to some DefId but - /// describe something global to the whole crate. - pub global_hashes: Vec<(DepNode<()>, Fingerprint)>, - /// For each DefIndex (as it occurs in SerializedMetadataHash), this /// map stores the DefPathIndex (as it occurs in DefIdDirectory), so /// that we can find the new DefId for a SerializedMetadataHash in a diff --git a/src/librustc_incremental/persist/hash.rs b/src/librustc_incremental/persist/hash.rs index 6ab280be470d..4a2dd274aae5 100644 --- a/src/librustc_incremental/persist/hash.rs +++ b/src/librustc_incremental/persist/hash.rs @@ -9,7 +9,7 @@ // except according to those terms. use rustc::dep_graph::DepNode; -use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE, CRATE_DEF_INDEX}; +use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use rustc::hir::svh::Svh; use rustc::ich::Fingerprint; use rustc::ty::TyCtxt; @@ -29,9 +29,8 @@ use std::fmt::Debug; pub struct HashContext<'a, 'tcx: 'a> { pub tcx: TyCtxt<'a, 'tcx, 'tcx>, incremental_hashes_map: &'a IncrementalHashesMap, - item_metadata_hashes: FxHashMap, + metadata_hashes: FxHashMap, crate_hashes: FxHashMap, - global_metadata_hashes: FxHashMap, Fingerprint>, } impl<'a, 'tcx> HashContext<'a, 'tcx> { @@ -41,9 +40,8 @@ impl<'a, 'tcx> HashContext<'a, 'tcx> { HashContext { tcx: tcx, incremental_hashes_map: incremental_hashes_map, - item_metadata_hashes: FxHashMap(), + metadata_hashes: FxHashMap(), crate_hashes: FxHashMap(), - global_metadata_hashes: FxHashMap(), } } @@ -53,8 +51,7 @@ impl<'a, 'tcx> HashContext<'a, 'tcx> { DepNode::Hir(_) | DepNode::HirBody(_) => true, - DepNode::MetaData(def_id) | - DepNode::GlobalMetaData(def_id, _) => !def_id.is_local(), + DepNode::MetaData(def_id) => !def_id.is_local(), _ => false, } } @@ -83,13 +80,7 @@ impl<'a, 'tcx> HashContext<'a, 'tcx> { DepNode::MetaData(def_id) if !def_id.is_local() => { Some(self.metadata_hash(def_id, def_id.krate, - |this| &mut this.item_metadata_hashes)) - } - - DepNode::GlobalMetaData(def_id, kind) => { - Some(self.metadata_hash(DepNode::GlobalMetaData(def_id, kind), - def_id.krate, - |this| &mut this.global_metadata_hashes)) + |this| &mut this.metadata_hashes)) } _ => { @@ -217,27 +208,11 @@ impl<'a, 'tcx> HashContext<'a, 'tcx> { let def_id = DefId { krate: cnum, index: serialized_hash.def_index }; // record the hash for this dep-node - let old = self.item_metadata_hashes.insert(def_id, serialized_hash.hash); + let old = self.metadata_hashes.insert(def_id, serialized_hash.hash); debug!("load_from_data: def_id={:?} hash={}", def_id, serialized_hash.hash); assert!(old.is_none(), "already have hash for {:?}", def_id); } - for (dep_node, fingerprint) in serialized_hashes.global_hashes { - // Here we need to remap the CrateNum in the DepNode. - let def_id = DefId { krate: cnum, index: CRATE_DEF_INDEX }; - let dep_node = match dep_node { - DepNode::GlobalMetaData(_, kind) => DepNode::GlobalMetaData(def_id, kind), - other => { - bug!("unexpected DepNode variant: {:?}", other) - } - }; - - // record the hash for this dep-node - debug!("load_from_data: def_node={:?} hash={}", dep_node, fingerprint); - let old = self.global_metadata_hashes.insert(dep_node.clone(), fingerprint); - assert!(old.is_none(), "already have hash for {:?}", dep_node); - } - Ok(()) } } diff --git a/src/librustc_incremental/persist/save.rs b/src/librustc_incremental/persist/save.rs index 6d717d6f409d..01db756f9de0 100644 --- a/src/librustc_incremental/persist/save.rs +++ b/src/librustc_incremental/persist/save.rs @@ -255,9 +255,11 @@ pub fn encode_metadata_hashes(tcx: TyCtxt, current_metadata_hashes: &mut FxHashMap, encoder: &mut Encoder) -> io::Result<()> { + assert_eq!(metadata_hashes.hashes.len(), + metadata_hashes.hashes.iter().map(|x| (x.def_index, ())).collect::>().len()); + let mut serialized_hashes = SerializedMetadataHashes { - entry_hashes: metadata_hashes.entry_hashes.to_vec(), - global_hashes: metadata_hashes.global_hashes.to_vec(), + entry_hashes: metadata_hashes.hashes.to_vec(), index_map: FxHashMap() }; diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 51f152991fda..c1b57a543a40 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -14,8 +14,7 @@ use cstore::{self, CStore, CrateSource, MetadataBlob}; use locator::{self, CratePaths}; use schema::{CrateRoot, Tracked}; -use rustc::dep_graph::{DepNode, GlobalMetaDataKind}; -use rustc::hir::def_id::{DefId, CrateNum, DefIndex, CRATE_DEF_INDEX}; +use rustc::hir::def_id::{CrateNum, DefIndex}; use rustc::hir::svh::Svh; use rustc::middle::cstore::DepKind; use rustc::session::Session; @@ -516,14 +515,11 @@ impl<'a> CrateLoader<'a> { return cstore::CrateNumMap::new(); } - let dep_node = DepNode::GlobalMetaData(DefId { krate, index: CRATE_DEF_INDEX }, - GlobalMetaDataKind::CrateDeps); - // The map from crate numbers in the crate we're resolving to local crate numbers. // We map 0 and all other holes in the map to our parent crate. The "additional" // self-dependencies should be harmless. ::std::iter::once(krate).chain(crate_root.crate_deps - .get(&self.sess.dep_graph, dep_node) + .get_untracked() .decode(metadata) .map(|dep| { debug!("resolving dep crate {} hash: `{}`", dep.name, dep.hash); diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs index 5066b927c115..ed67616e58f6 100644 --- a/src/librustc_metadata/cstore.rs +++ b/src/librustc_metadata/cstore.rs @@ -13,9 +13,9 @@ use schema::{self, Tracked}; -use rustc::dep_graph::{DepGraph, DepNode, GlobalMetaDataKind}; +use rustc::dep_graph::DepGraph; use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, CrateNum, DefIndex, DefId}; -use rustc::hir::map::definitions::DefPathTable; +use rustc::hir::map::definitions::{DefPathTable, GlobalMetaDataKind}; use rustc::hir::svh::Svh; use rustc::middle::cstore::{DepKind, ExternCrate, MetadataLoader}; use rustc_back::PanicStrategy; @@ -304,12 +304,7 @@ impl CrateMetadata { } pub fn panic_strategy(&self, dep_graph: &DepGraph) -> PanicStrategy { - let def_id = DefId { - krate: self.cnum, - index: CRATE_DEF_INDEX, - }; - let dep_node = DepNode::GlobalMetaData(def_id, GlobalMetaDataKind::Krate); - + let dep_node = self.metadata_dep_node(GlobalMetaDataKind::Krate); self.root .panic_strategy .get(dep_graph, dep_node) diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index dcc55846b53d..60cc03f7b792 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -23,9 +23,9 @@ use rustc::ty::{self, TyCtxt}; use rustc::ty::maps::Providers; use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE}; -use rustc::dep_graph::{DepNode, GlobalMetaDataKind}; +use rustc::dep_graph::{DepNode}; use rustc::hir::map::{DefKey, DefPath, DisambiguatedDefPathData, DefPathHash}; -use rustc::hir::map::definitions::DefPathTable; +use rustc::hir::map::definitions::{DefPathTable, GlobalMetaDataKind}; use rustc::util::nodemap::{NodeSet, DefIdMap}; use rustc_back::PanicStrategy; diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 91470f238ecb..a095fdd50841 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -13,8 +13,9 @@ use cstore::{self, CrateMetadata, MetadataBlob, NativeLibrary}; use schema::*; -use rustc::dep_graph::{DepGraph, DepNode, GlobalMetaDataKind}; +use rustc::dep_graph::{DepGraph, DepNode}; use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash}; +use rustc::hir::map::definitions::GlobalMetaDataKind; use rustc::hir; use rustc::middle::cstore::LinkagePreference; @@ -993,12 +994,8 @@ impl<'a, 'tcx> CrateMetadata { pub fn get_dylib_dependency_formats(&self, dep_graph: &DepGraph) -> Vec<(CrateNum, LinkagePreference)> { - let def_id = DefId { - krate: self.cnum, - index: CRATE_DEF_INDEX, - }; - let dep_node = DepNode::GlobalMetaData(def_id, - GlobalMetaDataKind::DylibDependencyFormats); + let dep_node = + self.metadata_dep_node(GlobalMetaDataKind::DylibDependencyFormats); self.root .dylib_dependency_formats .get(dep_graph, dep_node) @@ -1198,11 +1195,7 @@ impl<'a, 'tcx> CrateMetadata { } pub fn metadata_dep_node(&self, kind: GlobalMetaDataKind) -> DepNode { - let def_id = DefId { - krate: self.cnum, - index: CRATE_DEF_INDEX, - }; - - DepNode::GlobalMetaData(def_id, kind) + let def_index = kind.def_index(&self.def_path_table); + DepNode::MetaData(self.local_def_id(def_index)) } } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index a02a82dfe69a..2a504c4c0779 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -14,10 +14,10 @@ use isolated_encoder::IsolatedEncoder; use schema::*; use rustc::middle::cstore::{LinkMeta, LinkagePreference, NativeLibrary, - EncodedMetadata, EncodedMetadataHashes}; + EncodedMetadata, EncodedMetadataHashes, + EncodedMetadataHash}; use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefIndex, DefId, LOCAL_CRATE}; -use rustc::hir::map::definitions::DefPathTable; -use rustc::dep_graph::{DepNode, GlobalMetaDataKind}; +use rustc::hir::map::definitions::{DefPathTable, GlobalMetaDataKind}; use rustc::ich::Fingerprint; use rustc::middle::dependency_format::Linkage; use rustc::middle::lang_items; @@ -244,7 +244,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { // Encodes something that corresponds to a single DepNode::GlobalMetaData // and registers the Fingerprint in the `metadata_hashes` map. pub fn tracked<'x, DATA, R>(&'x mut self, - dep_node: DepNode<()>, + def_index: DefIndex, op: fn(&mut IsolatedEncoder<'x, 'a, 'tcx>, DATA) -> R, data: DATA) -> Tracked { @@ -253,7 +253,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let (fingerprint, this) = entry_builder.finish(); if let Some(fingerprint) = fingerprint { - this.metadata_hashes.global_hashes.push((dep_node, fingerprint)); + this.metadata_hashes.hashes.push(EncodedMetadataHash { + def_index, + hash: fingerprint, + }) } Tracked::new(ret) @@ -322,12 +325,17 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fn encode_crate_root(&mut self) -> Lazy { let mut i = self.position(); + let tcx = self.tcx; + let global_metadata_def_index = move |kind: GlobalMetaDataKind| { + kind.def_index(tcx.hir.definitions().def_path_table()) + }; + let crate_deps = self.tracked( - DepNode::GlobalMetaData((), GlobalMetaDataKind::CrateDeps), + global_metadata_def_index(GlobalMetaDataKind::CrateDeps), IsolatedEncoder::encode_crate_deps, ()); let dylib_dependency_formats = self.tracked( - DepNode::GlobalMetaData((), GlobalMetaDataKind::DylibDependencyFormats), + global_metadata_def_index(GlobalMetaDataKind::DylibDependencyFormats), IsolatedEncoder::encode_dylib_dependency_formats, ()); let dep_bytes = self.position() - i; @@ -335,12 +343,12 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { // Encode the language items. i = self.position(); let lang_items = self.tracked( - DepNode::GlobalMetaData((), GlobalMetaDataKind::LangItems), + global_metadata_def_index(GlobalMetaDataKind::LangItems), IsolatedEncoder::encode_lang_items, ()); let lang_items_missing = self.tracked( - DepNode::GlobalMetaData((), GlobalMetaDataKind::LangItemsMissing), + global_metadata_def_index(GlobalMetaDataKind::LangItemsMissing), IsolatedEncoder::encode_lang_items_missing, ()); let lang_item_bytes = self.position() - i; @@ -348,7 +356,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { // Encode the native libraries used i = self.position(); let native_libraries = self.tracked( - DepNode::GlobalMetaData((), GlobalMetaDataKind::NativeLibraries), + global_metadata_def_index(GlobalMetaDataKind::NativeLibraries), IsolatedEncoder::encode_native_libraries, ()); let native_lib_bytes = self.position() - i; @@ -366,7 +374,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { // Encode the def IDs of impls, for coherence checking. i = self.position(); let impls = self.tracked( - DepNode::GlobalMetaData((), GlobalMetaDataKind::Impls), + global_metadata_def_index(GlobalMetaDataKind::Impls), IsolatedEncoder::encode_impls, ()); let impl_bytes = self.position() - i; @@ -374,7 +382,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { // Encode exported symbols info. i = self.position(); let exported_symbols = self.tracked( - DepNode::GlobalMetaData((), GlobalMetaDataKind::ExportedSymbols), + global_metadata_def_index(GlobalMetaDataKind::ExportedSymbols), IsolatedEncoder::encode_exported_symbols, self.exported_symbols); let exported_symbols_bytes = self.position() - i; @@ -422,10 +430,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let total_bytes = self.position(); - self.metadata_hashes.global_hashes.push(( - DepNode::GlobalMetaData((), GlobalMetaDataKind::Krate), - Fingerprint::from_smaller_hash(link_meta.crate_hash.as_u64()) - )); + self.metadata_hashes.hashes.push(EncodedMetadataHash { + def_index: global_metadata_def_index(GlobalMetaDataKind::Krate), + hash: Fingerprint::from_smaller_hash(link_meta.crate_hash.as_u64()) + }); if self.tcx.sess.meta_stats() { let mut zero_bytes = 0; diff --git a/src/librustc_metadata/index_builder.rs b/src/librustc_metadata/index_builder.rs index 478202aeba44..2db9c6a4ff81 100644 --- a/src/librustc_metadata/index_builder.rs +++ b/src/librustc_metadata/index_builder.rs @@ -135,7 +135,7 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { let (fingerprint, ecx) = entry_builder.finish(); if let Some(hash) = fingerprint { - ecx.metadata_hashes.entry_hashes.push(EncodedMetadataHash { + ecx.metadata_hashes.hashes.push(EncodedMetadataHash { def_index: id.index, hash: hash, }); From ce56daf37b7b5b101db7ef895e6be4586d80d08e Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Wed, 7 Jun 2017 12:50:50 +0100 Subject: [PATCH 067/233] Don't enable profiler on MinGW targets, as compiler-rt can't currently be compiled with MinGW --- appveyor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index d4f805de5de3..4711f34f830e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -59,7 +59,7 @@ environment: SCRIPT: python x.py dist DEPLOY: 1 - MSYS_BITS: 32 - RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu --enable-extended --enable-profiler + RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu --enable-extended SCRIPT: python x.py dist MINGW_URL: https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z @@ -67,7 +67,7 @@ environment: DEPLOY: 1 - MSYS_BITS: 64 SCRIPT: python x.py dist - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu --enable-extended --enable-profiler + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu --enable-extended MINGW_URL: https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z MINGW_DIR: mingw64 From 9a054f2002e5a21e6e0d14c89e20ec44049306fc Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Wed, 7 Jun 2017 16:17:11 +0200 Subject: [PATCH 068/233] Fix translation of external spans. --- src/librustc/middle/cstore.rs | 12 ++++++++---- src/librustc/ty/item_path.rs | 2 +- src/librustc_metadata/cstore_impl.rs | 10 +++++----- src/librustc_metadata/decoder.rs | 16 ++++++++-------- src/librustc_resolve/build_reduced_graph.rs | 4 ++-- src/librustc_typeck/check/method/suggest.rs | 2 +- src/librustdoc/clean/inline.rs | 2 +- src/librustdoc/clean/mod.rs | 2 +- src/librustdoc/visit_lib.rs | 2 +- 9 files changed, 28 insertions(+), 24 deletions(-) diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 71b066c6688b..6c902b8c5c64 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -232,7 +232,7 @@ pub trait CrateStore { // item info fn visibility(&self, def: DefId) -> ty::Visibility; - fn visible_parent_map<'a>(&'a self) -> ::std::cell::Ref<'a, DefIdMap>; + fn visible_parent_map<'a>(&'a self, sess: &Session) -> ::std::cell::Ref<'a, DefIdMap>; fn item_generics_cloned(&self, def: DefId) -> ty::Generics; // trait info @@ -285,7 +285,7 @@ pub trait CrateStore { fn def_path_hash(&self, def: DefId) -> hir_map::DefPathHash; fn def_path_table(&self, cnum: CrateNum) -> Rc; fn struct_field_names(&self, def: DefId) -> Vec; - fn item_children(&self, did: DefId) -> Vec; + fn item_children(&self, did: DefId, sess: &Session) -> Vec; fn load_macro(&self, did: DefId, sess: &Session) -> LoadedMacro; // misc. metadata @@ -347,7 +347,9 @@ impl CrateStore for DummyCrateStore { { bug!("crate_data_as_rc_any") } // item info fn visibility(&self, def: DefId) -> ty::Visibility { bug!("visibility") } - fn visible_parent_map<'a>(&'a self) -> ::std::cell::Ref<'a, DefIdMap> { + fn visible_parent_map<'a>(&'a self, session: &Session) + -> ::std::cell::Ref<'a, DefIdMap> + { bug!("visible_parent_map") } fn item_generics_cloned(&self, def: DefId) -> ty::Generics @@ -421,7 +423,9 @@ impl CrateStore for DummyCrateStore { bug!("def_path_table") } fn struct_field_names(&self, def: DefId) -> Vec { bug!("struct_field_names") } - fn item_children(&self, did: DefId) -> Vec { bug!("item_children") } + fn item_children(&self, did: DefId, sess: &Session) -> Vec { + bug!("item_children") + } fn load_macro(&self, did: DefId, sess: &Session) -> LoadedMacro { bug!("load_macro") } // misc. metadata diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index 78536b53ba87..9000aab8a6a3 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -129,7 +129,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn try_push_visible_item_path(self, buffer: &mut T, external_def_id: DefId) -> bool where T: ItemPathBuffer { - let visible_parent_map = self.sess.cstore.visible_parent_map(); + let visible_parent_map = self.sess.cstore.visible_parent_map(self.sess); let (mut cur_def, mut cur_path) = (external_def_id, Vec::::new()); loop { diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index dcc55846b53d..f297276ff3ad 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -80,7 +80,7 @@ provide! { <'tcx> tcx, def_id, cdata variances_of => { Rc::new(cdata.get_item_variances(def_id.index)) } associated_item_def_ids => { let mut result = vec![]; - cdata.each_child_of_item(def_id.index, |child| result.push(child.def.def_id())); + cdata.each_child_of_item(def_id.index, |child| result.push(child.def.def_id()), tcx.sess); Rc::new(result) } associated_item => { cdata.get_associated_item(def_id.index) } @@ -348,12 +348,12 @@ impl CrateStore for cstore::CStore { self.get_crate_data(def.krate).get_struct_field_names(def.index) } - fn item_children(&self, def_id: DefId) -> Vec + fn item_children(&self, def_id: DefId, sess: &Session) -> Vec { self.dep_graph.read(DepNode::MetaData(def_id)); let mut result = vec![]; self.get_crate_data(def_id.krate) - .each_child_of_item(def_id.index, |child| result.push(child)); + .each_child_of_item(def_id.index, |child| result.push(child), sess); result } @@ -456,7 +456,7 @@ impl CrateStore for cstore::CStore { /// Returns a map from a sufficiently visible external item (i.e. an external item that is /// visible from at least one local module) to a sufficiently visible parent (considering /// modules that re-export the external item to be parents). - fn visible_parent_map<'a>(&'a self) -> ::std::cell::Ref<'a, DefIdMap> { + fn visible_parent_map<'a>(&'a self, sess: &Session) -> ::std::cell::Ref<'a, DefIdMap> { { let visible_parent_map = self.visible_parent_map.borrow(); if !visible_parent_map.is_empty() { @@ -506,7 +506,7 @@ impl CrateStore for cstore::CStore { index: CRATE_DEF_INDEX }); while let Some(def) = bfs_queue.pop_front() { - for child in self.item_children(def) { + for child in self.item_children(def, sess) { add_child(bfs_queue, child, def); } } diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 91470f238ecb..b08a9c4c1237 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -653,7 +653,7 @@ impl<'a, 'tcx> CrateMetadata { } /// Iterates over each child of the given item. - pub fn each_child_of_item(&self, id: DefIndex, mut callback: F) + pub fn each_child_of_item(&self, id: DefIndex, mut callback: F, sess: &Session) where F: FnMut(def::Export) { if let Some(ref proc_macros) = self.proc_macros { @@ -676,19 +676,19 @@ impl<'a, 'tcx> CrateMetadata { // Find the item. let item = match self.maybe_entry(id) { None => return, - Some(item) => item.decode(self), + Some(item) => item.decode((self, sess)), }; // Iterate over all children. let macros_only = self.dep_kind.get().macros_only(); - for child_index in item.children.decode(self) { + for child_index in item.children.decode((self, sess)) { if macros_only { continue } // Get the item. if let Some(child) = self.maybe_entry(child_index) { - let child = child.decode(self); + let child = child.decode((self, sess)); match child.kind { EntryKind::MacroDef(..) => {} _ if macros_only => continue, @@ -699,12 +699,12 @@ impl<'a, 'tcx> CrateMetadata { match child.kind { // FIXME(eddyb) Don't encode these in children. EntryKind::ForeignMod => { - for child_index in child.children.decode(self) { + for child_index in child.children.decode((self, sess)) { if let Some(def) = self.get_def(child_index) { callback(def::Export { def: def, ident: Ident::with_empty_ctxt(self.item_name(child_index)), - span: self.entry(child_index).span.decode(self), + span: self.entry(child_index).span.decode((self, sess)), }); } } @@ -717,7 +717,7 @@ impl<'a, 'tcx> CrateMetadata { } let def_key = self.def_key(child_index); - let span = child.span.decode(self); + let span = child.span.decode((self, sess)); if let (Some(def), Some(name)) = (self.get_def(child_index), def_key.disambiguated_data.data.get_opt_name()) { let ident = Ident::with_empty_ctxt(name); @@ -746,7 +746,7 @@ impl<'a, 'tcx> CrateMetadata { } if let EntryKind::Mod(data) = item.kind { - for exp in data.decode(self).reexports.decode(self) { + for exp in data.decode((self, sess)).reexports.decode((self, sess)) { match exp.def { Def::Macro(..) => {} _ if macros_only => continue, diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 597a62f86884..49fb44f9d372 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -478,7 +478,7 @@ impl<'a> Resolver<'a> { span); self.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, expansion)); - for child in self.session.cstore.item_children(def_id) { + for child in self.session.cstore.item_children(def_id, self.session) { let ns = if let Def::AssociatedTy(..) = child.def { TypeNS } else { ValueNS }; self.define(module, child.ident, ns, (child.def, ty::Visibility::Public, DUMMY_SP, expansion)); @@ -564,7 +564,7 @@ impl<'a> Resolver<'a> { /// is built, building it if it is not. pub fn populate_module_if_necessary(&mut self, module: Module<'a>) { if module.populated.get() { return } - for child in self.session.cstore.item_children(module.def_id().unwrap()) { + for child in self.session.cstore.item_children(module.def_id().unwrap(), self.session) { self.build_reduced_graph_for_external_crate_def(module, child); } module.populated.set(true) diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index f8dd5774793a..4faf71e0cc94 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -526,7 +526,7 @@ pub fn all_traits<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> AllTraits<'a> if !external_mods.insert(def_id) { return; } - for child in tcx.sess.cstore.item_children(def_id) { + for child in tcx.sess.cstore.item_children(def_id, tcx.sess) { handle_external_def(tcx, traits, external_mods, child.def) } } diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 8f7add14d0a0..89c1bc99c225 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -443,7 +443,7 @@ fn build_module(cx: &DocContext, did: DefId) -> clean::Module { // two namespaces, so the target may be listed twice. Make sure we only // visit each node at most once. let mut visited = FxHashSet(); - for item in cx.tcx.sess.cstore.item_children(did) { + for item in cx.tcx.sess.cstore.item_children(did, cx.tcx.sess) { let def_id = item.def.def_id(); if cx.tcx.sess.cstore.visibility(def_id) == ty::Visibility::Public { if !visited.insert(def_id) { continue } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 20ce2c024962..bba4df6bd5f8 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -241,7 +241,7 @@ impl Clean for CrateNum { } }).collect() } else { - cx.tcx.sess.cstore.item_children(root).iter().map(|item| item.def) + cx.tcx.sess.cstore.item_children(root, cx.tcx.sess).iter().map(|item| item.def) .filter_map(as_primitive).collect() }; diff --git a/src/librustdoc/visit_lib.rs b/src/librustdoc/visit_lib.rs index 40a6ffe9505f..5518d854348c 100644 --- a/src/librustdoc/visit_lib.rs +++ b/src/librustdoc/visit_lib.rs @@ -70,7 +70,7 @@ impl<'a, 'b, 'tcx> LibEmbargoVisitor<'a, 'b, 'tcx> { return; } - for item in self.cstore.item_children(def_id) { + for item in self.cstore.item_children(def_id, self.cx.tcx.sess) { self.visit_item(item.def); } } From 453080f13e198d6cd60ef8017f02731c341ee561 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 5 Jun 2017 09:36:48 -0700 Subject: [PATCH 069/233] Update Cargo Brings in some perf improvements! --- src/Cargo.lock | 124 ++++++++++++++++++------------------------------ src/tools/cargo | 2 +- src/tools/rls | 2 +- 3 files changed, 49 insertions(+), 79 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index cc2da1a02dc9..d72ffa14a2a2 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -156,6 +156,7 @@ dependencies = [ "curl 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "docopt 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", "fs2 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -163,6 +164,7 @@ dependencies = [ "git2-curl 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "hamcrest 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "jobserver 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", "libgit2-sys 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -172,6 +174,7 @@ dependencies = [ "openssl 0.9.12 (registry+https://github.com/rust-lang/crates.io-index)", "psapi-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", + "scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -280,6 +283,7 @@ name = "crates-io" version = "0.9.0" dependencies = [ "curl 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -355,11 +359,6 @@ name = "dtoa" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "either" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "enum_primitive" version = "0.1.1" @@ -546,19 +545,22 @@ dependencies = [ "xz2 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "itertools" -version = "0.5.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "either 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "itoa" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "jobserver" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "kernel32-sys" version = "0.2.2" @@ -712,11 +714,6 @@ dependencies = [ "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "multimap" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "net2" version = "0.2.29" @@ -1011,11 +1008,11 @@ dependencies = [ "languageserver-types 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "racer 2.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rls-analysis 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rls-data 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rls-analysis 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rls-data 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rls-vfs 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustfmt 0.8.4 (git+https://github.com/rust-lang-nursery/rustfmt)", + "rls-vfs 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rustfmt 0.9.0 (git+https://github.com/rust-lang-nursery/rustfmt?branch=libsyntax)", "serde 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1026,12 +1023,12 @@ dependencies = [ [[package]] name = "rls-analysis" -version = "0.2.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "derive-new 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "rls-data 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rls-data 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1045,6 +1042,15 @@ dependencies = [ "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rls-data" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rls-span" version = "0.4.0" @@ -1057,7 +1063,7 @@ dependencies = [ [[package]] name = "rls-vfs" -version = "0.3.0" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "racer 2.0.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1446,28 +1452,23 @@ dependencies = [ [[package]] name = "rustfmt" -version = "0.8.4" -source = "git+https://github.com/rust-lang-nursery/rustfmt#bf9b3fa1d7cab2f7bd541539d397a92b4954ec96" +version = "0.9.0" +source = "git+https://github.com/rust-lang-nursery/rustfmt?branch=libsyntax#6c1de7694782d9f710b2f00b1f650f266a99b384" dependencies = [ "diff 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", - "itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "multimap 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "strings 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_errors 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_syntax 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", + "strings 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1480,6 +1481,11 @@ dependencies = [ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "scoped-tls" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "semver" version = "0.7.0" @@ -1600,7 +1606,7 @@ dependencies = [ [[package]] name = "strings" -version = "0.0.1" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1687,18 +1693,6 @@ dependencies = [ "unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "syntex_errors" -version = "0.58.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_pos 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", - "term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "syntex_pos" version = "0.52.0" @@ -1707,14 +1701,6 @@ dependencies = [ "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "syntex_pos" -version = "0.58.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "syntex_syntax" version = "0.52.0" @@ -1730,19 +1716,6 @@ dependencies = [ "unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "syntex_syntax" -version = "0.58.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_errors 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_pos 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "tar" version = "0.4.13" @@ -2034,7 +2007,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum diff 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0a515461b6c8c08419850ced27bc29e86166dcdcde8fbe76f8b1f0589bb49472" "checksum docopt 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ab32ea6e284d87987066f21a9e809a73c14720571ef34516f0890b3d355ccfd8" "checksum dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80c8b71fd71146990a9742fc06dcbbde19161a267e0ad4e572c35162f4578c90" -"checksum either 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18785c1ba806c258137c937e44ada9ee7e69a37e3c72077542cd2f069d78562a" "checksum enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be4551092f4d519593039259a9ed8daedf0da12e5109c5280338073eaeb81180" "checksum env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "15abd780e45b3ea4f76b4e9a26ff4843258dd8a3eed2775a0e7368c2e7936c2f" "checksum env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e3856f1697098606fc6cb97a93de88ca3f3bc35bb878c725920e6e82ecf05e83" @@ -2052,8 +2024,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum hamcrest 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bf088f042a467089e9baa4972f57f9247e42a0cc549ba264c7a04fbb8ecb89d4" "checksum handlebars 0.25.3 (registry+https://github.com/rust-lang/crates.io-index)" = "15bdf598fc3c2de40c6b340213028301c0d225eea55a2294e6cc148074e557a1" "checksum idna 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6ac85ec3f80c8e4e99d9325521337e14ec7555c458a14e377d189659a427f375" -"checksum itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4833d6978da405305126af4ac88569b5d71ff758581ce5a987dbfa3755f694fc" "checksum itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2f404fbc66fd9aac13e998248505e7ecb2ad8e44ab6388684c5fb11c6c251c" +"checksum jobserver 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c43fc6e4066b2adf0539c854daa1d926d7f23e6926e019850d34b8ae46391b2e" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum languageserver-types 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97c2985bfcbbcb0189cfa25e1c10c1ac7111df2b6214b652c690127aefdf4e5b" "checksum lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3b37545ab726dd833ec6420aaba8231c5b320814b9029ad585555d2a03e94fbf" @@ -2069,7 +2041,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4" "checksum miniz-sys 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "28eaee17666671fa872e567547e8428e83308ebe5808cdf6a0e28397dbe2c726" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" -"checksum multimap 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9223f4774d08e06185e44e555b9a7561243d387bac49c78a6205c42d6975fbf2" "checksum net2 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)" = "bc01404e7568680f1259aa5729539f221cb1e6d047a0d9053cab4be8a73b5d67" "checksum num 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "98b15ba84e910ea7a1973bccd3df7b31ae282bf9d8bd2897779950c9b8303d40" "checksum num-bigint 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "ba6d838b16e56da1b6c383d065ff1ec3c7d7797f65a3e8f6ba7092fd87820bac" @@ -2098,14 +2069,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4278c17d0f6d62dfef0ab00028feb45bd7d2102843f80763474eeb1be8a10c01" "checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957" "checksum regex-syntax 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9191b1f57603095f105d317e375d19b1c9c5c3185ea9633a99a6dcbed04457" -"checksum rls-analysis 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a62d88c341375c6f3f8b2e18b9b364896e7d3e7aa916907de717d0267e116506" +"checksum rls-analysis 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8d77d58e8933752142b5b92e3f8ba6d6f1630be6da5627c492268a43f79ffbda" "checksum rls-data 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fc4277ce3c57f456b11fe3145b181a844a25201bab5cbaa1978457e6e2f27d47" +"checksum rls-data 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "374a8fad31cc0681a7bfd8a04079dd4afd0e981d34e18a171b1a467445bdf51e" "checksum rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d7c7046dc6a92f2ae02ed302746db4382e75131b9ce20ce967259f6b5867a6a" -"checksum rls-vfs 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "986eada111517bcb5a7a75205b3f2b70c82e7766653cca61a23f5afce79bdb94" +"checksum rls-vfs 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ace07060dd154731b39254864245cbdd33c8f5f64fe1f630a089c72e2468f854" "checksum rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3058a43ada2c2d0b92b3ae38007a2d0fa5e9db971be260e0171408a4ff471c95" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" -"checksum rustfmt 0.8.4 (git+https://github.com/rust-lang-nursery/rustfmt)" = "" +"checksum rustfmt 0.9.0 (git+https://github.com/rust-lang-nursery/rustfmt?branch=libsyntax)" = "" "checksum same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d931a44fdaa43b8637009e7632a02adc4f2b2e0733c08caa4cf00e8da4a117a7" +"checksum scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f417c22df063e9450888a7561788e9bd46d3bb3c1466435b4eccb903807f147d" "checksum semver 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3fdd61b85a0fa777f7fb7c454b9189b2941b110d1385ce84d7f76efdf1606a85" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" "checksum serde 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)" = "34b623917345a631dc9608d5194cc206b3fe6c3554cd1c75b937e55e285254af" @@ -2117,18 +2090,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "48b04779552e92037212c3615370f6bd57a40ebba7f20e554ff9f55e41a69a7b" "checksum shell-escape 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "dd5cc96481d54583947bfe88bf30c23d53f883c6cd0145368b69989d97b84ef8" "checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b" -"checksum strings 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "54f86446ab480b4f60782188f4f78886465c5793aee248cbb48b7fdc0d022420" +"checksum strings 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "da75d8bf2c4d210d63dd09581a041b036001f9f6e03d9b151dbff810fb7ba26a" "checksum strsim 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "67f84c44fbb2f91db7fef94554e6b2ac05909c9c0b0bc23bb98d3a1aebfe7f7c" "checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694" "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" "checksum syn 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6ae6fb0dcc9bd85f89a1a4adc0df2fd90c90c98849d61433983dd7a9df6363f7" "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" "checksum syntex_errors 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9e52bffe6202cfb67587784cf23e0ec5bf26d331eef4922a16d5c42e12aa1e9b" -"checksum syntex_errors 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)" = "867cc5c2d7140ae7eaad2ae9e8bf39cb18a67ca651b7834f88d46ca98faadb9c" "checksum syntex_pos 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)" = "955ef4b16af4c468e4680d1497f873ff288f557d338180649e18f915af5e15ac" -"checksum syntex_pos 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)" = "13ad4762fe52abc9f4008e85c4fb1b1fe3aa91ccb99ff4826a439c7c598e1047" "checksum syntex_syntax 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)" = "76a302e717e348aa372ff577791c3832395650073b8d8432f8b3cb170b34afde" -"checksum syntex_syntax 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6e0e4dbae163dd98989464c23dd503161b338790640e11537686f2ef0f25c791" "checksum tar 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "281285b717926caa919ad905ef89c63d75805c7d89437fb873100925a53f2b1b" "checksum tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "87974a6f5c1dfb344d733055601650059a3363de2a6104819293baff662132d6" "checksum term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d168af3930b369cfe245132550579d47dfd873d69470755a19c2c6568dbbd989" diff --git a/src/tools/cargo b/src/tools/cargo index 82733b01471a..bbfe9b3a9d64 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 82733b01471a2c62bb1cec966d888c52ff118914 +Subproject commit bbfe9b3a9d64aa8698b18cbb3803b3fa00ee3f44 diff --git a/src/tools/rls b/src/tools/rls index 38ca9b702b73..bfe80cfa8db7 160000 --- a/src/tools/rls +++ b/src/tools/rls @@ -1 +1 @@ -Subproject commit 38ca9b702b73c03959e447f5dae56eff7497c986 +Subproject commit bfe80cfa8db75500e67ca8762465d27662674637 From b6193f3c005e52e93b00d2d69eea96b4b91d002b Mon Sep 17 00:00:00 2001 From: Matt Brubeck Date: Wed, 7 Jun 2017 09:24:35 -0700 Subject: [PATCH 070/233] Update docs to say iterator instead of range --- src/libcore/iter/iterator.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs index 85149a0f5707..30d09e5453b3 100644 --- a/src/libcore/iter/iterator.rs +++ b/src/libcore/iter/iterator.rs @@ -262,7 +262,7 @@ pub trait Iterator { /// Creates an iterator starting at the same point, but stepping by /// the given amount at each iteration. /// - /// Note that it will always return the first element of the range, + /// Note that it will always return the first element of the iterator, /// regardless of the step given. /// /// # Panics From 95bc0d6c79499b9ec0b587d8de16a0e919b336aa Mon Sep 17 00:00:00 2001 From: Marc-Antoine Perennou Date: Wed, 7 Jun 2017 21:42:17 +0200 Subject: [PATCH 071/233] update git2 Fixes build with libressl Signed-off-by: Marc-Antoine Perennou --- src/Cargo.lock | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index cc2da1a02dc9..fbc918a489b0 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -103,6 +103,11 @@ name = "bitflags" version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "bitflags" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "bootstrap" version = "0.0.0" @@ -159,13 +164,13 @@ dependencies = [ "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", "fs2 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "git2 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "git2 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "git2-curl 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "hamcrest 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "libgit2-sys 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "libgit2-sys 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -194,7 +199,7 @@ dependencies = [ "cargo 0.20.0", "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", - "git2 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "git2 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "hamcrest 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", @@ -467,12 +472,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "git2" -version = "0.6.5" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "libgit2-sys 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "libgit2-sys 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-probe 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.9.12 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -484,7 +489,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "curl 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "git2 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "git2 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -600,7 +605,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libgit2-sys" -version = "0.6.11" +version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cmake 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2021,6 +2026,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4f67931368edf3a9a51d29886d245f1c3db2f1ef0dcc9e35ff70341b78c10d23" "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" "checksum bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1370e9fc2a6ae53aea8b7a5110edbd08836ed87c88736dfabccade1c2b44bff4" +"checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" "checksum bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f382711e76b9de6c744cc00d0497baba02fb00a787f088c879f01d09468e32" "checksum cargo 0.20.0 (git+https://github.com/rust-lang/cargo)" = "" "checksum cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de1e760d7b6535af4241fca8bd8adf68e2e7edacc6b29f5d399050c5e48cf88c" @@ -2046,7 +2052,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)" = "5f837c392f2ea61cb1576eac188653df828c861b7137d74ea4a5caa89621f9e6" "checksum gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0912515a8ff24ba900422ecda800b52f4016a56251922d397c576bf92c690518" "checksum getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9047cfbd08a437050b363d35ef160452c5fe8ea5187ae0a624708c91581d685" -"checksum git2 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "9de9df4358c17e448a778d90cd0272e1dab5eae30244502333fa2001c4e24357" +"checksum git2 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "aa01936ac96555c083c0e8553f672616274408d9d3fc5b8696603fbf63ff43ee" "checksum git2-curl 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "68676bc784bf0bef83278898929bf64a251e87c0340723d0b93fa096c9c5bf8e" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" "checksum hamcrest 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bf088f042a467089e9baa4972f57f9247e42a0cc549ba264c7a04fbb8ecb89d4" @@ -2058,7 +2064,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum languageserver-types 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97c2985bfcbbcb0189cfa25e1c10c1ac7111df2b6214b652c690127aefdf4e5b" "checksum lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3b37545ab726dd833ec6420aaba8231c5b320814b9029ad585555d2a03e94fbf" "checksum libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)" = "babb8281da88cba992fa1f4ddec7d63ed96280a1a53ec9b919fd37b53d71e502" -"checksum libgit2-sys 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d9dc31ee90fb179b706d35fb672e91d0b74e950d7fb4ea7eae3c0f5ecbf2d3d3" +"checksum libgit2-sys 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "df18a822100352d9863b302faf6f8f25c0e77f0e60feb40e5dbe1238b7f13b1d" "checksum libssh2-sys 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0db4ec23611747ef772db1c4d650f8bd762f07b461727ec998f953c614024b75" "checksum libz-sys 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e5ee912a45d686d393d5ac87fac15ba0ba18daae14e8e7543c63ebf7fb7e970c" "checksum log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "5141eca02775a762cc6cd564d8d2c50f67c0ea3a372cbf1c51592b3e029e10ad" From 345b8332bde78dca7664b1b1b4f4a7284bd70a6d Mon Sep 17 00:00:00 2001 From: Tommy Ip Date: Wed, 7 Jun 2017 21:26:28 +0100 Subject: [PATCH 072/233] Cover all cases in closure errors --- src/librustc/traits/error_reporting.rs | 11 ++++++----- src/test/ui/closure_context/issue-26046-fn-mut.stderr | 3 +++ .../ui/closure_context/issue-26046-fn-once.stderr | 3 +++ 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 73753382a7cd..c8e99c0354ab 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -648,6 +648,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { kind, found_kind); + err.span_label( + obligation.cause.span, + format!("the requirement to implement `{}` derives from here", kind)); + let infer_tables = match self.tables { InferTables::Interned(tables) => Some(InferTablesRef::Interned(tables)), @@ -656,6 +660,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { InferTables::Missing => None, }; + // Additional context information explaining why the closure only implements + // a particular trait. if let Some(tables) = infer_tables { match tables.closure_kinds.get(&node_id) { Some(&(ty::ClosureKind::FnOnce, Some((span, name)))) => { @@ -670,11 +676,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { }, _ => {} } - } else { - err.span_note( - obligation.cause.span, - &format!("the requirement to implement `{}` \ - derives from here", kind)); } err.emit(); diff --git a/src/test/ui/closure_context/issue-26046-fn-mut.stderr b/src/test/ui/closure_context/issue-26046-fn-mut.stderr index 4dd33ef8a0e1..dbf702e45030 100644 --- a/src/test/ui/closure_context/issue-26046-fn-mut.stderr +++ b/src/test/ui/closure_context/issue-26046-fn-mut.stderr @@ -6,6 +6,9 @@ error[E0525]: expected a closure that implements the `Fn` trait, but this closur 15 | | num += 1; 16 | | }; | |_____^ +17 | +18 | Box::new(closure) + | ----------------- the requirement to implement `Fn` derives from here | note: closure is `FnMut` because it mutates the variable `num` here --> $DIR/issue-26046-fn-mut.rs:15:9 diff --git a/src/test/ui/closure_context/issue-26046-fn-once.stderr b/src/test/ui/closure_context/issue-26046-fn-once.stderr index 4a7aae87439f..3ec3f0cc9aa5 100644 --- a/src/test/ui/closure_context/issue-26046-fn-once.stderr +++ b/src/test/ui/closure_context/issue-26046-fn-once.stderr @@ -6,6 +6,9 @@ error[E0525]: expected a closure that implements the `Fn` trait, but this closur 15 | | vec 16 | | }; | |_____^ +17 | +18 | Box::new(closure) + | ----------------- the requirement to implement `Fn` derives from here | note: closure is `FnOnce` because it moves the variable `vec` out of its environment --> $DIR/issue-26046-fn-once.rs:15:9 From f51771939ba5b36ec89b9f0b51c2cbda51164676 Mon Sep 17 00:00:00 2001 From: Sean McArthur Date: Wed, 7 Jun 2017 17:06:55 -0700 Subject: [PATCH 073/233] core: allow messages in unimplemented!() macro --- src/libcore/macros.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index bf4e414d4168..320d32368401 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -542,7 +542,8 @@ macro_rules! unreachable { #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] macro_rules! unimplemented { - () => (panic!("not yet implemented")) + () => (panic!("not yet implemented")); + ($($arg:tt)+) => (panic!("not yet implemented: {}", format_args!($($arg)*))); } /// Built-in macros to the compiler itself. From 6f5987b05b09d1d19d7debbe466ecaeb6c3e997b Mon Sep 17 00:00:00 2001 From: Clar Charr Date: Wed, 7 Jun 2017 21:40:25 -0400 Subject: [PATCH 074/233] Move ops.rs to folder. --- src/libcore/{ops.rs => ops/mod.rs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/libcore/{ops.rs => ops/mod.rs} (100%) diff --git a/src/libcore/ops.rs b/src/libcore/ops/mod.rs similarity index 100% rename from src/libcore/ops.rs rename to src/libcore/ops/mod.rs From cee5a2dd20a93145026119f46f924c7649e4b21c Mon Sep 17 00:00:00 2001 From: Clar Charr Date: Wed, 7 Jun 2017 21:44:03 -0400 Subject: [PATCH 075/233] Move Range to module. --- src/libcore/ops/mod.rs | 364 +------------------------------------- src/libcore/ops/range.rs | 366 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 374 insertions(+), 356 deletions(-) create mode 100644 src/libcore/ops/range.rs diff --git a/src/libcore/ops/mod.rs b/src/libcore/ops/mod.rs index a1de8fe76e25..e67add65ab36 100644 --- a/src/libcore/ops/mod.rs +++ b/src/libcore/ops/mod.rs @@ -147,7 +147,14 @@ #![stable(feature = "rust1", since = "1.0.0")] -use fmt; +mod range; + +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::range::{Range, RangeFrom, RangeFull, RangeTo}; + +#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] +pub use self::range::{RangeInclusive, RangeToInclusive}; + use marker::Unsize; /// The `Drop` trait is used to run some code when a value goes out of scope. @@ -2083,361 +2090,6 @@ pub trait IndexMut: Index { fn index_mut(&mut self, index: Idx) -> &mut Self::Output; } -/// An unbounded range. Use `..` (two dots) for its shorthand. -/// -/// Its primary use case is slicing index. It cannot serve as an iterator -/// because it doesn't have a starting point. -/// -/// # Examples -/// -/// The `..` syntax is a `RangeFull`: -/// -/// ``` -/// assert_eq!((..), std::ops::RangeFull); -/// ``` -/// -/// It does not have an `IntoIterator` implementation, so you can't use it in a -/// `for` loop directly. This won't compile: -/// -/// ```ignore -/// for i in .. { -/// // ... -/// } -/// ``` -/// -/// Used as a slicing index, `RangeFull` produces the full array as a slice. -/// -/// ``` -/// let arr = [0, 1, 2, 3]; -/// assert_eq!(arr[ .. ], [0,1,2,3]); // RangeFull -/// assert_eq!(arr[ ..3], [0,1,2 ]); -/// assert_eq!(arr[1.. ], [ 1,2,3]); -/// assert_eq!(arr[1..3], [ 1,2 ]); -/// ``` -#[derive(Copy, Clone, PartialEq, Eq, Hash)] -#[stable(feature = "rust1", since = "1.0.0")] -pub struct RangeFull; - -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Debug for RangeFull { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - write!(fmt, "..") - } -} - -/// A (half-open) range which is bounded at both ends: { x | start <= x < end }. -/// Use `start..end` (two dots) for its shorthand. -/// -/// See the [`contains`](#method.contains) method for its characterization. -/// -/// # Examples -/// -/// ``` -/// fn main() { -/// assert_eq!((3..5), std::ops::Range{ start: 3, end: 5 }); -/// assert_eq!(3+4+5, (3..6).sum()); -/// -/// let arr = [0, 1, 2, 3]; -/// assert_eq!(arr[ .. ], [0,1,2,3]); -/// assert_eq!(arr[ ..3], [0,1,2 ]); -/// assert_eq!(arr[1.. ], [ 1,2,3]); -/// assert_eq!(arr[1..3], [ 1,2 ]); // Range -/// } -/// ``` -#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186 -#[stable(feature = "rust1", since = "1.0.0")] -pub struct Range { - /// The lower bound of the range (inclusive). - #[stable(feature = "rust1", since = "1.0.0")] - pub start: Idx, - /// The upper bound of the range (exclusive). - #[stable(feature = "rust1", since = "1.0.0")] - pub end: Idx, -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Debug for Range { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - write!(fmt, "{:?}..{:?}", self.start, self.end) - } -} - -#[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")] -impl> Range { - /// # Examples - /// - /// ``` - /// #![feature(range_contains)] - /// fn main() { - /// assert!( ! (3..5).contains(2)); - /// assert!( (3..5).contains(3)); - /// assert!( (3..5).contains(4)); - /// assert!( ! (3..5).contains(5)); - /// - /// assert!( ! (3..3).contains(3)); - /// assert!( ! (3..2).contains(3)); - /// } - /// ``` - pub fn contains(&self, item: Idx) -> bool { - (self.start <= item) && (item < self.end) - } -} - -/// A range which is only bounded below: { x | start <= x }. -/// Use `start..` for its shorthand. -/// -/// See the [`contains`](#method.contains) method for its characterization. -/// -/// Note: Currently, no overflow checking is done for the iterator -/// implementation; if you use an integer range and the integer overflows, it -/// might panic in debug mode or create an endless loop in release mode. This -/// overflow behavior might change in the future. -/// -/// # Examples -/// -/// ``` -/// fn main() { -/// assert_eq!((2..), std::ops::RangeFrom{ start: 2 }); -/// assert_eq!(2+3+4, (2..).take(3).sum()); -/// -/// let arr = [0, 1, 2, 3]; -/// assert_eq!(arr[ .. ], [0,1,2,3]); -/// assert_eq!(arr[ ..3], [0,1,2 ]); -/// assert_eq!(arr[1.. ], [ 1,2,3]); // RangeFrom -/// assert_eq!(arr[1..3], [ 1,2 ]); -/// } -/// ``` -#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186 -#[stable(feature = "rust1", since = "1.0.0")] -pub struct RangeFrom { - /// The lower bound of the range (inclusive). - #[stable(feature = "rust1", since = "1.0.0")] - pub start: Idx, -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Debug for RangeFrom { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - write!(fmt, "{:?}..", self.start) - } -} - -#[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")] -impl> RangeFrom { - /// # Examples - /// - /// ``` - /// #![feature(range_contains)] - /// fn main() { - /// assert!( ! (3..).contains(2)); - /// assert!( (3..).contains(3)); - /// assert!( (3..).contains(1_000_000_000)); - /// } - /// ``` - pub fn contains(&self, item: Idx) -> bool { - (self.start <= item) - } -} - -/// A range which is only bounded above: { x | x < end }. -/// Use `..end` (two dots) for its shorthand. -/// -/// See the [`contains`](#method.contains) method for its characterization. -/// -/// It cannot serve as an iterator because it doesn't have a starting point. -/// -/// # Examples -/// -/// The `..{integer}` syntax is a `RangeTo`: -/// -/// ``` -/// assert_eq!((..5), std::ops::RangeTo{ end: 5 }); -/// ``` -/// -/// It does not have an `IntoIterator` implementation, so you can't use it in a -/// `for` loop directly. This won't compile: -/// -/// ```ignore -/// for i in ..5 { -/// // ... -/// } -/// ``` -/// -/// When used as a slicing index, `RangeTo` produces a slice of all array -/// elements before the index indicated by `end`. -/// -/// ``` -/// let arr = [0, 1, 2, 3]; -/// assert_eq!(arr[ .. ], [0,1,2,3]); -/// assert_eq!(arr[ ..3], [0,1,2 ]); // RangeTo -/// assert_eq!(arr[1.. ], [ 1,2,3]); -/// assert_eq!(arr[1..3], [ 1,2 ]); -/// ``` -#[derive(Copy, Clone, PartialEq, Eq, Hash)] -#[stable(feature = "rust1", since = "1.0.0")] -pub struct RangeTo { - /// The upper bound of the range (exclusive). - #[stable(feature = "rust1", since = "1.0.0")] - pub end: Idx, -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Debug for RangeTo { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - write!(fmt, "..{:?}", self.end) - } -} - -#[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")] -impl> RangeTo { - /// # Examples - /// - /// ``` - /// #![feature(range_contains)] - /// fn main() { - /// assert!( (..5).contains(-1_000_000_000)); - /// assert!( (..5).contains(4)); - /// assert!( ! (..5).contains(5)); - /// } - /// ``` - pub fn contains(&self, item: Idx) -> bool { - (item < self.end) - } -} - -/// An inclusive range which is bounded at both ends: { x | start <= x <= end }. -/// Use `start...end` (three dots) for its shorthand. -/// -/// See the [`contains`](#method.contains) method for its characterization. -/// -/// # Examples -/// -/// ``` -/// #![feature(inclusive_range,inclusive_range_syntax)] -/// fn main() { -/// assert_eq!((3...5), std::ops::RangeInclusive{ start: 3, end: 5 }); -/// assert_eq!(3+4+5, (3...5).sum()); -/// -/// let arr = [0, 1, 2, 3]; -/// assert_eq!(arr[ ...2], [0,1,2 ]); -/// assert_eq!(arr[1...2], [ 1,2 ]); // RangeInclusive -/// } -/// ``` -#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186 -#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] -pub struct RangeInclusive { - /// The lower bound of the range (inclusive). - #[unstable(feature = "inclusive_range", - reason = "recently added, follows RFC", - issue = "28237")] - pub start: Idx, - /// The upper bound of the range (inclusive). - #[unstable(feature = "inclusive_range", - reason = "recently added, follows RFC", - issue = "28237")] - pub end: Idx, -} - -#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] -impl fmt::Debug for RangeInclusive { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - write!(fmt, "{:?}...{:?}", self.start, self.end) - } -} - -#[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")] -impl> RangeInclusive { - /// # Examples - /// - /// ``` - /// #![feature(range_contains,inclusive_range_syntax)] - /// fn main() { - /// assert!( ! (3...5).contains(2)); - /// assert!( (3...5).contains(3)); - /// assert!( (3...5).contains(4)); - /// assert!( (3...5).contains(5)); - /// assert!( ! (3...5).contains(6)); - /// - /// assert!( (3...3).contains(3)); - /// assert!( ! (3...2).contains(3)); - /// } - /// ``` - pub fn contains(&self, item: Idx) -> bool { - self.start <= item && item <= self.end - } -} - -/// An inclusive range which is only bounded above: { x | x <= end }. -/// Use `...end` (three dots) for its shorthand. -/// -/// See the [`contains`](#method.contains) method for its characterization. -/// -/// It cannot serve as an iterator because it doesn't have a starting point. -/// -/// # Examples -/// -/// The `...{integer}` syntax is a `RangeToInclusive`: -/// -/// ``` -/// #![feature(inclusive_range,inclusive_range_syntax)] -/// assert_eq!((...5), std::ops::RangeToInclusive{ end: 5 }); -/// ``` -/// -/// It does not have an `IntoIterator` implementation, so you can't use it in a -/// `for` loop directly. This won't compile: -/// -/// ```ignore -/// for i in ...5 { -/// // ... -/// } -/// ``` -/// -/// When used as a slicing index, `RangeToInclusive` produces a slice of all -/// array elements up to and including the index indicated by `end`. -/// -/// ``` -/// #![feature(inclusive_range_syntax)] -/// let arr = [0, 1, 2, 3]; -/// assert_eq!(arr[ ...2], [0,1,2 ]); // RangeToInclusive -/// assert_eq!(arr[1...2], [ 1,2 ]); -/// ``` -#[derive(Copy, Clone, PartialEq, Eq, Hash)] -#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] -pub struct RangeToInclusive { - /// The upper bound of the range (inclusive) - #[unstable(feature = "inclusive_range", - reason = "recently added, follows RFC", - issue = "28237")] - pub end: Idx, -} - -#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] -impl fmt::Debug for RangeToInclusive { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - write!(fmt, "...{:?}", self.end) - } -} - -#[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")] -impl> RangeToInclusive { - /// # Examples - /// - /// ``` - /// #![feature(range_contains,inclusive_range_syntax)] - /// fn main() { - /// assert!( (...5).contains(-1_000_000_000)); - /// assert!( (...5).contains(5)); - /// assert!( ! (...5).contains(6)); - /// } - /// ``` - pub fn contains(&self, item: Idx) -> bool { - (item <= self.end) - } -} - -// RangeToInclusive cannot impl From> -// because underflow would be possible with (..0).into() - /// The `Deref` trait is used to specify the functionality of dereferencing /// operations, like `*v`. /// diff --git a/src/libcore/ops/range.rs b/src/libcore/ops/range.rs new file mode 100644 index 000000000000..70c35df87dda --- /dev/null +++ b/src/libcore/ops/range.rs @@ -0,0 +1,366 @@ +// 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. + +use fmt; + +/// An unbounded range. Use `..` (two dots) for its shorthand. +/// +/// Its primary use case is slicing index. It cannot serve as an iterator +/// because it doesn't have a starting point. +/// +/// # Examples +/// +/// The `..` syntax is a `RangeFull`: +/// +/// ``` +/// assert_eq!((..), std::ops::RangeFull); +/// ``` +/// +/// It does not have an `IntoIterator` implementation, so you can't use it in a +/// `for` loop directly. This won't compile: +/// +/// ```ignore +/// for i in .. { +/// // ... +/// } +/// ``` +/// +/// Used as a slicing index, `RangeFull` produces the full array as a slice. +/// +/// ``` +/// let arr = [0, 1, 2, 3]; +/// assert_eq!(arr[ .. ], [0,1,2,3]); // RangeFull +/// assert_eq!(arr[ ..3], [0,1,2 ]); +/// assert_eq!(arr[1.. ], [ 1,2,3]); +/// assert_eq!(arr[1..3], [ 1,2 ]); +/// ``` +#[derive(Copy, Clone, PartialEq, Eq, Hash)] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct RangeFull; + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for RangeFull { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + write!(fmt, "..") + } +} + +/// A (half-open) range which is bounded at both ends: { x | start <= x < end }. +/// Use `start..end` (two dots) for its shorthand. +/// +/// See the [`contains`](#method.contains) method for its characterization. +/// +/// # Examples +/// +/// ``` +/// fn main() { +/// assert_eq!((3..5), std::ops::Range{ start: 3, end: 5 }); +/// assert_eq!(3+4+5, (3..6).sum()); +/// +/// let arr = [0, 1, 2, 3]; +/// assert_eq!(arr[ .. ], [0,1,2,3]); +/// assert_eq!(arr[ ..3], [0,1,2 ]); +/// assert_eq!(arr[1.. ], [ 1,2,3]); +/// assert_eq!(arr[1..3], [ 1,2 ]); // Range +/// } +/// ``` +#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186 +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Range { + /// The lower bound of the range (inclusive). + #[stable(feature = "rust1", since = "1.0.0")] + pub start: Idx, + /// The upper bound of the range (exclusive). + #[stable(feature = "rust1", since = "1.0.0")] + pub end: Idx, +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for Range { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + write!(fmt, "{:?}..{:?}", self.start, self.end) + } +} + +#[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")] +impl> Range { + /// # Examples + /// + /// ``` + /// #![feature(range_contains)] + /// fn main() { + /// assert!( ! (3..5).contains(2)); + /// assert!( (3..5).contains(3)); + /// assert!( (3..5).contains(4)); + /// assert!( ! (3..5).contains(5)); + /// + /// assert!( ! (3..3).contains(3)); + /// assert!( ! (3..2).contains(3)); + /// } + /// ``` + pub fn contains(&self, item: Idx) -> bool { + (self.start <= item) && (item < self.end) + } +} + +/// A range which is only bounded below: { x | start <= x }. +/// Use `start..` for its shorthand. +/// +/// See the [`contains`](#method.contains) method for its characterization. +/// +/// Note: Currently, no overflow checking is done for the iterator +/// implementation; if you use an integer range and the integer overflows, it +/// might panic in debug mode or create an endless loop in release mode. This +/// overflow behavior might change in the future. +/// +/// # Examples +/// +/// ``` +/// fn main() { +/// assert_eq!((2..), std::ops::RangeFrom{ start: 2 }); +/// assert_eq!(2+3+4, (2..).take(3).sum()); +/// +/// let arr = [0, 1, 2, 3]; +/// assert_eq!(arr[ .. ], [0,1,2,3]); +/// assert_eq!(arr[ ..3], [0,1,2 ]); +/// assert_eq!(arr[1.. ], [ 1,2,3]); // RangeFrom +/// assert_eq!(arr[1..3], [ 1,2 ]); +/// } +/// ``` +#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186 +#[stable(feature = "rust1", since = "1.0.0")] +pub struct RangeFrom { + /// The lower bound of the range (inclusive). + #[stable(feature = "rust1", since = "1.0.0")] + pub start: Idx, +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for RangeFrom { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + write!(fmt, "{:?}..", self.start) + } +} + +#[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")] +impl> RangeFrom { + /// # Examples + /// + /// ``` + /// #![feature(range_contains)] + /// fn main() { + /// assert!( ! (3..).contains(2)); + /// assert!( (3..).contains(3)); + /// assert!( (3..).contains(1_000_000_000)); + /// } + /// ``` + pub fn contains(&self, item: Idx) -> bool { + (self.start <= item) + } +} + +/// A range which is only bounded above: { x | x < end }. +/// Use `..end` (two dots) for its shorthand. +/// +/// See the [`contains`](#method.contains) method for its characterization. +/// +/// It cannot serve as an iterator because it doesn't have a starting point. +/// +/// # Examples +/// +/// The `..{integer}` syntax is a `RangeTo`: +/// +/// ``` +/// assert_eq!((..5), std::ops::RangeTo{ end: 5 }); +/// ``` +/// +/// It does not have an `IntoIterator` implementation, so you can't use it in a +/// `for` loop directly. This won't compile: +/// +/// ```ignore +/// for i in ..5 { +/// // ... +/// } +/// ``` +/// +/// When used as a slicing index, `RangeTo` produces a slice of all array +/// elements before the index indicated by `end`. +/// +/// ``` +/// let arr = [0, 1, 2, 3]; +/// assert_eq!(arr[ .. ], [0,1,2,3]); +/// assert_eq!(arr[ ..3], [0,1,2 ]); // RangeTo +/// assert_eq!(arr[1.. ], [ 1,2,3]); +/// assert_eq!(arr[1..3], [ 1,2 ]); +/// ``` +#[derive(Copy, Clone, PartialEq, Eq, Hash)] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct RangeTo { + /// The upper bound of the range (exclusive). + #[stable(feature = "rust1", since = "1.0.0")] + pub end: Idx, +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for RangeTo { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + write!(fmt, "..{:?}", self.end) + } +} + +#[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")] +impl> RangeTo { + /// # Examples + /// + /// ``` + /// #![feature(range_contains)] + /// fn main() { + /// assert!( (..5).contains(-1_000_000_000)); + /// assert!( (..5).contains(4)); + /// assert!( ! (..5).contains(5)); + /// } + /// ``` + pub fn contains(&self, item: Idx) -> bool { + (item < self.end) + } +} + +/// An inclusive range which is bounded at both ends: { x | start <= x <= end }. +/// Use `start...end` (three dots) for its shorthand. +/// +/// See the [`contains`](#method.contains) method for its characterization. +/// +/// # Examples +/// +/// ``` +/// #![feature(inclusive_range,inclusive_range_syntax)] +/// fn main() { +/// assert_eq!((3...5), std::ops::RangeInclusive{ start: 3, end: 5 }); +/// assert_eq!(3+4+5, (3...5).sum()); +/// +/// let arr = [0, 1, 2, 3]; +/// assert_eq!(arr[ ...2], [0,1,2 ]); +/// assert_eq!(arr[1...2], [ 1,2 ]); // RangeInclusive +/// } +/// ``` +#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186 +#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] +pub struct RangeInclusive { + /// The lower bound of the range (inclusive). + #[unstable(feature = "inclusive_range", + reason = "recently added, follows RFC", + issue = "28237")] + pub start: Idx, + /// The upper bound of the range (inclusive). + #[unstable(feature = "inclusive_range", + reason = "recently added, follows RFC", + issue = "28237")] + pub end: Idx, +} + +#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] +impl fmt::Debug for RangeInclusive { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + write!(fmt, "{:?}...{:?}", self.start, self.end) + } +} + +#[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")] +impl> RangeInclusive { + /// # Examples + /// + /// ``` + /// #![feature(range_contains,inclusive_range_syntax)] + /// fn main() { + /// assert!( ! (3...5).contains(2)); + /// assert!( (3...5).contains(3)); + /// assert!( (3...5).contains(4)); + /// assert!( (3...5).contains(5)); + /// assert!( ! (3...5).contains(6)); + /// + /// assert!( (3...3).contains(3)); + /// assert!( ! (3...2).contains(3)); + /// } + /// ``` + pub fn contains(&self, item: Idx) -> bool { + self.start <= item && item <= self.end + } +} + +/// An inclusive range which is only bounded above: { x | x <= end }. +/// Use `...end` (three dots) for its shorthand. +/// +/// See the [`contains`](#method.contains) method for its characterization. +/// +/// It cannot serve as an iterator because it doesn't have a starting point. +/// +/// # Examples +/// +/// The `...{integer}` syntax is a `RangeToInclusive`: +/// +/// ``` +/// #![feature(inclusive_range,inclusive_range_syntax)] +/// assert_eq!((...5), std::ops::RangeToInclusive{ end: 5 }); +/// ``` +/// +/// It does not have an `IntoIterator` implementation, so you can't use it in a +/// `for` loop directly. This won't compile: +/// +/// ```ignore +/// for i in ...5 { +/// // ... +/// } +/// ``` +/// +/// When used as a slicing index, `RangeToInclusive` produces a slice of all +/// array elements up to and including the index indicated by `end`. +/// +/// ``` +/// #![feature(inclusive_range_syntax)] +/// let arr = [0, 1, 2, 3]; +/// assert_eq!(arr[ ...2], [0,1,2 ]); // RangeToInclusive +/// assert_eq!(arr[1...2], [ 1,2 ]); +/// ``` +#[derive(Copy, Clone, PartialEq, Eq, Hash)] +#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] +pub struct RangeToInclusive { + /// The upper bound of the range (inclusive) + #[unstable(feature = "inclusive_range", + reason = "recently added, follows RFC", + issue = "28237")] + pub end: Idx, +} + +#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] +impl fmt::Debug for RangeToInclusive { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + write!(fmt, "...{:?}", self.end) + } +} + +#[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")] +impl> RangeToInclusive { + /// # Examples + /// + /// ``` + /// #![feature(range_contains,inclusive_range_syntax)] + /// fn main() { + /// assert!( (...5).contains(-1_000_000_000)); + /// assert!( (...5).contains(5)); + /// assert!( ! (...5).contains(6)); + /// } + /// ``` + pub fn contains(&self, item: Idx) -> bool { + (item <= self.end) + } +} + +// RangeToInclusive cannot impl From> +// because underflow would be possible with (..0).into() From dd23fda9bd6c79ef8e0a389622352759dc159b15 Mon Sep 17 00:00:00 2001 From: Clar Charr Date: Tue, 30 May 2017 00:17:11 -0400 Subject: [PATCH 076/233] Make rustdoc.js use license comments. --- src/librustdoc/html/static/main.js | 20 +++++++++++--------- src/tools/tidy/src/style.rs | 4 +++- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 53e341226af3..38f83687d1d8 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -1,12 +1,14 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. +/*! + * Copyright 2014 The Rust Project Developers. See the COPYRIGHT + * file at the top-level directory of this distribution and at + * http://rust-lang.org/COPYRIGHT. + * + * Licensed under the Apache License, Version 2.0 or the MIT license + * , at your + * option. This file may not be copied, modified, or distributed + * except according to those terms. + */ /*jslint browser: true, es5: true */ /*globals $: true, rootPath: true */ diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs index 8bf683de8704..35073b63723d 100644 --- a/src/tools/tidy/src/style.rs +++ b/src/tools/tidy/src/style.rs @@ -169,8 +169,10 @@ fn licenseck(file: &Path, contents: &str) -> bool { lines.windows(LICENSE.lines().count()).any(|window| { let offset = if window.iter().all(|w| w.starts_with("//")) { 2 - } else if window.iter().all(|w| w.starts_with("#")) { + } else if window.iter().all(|w| w.starts_with('#')) { 1 + } else if window.iter().all(|w| w.starts_with(" *")) { + 2 } else { return false }; From 7359c791b50ebe0fa7ccf48faf5a272491c779e3 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 7 Jun 2017 22:08:48 -0700 Subject: [PATCH 077/233] bootstrap: further clarify build --help --- src/bootstrap/flags.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index 3a265b2f3bbb..56cbb4cecf2a 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -196,13 +196,14 @@ Arguments: ./x.py build ./x.py build --stage 1 - For a quick build with a usable compile, you can pass: + For a quick build of a usable compiler, you can pass: ./x.py build --stage 1 src/libtest This will first build everything once (like --stage 0 without further arguments would), and then use the compiler built in stage 0 to build - src/libtest and its dependencies."); + src/libtest and its dependencies. + Once this is done, build/$ARCH/stage1 contains a usable compiler."); } "test" => { subcommand_help.push_str("\n From 70e48b12e9ed06cc500061b9026aac9ea598a1e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1ty=C3=A1s=20Mustoha?= Date: Thu, 8 Jun 2017 12:03:08 +0200 Subject: [PATCH 078/233] Ignore variadic FFI test on AArch64 --- src/test/compile-fail/variadic-ffi.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/compile-fail/variadic-ffi.rs b/src/test/compile-fail/variadic-ffi.rs index 125177efc53c..f245306f4d8f 100644 --- a/src/test/compile-fail/variadic-ffi.rs +++ b/src/test/compile-fail/variadic-ffi.rs @@ -9,6 +9,7 @@ // except according to those terms. // ignore-arm stdcall isn't suppported +// ignore-aarch64 stdcall isn't suppported extern "stdcall" { fn printf(_: *const u8, ...); //~ ERROR: variadic function must have C or cdecl calling From 52805d233b59503cdfe58ee21e894ed6bb3b1da9 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 6 Jun 2017 11:34:10 -0700 Subject: [PATCH 079/233] std: Avoid panics in rust_eh_personality This commit removes a few calls to panic and/or assert in `rust_eh_personality`. This function definitely can't itself panic (that'd probably segfault or do something else weird) and I was also noticing that a `pub extern fn foo() {}` cdylib was abnormally large. Turns out all that size was the panicking machinery brought in by the personality function! The change here is to return a `Result` internally so we can bubble up the fatal error, eventually translating to the appropriate error code for the libunwind ABI. --- src/libpanic_unwind/dwarf/eh.rs | 55 +++++++++++++++++++------------- src/libpanic_unwind/gcc.rs | 14 ++++++-- src/libpanic_unwind/seh64_gnu.rs | 9 +++--- 3 files changed, 48 insertions(+), 30 deletions(-) diff --git a/src/libpanic_unwind/dwarf/eh.rs b/src/libpanic_unwind/dwarf/eh.rs index e7994f4e0ef0..0c326ce37184 100644 --- a/src/libpanic_unwind/dwarf/eh.rs +++ b/src/libpanic_unwind/dwarf/eh.rs @@ -61,9 +61,11 @@ pub enum EHAction { pub const USING_SJLJ_EXCEPTIONS: bool = cfg!(all(target_os = "ios", target_arch = "arm")); -pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext) -> EHAction { +pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext) + -> Result +{ if lsda.is_null() { - return EHAction::None; + return Ok(EHAction::None) } let func_start = context.func_start; @@ -72,7 +74,7 @@ pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext) -> EHAction { let start_encoding = reader.read::(); // base address for landing pad offsets let lpad_base = if start_encoding != DW_EH_PE_omit { - read_encoded_pointer(&mut reader, context, start_encoding) + read_encoded_pointer(&mut reader, context, start_encoding)? } else { func_start }; @@ -90,9 +92,9 @@ pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext) -> EHAction { if !USING_SJLJ_EXCEPTIONS { while reader.ptr < action_table { - let cs_start = read_encoded_pointer(&mut reader, context, call_site_encoding); - let cs_len = read_encoded_pointer(&mut reader, context, call_site_encoding); - let cs_lpad = read_encoded_pointer(&mut reader, context, call_site_encoding); + let cs_start = read_encoded_pointer(&mut reader, context, call_site_encoding)?; + let cs_len = read_encoded_pointer(&mut reader, context, call_site_encoding)?; + let cs_lpad = read_encoded_pointer(&mut reader, context, call_site_encoding)?; let cs_action = reader.read_uleb128(); // Callsite table is sorted by cs_start, so if we've passed the ip, we // may stop searching. @@ -101,23 +103,23 @@ pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext) -> EHAction { } if ip < func_start + cs_start + cs_len { if cs_lpad == 0 { - return EHAction::None; + return Ok(EHAction::None) } else { let lpad = lpad_base + cs_lpad; - return interpret_cs_action(cs_action, lpad); + return Ok(interpret_cs_action(cs_action, lpad)) } } } // Ip is not present in the table. This should not happen... but it does: issue #35011. // So rather than returning EHAction::Terminate, we do this. - EHAction::None + Ok(EHAction::None) } else { // SjLj version: // The "IP" is an index into the call-site table, with two exceptions: // -1 means 'no-action', and 0 means 'terminate'. match ip as isize { - -1 => return EHAction::None, - 0 => return EHAction::Terminate, + -1 => return Ok(EHAction::None), + 0 => return Ok(EHAction::Terminate), _ => (), } let mut idx = ip; @@ -129,7 +131,7 @@ pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext) -> EHAction { // Can never have null landing pad for sjlj -- that would have // been indicated by a -1 call site index. let lpad = (cs_lpad + 1) as usize; - return interpret_cs_action(cs_action, lpad); + return Ok(interpret_cs_action(cs_action, lpad)) } } } @@ -144,21 +146,26 @@ fn interpret_cs_action(cs_action: u64, lpad: usize) -> EHAction { } #[inline] -fn round_up(unrounded: usize, align: usize) -> usize { - assert!(align.is_power_of_two()); - (unrounded + align - 1) & !(align - 1) +fn round_up(unrounded: usize, align: usize) -> Result { + if align.is_power_of_two() { + Ok((unrounded + align - 1) & !(align - 1)) + } else { + Err(()) + } } unsafe fn read_encoded_pointer(reader: &mut DwarfReader, context: &EHContext, encoding: u8) - -> usize { - assert!(encoding != DW_EH_PE_omit); + -> Result { + if encoding == DW_EH_PE_omit { + return Err(()) + } // DW_EH_PE_aligned implies it's an absolute pointer value if encoding == DW_EH_PE_aligned { - reader.ptr = round_up(reader.ptr as usize, mem::size_of::()) as *const u8; - return reader.read::(); + reader.ptr = round_up(reader.ptr as usize, mem::size_of::())? as *const u8; + return Ok(reader.read::()) } let mut result = match encoding & 0x0F { @@ -171,7 +178,7 @@ unsafe fn read_encoded_pointer(reader: &mut DwarfReader, DW_EH_PE_sdata2 => reader.read::() as usize, DW_EH_PE_sdata4 => reader.read::() as usize, DW_EH_PE_sdata8 => reader.read::() as usize, - _ => panic!(), + _ => return Err(()), }; result += match encoding & 0x70 { @@ -179,17 +186,19 @@ unsafe fn read_encoded_pointer(reader: &mut DwarfReader, // relative to address of the encoded value, despite the name DW_EH_PE_pcrel => reader.ptr as usize, DW_EH_PE_funcrel => { - assert!(context.func_start != 0); + if context.func_start == 0 { + return Err(()) + } context.func_start } DW_EH_PE_textrel => (*context.get_text_start)(), DW_EH_PE_datarel => (*context.get_data_start)(), - _ => panic!(), + _ => return Err(()), }; if encoding & DW_EH_PE_indirect != 0 { result = *(result as *const usize); } - result + Ok(result) } diff --git a/src/libpanic_unwind/gcc.rs b/src/libpanic_unwind/gcc.rs index 84abc6bc4a51..aadbeb96b2d2 100644 --- a/src/libpanic_unwind/gcc.rs +++ b/src/libpanic_unwind/gcc.rs @@ -156,7 +156,10 @@ unsafe extern "C" fn rust_eh_personality(version: c_int, if version != 1 { return uw::_URC_FATAL_PHASE1_ERROR; } - let eh_action = find_eh_action(context); + let eh_action = match find_eh_action(context) { + Ok(action) => action, + Err(_) => return uw::_URC_FATAL_PHASE1_ERROR, + }; if actions as i32 & uw::_UA_SEARCH_PHASE as i32 != 0 { match eh_action { EHAction::None | @@ -219,7 +222,10 @@ unsafe extern "C" fn rust_eh_personality(state: uw::_Unwind_State, // _Unwind_Context in our libunwind bindings and fetch the required data from there directly, // bypassing DWARF compatibility functions. - let eh_action = find_eh_action(context); + let eh_action = match find_eh_action(context) { + Ok(action) => action, + Err(_) => return uw::_URC_FAILURE, + }; if search_phase { match eh_action { EHAction::None | @@ -260,7 +266,9 @@ unsafe extern "C" fn rust_eh_personality(state: uw::_Unwind_State, } } -unsafe fn find_eh_action(context: *mut uw::_Unwind_Context) -> EHAction { +unsafe fn find_eh_action(context: *mut uw::_Unwind_Context) + -> Result +{ let lsda = uw::_Unwind_GetLanguageSpecificData(context) as *const u8; let mut ip_before_instr: c_int = 0; let ip = uw::_Unwind_GetIPInfo(context, &mut ip_before_instr); diff --git a/src/libpanic_unwind/seh64_gnu.rs b/src/libpanic_unwind/seh64_gnu.rs index d4906b556b31..0a9fa7d9a80b 100644 --- a/src/libpanic_unwind/seh64_gnu.rs +++ b/src/libpanic_unwind/seh64_gnu.rs @@ -128,9 +128,10 @@ unsafe fn find_landing_pad(dc: &c::DISPATCHER_CONTEXT) -> Option { get_data_start: &|| unimplemented!(), }; match find_eh_action(dc.HandlerData, &eh_ctx) { - EHAction::None => None, - EHAction::Cleanup(lpad) | - EHAction::Catch(lpad) => Some(lpad), - EHAction::Terminate => intrinsics::abort(), + Err(_) | + Ok(EHAction::None) => None, + Ok(EHAction::Cleanup(lpad)) | + Ok(EHAction::Catch(lpad)) => Some(lpad), + Ok(EHAction::Terminate) => intrinsics::abort(), } } From 8938269db63bf1f9c0f17f3c2c39d3449b4d652e Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Sat, 3 Jun 2017 15:07:57 +0300 Subject: [PATCH 080/233] Upgrade LLVM Includes https://github.com/rust-lang/llvm/pull/80 Includes https://github.com/rust-lang/llvm/pull/79 Also adds tests and thus fixes #24194 --- src/llvm | 2 +- src/rustllvm/llvm-rebuild-trigger | 2 +- src/test/codegen/alloc-optimisation.rs | 28 ++++++++++++++++++++++++++ 3 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 src/test/codegen/alloc-optimisation.rs diff --git a/src/llvm b/src/llvm index 1ef3b9128e1b..84c52ce9b75d 160000 --- a/src/llvm +++ b/src/llvm @@ -1 +1 @@ -Subproject commit 1ef3b9128e1baaed61b42d5b0de79dee100acf17 +Subproject commit 84c52ce9b75d841629e6f821b3794998fb0ddbd9 diff --git a/src/rustllvm/llvm-rebuild-trigger b/src/rustllvm/llvm-rebuild-trigger index 70663f30e8f9..b2746bb6e68a 100644 --- a/src/rustllvm/llvm-rebuild-trigger +++ b/src/rustllvm/llvm-rebuild-trigger @@ -1,4 +1,4 @@ # If this file is modified, then llvm will be (optionally) cleaned and then rebuilt. # The actual contents of this file do not matter, but to trigger a change on the # build bots then the contents should be changed so git updates the mtime. -2017-05-13 +2017-06-03 diff --git a/src/test/codegen/alloc-optimisation.rs b/src/test/codegen/alloc-optimisation.rs new file mode 100644 index 000000000000..3953f637cf7a --- /dev/null +++ b/src/test/codegen/alloc-optimisation.rs @@ -0,0 +1,28 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +#![crate_type="lib"] + +#[no_mangle] +pub fn alloc_zeroed_test(size: u8) { + // CHECK-LABEL: @alloc_zeroed_test + // CHECK-NEXT: start: + // CHECK-NEXT: ret void + let x = vec![0u8; size as usize]; + drop(x); +} + +#[no_mangle] +pub fn alloc_test(data: u32) { + // CHECK-LABEL: @alloc_test + // CHECK-NEXT: start: + // CHECK-NEXT: ret void + let x = Box::new(data); + drop(x); +} From 44e6406f9a29e03280f4e16434c06e1d0abfaffc Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 7 Jun 2017 18:31:35 -0700 Subject: [PATCH 081/233] std: Handle ENOSYS when calling `pipe2` Should help fix an accidental regression from #39386. --- src/libstd/sys/unix/pipe.rs | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/src/libstd/sys/unix/pipe.rs b/src/libstd/sys/unix/pipe.rs index 706256ff10ec..ca5ef4bcfc5f 100644 --- a/src/libstd/sys/unix/pipe.rs +++ b/src/libstd/sys/unix/pipe.rs @@ -11,8 +11,9 @@ use io; use libc::{self, c_int}; use mem; -use sys::{cvt, cvt_r}; +use sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering}; use sys::fd::FileDesc; +use sys::{cvt, cvt_r}; //////////////////////////////////////////////////////////////////////////////// // Anonymous pipes @@ -21,6 +22,9 @@ use sys::fd::FileDesc; pub struct AnonPipe(FileDesc); pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> { + weak! { fn pipe2(*mut c_int, c_int) -> c_int } + static INVALID: AtomicBool = ATOMIC_BOOL_INIT; + let mut fds = [0; 2]; // Unfortunately the only known way right now to create atomically set the @@ -31,13 +35,26 @@ pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> { target_os = "freebsd", target_os = "linux", target_os = "netbsd", - target_os = "openbsd")) + target_os = "openbsd")) && + !INVALID.load(Ordering::SeqCst) { - weak! { fn pipe2(*mut c_int, c_int) -> c_int } + if let Some(pipe) = pipe2.get() { - cvt(unsafe { pipe(fds.as_mut_ptr(), libc::O_CLOEXEC) })?; - return Ok((AnonPipe(FileDesc::new(fds[0])), - AnonPipe(FileDesc::new(fds[1])))); + // Note that despite calling a glibc function here we may still + // get ENOSYS. Glibc has `pipe2` since 2.9 and doesn't try to + // emulate on older kernels, so if you happen to be running on + // an older kernel you may see `pipe2` as a symbol but still not + // see the syscall. + match cvt(unsafe { pipe(fds.as_mut_ptr(), libc::O_CLOEXEC) }) { + Ok(_) => { + return Ok((AnonPipe(FileDesc::new(fds[0])), + AnonPipe(FileDesc::new(fds[1])))); + } + Err(ref e) if e.raw_os_error() == Some(libc::ENOSYS) => { + INVALID.store(true, Ordering::SeqCst); + } + Err(e) => return Err(e), + } } } cvt(unsafe { libc::pipe(fds.as_mut_ptr()) })?; From 3d9ebf2916f96c6934a84a5abc2067145e062e75 Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Thu, 8 Jun 2017 05:51:32 -0600 Subject: [PATCH 082/233] Speed up expansion. This reduces duplication, thereby increasing expansion speed. --- src/libsyntax/ext/tt/macro_parser.rs | 40 +++++++++++-------- src/libsyntax/ext/tt/macro_rules.rs | 4 +- src/libsyntax/ext/tt/transcribe.rs | 17 ++++---- .../auxiliary/procedural_mbe_matching.rs | 2 +- 4 files changed, 35 insertions(+), 28 deletions(-) diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index 0b6a2eb536a2..61d8fc2941af 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -139,13 +139,20 @@ struct MatcherPos { sep: Option, idx: usize, up: Option>, - matches: Vec>>, + matches: Vec>>, match_lo: usize, match_cur: usize, match_hi: usize, sp_lo: BytePos, } +impl MatcherPos { + fn push_match(&mut self, idx: usize, m: NamedMatch) { + let matches = Rc::make_mut(&mut self.matches[idx]); + matches.push(m); + } +} + pub type NamedParseResult = ParseResult>>; pub fn count_names(ms: &[TokenTree]) -> usize { @@ -199,14 +206,15 @@ fn initial_matcher_pos(ms: Vec, lo: BytePos) -> Box { /// only on the nesting depth of `ast::TTSeq`s in the originating /// token tree it was derived from. +#[derive(Debug, Clone)] pub enum NamedMatch { - MatchedSeq(Vec>, syntax_pos::Span), + MatchedSeq(Rc>, syntax_pos::Span), MatchedNonterminal(Rc) } -fn nameize>>(sess: &ParseSess, ms: &[TokenTree], mut res: I) +fn nameize>(sess: &ParseSess, ms: &[TokenTree], mut res: I) -> NamedParseResult { - fn n_rec>>(sess: &ParseSess, m: &TokenTree, mut res: &mut I, + fn n_rec>(sess: &ParseSess, m: &TokenTree, mut res: &mut I, ret_val: &mut HashMap>) -> Result<(), (syntax_pos::Span, String)> { match *m { @@ -228,7 +236,8 @@ fn nameize>>(sess: &ParseSess, ms: &[TokenTree], TokenTree::MetaVarDecl(sp, bind_name, _) => { match ret_val.entry(bind_name) { Vacant(spot) => { - spot.insert(res.next().unwrap()); + // FIXME(simulacrum): Don't construct Rc here + spot.insert(Rc::new(res.next().unwrap())); } Occupied(..) => { return Err((sp, format!("duplicated bind name: {}", bind_name))) @@ -280,8 +289,8 @@ fn token_name_eq(t1 : &Token, t2 : &Token) -> bool { } } -fn create_matches(len: usize) -> Vec>> { - (0..len).into_iter().map(|_| Vec::new()).collect() +fn create_matches(len: usize) -> Vec>> { + (0..len).into_iter().map(|_| Rc::new(Vec::new())).collect() } fn inner_parse_loop(sess: &ParseSess, @@ -320,15 +329,10 @@ fn inner_parse_loop(sess: &ParseSess, // update matches (the MBE "parse tree") by appending // each tree as a subtree. - // I bet this is a perf problem: we're preemptively - // doing a lot of array work that will get thrown away - // most of the time. - // Only touch the binders we have actually bound for idx in ei.match_lo..ei.match_hi { let sub = ei.matches[idx].clone(); - new_pos.matches[idx] - .push(Rc::new(MatchedSeq(sub, Span { lo: ei.sp_lo, ..span }))); + new_pos.push_match(idx, MatchedSeq(sub, Span { lo: ei.sp_lo, ..span })); } new_pos.match_cur = ei.match_hi; @@ -362,7 +366,7 @@ fn inner_parse_loop(sess: &ParseSess, new_ei.match_cur += seq.num_captures; new_ei.idx += 1; for idx in ei.match_cur..ei.match_cur + seq.num_captures { - new_ei.matches[idx].push(Rc::new(MatchedSeq(vec![], sp))); + new_ei.push_match(idx, MatchedSeq(Rc::new(vec![]), sp)); } cur_eis.push(new_ei); } @@ -446,7 +450,9 @@ pub fn parse(sess: &ParseSess, /* error messages here could be improved with links to orig. rules */ if token_name_eq(&parser.token, &token::Eof) { if eof_eis.len() == 1 { - let matches = eof_eis[0].matches.iter_mut().map(|mut dv| dv.pop().unwrap()); + let matches = eof_eis[0].matches.iter_mut().map(|mut dv| { + Rc::make_mut(dv).pop().unwrap() + }); return nameize(sess, ms, matches); } else if eof_eis.len() > 1 { return Error(parser.span, "ambiguity: multiple successful parses".to_string()); @@ -479,8 +485,8 @@ pub fn parse(sess: &ParseSess, let mut ei = bb_eis.pop().unwrap(); if let TokenTree::MetaVarDecl(span, _, ident) = ei.top_elts.get_tt(ei.idx) { let match_cur = ei.match_cur; - ei.matches[match_cur].push(Rc::new(MatchedNonterminal( - Rc::new(parse_nt(&mut parser, span, &ident.name.as_str()))))); + ei.push_match(match_cur, + MatchedNonterminal(Rc::new(parse_nt(&mut parser, span, &ident.name.as_str())))); ei.idx += 1; ei.match_cur += 1; } else { diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 0472a94e0ced..9c728c9f2ebf 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -219,7 +219,7 @@ pub fn compile(sess: &ParseSess, features: &RefCell, def: &ast::Item) let lhses = match *argument_map[&lhs_nm] { MatchedSeq(ref s, _) => { s.iter().map(|m| { - if let MatchedNonterminal(ref nt) = **m { + if let MatchedNonterminal(ref nt) = *m { if let NtTT(ref tt) = **nt { let tt = quoted::parse(tt.clone().into(), true, sess).pop().unwrap(); valid &= check_lhs_nt_follows(sess, features, &tt); @@ -235,7 +235,7 @@ pub fn compile(sess: &ParseSess, features: &RefCell, def: &ast::Item) let rhses = match *argument_map[&rhs_nm] { MatchedSeq(ref s, _) => { s.iter().map(|m| { - if let MatchedNonterminal(ref nt) = **m { + if let MatchedNonterminal(ref nt) = *m { if let NtTT(ref tt) = **nt { return quoted::parse(tt.clone().into(), false, sess).pop().unwrap(); } diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs index 2a435bdea107..78e755e73fa3 100644 --- a/src/libsyntax/ext/tt/transcribe.rs +++ b/src/libsyntax/ext/tt/transcribe.rs @@ -182,15 +182,16 @@ fn lookup_cur_matched(ident: Ident, repeats: &[(usize, usize)]) -> Option> { interpolations.get(&ident).map(|matched| { - repeats.iter().fold(matched.clone(), |ad, &(idx, _)| { - match *ad { - MatchedNonterminal(_) => { - // end of the line; duplicate henceforth - ad.clone() - } - MatchedSeq(ref ads, _) => ads[idx].clone() + let mut matched = matched.clone(); + for &(idx, _) in repeats { + let m = matched.clone(); + match *m { + MatchedNonterminal(_) => break, + MatchedSeq(ref ads, _) => matched = Rc::new(ads[idx].clone()), } - }) + } + + matched }) } diff --git a/src/test/run-pass-fulldeps/auxiliary/procedural_mbe_matching.rs b/src/test/run-pass-fulldeps/auxiliary/procedural_mbe_matching.rs index c9fa96b83c28..b5d6ff595afd 100644 --- a/src/test/run-pass-fulldeps/auxiliary/procedural_mbe_matching.rs +++ b/src/test/run-pass-fulldeps/auxiliary/procedural_mbe_matching.rs @@ -54,7 +54,7 @@ fn expand_mbe_matches(cx: &mut ExtCtxt, _: Span, args: &[TokenTree]) let mac_expr = match (&*matched_nt, &*map[&Ident::from_str("pat")]) { (&NtExpr(ref matched_expr), &MatchedSeq(ref pats, seq_sp)) => { let pats: Vec> = pats.iter().map(|pat_nt| { - match **pat_nt { + match *pat_nt { MatchedNonterminal(ref nt) => match **nt { NtPat(ref pat) => pat.clone(), _ => unreachable!(), From c288864ed0b83f58183a9ddc53d02d36eac29287 Mon Sep 17 00:00:00 2001 From: Tshepang Lekhonkhobe Date: Thu, 8 Jun 2017 22:46:11 +0200 Subject: [PATCH 083/233] doc: a more complete explanation, and a better example --- src/libcore/cell.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index ea480f38947f..e75401f6ce03 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -391,17 +391,17 @@ impl Cell { } } - /// Replaces the contained value. + /// Replaces the contained value, and returns it. /// /// # Examples /// /// ``` /// use std::cell::Cell; /// - /// let c = Cell::new(5); - /// let old = c.replace(10); - /// - /// assert_eq!(5, old); + /// let cell = Cell::new(5); + /// assert_eq!(cell.get(), 5); + /// assert_eq!(cell.replace(10), 5); + /// assert_eq!(cell.get(), 10); /// ``` #[stable(feature = "move_cell", since = "1.17.0")] pub fn replace(&self, val: T) -> T { From 2da350168df9dc51806fc72040a1022d45431879 Mon Sep 17 00:00:00 2001 From: Michael Killough Date: Tue, 16 May 2017 13:16:44 +0700 Subject: [PATCH 084/233] Document direct implementations on type aliases. This improves #32077, but is not a complete fix. For a type alias `type NewType = AliasedType`, it will include any `impl NewType` and `impl Trait for NewType` blocks in the documentation for `NewType`. A complete fix would include the implementations from the aliased type in the type alias' documentation, so that users have a complete picture of methods that are available on the alias. However, to do this properly would require a fix for #14072, as the alias may affect the type parameters of the type alias, making the documentation difficult to understand. (That is, for `type Result = std::result::Result<(), ()>` we would ideally show documentation for `impl Result<(), ()>`, rather than generic documentation for `impl Result`). I think this improvement is worthwhile, as it exposes implementations which are not currently documented by rustdoc. The documentation for the implementations on the aliased type are still accessible by clicking through to the docs for that type. (Although perhaps it's now less obvious to the user that they should click-through to get there). --- src/librustdoc/clean/mod.rs | 3 +++ src/librustdoc/html/render.rs | 22 ++++++++++++++++++++-- src/test/rustdoc/typedef.rs | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 src/test/rustdoc/typedef.rs diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 20ce2c024962..3db0e1444db7 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -311,6 +311,9 @@ impl Item { pub fn is_ty_method(&self) -> bool { self.type_() == ItemType::TyMethod } + pub fn is_typedef(&self) -> bool { + self.type_() == ItemType::Typedef + } pub fn is_primitive(&self) -> bool { self.type_() == ItemType::Primitive } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 0d9f98e05d2c..fea059e2757d 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -3082,7 +3082,13 @@ fn item_typedef(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, where_clause = WhereClause { gens: &t.generics, indent: 0, end_newline: true }, type_ = t.type_)?; - document(w, cx, it) + document(w, cx, it)?; + + // Render any items associated directly to this alias, as otherwise they + // won't be visible anywhere in the docs. It would be nice to also show + // associated items from the aliased type (see discussion in #32077), but + // we need #14072 to make sense of the generics. + render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All) } impl<'a> fmt::Display for Sidebar<'a> { @@ -3092,7 +3098,7 @@ impl<'a> fmt::Display for Sidebar<'a> { let parentlen = cx.current.len() - if it.is_mod() {1} else {0}; if it.is_struct() || it.is_trait() || it.is_primitive() || it.is_union() - || it.is_enum() || it.is_mod() + || it.is_enum() || it.is_mod() || it.is_typedef() { write!(fmt, "

")?; match it.inner { @@ -3101,6 +3107,7 @@ impl<'a> fmt::Display for Sidebar<'a> { clean::PrimitiveItem(..) => write!(fmt, "Primitive Type ")?, clean::UnionItem(..) => write!(fmt, "Union ")?, clean::EnumItem(..) => write!(fmt, "Enum ")?, + clean::TypedefItem(..) => write!(fmt, "Type Definition ")?, clean::ModuleItem(..) => if it.is_crate() { write!(fmt, "Crate ")?; } else { @@ -3117,6 +3124,7 @@ impl<'a> fmt::Display for Sidebar<'a> { clean::PrimitiveItem(ref p) => sidebar_primitive(fmt, it, p)?, clean::UnionItem(ref u) => sidebar_union(fmt, it, u)?, clean::EnumItem(ref e) => sidebar_enum(fmt, it, e)?, + clean::TypedefItem(ref t, _) => sidebar_typedef(fmt, it, t)?, clean::ModuleItem(ref m) => sidebar_module(fmt, it, &m.items)?, _ => (), } @@ -3259,6 +3267,16 @@ fn sidebar_primitive(fmt: &mut fmt::Formatter, it: &clean::Item, Ok(()) } +fn sidebar_typedef(fmt: &mut fmt::Formatter, it: &clean::Item, + _t: &clean::Typedef) -> fmt::Result { + let sidebar = sidebar_assoc_items(it); + + if !sidebar.is_empty() { + write!(fmt, "

    {}
", sidebar)?; + } + Ok(()) +} + fn sidebar_union(fmt: &mut fmt::Formatter, it: &clean::Item, u: &clean::Union) -> fmt::Result { let mut sidebar = String::new(); diff --git a/src/test/rustdoc/typedef.rs b/src/test/rustdoc/typedef.rs new file mode 100644 index 000000000000..4ac91d354514 --- /dev/null +++ b/src/test/rustdoc/typedef.rs @@ -0,0 +1,35 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub trait MyTrait { + fn method_on_mytrait() {} +} + +pub struct MyStruct; + +impl MyStruct { + pub fn method_on_mystruct() {} +} + +// @has typedef/type.MyAlias.html +// @has - '//*[@class="impl"]//code' 'impl MyAlias' +// @has - '//*[@class="impl"]//code' 'impl MyTrait for MyAlias' +// @has - 'Alias docstring' +// @has - '//*[@class="sidebar"]//p[@class="location"]' 'Type Definition MyAlias' +// @has - '//*[@class="sidebar"]//a[@href="#methods"]' 'Methods' +// @has - '//*[@class="sidebar"]//a[@href="#implementations"]' 'Trait Implementations' +/// Alias docstring +pub type MyAlias = MyStruct; + +impl MyAlias { + pub fn method_on_myalias() {} +} + +impl MyTrait for MyAlias {} From 09ac478c5c33bb99055c88fb36d7229baae92762 Mon Sep 17 00:00:00 2001 From: Fuqiao Xue Date: Fri, 9 Jun 2017 13:37:22 +0800 Subject: [PATCH 085/233] Update TRPL link in README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index dbb5bf9ce38d..0b209fd3e949 100644 --- a/README.md +++ b/README.md @@ -7,9 +7,9 @@ standard library, and documentation. ## Quick Start -Read ["Installing Rust"] from [The Book]. +Read ["Installation"] from [The Book]. -["Installing Rust"]: https://doc.rust-lang.org/book/getting-started.html#installing-rust +["Installation"]: https://doc.rust-lang.org/book/second-edition/ch01-01-installation.html [The Book]: https://doc.rust-lang.org/book/index.html ## Building from Source From 13e24003472c13636d4350a530d6e6495775afeb Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sat, 27 May 2017 20:56:25 -0700 Subject: [PATCH 086/233] Add ctlz_nonzero & cttz_nonzero intrinsics LLVM currently doesn't remove the "bypass if argument is zero" assembly inside branches where the value is known to be non-zero, pessimizing code that uses uN::leading_zeros --- src/libcore/intrinsics.rs | 34 +++++++++++++++++++++++ src/librustc_trans/intrinsic.rs | 8 +++++- src/librustc_typeck/check/intrinsic.rs | 3 +- src/test/run-pass/intrinsics-integer.rs | 37 +++++++++++++++++++++++++ 4 files changed, 80 insertions(+), 2 deletions(-) diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 3566bbdebc2b..8188c15a2829 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -1229,6 +1229,23 @@ extern "rust-intrinsic" { /// ``` pub fn ctlz(x: T) -> T; + /// Like `ctlz`, but extra-unsafe as it returns `undef` when + /// given an `x` with value `0`. + /// + /// # Examples + /// + /// ``` + /// #![feature(core_intrinsics)] + /// + /// use std::intrinsics::ctlz_nonzero; + /// + /// let x = 0b0001_1100_u8; + /// let num_leading = unsafe { ctlz_nonzero(x) }; + /// assert_eq!(num_leading, 3); + /// ``` + #[cfg(not(stage0))] + pub fn ctlz_nonzero(x: T) -> T; + /// Returns the number of trailing unset bits (zeroes) in an integer type `T`. /// /// # Examples @@ -1256,6 +1273,23 @@ extern "rust-intrinsic" { /// ``` pub fn cttz(x: T) -> T; + /// Like `cttz`, but extra-unsafe as it returns `undef` when + /// given an `x` with value `0`. + /// + /// # Examples + /// + /// ``` + /// #![feature(core_intrinsics)] + /// + /// use std::intrinsics::cttz_nonzero; + /// + /// let x = 0b0011_1000_u8; + /// let num_trailing = unsafe { cttz_nonzero(x) }; + /// assert_eq!(num_trailing, 3); + /// ``` + #[cfg(not(stage0))] + pub fn cttz_nonzero(x: T) -> T; + /// Reverses the bytes in an integer type `T`. pub fn bswap(x: T) -> T; diff --git a/src/librustc_trans/intrinsic.rs b/src/librustc_trans/intrinsic.rs index f2e6aa3ef00b..de908bb24a7a 100644 --- a/src/librustc_trans/intrinsic.rs +++ b/src/librustc_trans/intrinsic.rs @@ -267,7 +267,7 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, }; bcx.call(expect, &[llargs[0], C_i32(ccx, rw), llargs[1], C_i32(ccx, cache_type)], None) }, - "ctlz" | "cttz" | "ctpop" | "bswap" | + "ctlz" | "ctlz_nonzero" | "cttz" | "cttz_nonzero" | "ctpop" | "bswap" | "add_with_overflow" | "sub_with_overflow" | "mul_with_overflow" | "overflowing_add" | "overflowing_sub" | "overflowing_mul" | "unchecked_div" | "unchecked_rem" | "unchecked_shl" | "unchecked_shr" => { @@ -280,6 +280,12 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, let llfn = ccx.get_intrinsic(&format!("llvm.{}.i{}", name, width)); bcx.call(llfn, &[llargs[0], y], None) } + "ctlz_nonzero" | "cttz_nonzero" => { + let y = C_bool(bcx.ccx, true); + let llvm_name = &format!("llvm.{}.i{}", &name[..4], width); + let llfn = ccx.get_intrinsic(llvm_name); + bcx.call(llfn, &[llargs[0], y], None) + } "ctpop" => bcx.call(ccx.get_intrinsic(&format!("llvm.ctpop.i{}", width)), &llargs, None), "bswap" => { diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index daf202cd7973..4d9f50b0fc0c 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -272,7 +272,8 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, "volatile_store" => (1, vec![ tcx.mk_mut_ptr(param(0)), param(0) ], tcx.mk_nil()), - "ctpop" | "ctlz" | "cttz" | "bswap" => (1, vec![param(0)], param(0)), + "ctpop" | "ctlz" | "ctlz_nonzero" | "cttz" | "cttz_nonzero" | "bswap" => + (1, vec![param(0)], param(0)), "add_with_overflow" | "sub_with_overflow" | "mul_with_overflow" => (1, vec![param(0), param(0)], diff --git a/src/test/run-pass/intrinsics-integer.rs b/src/test/run-pass/intrinsics-integer.rs index 759dc515456d..4896f02da20b 100644 --- a/src/test/run-pass/intrinsics-integer.rs +++ b/src/test/run-pass/intrinsics-integer.rs @@ -14,7 +14,9 @@ mod rusti { extern "rust-intrinsic" { pub fn ctpop(x: T) -> T; pub fn ctlz(x: T) -> T; + pub fn ctlz_nonzero(x: T) -> T; pub fn cttz(x: T) -> T; + pub fn cttz_nonzero(x: T) -> T; pub fn bswap(x: T) -> T; } } @@ -68,6 +70,21 @@ pub fn main() { assert_eq!(ctlz(100u32), 25); assert_eq!(ctlz(100i32), 25); assert_eq!(ctlz(100u64), 57); assert_eq!(ctlz(100i64), 57); + assert_eq!(ctlz_nonzero(1u8), 7); assert_eq!(ctlz_nonzero(1i8), 7); + assert_eq!(ctlz_nonzero(1u16), 15); assert_eq!(ctlz_nonzero(1i16), 15); + assert_eq!(ctlz_nonzero(1u32), 31); assert_eq!(ctlz_nonzero(1i32), 31); + assert_eq!(ctlz_nonzero(1u64), 63); assert_eq!(ctlz_nonzero(1i64), 63); + + assert_eq!(ctlz_nonzero(10u8), 4); assert_eq!(ctlz_nonzero(10i8), 4); + assert_eq!(ctlz_nonzero(10u16), 12); assert_eq!(ctlz_nonzero(10i16), 12); + assert_eq!(ctlz_nonzero(10u32), 28); assert_eq!(ctlz_nonzero(10i32), 28); + assert_eq!(ctlz_nonzero(10u64), 60); assert_eq!(ctlz_nonzero(10i64), 60); + + assert_eq!(ctlz_nonzero(100u8), 1); assert_eq!(ctlz_nonzero(100i8), 1); + assert_eq!(ctlz_nonzero(100u16), 9); assert_eq!(ctlz_nonzero(100i16), 9); + assert_eq!(ctlz_nonzero(100u32), 25); assert_eq!(ctlz_nonzero(100i32), 25); + assert_eq!(ctlz_nonzero(100u64), 57); assert_eq!(ctlz_nonzero(100i64), 57); + assert_eq!(cttz(-1i8 as u8), 0); assert_eq!(cttz(-1i8), 0); assert_eq!(cttz(-1i16 as u16), 0); assert_eq!(cttz(-1i16), 0); assert_eq!(cttz(-1i32 as u32), 0); assert_eq!(cttz(-1i32), 0); @@ -93,6 +110,26 @@ pub fn main() { assert_eq!(cttz(100u32), 2); assert_eq!(cttz(100i32), 2); assert_eq!(cttz(100u64), 2); assert_eq!(cttz(100i64), 2); + assert_eq!(cttz_nonzero(-1i8 as u8), 0); assert_eq!(cttz_nonzero(-1i8), 0); + assert_eq!(cttz_nonzero(-1i16 as u16), 0); assert_eq!(cttz_nonzero(-1i16), 0); + assert_eq!(cttz_nonzero(-1i32 as u32), 0); assert_eq!(cttz_nonzero(-1i32), 0); + assert_eq!(cttz_nonzero(-1i64 as u64), 0); assert_eq!(cttz_nonzero(-1i64), 0); + + assert_eq!(cttz_nonzero(1u8), 0); assert_eq!(cttz_nonzero(1i8), 0); + assert_eq!(cttz_nonzero(1u16), 0); assert_eq!(cttz_nonzero(1i16), 0); + assert_eq!(cttz_nonzero(1u32), 0); assert_eq!(cttz_nonzero(1i32), 0); + assert_eq!(cttz_nonzero(1u64), 0); assert_eq!(cttz_nonzero(1i64), 0); + + assert_eq!(cttz_nonzero(10u8), 1); assert_eq!(cttz_nonzero(10i8), 1); + assert_eq!(cttz_nonzero(10u16), 1); assert_eq!(cttz_nonzero(10i16), 1); + assert_eq!(cttz_nonzero(10u32), 1); assert_eq!(cttz_nonzero(10i32), 1); + assert_eq!(cttz_nonzero(10u64), 1); assert_eq!(cttz_nonzero(10i64), 1); + + assert_eq!(cttz_nonzero(100u8), 2); assert_eq!(cttz_nonzero(100i8), 2); + assert_eq!(cttz_nonzero(100u16), 2); assert_eq!(cttz_nonzero(100i16), 2); + assert_eq!(cttz_nonzero(100u32), 2); assert_eq!(cttz_nonzero(100i32), 2); + assert_eq!(cttz_nonzero(100u64), 2); assert_eq!(cttz_nonzero(100i64), 2); + assert_eq!(bswap(0x0Au8), 0x0A); // no-op assert_eq!(bswap(0x0Ai8), 0x0A); // no-op assert_eq!(bswap(0x0A0Bu16), 0x0B0A); From 6d86f0c018b57fcb9ca12c801939130b7f8e441e Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Thu, 8 Jun 2017 21:29:45 -0700 Subject: [PATCH 087/233] Use ctlz_nonzero to improve ASM from next_power_of_two --- src/libcore/num/mod.rs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index b76eac9e51f1..62d75445cc95 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -1262,6 +1262,7 @@ macro_rules! uint_impl { ($SelfT:ty, $ActualT:ty, $BITS:expr, $ctpop:path, $ctlz:path, + $ctlz_nonzero:path, $cttz:path, $bswap:path, $add_with_overflow:path, @@ -2184,6 +2185,7 @@ macro_rules! uint_impl { // This method cannot overflow, as in the `next_power_of_two` // overflow cases it instead ends up returning the maximum value // of the type, and can return 0 for 0. + #[inline] fn one_less_than_next_power_of_two(self) -> Self { if self <= 1 { return 0; } @@ -2192,7 +2194,7 @@ macro_rules! uint_impl { // (such as intel pre-haswell) have more efficient ctlz // intrinsics when the argument is non-zero. let p = self - 1; - let z = p.leading_zeros(); + let z = unsafe { $ctlz_nonzero(p) }; <$SelfT>::max_value() >> z } @@ -2236,11 +2238,17 @@ macro_rules! uint_impl { } } +#[cfg(stage0)] +unsafe fn ctlz_nonzero(x: T) -> T { intrinsics::ctlz(x) } +#[cfg(not(stage0))] +unsafe fn ctlz_nonzero(x: T) -> T { intrinsics::ctlz_nonzero(x) } + #[lang = "u8"] impl u8 { uint_impl! { u8, u8, 8, intrinsics::ctpop, intrinsics::ctlz, + ctlz_nonzero, intrinsics::cttz, intrinsics::bswap, intrinsics::add_with_overflow, @@ -2253,6 +2261,7 @@ impl u16 { uint_impl! { u16, u16, 16, intrinsics::ctpop, intrinsics::ctlz, + ctlz_nonzero, intrinsics::cttz, intrinsics::bswap, intrinsics::add_with_overflow, @@ -2265,6 +2274,7 @@ impl u32 { uint_impl! { u32, u32, 32, intrinsics::ctpop, intrinsics::ctlz, + ctlz_nonzero, intrinsics::cttz, intrinsics::bswap, intrinsics::add_with_overflow, @@ -2277,6 +2287,7 @@ impl u64 { uint_impl! { u64, u64, 64, intrinsics::ctpop, intrinsics::ctlz, + ctlz_nonzero, intrinsics::cttz, intrinsics::bswap, intrinsics::add_with_overflow, @@ -2289,6 +2300,7 @@ impl u128 { uint_impl! { u128, u128, 128, intrinsics::ctpop, intrinsics::ctlz, + ctlz_nonzero, intrinsics::cttz, intrinsics::bswap, intrinsics::add_with_overflow, @@ -2302,6 +2314,7 @@ impl usize { uint_impl! { usize, u16, 16, intrinsics::ctpop, intrinsics::ctlz, + ctlz_nonzero, intrinsics::cttz, intrinsics::bswap, intrinsics::add_with_overflow, @@ -2314,6 +2327,7 @@ impl usize { uint_impl! { usize, u32, 32, intrinsics::ctpop, intrinsics::ctlz, + ctlz_nonzero, intrinsics::cttz, intrinsics::bswap, intrinsics::add_with_overflow, @@ -2327,6 +2341,7 @@ impl usize { uint_impl! { usize, u64, 64, intrinsics::ctpop, intrinsics::ctlz, + ctlz_nonzero, intrinsics::cttz, intrinsics::bswap, intrinsics::add_with_overflow, From 83f1f118e56320667c04a522e05f09a9f4abb6ff Mon Sep 17 00:00:00 2001 From: Djzin Date: Fri, 9 Jun 2017 07:07:58 +0100 Subject: [PATCH 088/233] hack around bug in emscripten --- src/libcore/mem.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 91b348fb5d67..7c63ecd203e2 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -503,7 +503,9 @@ pub fn swap(x: &mut T, y: &mut T) { // that swapping either 32 bytes or 64 bytes at a time is most efficient for intel // Haswell E processors. LLVM is more able to optimize if we give a struct a // #[repr(simd)], even if we don't actually use this struct directly. - #[repr(simd)] + // + // FIXME repr(simd) broken on emscripten + #[cfg_attr(not(target_os = "emscripten"), repr(simd))] struct Block(u64, u64, u64, u64); struct UnalignedBlock(u64, u64, u64, u64); From 76a50706a8e19ecc253bb2a5749b1a3f4f5dc89d Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 7 Jun 2017 15:21:29 +0300 Subject: [PATCH 089/233] rustc: remove redundant krate field from lint::LateContext. --- src/librustc/lint/context.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 2022565d533b..b14f549cbf6d 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -411,9 +411,6 @@ pub struct LateContext<'a, 'tcx: 'a> { /// Side-tables for the body we are in. pub tables: &'a ty::TypeckTables<'tcx>, - /// The crate being checked. - pub krate: &'a hir::Crate, - /// Items accessible from the crate being checked. pub access_levels: &'a AccessLevels, @@ -1330,7 +1327,6 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { let mut cx = LateContext { tcx: tcx, tables: &ty::TypeckTables::empty(), - krate: krate, access_levels: access_levels, lint_sess: LintSession::new(&tcx.sess.lint_store), }; From 8b1b05bcebc1c6c8c2a7acdaa1970167c5b98cb4 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 7 Jun 2017 15:21:55 +0300 Subject: [PATCH 090/233] rustc: track the current ty::ParamEnv in lint::LateContext. --- src/librustc/lint/context.rs | 48 +++++++++++++++++++++++++++--------- src/librustc_lint/builtin.rs | 19 ++++++-------- src/librustc_lint/types.rs | 2 +- 3 files changed, 45 insertions(+), 24 deletions(-) diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index b14f549cbf6d..40734469718b 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -27,6 +27,7 @@ use self::TargetLint::*; use dep_graph::DepNode; use middle::privacy::AccessLevels; +use traits::Reveal; use ty::{self, TyCtxt}; use session::{config, early_error, Session}; use lint::{Level, LevelSource, Lint, LintId, LintPass, LintSource}; @@ -411,6 +412,9 @@ pub struct LateContext<'a, 'tcx: 'a> { /// Side-tables for the body we are in. pub tables: &'a ty::TypeckTables<'tcx>, + /// Parameter environment for the item we are in. + pub param_env: ty::ParamEnv<'tcx>, + /// Items accessible from the crate being checked. pub access_levels: &'a AccessLevels, @@ -866,6 +870,17 @@ impl<'a> LintContext<'a> for EarlyContext<'a> { } } +impl<'a, 'tcx> LateContext<'a, 'tcx> { + fn with_param_env(&mut self, id: ast::NodeId, f: F) + where F: FnOnce(&mut Self), + { + let old_param_env = self.param_env; + self.param_env = self.tcx.param_env(self.tcx.hir.local_def_id(id)); + f(self); + self.param_env = old_param_env; + } +} + impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> { /// Because lints are scoped lexically, we want to walk nested /// items in the context of the outer item, so enable @@ -899,17 +914,21 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> { fn visit_item(&mut self, it: &'tcx hir::Item) { self.with_lint_attrs(&it.attrs, |cx| { - run_lints!(cx, check_item, late_passes, it); - hir_visit::walk_item(cx, it); - run_lints!(cx, check_item_post, late_passes, it); + cx.with_param_env(it.id, |cx| { + run_lints!(cx, check_item, late_passes, it); + hir_visit::walk_item(cx, it); + run_lints!(cx, check_item_post, late_passes, it); + }); }) } fn visit_foreign_item(&mut self, it: &'tcx hir::ForeignItem) { self.with_lint_attrs(&it.attrs, |cx| { - run_lints!(cx, check_foreign_item, late_passes, it); - hir_visit::walk_foreign_item(cx, it); - run_lints!(cx, check_foreign_item_post, late_passes, it); + cx.with_param_env(it.id, |cx| { + run_lints!(cx, check_foreign_item, late_passes, it); + hir_visit::walk_foreign_item(cx, it); + run_lints!(cx, check_foreign_item_post, late_passes, it); + }); }) } @@ -1023,17 +1042,21 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> { fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) { self.with_lint_attrs(&trait_item.attrs, |cx| { - run_lints!(cx, check_trait_item, late_passes, trait_item); - hir_visit::walk_trait_item(cx, trait_item); - run_lints!(cx, check_trait_item_post, late_passes, trait_item); + cx.with_param_env(trait_item.id, |cx| { + run_lints!(cx, check_trait_item, late_passes, trait_item); + hir_visit::walk_trait_item(cx, trait_item); + run_lints!(cx, check_trait_item_post, late_passes, trait_item); + }); }); } fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) { self.with_lint_attrs(&impl_item.attrs, |cx| { - run_lints!(cx, check_impl_item, late_passes, impl_item); - hir_visit::walk_impl_item(cx, impl_item); - run_lints!(cx, check_impl_item_post, late_passes, impl_item); + cx.with_param_env(impl_item.id, |cx| { + run_lints!(cx, check_impl_item, late_passes, impl_item); + hir_visit::walk_impl_item(cx, impl_item); + run_lints!(cx, check_impl_item_post, late_passes, impl_item); + }); }); } @@ -1327,6 +1350,7 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { let mut cx = LateContext { tcx: tcx, tables: &ty::TypeckTables::empty(), + param_env: ty::ParamEnv::empty(Reveal::UserFacing), access_levels: access_levels, lint_sess: LintSession::new(&tcx.sess.lint_store), }; diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 3a4729e64548..bccdac91423c 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -32,7 +32,7 @@ use rustc::hir::def::Def; use rustc::hir::def_id::DefId; use rustc::cfg; use rustc::ty::subst::Substs; -use rustc::ty::{self, Ty, TyCtxt}; +use rustc::ty::{self, Ty}; use rustc::traits::{self, Reveal}; use rustc::hir::map as hir_map; use util::nodemap::NodeSet; @@ -893,7 +893,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion { for adjustment in cx.tables.expr_adjustments(expr) { if let Adjust::Deref(Some(deref)) = adjustment.kind { let (def_id, substs) = deref.method_call(cx.tcx, source); - if method_call_refers_to_method(cx.tcx, method, def_id, substs, id) { + if method_call_refers_to_method(cx, method, def_id, substs, id) { return true; } } @@ -904,7 +904,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion { if cx.tables.is_method_call(expr) { let def_id = cx.tables.type_dependent_defs[&id].def_id(); let substs = cx.tables.node_substs(id); - if method_call_refers_to_method(cx.tcx, method, def_id, substs, id) { + if method_call_refers_to_method(cx, method, def_id, substs, id) { return true; } } @@ -920,8 +920,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion { match def { Def::Method(def_id) => { let substs = cx.tables.node_substs(callee.id); - method_call_refers_to_method( - cx.tcx, method, def_id, substs, id) + method_call_refers_to_method(cx, method, def_id, substs, id) } _ => false, } @@ -932,12 +931,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion { // Check if the method call to the method with the ID `callee_id` // and instantiated with `callee_substs` refers to method `method`. - fn method_call_refers_to_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + fn method_call_refers_to_method<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, method: &ty::AssociatedItem, callee_id: DefId, callee_substs: &Substs<'tcx>, expr_id: ast::NodeId) -> bool { + let tcx = cx.tcx; let callee_item = tcx.associated_item(callee_id); match callee_item.container { @@ -951,10 +951,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion { let trait_ref = ty::TraitRef::from_method(tcx, trait_def_id, callee_substs); let trait_ref = ty::Binder(trait_ref); let span = tcx.hir.span(expr_id); - let param_env = tcx.param_env(method.def_id); let obligation = traits::Obligation::new(traits::ObligationCause::misc(span, expr_id), - param_env, + cx.param_env, trait_ref.to_poly_trait_predicate()); tcx.infer_ctxt(()).enter(|infcx| { @@ -1224,11 +1223,9 @@ impl LintPass for UnionsWithDropFields { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnionsWithDropFields { fn check_item(&mut self, ctx: &LateContext, item: &hir::Item) { if let hir::ItemUnion(ref vdata, _) = item.node { - let item_def_id = ctx.tcx.hir.local_def_id(item.id); - let param_env = ctx.tcx.param_env(item_def_id); for field in vdata.fields() { let field_ty = ctx.tcx.type_of(ctx.tcx.hir.local_def_id(field.id)); - if field_ty.needs_drop(ctx.tcx, param_env) { + if field_ty.needs_drop(ctx.tcx, ctx.param_env) { ctx.span_lint(UNIONS_WITH_DROP_FIELDS, field.span, "union contains a field with possibly non-trivial drop code, \ diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index 3019165bfbf9..32bde42b5261 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -725,7 +725,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VariantSizeDifferences { // sizes only make sense for non-generic types let item_def_id = cx.tcx.hir.local_def_id(it.id); let t = cx.tcx.type_of(item_def_id); - let param_env = cx.tcx.param_env(item_def_id).reveal_all(); + let param_env = cx.param_env.reveal_all(); let ty = cx.tcx.erase_regions(&t); let layout = ty.layout(cx.tcx, param_env).unwrap_or_else(|e| { bug!("failed to get layout for `{}`: {}", t, e) From 5175bc18b5ece1f66a7bfca09202a97728f1d920 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 8 Jun 2017 13:38:30 +0300 Subject: [PATCH 091/233] rustc_typeck: do not mutate tables directly during upvar inference. --- src/librustc/infer/mod.rs | 4 - src/librustc/middle/expr_use_visitor.rs | 22 +-- src/librustc/middle/mem_categorization.rs | 69 ++------ src/librustc/ty/context.rs | 4 +- src/librustc_mir/build/mod.rs | 7 +- src/librustc_mir/hair/cx/expr.rs | 10 +- src/librustc_typeck/check/regionck.rs | 7 +- src/librustc_typeck/check/upvar.rs | 203 +++++++++------------- 8 files changed, 107 insertions(+), 219 deletions(-) diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index f5869b8a20fa..6e9d028aa647 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -1521,10 +1521,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { !traits::type_known_to_meet_bound(self, param_env, ty, copy_def_id, span) } - pub fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option> { - self.tables.borrow().upvar_capture_map.get(&upvar_id).cloned() - } - pub fn closure_kind(&self, def_id: DefId) -> Option diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 0b2652c74881..4075d28a396a 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -270,23 +270,9 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, param_env: ty::ParamEnv<'tcx>) -> Self - { - ExprUseVisitor::with_options(delegate, - infcx, - param_env, - region_maps, - mc::MemCategorizationOptions::default()) - } - - pub fn with_options(delegate: &'a mut (Delegate<'tcx>+'a), - infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, - param_env: ty::ParamEnv<'tcx>, - region_maps: &'a RegionMaps, - options: mc::MemCategorizationOptions) - -> Self { ExprUseVisitor { - mc: mc::MemCategorizationContext::with_options(infcx, region_maps, options), + mc: mc::MemCategorizationContext::new(infcx, region_maps), delegate, param_env, } @@ -678,8 +664,8 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { // consumed or borrowed as part of the automatic adjustment // process. fn walk_adjustment(&mut self, expr: &hir::Expr) { - //NOTE(@jroesch): mixed RefCell borrow causes crash - let adjustments = self.mc.infcx.tables.borrow().expr_adjustments(expr).to_vec(); + let tables = self.mc.infcx.tables.borrow(); + let adjustments = tables.expr_adjustments(expr); let mut cmt = return_if_err!(self.mc.cat_expr_unadjusted(expr)); for adjustment in adjustments { debug!("walk_adjustment expr={:?} adj={:?}", expr, adjustment); @@ -896,7 +882,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { let id_var = self.tcx().hir.as_local_node_id(def_id).unwrap(); let upvar_id = ty::UpvarId { var_id: id_var, closure_expr_id: closure_expr.id }; - let upvar_capture = self.mc.infcx.upvar_capture(upvar_id).unwrap(); + let upvar_capture = self.mc.infcx.tables.borrow().upvar_capture(upvar_id); let cmt_var = return_if_err!(self.cat_captured_var(closure_expr.id, fn_decl_span, freevar.def)); diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index c114aa1d7a88..ddbc7f91097d 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -283,18 +283,6 @@ impl ast_node for hir::Pat { pub struct MemCategorizationContext<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { pub infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, pub region_maps: &'a RegionMaps, - options: MemCategorizationOptions, -} - -#[derive(Copy, Clone, Default)] -pub struct MemCategorizationOptions { - // If true, then when analyzing a closure upvar, if the closure - // has a missing kind, we treat it like a Fn closure. When false, - // we ICE if the closure has a missing kind. Should be false - // except during closure kind inference. It is used by the - // mem-categorization code to be able to have stricter assertions - // (which are always true except during upvar inference). - pub during_closure_kind_inference: bool, } pub type McResult = Result; @@ -400,20 +388,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, region_maps: &'a RegionMaps) -> MemCategorizationContext<'a, 'gcx, 'tcx> { - MemCategorizationContext::with_options(infcx, - region_maps, - MemCategorizationOptions::default()) - } - - pub fn with_options(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, - region_maps: &'a RegionMaps, - options: MemCategorizationOptions) - -> MemCategorizationContext<'a, 'gcx, 'tcx> { - MemCategorizationContext { - infcx: infcx, - region_maps: region_maps, - options: options, - } + MemCategorizationContext { infcx, region_maps } } fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> { @@ -620,38 +595,14 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { Def::Upvar(def_id, _, fn_node_id) => { let var_id = self.tcx().hir.as_local_node_id(def_id).unwrap(); - let ty = self.node_ty(fn_node_id)?; - match ty.sty { - ty::TyClosure(closure_id, _) => { - match self.infcx.closure_kind(closure_id) { - Some(kind) => { - self.cat_upvar(id, span, var_id, fn_node_id, kind) - } - None => { - if !self.options.during_closure_kind_inference { - span_bug!( - span, - "No closure kind for {:?}", - closure_id); - } - - // during closure kind inference, we - // don't know the closure kind yet, but - // it's ok because we detect that we are - // accessing an upvar and handle that - // case specially anyhow. Use Fn - // arbitrarily. - self.cat_upvar(id, span, var_id, fn_node_id, ty::ClosureKind::Fn) - } - } - } - _ => { - span_bug!( - span, - "Upvar of non-closure {} - {:?}", - fn_node_id, - ty); - } + let closure_id = self.tcx().hir.local_def_id(fn_node_id); + match self.infcx.closure_kind(closure_id) { + Some(kind) => { + self.cat_upvar(id, span, var_id, fn_node_id, kind) + } + None => { + span_bug!(span, "No closure kind for {:?}", closure_id); + } } } @@ -743,7 +694,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { // for that. let upvar_id = ty::UpvarId { var_id: var_id, closure_expr_id: fn_node_id }; - let upvar_capture = self.infcx.upvar_capture(upvar_id).unwrap(); + let upvar_capture = self.infcx.tables.borrow().upvar_capture(upvar_id); let cmt_result = match upvar_capture { ty::UpvarCapture::ByValue => { cmt_result diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 2bbb71610ad0..2d81606329e5 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -376,8 +376,8 @@ impl<'tcx> TypeckTables<'tcx> { } } - pub fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option> { - Some(self.upvar_capture_map.get(&upvar_id).unwrap().clone()) + pub fn upvar_capture(&self, upvar_id: ty::UpvarId) -> ty::UpvarCapture<'tcx> { + self.upvar_capture_map[&upvar_id] } } diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 08a5cb37e578..7490ee60e1f9 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -365,13 +365,14 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, let upvar_decls: Vec<_> = tcx.with_freevars(fn_id, |freevars| { freevars.iter().map(|fv| { let var_id = tcx.hir.as_local_node_id(fv.def.def_id()).unwrap(); - let by_ref = hir.tables().upvar_capture(ty::UpvarId { + let capture = hir.tables().upvar_capture(ty::UpvarId { var_id: var_id, closure_expr_id: fn_id - }).map_or(false, |capture| match capture { + }); + let by_ref = match capture { ty::UpvarCapture::ByValue => false, ty::UpvarCapture::ByRef(..) => true - }); + }; let mut decl = UpvarDecl { debug_name: keywords::Invalid.name(), by_ref: by_ref diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 8cfeecdafb51..474feefabbb8 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -758,13 +758,7 @@ fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, var_id: id_var, closure_expr_id: closure_expr_id, }; - let upvar_capture = match cx.tables().upvar_capture(upvar_id) { - Some(c) => c, - None => { - span_bug!(expr.span, "no upvar_capture for {:?}", upvar_id); - } - }; - match upvar_capture { + match cx.tables().upvar_capture(upvar_id) { ty::UpvarCapture::ByValue => field_kind, ty::UpvarCapture::ByRef(borrow) => { ExprKind::Deref { @@ -878,7 +872,7 @@ fn capture_freevar<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, var_id: id_var, closure_expr_id: closure_expr.id, }; - let upvar_capture = cx.tables().upvar_capture(upvar_id).unwrap(); + let upvar_capture = cx.tables().upvar_capture(upvar_id); let temp_lifetime = cx.region_maps.temporary_scope(closure_expr.id); let var_ty = cx.tables().node_id_to_type(id_var); let captured_var = Expr { diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index b66e311f04c6..9c3e5cd1f400 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -834,8 +834,8 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { mc.cat_expr_unadjusted(expr)? }; - //NOTE(@jroesch): mixed RefCell borrow causes crash - let adjustments = self.tables.borrow().expr_adjustments(&expr).to_vec(); + let tables = self.tables.borrow(); + let adjustments = tables.expr_adjustments(&expr); if adjustments.is_empty() { return Ok(cmt); } @@ -1215,8 +1215,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { // Detect by-ref upvar `x`: let cause = match note { mc::NoteUpvarRef(ref upvar_id) => { - let upvar_capture_map = &self.tables.borrow_mut().upvar_capture_map; - match upvar_capture_map.get(upvar_id) { + match self.tables.borrow().upvar_capture_map.get(upvar_id) { Some(&ty::UpvarCapture::ByRef(ref upvar_borrow)) => { // The mutability of the upvar may have been modified // by the above adjustment, so update our local variable. diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs index 25f5418bea9c..1f0911bb234e 100644 --- a/src/librustc_typeck/check/upvar.rs +++ b/src/librustc_typeck/check/upvar.rs @@ -53,31 +53,22 @@ use rustc::hir; use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; use rustc::util::nodemap::NodeMap; -/////////////////////////////////////////////////////////////////////////// -// PUBLIC ENTRY POINTS +use std::collections::hash_map::Entry; impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { pub fn closure_analyze(&self, body: &'gcx hir::Body) { - let mut seed = SeedBorrowKind::new(self); - seed.visit_body(body); - - let mut adjust = AdjustBorrowKind::new(self, seed.temp_closure_kinds); - adjust.visit_body(body); + InferBorrowKindVisitor { fcx: self }.visit_body(body); // it's our job to process these. assert!(self.deferred_call_resolutions.borrow().is_empty()); } } -/////////////////////////////////////////////////////////////////////////// -// SEED BORROW KIND - -struct SeedBorrowKind<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { +struct InferBorrowKindVisitor<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { fcx: &'a FnCtxt<'a, 'gcx, 'tcx>, - temp_closure_kinds: NodeMap<(ty::ClosureKind, Option<(Span, ast::Name)>)>, } -impl<'a, 'gcx, 'tcx> Visitor<'gcx> for SeedBorrowKind<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> Visitor<'gcx> for InferBorrowKindVisitor<'a, 'gcx, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> { NestedVisitorMap::None } @@ -87,7 +78,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for SeedBorrowKind<'a, 'gcx, 'tcx> { hir::ExprClosure(cc, _, body_id, _) => { let body = self.fcx.tcx.hir.body(body_id); self.visit_body(body); - self.check_closure(expr, cc); + self.fcx.analyze_closure(expr.id, expr.span, body, cc); } _ => { } @@ -97,26 +88,33 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for SeedBorrowKind<'a, 'gcx, 'tcx> { } } -impl<'a, 'gcx, 'tcx> SeedBorrowKind<'a, 'gcx, 'tcx> { - fn new(fcx: &'a FnCtxt<'a, 'gcx, 'tcx>) -> SeedBorrowKind<'a, 'gcx, 'tcx> { - SeedBorrowKind { fcx: fcx, temp_closure_kinds: NodeMap() } - } +impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { + fn analyze_closure(&self, + id: ast::NodeId, + span: Span, + body: &hir::Body, + capture_clause: hir::CaptureClause) { + /*! + * Analysis starting point. + */ - fn check_closure(&mut self, - expr: &hir::Expr, - capture_clause: hir::CaptureClause) - { - if !self.fcx.tables.borrow().closure_kinds.contains_key(&expr.id) { - self.temp_closure_kinds.insert(expr.id, (ty::ClosureKind::Fn, None)); - debug!("check_closure: adding closure {:?} as Fn", expr.id); - } + debug!("analyze_closure(id={:?}, body.id={:?})", id, body.id()); - self.fcx.tcx.with_freevars(expr.id, |freevars| { + let infer_kind = match self.tables.borrow_mut().closure_kinds.entry(id) { + Entry::Occupied(_) => false, + Entry::Vacant(entry) => { + debug!("check_closure: adding closure {:?} as Fn", id); + entry.insert((ty::ClosureKind::Fn, None)); + true + } + }; + + self.tcx.with_freevars(id, |freevars| { for freevar in freevars { let def_id = freevar.def.def_id(); - let var_node_id = self.fcx.tcx.hir.as_local_node_id(def_id).unwrap(); + let var_node_id = self.tcx.hir.as_local_node_id(def_id).unwrap(); let upvar_id = ty::UpvarId { var_id: var_node_id, - closure_expr_id: expr.id }; + closure_expr_id: id }; debug!("seed upvar_id {:?}", upvar_id); let capture_kind = match capture_clause { @@ -124,58 +122,37 @@ impl<'a, 'gcx, 'tcx> SeedBorrowKind<'a, 'gcx, 'tcx> { ty::UpvarCapture::ByValue } hir::CaptureByRef => { - let origin = UpvarRegion(upvar_id, expr.span); - let freevar_region = self.fcx.next_region_var(origin); + let origin = UpvarRegion(upvar_id, span); + let freevar_region = self.next_region_var(origin); let upvar_borrow = ty::UpvarBorrow { kind: ty::ImmBorrow, region: freevar_region }; ty::UpvarCapture::ByRef(upvar_borrow) } }; - self.fcx.tables.borrow_mut().upvar_capture_map.insert(upvar_id, capture_kind); + self.tables.borrow_mut().upvar_capture_map.insert(upvar_id, capture_kind); } }); - } -} - -/////////////////////////////////////////////////////////////////////////// -// ADJUST BORROW KIND - -struct AdjustBorrowKind<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { - fcx: &'a FnCtxt<'a, 'gcx, 'tcx>, - temp_closure_kinds: NodeMap<(ty::ClosureKind, Option<(Span, ast::Name)>)>, -} - -impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> { - fn new(fcx: &'a FnCtxt<'a, 'gcx, 'tcx>, - temp_closure_kinds: NodeMap<(ty::ClosureKind, Option<(Span, ast::Name)>)>) - -> AdjustBorrowKind<'a, 'gcx, 'tcx> { - AdjustBorrowKind { fcx: fcx, temp_closure_kinds: temp_closure_kinds } - } - - fn analyze_closure(&mut self, - id: ast::NodeId, - span: Span, - body: &hir::Body) { - /*! - * Analysis starting point. - */ - - debug!("analyze_closure(id={:?}, body.id={:?})", id, body.id()); { - let body_owner_def_id = self.fcx.tcx.hir.body_owner_def_id(body.id()); - let region_maps = &self.fcx.tcx.region_maps(body_owner_def_id); - let param_env = self.fcx.param_env; - let mut euv = - euv::ExprUseVisitor::with_options(self, - self.fcx, - param_env, - region_maps, - mc::MemCategorizationOptions { - during_closure_kind_inference: true - }); - euv.consume_body(body); + let body_owner_def_id = self.tcx.hir.body_owner_def_id(body.id()); + let region_maps = &self.tcx.region_maps(body_owner_def_id); + let mut delegate = InferBorrowKind { + fcx: self, + adjust_closure_kinds: NodeMap(), + adjust_upvar_captures: ty::UpvarCaptureMap::default(), + }; + euv::ExprUseVisitor::new(&mut delegate, region_maps, self, self.param_env) + .consume_body(body); + + // Write the adjusted values back into the main tables. + if infer_kind { + if let Some(kind) = delegate.adjust_closure_kinds.remove(&id) { + self.tables.borrow_mut().closure_kinds.insert(id, kind); + } + } + self.tables.borrow_mut().upvar_capture_map.extend( + delegate.adjust_upvar_captures); } // Now that we've analyzed the closure, we know how each @@ -191,7 +168,7 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> { // inference algorithm will reject it). // Extract the type variables UV0...UVn. - let (def_id, closure_substs) = match self.fcx.node_ty(id).sty { + let (def_id, closure_substs) = match self.node_ty(id).sty { ty::TyClosure(def_id, substs) => (def_id, substs), ref t => { span_bug!( @@ -206,44 +183,41 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> { debug!("analyze_closure: id={:?} closure_substs={:?} final_upvar_tys={:?}", id, closure_substs, final_upvar_tys); for (upvar_ty, final_upvar_ty) in - closure_substs.upvar_tys(def_id, self.fcx.tcx).zip(final_upvar_tys) + closure_substs.upvar_tys(def_id, self.tcx).zip(final_upvar_tys) { - self.fcx.demand_eqtype(span, final_upvar_ty, upvar_ty); + self.demand_eqtype(span, final_upvar_ty, upvar_ty); } - // If we are also inferred the closure kind here, update the - // main table and process any deferred resolutions. - if let Some(&(kind, context)) = self.temp_closure_kinds.get(&id) { - self.fcx.tables.borrow_mut().closure_kinds.insert(id, (kind, context)); - let closure_def_id = self.fcx.tcx.hir.local_def_id(id); - debug!("closure_kind({:?}) = {:?}", closure_def_id, kind); - + // If we are also inferred the closure kind here, + // process any deferred resolutions. + if infer_kind { + let closure_def_id = self.tcx.hir.local_def_id(id); let deferred_call_resolutions = - self.fcx.remove_deferred_call_resolutions(closure_def_id); + self.remove_deferred_call_resolutions(closure_def_id); for deferred_call_resolution in deferred_call_resolutions { - deferred_call_resolution.resolve(self.fcx); + deferred_call_resolution.resolve(self); } } } // Returns a list of `ClosureUpvar`s for each upvar. - fn final_upvar_tys(&mut self, closure_id: ast::NodeId) -> Vec> { + fn final_upvar_tys(&self, closure_id: ast::NodeId) -> Vec> { // Presently an unboxed closure type cannot "escape" out of a // function, so we will only encounter ones that originated in the // local crate or were inlined into it along with some function. // This may change if abstract return types of some sort are // implemented. - let tcx = self.fcx.tcx; + let tcx = self.tcx; tcx.with_freevars(closure_id, |freevars| { freevars.iter().map(|freevar| { let def_id = freevar.def.def_id(); let var_id = tcx.hir.as_local_node_id(def_id).unwrap(); - let freevar_ty = self.fcx.node_ty(var_id); + let freevar_ty = self.node_ty(var_id); let upvar_id = ty::UpvarId { var_id: var_id, closure_expr_id: closure_id }; - let capture = self.fcx.upvar_capture(upvar_id).unwrap(); + let capture = self.tables.borrow().upvar_capture(upvar_id); debug!("var_id={:?} freevar_ty={:?} capture={:?}", var_id, freevar_ty, capture); @@ -260,7 +234,15 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> { }).collect() }) } +} +struct InferBorrowKind<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { + fcx: &'a FnCtxt<'a, 'gcx, 'tcx>, + adjust_closure_kinds: NodeMap<(ty::ClosureKind, Option<(Span, ast::Name)>)>, + adjust_upvar_captures: ty::UpvarCaptureMap<'tcx>, +} + +impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> { fn adjust_upvar_borrow_kind_for_consume(&mut self, cmt: mc::cmt<'tcx>, mode: euv::ConsumeMode) @@ -297,9 +279,7 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> { guarantor.span, tcx.hir.name(upvar_id.var_id)); - let upvar_capture_map = - &mut self.fcx.tables.borrow_mut().upvar_capture_map; - upvar_capture_map.insert(upvar_id, ty::UpvarCapture::ByValue); + self.adjust_upvar_captures.insert(upvar_id, ty::UpvarCapture::ByValue); } mc::NoteClosureEnv(upvar_id) => { // we get just a closureenv ref if this is a @@ -410,11 +390,7 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> { // upvar, then we need to modify the // borrow_kind of the upvar to make sure it // is inferred to mutable if necessary - { - let upvar_capture_map = &mut self.fcx.tables.borrow_mut().upvar_capture_map; - let ub = upvar_capture_map.get_mut(&upvar_id).unwrap(); - self.adjust_upvar_borrow_kind(upvar_id, ub, borrow_kind); - } + self.adjust_upvar_borrow_kind(upvar_id, borrow_kind); // also need to be in an FnMut closure since this is not an ImmBorrow self.adjust_closure_kind(upvar_id.closure_expr_id, @@ -448,22 +424,25 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> { /// some particular use. fn adjust_upvar_borrow_kind(&mut self, upvar_id: ty::UpvarId, - upvar_capture: &mut ty::UpvarCapture, kind: ty::BorrowKind) { + let upvar_capture = self.adjust_upvar_captures.get(&upvar_id).cloned() + .unwrap_or_else(|| self.fcx.tables.borrow().upvar_capture(upvar_id)); debug!("adjust_upvar_borrow_kind(upvar_id={:?}, upvar_capture={:?}, kind={:?})", upvar_id, upvar_capture, kind); - match *upvar_capture { + match upvar_capture { ty::UpvarCapture::ByValue => { // Upvar is already by-value, the strongest criteria. } - ty::UpvarCapture::ByRef(ref mut upvar_borrow) => { + ty::UpvarCapture::ByRef(mut upvar_borrow) => { match (upvar_borrow.kind, kind) { // Take RHS: (ty::ImmBorrow, ty::UniqueImmBorrow) | (ty::ImmBorrow, ty::MutBorrow) | (ty::UniqueImmBorrow, ty::MutBorrow) => { upvar_borrow.kind = kind; + self.adjust_upvar_captures.insert(upvar_id, + ty::UpvarCapture::ByRef(upvar_borrow)); } // Take LHS: (ty::ImmBorrow, ty::ImmBorrow) | @@ -484,7 +463,9 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> { debug!("adjust_closure_kind(closure_id={}, new_kind={:?}, upvar_span={:?}, var_name={})", closure_id, new_kind, upvar_span, var_name); - if let Some(&(existing_kind, _)) = self.temp_closure_kinds.get(&closure_id) { + let closure_kind = self.adjust_closure_kinds.get(&closure_id).cloned() + .or_else(|| self.fcx.tables.borrow().closure_kinds.get(&closure_id).cloned()); + if let Some((existing_kind, _)) = closure_kind { debug!("adjust_closure_kind: closure_id={}, existing_kind={:?}, new_kind={:?}", closure_id, existing_kind, new_kind); @@ -500,7 +481,7 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> { (ty::ClosureKind::Fn, ty::ClosureKind::FnOnce) | (ty::ClosureKind::FnMut, ty::ClosureKind::FnOnce) => { // new kind is stronger than the old kind - self.temp_closure_kinds.insert( + self.adjust_closure_kinds.insert( closure_id, (new_kind, Some((upvar_span, var_name))) ); @@ -510,27 +491,7 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> { } } -impl<'a, 'gcx, 'tcx> Visitor<'gcx> for AdjustBorrowKind<'a, 'gcx, 'tcx> { - fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> { - NestedVisitorMap::None - } - - fn visit_fn(&mut self, - fn_kind: intravisit::FnKind<'gcx>, - decl: &'gcx hir::FnDecl, - body: hir::BodyId, - span: Span, - id: ast::NodeId) - { - intravisit::walk_fn(self, fn_kind, decl, body, span, id); - - let body = self.fcx.tcx.hir.body(body); - self.visit_body(body); - self.analyze_closure(id, span, body); - } -} - -impl<'a, 'gcx, 'tcx> euv::Delegate<'tcx> for AdjustBorrowKind<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'gcx, 'tcx> { fn consume(&mut self, _consume_id: ast::NodeId, _consume_span: Span, From 36071749092b03ba454aa16eaf68dd5341d69619 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Fri, 2 Jun 2017 17:36:30 +0200 Subject: [PATCH 092/233] incr.comp.: Uniformly represent DepNodes as (Kind, StableHash) pairs. --- src/librustc/dep_graph/debug.rs | 11 +- src/librustc/dep_graph/dep_node.rs | 615 +++++++++++------- src/librustc/dep_graph/dep_tracking_map.rs | 33 +- src/librustc/dep_graph/edges.rs | 26 +- src/librustc/dep_graph/graph.rs | 9 +- src/librustc/dep_graph/mod.rs | 2 + src/librustc/dep_graph/query.rs | 30 +- src/librustc/dep_graph/raii.rs | 5 +- src/librustc/dep_graph/shadow.rs | 11 +- src/librustc/dep_graph/thread.rs | 15 +- src/librustc/hir/map/mod.rs | 45 +- src/librustc/lint/context.rs | 4 +- src/librustc/traits/fulfill.rs | 15 +- src/librustc/traits/select.rs | 6 +- src/librustc/traits/trans/mod.rs | 15 +- src/librustc/ty/instance.rs | 7 +- src/librustc/ty/maps.rs | 79 ++- src/librustc/ty/mod.rs | 12 +- src/librustc/util/common.rs | 6 +- src/librustc_incremental/assert_dep_graph.rs | 71 +- src/librustc_incremental/calculate_svh/mod.rs | 84 ++- src/librustc_incremental/persist/data.rs | 6 +- .../persist/dirty_clean.rs | 61 +- src/librustc_incremental/persist/hash.rs | 41 +- src/librustc_incremental/persist/load.rs | 210 +++--- src/librustc_incremental/persist/preds/mod.rs | 35 +- src/librustc_incremental/persist/save.rs | 20 +- src/librustc_metadata/cstore.rs | 7 + src/librustc_metadata/cstore_impl.rs | 26 +- src/librustc_metadata/decoder.rs | 10 +- src/librustc_metadata/schema.rs | 2 +- src/librustc_trans/back/link.rs | 5 +- src/librustc_trans/partitioning.rs | 4 +- src/librustc_trans/trans_item.rs | 15 +- .../coherence/inherent_impls.rs | 5 +- src/librustc_typeck/coherence/overlap.rs | 5 +- src/librustc_typeck/variance/constraints.rs | 5 +- src/librustc_typeck/variance/mod.rs | 11 +- src/test/incremental/dirty_clean.rs | 8 +- 39 files changed, 860 insertions(+), 717 deletions(-) diff --git a/src/librustc/dep_graph/debug.rs b/src/librustc/dep_graph/debug.rs index 5b15c5e67174..e22552008d5a 100644 --- a/src/librustc/dep_graph/debug.rs +++ b/src/librustc/dep_graph/debug.rs @@ -12,7 +12,6 @@ use super::dep_node::DepNode; use std::error::Error; -use std::fmt::Debug; /// A dep-node filter goes from a user-defined string to a query over /// nodes. Right now the format is like this: @@ -39,7 +38,7 @@ impl DepNodeFilter { } /// Tests whether `node` meets the filter, returning true if so. - pub fn test(&self, node: &DepNode) -> bool { + pub fn test(&self, node: &DepNode) -> bool { let debug_str = format!("{:?}", node); self.text.split("&") .map(|s| s.trim()) @@ -67,10 +66,10 @@ impl EdgeFilter { } } - pub fn test(&self, - source: &DepNode, - target: &DepNode) - -> bool { + pub fn test(&self, + source: &DepNode, + target: &DepNode) + -> bool { self.source.test(source) && self.target.test(target) } } diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 1571cf344ede..5f3dd9052034 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -8,79 +8,280 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use hir::def_id::CrateNum; +use hir::def_id::{CrateNum, DefId}; +use hir::map::DefPathHash; + use ich::Fingerprint; -use rustc_data_structures::stable_hasher::StableHasher; -use std::fmt::Debug; +use ty::TyCtxt; +use rustc_data_structures::stable_hasher::{StableHasher, HashStable}; +use ich::StableHashingContext; use std::hash::Hash; -macro_rules! try_opt { - ($e:expr) => ( - match $e { - Some(r) => r, - None => return None, - } - ) +// erase!() just makes tokens go away. It's used to specify which macro argument +// is repeated (i.e. which sub-expression of the macro we are in) but don't need +// to actually use any of the arguments. +macro_rules! erase { + ($x:tt) => ({}) } -#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] -pub enum DepNode { - // The `D` type is "how definitions are identified". - // During compilation, it is always `DefId`, but when serializing - // it is mapped to `DefPath`. +macro_rules! define_dep_nodes { + ($( + $variant:ident $(( $($tuple_arg:tt),* ))* + $({ $($struct_arg_name:ident : $struct_arg_ty:ty),* })* + ),* + ) => ( + #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, + RustcEncodable, RustcDecodable)] + pub enum DepKind { + $($variant),* + } - /// Represents the `Krate` as a whole (the `hir::Krate` value) (as - /// distinct from the krate module). This is basically a hash of - /// the entire krate, so if you read from `Krate` (e.g., by calling - /// `tcx.hir.krate()`), we will have to assume that any change - /// means that you need to be recompiled. This is because the - /// `Krate` value gives you access to all other items. To avoid - /// this fate, do not call `tcx.hir.krate()`; instead, prefer - /// wrappers like `tcx.visit_all_items_in_krate()`. If there is no - /// suitable wrapper, you can use `tcx.dep_graph.ignore()` to gain - /// access to the krate, but you must remember to add suitable - /// edges yourself for the individual items that you read. + impl DepKind { + #[allow(unreachable_code)] + #[inline] + pub fn can_reconstruct_query_key(&self) -> bool { + match *self { + $( + DepKind :: $variant => { + // tuple args + $({ + return <( $($tuple_arg,)* ) as DepNodeParams> + ::CAN_RECONSTRUCT_QUERY_KEY; + })* + + // struct args + $({ + return <( $($struct_arg_ty,)* ) as DepNodeParams> + ::CAN_RECONSTRUCT_QUERY_KEY; + })* + + true + } + )* + } + } + + #[allow(unreachable_code)] + #[inline] + pub fn has_params(&self) -> bool { + match *self { + $( + DepKind :: $variant => { + // tuple args + $({ + $(erase!($tuple_arg);)* + return true; + })* + + // struct args + $({ + $(erase!($struct_arg_name);)* + return true; + })* + + false + } + )* + } + } + } + + pub enum DepConstructor { + $( + $variant $(( $($tuple_arg),* ))* + $({ $($struct_arg_name : $struct_arg_ty),* })* + ),* + } + + #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, + RustcEncodable, RustcDecodable)] + pub struct DepNode { + pub kind: DepKind, + pub hash: Fingerprint, + } + + impl DepNode { + #[allow(unreachable_code, non_snake_case)] + pub fn new(tcx: TyCtxt, dep: DepConstructor) -> DepNode { + match dep { + $( + DepConstructor :: $variant $(( $($tuple_arg),* ))* + $({ $($struct_arg_name),* })* + => + { + // tuple args + $({ + let tupled_args = ( $($tuple_arg,)* ); + let hash = DepNodeParams::to_fingerprint(&tupled_args, + tcx); + return DepNode { + kind: DepKind::$variant, + hash + }; + })* + + // struct args + $({ + let tupled_args = ( $($struct_arg_name,)* ); + let hash = DepNodeParams::to_fingerprint(&tupled_args, + tcx); + return DepNode { + kind: DepKind::$variant, + hash + }; + })* + + DepNode { + kind: DepKind::$variant, + hash: Fingerprint::zero(), + } + } + )* + } + } + + /// Construct a DepNode from the given DepKind and DefPathHash. This + /// method will assert that the given DepKind actually requires a + /// single DefId/DefPathHash parameter. + #[inline] + pub fn from_def_path_hash(kind: DepKind, + def_path_hash: DefPathHash) + -> DepNode { + assert!(kind.can_reconstruct_query_key() && kind.has_params()); + DepNode { + kind, + hash: def_path_hash.0, + } + } + + /// Create a new, parameterless DepNode. This method will assert + /// that the DepNode corresponding to the given DepKind actually + /// does not require any parameters. + #[inline] + pub fn new_no_params(kind: DepKind) -> DepNode { + assert!(!kind.has_params()); + DepNode { + kind, + hash: Fingerprint::zero(), + } + } + + /// Extract the DefId corresponding to this DepNode. This will work + /// if two conditions are met: + /// + /// 1. The Fingerprint of the DepNode actually is a DefPathHash, and + /// 2. the item that the DefPath refers to exists in the current tcx. + /// + /// Condition (1) is determined by the DepKind variant of the + /// DepNode. Condition (2) might not be fulfilled if a DepNode + /// refers to something from the previous compilation session that + /// has been removed. + #[inline] + pub fn extract_def_id(&self, tcx: TyCtxt) -> Option { + if self.kind.can_reconstruct_query_key() { + let def_path_hash = DefPathHash(self.hash); + tcx.def_path_hash_to_def_id + .as_ref() + .unwrap() + .get(&def_path_hash) + .cloned() + } else { + None + } + } + + /// Used in testing + pub fn from_label_string(label: &str, + def_path_hash: DefPathHash) + -> Result { + let kind = match label { + $( + stringify!($variant) => DepKind::$variant, + )* + _ => return Err(()), + }; + + if !kind.can_reconstruct_query_key() { + return Err(()); + } + + if kind.has_params() { + Ok(def_path_hash.to_dep_node(kind)) + } else { + Ok(DepNode::new_no_params(kind)) + } + } + } + ); +} + +impl DefPathHash { + #[inline] + pub fn to_dep_node(self, kind: DepKind) -> DepNode { + DepNode::from_def_path_hash(kind, self) + } +} + +impl DefId { + #[inline] + pub fn to_dep_node(self, tcx: TyCtxt, kind: DepKind) -> DepNode { + DepNode::from_def_path_hash(kind, tcx.def_path_hash(self)) + } +} + +define_dep_nodes!( + // Represents the `Krate` as a whole (the `hir::Krate` value) (as + // distinct from the krate module). This is basically a hash of + // the entire krate, so if you read from `Krate` (e.g., by calling + // `tcx.hir.krate()`), we will have to assume that any change + // means that you need to be recompiled. This is because the + // `Krate` value gives you access to all other items. To avoid + // this fate, do not call `tcx.hir.krate()`; instead, prefer + // wrappers like `tcx.visit_all_items_in_krate()`. If there is no + // suitable wrapper, you can use `tcx.dep_graph.ignore()` to gain + // access to the krate, but you must remember to add suitable + // edges yourself for the individual items that you read. Krate, - /// Represents the HIR node with the given node-id - Hir(D), + // Represents the HIR node with the given node-id + Hir(DefId), - /// Represents the body of a function or method. The def-id is that of the - /// function/method. - HirBody(D), + // Represents the body of a function or method. The def-id is that of the + // function/method. + HirBody(DefId), - /// Represents the metadata for a given HIR node, typically found - /// in an extern crate. - MetaData(D), + // Represents the metadata for a given HIR node, typically found + // in an extern crate. + MetaData(DefId), - /// Represents some artifact that we save to disk. Note that these - /// do not have a def-id as part of their identifier. + // Represents some artifact that we save to disk. Note that these + // do not have a def-id as part of their identifier. WorkProduct(WorkProductId), // Represents different phases in the compiler. - RegionMaps(D), + RegionMaps(DefId), Coherence, Resolve, - CoherenceCheckTrait(D), - CoherenceCheckImpl(D), - CoherenceOverlapCheck(D), - CoherenceOverlapCheckSpecial(D), + CoherenceCheckTrait(DefId), + CoherenceCheckImpl(DefId), + CoherenceOverlapCheck(DefId), + CoherenceOverlapCheckSpecial(DefId), Variance, PrivacyAccessLevels(CrateNum), // Represents the MIR for a fn; also used as the task node for // things read/modify that MIR. MirKrate, - Mir(D), - MirShim(Vec), + Mir(DefId), + MirShim(DefIdList), BorrowCheckKrate, - BorrowCheck(D), - RvalueCheck(D), + BorrowCheck(DefId), + RvalueCheck(DefId), Reachability, MirKeys, LateLintCheck, - TransCrateItem(D), + TransCrateItem(DefId), TransWriteMetadata, CrateVariances, @@ -89,38 +290,38 @@ pub enum DepNode { // nodes. Often we map multiple tables to the same node if there // is no point in distinguishing them (e.g., both the type and // predicates for an item wind up in `ItemSignature`). - AssociatedItems(D), - ItemSignature(D), - ItemVarianceConstraints(D), - ItemVariances(D), - IsForeignItem(D), - TypeParamPredicates((D, D)), - SizedConstraint(D), - DtorckConstraint(D), - AdtDestructor(D), - AssociatedItemDefIds(D), - InherentImpls(D), + AssociatedItems(DefId), + ItemSignature(DefId), + ItemVarianceConstraints(DefId), + ItemVariances(DefId), + IsForeignItem(DefId), + TypeParamPredicates { item_id: DefId, param_id: DefId }, + SizedConstraint(DefId), + DtorckConstraint(DefId), + AdtDestructor(DefId), + AssociatedItemDefIds(DefId), + InherentImpls(DefId), TypeckBodiesKrate, - TypeckTables(D), - UsedTraitImports(D), - ConstEval(D), - SymbolName(D), - SpecializationGraph(D), - ObjectSafety(D), - IsCopy(D), - IsSized(D), - IsFreeze(D), - NeedsDrop(D), - Layout(D), + TypeckTables(DefId), + UsedTraitImports(DefId), + ConstEval(DefId), + SymbolName(DefId), + SpecializationGraph(DefId), + ObjectSafety(DefId), + IsCopy(DefId), + IsSized(DefId), + IsFreeze(DefId), + NeedsDrop(DefId), + Layout(DefId), - /// The set of impls for a given trait. Ultimately, it would be - /// nice to get more fine-grained here (e.g., to include a - /// simplified type), but we can't do that until we restructure the - /// HIR to distinguish the *header* of an impl from its body. This - /// is because changes to the header may change the self-type of - /// the impl and hence would require us to be more conservative - /// than changes in the impl body. - TraitImpls(D), + // The set of impls for a given trait. Ultimately, it would be + // nice to get more fine-grained here (e.g., to include a + // simplified type), but we can't do that until we restructure the + // HIR to distinguish the *header* of an impl from its body. This + // is because changes to the header may change the self-type of + // the impl and hence would require us to be more conservative + // than changes in the impl body. + TraitImpls(DefId), AllLocalTraitImpls, @@ -129,184 +330,80 @@ pub enum DepNode { // Otherwise the write into the map would be incorrectly // attributed to the first task that happened to fill the cache, // which would yield an overly conservative dep-graph. - TraitItems(D), - ReprHints(D), + TraitItems(DefId), + ReprHints(DefId), - /// Trait selection cache is a little funny. Given a trait - /// reference like `Foo: SomeTrait`, there could be - /// arbitrarily many def-ids to map on in there (e.g., `Foo`, - /// `SomeTrait`, `Bar`). We could have a vector of them, but it - /// requires heap-allocation, and trait sel in general can be a - /// surprisingly hot path. So instead we pick two def-ids: the - /// trait def-id, and the first def-id in the input types. If there - /// is no def-id in the input types, then we use the trait def-id - /// again. So for example: - /// - /// - `i32: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Clone }` - /// - `u32: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Clone }` - /// - `Clone: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Clone }` - /// - `Vec: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Vec }` - /// - `String: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: String }` - /// - `Foo: Trait` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }` - /// - `Foo: Trait` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }` - /// - `(Foo, Bar): Trait` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }` - /// - `i32: Trait` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }` - /// - /// You can see that we map many trait refs to the same - /// trait-select node. This is not a problem, it just means - /// imprecision in our dep-graph tracking. The important thing is - /// that for any given trait-ref, we always map to the **same** - /// trait-select node. - TraitSelect { trait_def_id: D, input_def_id: D }, + // Trait selection cache is a little funny. Given a trait + // reference like `Foo: SomeTrait`, there could be + // arbitrarily many def-ids to map on in there (e.g., `Foo`, + // `SomeTrait`, `Bar`). We could have a vector of them, but it + // requires heap-allocation, and trait sel in general can be a + // surprisingly hot path. So instead we pick two def-ids: the + // trait def-id, and the first def-id in the input types. If there + // is no def-id in the input types, then we use the trait def-id + // again. So for example: + // + // - `i32: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Clone }` + // - `u32: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Clone }` + // - `Clone: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Clone }` + // - `Vec: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Vec }` + // - `String: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: String }` + // - `Foo: Trait` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }` + // - `Foo: Trait` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }` + // - `(Foo, Bar): Trait` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }` + // - `i32: Trait` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }` + // + // You can see that we map many trait refs to the same + // trait-select node. This is not a problem, it just means + // imprecision in our dep-graph tracking. The important thing is + // that for any given trait-ref, we always map to the **same** + // trait-select node. + TraitSelect { trait_def_id: DefId, input_def_id: DefId }, - /// For proj. cache, we just keep a list of all def-ids, since it is - /// not a hotspot. - ProjectionCache { def_ids: Vec }, + // For proj. cache, we just keep a list of all def-ids, since it is + // not a hotspot. + ProjectionCache { def_ids: DefIdList }, - ParamEnv(D), - DescribeDef(D), - DefSpan(D), - Stability(D), - Deprecation(D), - ItemBodyNestedBodies(D), - ConstIsRvaluePromotableToStatic(D), - ImplParent(D), - TraitOfItem(D), - IsExportedSymbol(D), - IsMirAvailable(D), - ItemAttrs(D), - FnArgNames(D), + ParamEnv(DefId), + DescribeDef(DefId), + DefSpan(DefId), + Stability(DefId), + Deprecation(DefId), + ItemBodyNestedBodies(DefId), + ConstIsRvaluePromotableToStatic(DefId), + ImplParent(DefId), + TraitOfItem(DefId), + IsExportedSymbol(DefId), + IsMirAvailable(DefId), + ItemAttrs(DefId), + FnArgNames(DefId) +); + +trait DepNodeParams<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> { + const CAN_RECONSTRUCT_QUERY_KEY: bool; + fn to_fingerprint(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Fingerprint; } -impl DepNode { - /// Used in testing - pub fn from_label_string(label: &str, data: D) -> Result, ()> { - macro_rules! check { - ($($name:ident,)*) => { - match label { - $(stringify!($name) => Ok(DepNode::$name(data)),)* - _ => Err(()) - } - } - } +impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a, T> DepNodeParams<'a, 'gcx, 'tcx> for T + where T: HashStable> +{ + default const CAN_RECONSTRUCT_QUERY_KEY: bool = false; - if label == "Krate" { - // special case - return Ok(DepNode::Krate); - } + default fn to_fingerprint(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Fingerprint { + let mut hcx = StableHashingContext::new(tcx); + let mut hasher = StableHasher::new(); - check! { - BorrowCheck, - Hir, - HirBody, - TransCrateItem, - AssociatedItems, - ItemSignature, - ItemVariances, - IsForeignItem, - AssociatedItemDefIds, - InherentImpls, - TypeckTables, - UsedTraitImports, - TraitImpls, - ReprHints, - } + self.hash_stable(&mut hcx, &mut hasher); + + hasher.finish() } +} - pub fn map_def(&self, mut op: OP) -> Option> - where OP: FnMut(&D) -> Option, E: Clone + Debug - { - use self::DepNode::*; +impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for (DefId,) { + const CAN_RECONSTRUCT_QUERY_KEY: bool = true; - match *self { - Krate => Some(Krate), - BorrowCheckKrate => Some(BorrowCheckKrate), - MirKrate => Some(MirKrate), - TypeckBodiesKrate => Some(TypeckBodiesKrate), - Coherence => Some(Coherence), - CrateVariances => Some(CrateVariances), - Resolve => Some(Resolve), - Variance => Some(Variance), - PrivacyAccessLevels(k) => Some(PrivacyAccessLevels(k)), - Reachability => Some(Reachability), - MirKeys => Some(MirKeys), - LateLintCheck => Some(LateLintCheck), - TransWriteMetadata => Some(TransWriteMetadata), - - // work product names do not need to be mapped, because - // they are always absolute. - WorkProduct(ref id) => Some(WorkProduct(id.clone())), - - IsCopy(ref d) => op(d).map(IsCopy), - IsSized(ref d) => op(d).map(IsSized), - IsFreeze(ref d) => op(d).map(IsFreeze), - NeedsDrop(ref d) => op(d).map(NeedsDrop), - Layout(ref d) => op(d).map(Layout), - Hir(ref d) => op(d).map(Hir), - HirBody(ref d) => op(d).map(HirBody), - MetaData(ref d) => op(d).map(MetaData), - CoherenceCheckTrait(ref d) => op(d).map(CoherenceCheckTrait), - CoherenceCheckImpl(ref d) => op(d).map(CoherenceCheckImpl), - CoherenceOverlapCheck(ref d) => op(d).map(CoherenceOverlapCheck), - CoherenceOverlapCheckSpecial(ref d) => op(d).map(CoherenceOverlapCheckSpecial), - Mir(ref d) => op(d).map(Mir), - MirShim(ref def_ids) => { - let def_ids: Option> = def_ids.iter().map(op).collect(); - def_ids.map(MirShim) - } - BorrowCheck(ref d) => op(d).map(BorrowCheck), - RegionMaps(ref d) => op(d).map(RegionMaps), - RvalueCheck(ref d) => op(d).map(RvalueCheck), - TransCrateItem(ref d) => op(d).map(TransCrateItem), - AssociatedItems(ref d) => op(d).map(AssociatedItems), - ItemSignature(ref d) => op(d).map(ItemSignature), - ItemVariances(ref d) => op(d).map(ItemVariances), - ItemVarianceConstraints(ref d) => op(d).map(ItemVarianceConstraints), - IsForeignItem(ref d) => op(d).map(IsForeignItem), - TypeParamPredicates((ref item, ref param)) => { - Some(TypeParamPredicates((try_opt!(op(item)), try_opt!(op(param))))) - } - SizedConstraint(ref d) => op(d).map(SizedConstraint), - DtorckConstraint(ref d) => op(d).map(DtorckConstraint), - AdtDestructor(ref d) => op(d).map(AdtDestructor), - AssociatedItemDefIds(ref d) => op(d).map(AssociatedItemDefIds), - InherentImpls(ref d) => op(d).map(InherentImpls), - TypeckTables(ref d) => op(d).map(TypeckTables), - UsedTraitImports(ref d) => op(d).map(UsedTraitImports), - ConstEval(ref d) => op(d).map(ConstEval), - SymbolName(ref d) => op(d).map(SymbolName), - SpecializationGraph(ref d) => op(d).map(SpecializationGraph), - ObjectSafety(ref d) => op(d).map(ObjectSafety), - TraitImpls(ref d) => op(d).map(TraitImpls), - AllLocalTraitImpls => Some(AllLocalTraitImpls), - TraitItems(ref d) => op(d).map(TraitItems), - ReprHints(ref d) => op(d).map(ReprHints), - TraitSelect { ref trait_def_id, ref input_def_id } => { - op(trait_def_id).and_then(|trait_def_id| { - op(input_def_id).and_then(|input_def_id| { - Some(TraitSelect { trait_def_id: trait_def_id, - input_def_id: input_def_id }) - }) - }) - } - ProjectionCache { ref def_ids } => { - let def_ids: Option> = def_ids.iter().map(op).collect(); - def_ids.map(|d| ProjectionCache { def_ids: d }) - } - ParamEnv(ref d) => op(d).map(ParamEnv), - DescribeDef(ref d) => op(d).map(DescribeDef), - DefSpan(ref d) => op(d).map(DefSpan), - Stability(ref d) => op(d).map(Stability), - Deprecation(ref d) => op(d).map(Deprecation), - ItemAttrs(ref d) => op(d).map(ItemAttrs), - FnArgNames(ref d) => op(d).map(FnArgNames), - ImplParent(ref d) => op(d).map(ImplParent), - TraitOfItem(ref d) => op(d).map(TraitOfItem), - IsExportedSymbol(ref d) => op(d).map(IsExportedSymbol), - ItemBodyNestedBodies(ref d) => op(d).map(ItemBodyNestedBodies), - ConstIsRvaluePromotableToStatic(ref d) => op(d).map(ConstIsRvaluePromotableToStatic), - IsMirAvailable(ref d) => op(d).map(IsMirAvailable), - } + fn to_fingerprint(&self, tcx: TyCtxt) -> Fingerprint { + tcx.def_path_hash(self.0).0 } } @@ -315,14 +412,38 @@ impl DepNode { /// some independent path or string that persists between runs without /// the need to be mapped or unmapped. (This ensures we can serialize /// them even in the absence of a tcx.) -#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] -pub struct WorkProductId(pub Fingerprint); +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, + RustcEncodable, RustcDecodable)] +pub struct WorkProductId { + hash: Fingerprint +} impl WorkProductId { pub fn from_cgu_name(cgu_name: &str) -> WorkProductId { let mut hasher = StableHasher::new(); cgu_name.len().hash(&mut hasher); cgu_name.hash(&mut hasher); - WorkProductId(hasher.finish()) + WorkProductId { + hash: hasher.finish() + } + } + + pub fn from_fingerprint(fingerprint: Fingerprint) -> WorkProductId { + WorkProductId { + hash: fingerprint + } + } + + pub fn to_dep_node(self) -> DepNode { + DepNode { + kind: DepKind::WorkProduct, + hash: self.hash, + } } } + +impl_stable_hash_for!(struct ::dep_graph::WorkProductId { + hash +}); + +type DefIdList = Vec; diff --git a/src/librustc/dep_graph/dep_tracking_map.rs b/src/librustc/dep_graph/dep_tracking_map.rs index 7a246c814d3e..43f8d6b938da 100644 --- a/src/librustc/dep_graph/dep_tracking_map.rs +++ b/src/librustc/dep_graph/dep_tracking_map.rs @@ -8,12 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use hir::def_id::DefId; use rustc_data_structures::fx::FxHashMap; use std::cell::RefCell; -use std::ops::Index; use std::hash::Hash; use std::marker::PhantomData; +use ty::TyCtxt; use util::common::MemoizationMap; use super::{DepNode, DepGraph}; @@ -30,7 +29,7 @@ pub struct DepTrackingMap { pub trait DepTrackingMapConfig { type Key: Eq + Hash + Clone; type Value: Clone; - fn to_dep_node(key: &Self::Key) -> DepNode; + fn to_dep_node(tcx: TyCtxt, key: &Self::Key) -> DepNode; } impl DepTrackingMap { @@ -44,18 +43,18 @@ impl DepTrackingMap { /// Registers a (synthetic) read from the key `k`. Usually this /// is invoked automatically by `get`. - fn read(&self, k: &M::Key) { - let dep_node = M::to_dep_node(k); + fn read(&self, tcx: TyCtxt, k: &M::Key) { + let dep_node = M::to_dep_node(tcx, k); self.graph.read(dep_node); } - pub fn get(&self, k: &M::Key) -> Option<&M::Value> { - self.read(k); + pub fn get(&self, tcx: TyCtxt, k: &M::Key) -> Option<&M::Value> { + self.read(tcx, k); self.map.get(k) } - pub fn contains_key(&self, k: &M::Key) -> bool { - self.read(k); + pub fn contains_key(&self, tcx: TyCtxt, k: &M::Key) -> bool { + self.read(tcx, k); self.map.contains_key(k) } @@ -99,32 +98,22 @@ impl MemoizationMap for RefCell> { /// The key is the line marked `(*)`: the closure implicitly /// accesses the body of the item `item`, so we register a read /// from `Hir(item_def_id)`. - fn memoize(&self, key: M::Key, op: OP) -> M::Value + fn memoize(&self, tcx: TyCtxt, key: M::Key, op: OP) -> M::Value where OP: FnOnce() -> M::Value { let graph; { let this = self.borrow(); if let Some(result) = this.map.get(&key) { - this.read(&key); + this.read(tcx, &key); return result.clone(); } graph = this.graph.clone(); } - let _task = graph.in_task(M::to_dep_node(&key)); + let _task = graph.in_task(M::to_dep_node(tcx, &key)); let result = op(); self.borrow_mut().map.insert(key, result.clone()); result } } - -impl<'k, M: DepTrackingMapConfig> Index<&'k M::Key> for DepTrackingMap { - type Output = M::Value; - - #[inline] - fn index(&self, k: &'k M::Key) -> &M::Value { - self.get(k).unwrap() - } -} - diff --git a/src/librustc/dep_graph/edges.rs b/src/librustc/dep_graph/edges.rs index 5dbabcc92304..a323e44d0d42 100644 --- a/src/librustc/dep_graph/edges.rs +++ b/src/librustc/dep_graph/edges.rs @@ -9,13 +9,11 @@ // except according to those terms. use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use std::fmt::Debug; -use std::hash::Hash; use super::{DepGraphQuery, DepNode}; -pub struct DepGraphEdges { - nodes: Vec>, - indices: FxHashMap, IdIndex>, +pub struct DepGraphEdges { + nodes: Vec, + indices: FxHashMap, edges: FxHashSet<(IdIndex, IdIndex)>, open_nodes: Vec, } @@ -42,8 +40,8 @@ enum OpenNode { Ignore, } -impl DepGraphEdges { - pub fn new() -> DepGraphEdges { +impl DepGraphEdges { + pub fn new() -> DepGraphEdges { DepGraphEdges { nodes: vec![], indices: FxHashMap(), @@ -52,12 +50,12 @@ impl DepGraphEdges { } } - fn id(&self, index: IdIndex) -> DepNode { + fn id(&self, index: IdIndex) -> DepNode { self.nodes[index.index()].clone() } /// Creates a node for `id` in the graph. - fn make_node(&mut self, id: DepNode) -> IdIndex { + fn make_node(&mut self, id: DepNode) -> IdIndex { if let Some(&i) = self.indices.get(&id) { return i; } @@ -82,7 +80,7 @@ impl DepGraphEdges { assert_eq!(popped_node, OpenNode::Ignore); } - pub fn push_task(&mut self, key: DepNode) { + pub fn push_task(&mut self, key: DepNode) { let top_node = self.current_node(); let new_node = self.make_node(key); @@ -95,7 +93,7 @@ impl DepGraphEdges { } } - pub fn pop_task(&mut self, key: DepNode) { + pub fn pop_task(&mut self, key: DepNode) { let popped_node = self.open_nodes.pop().unwrap(); assert_eq!(OpenNode::Node(self.indices[&key]), popped_node); } @@ -105,7 +103,7 @@ impl DepGraphEdges { /// effect. Note that *reading* from tracked state is harmless if /// you are not in a task; what is bad is *writing* to tracked /// state (and leaking data that you read into a tracked task). - pub fn read(&mut self, v: DepNode) { + pub fn read(&mut self, v: DepNode) { if self.current_node().is_some() { let source = self.make_node(v); self.add_edge_from_current_node(|current| (source, current)) @@ -115,7 +113,7 @@ impl DepGraphEdges { /// Indicates that the current task `C` writes `v` by adding an /// edge from `C` to `v`. If there is no current task, panics. If /// you want to suppress this edge, use `ignore`. - pub fn write(&mut self, v: DepNode) { + pub fn write(&mut self, v: DepNode) { let target = self.make_node(v); self.add_edge_from_current_node(|current| (current, target)) } @@ -159,7 +157,7 @@ impl DepGraphEdges { } } - pub fn query(&self) -> DepGraphQuery { + pub fn query(&self) -> DepGraphQuery { let edges: Vec<_> = self.edges.iter() .map(|&(i, j)| (self.id(i), self.id(j))) .collect(); diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index dc482b0d6ac8..6afd31bfe92d 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use hir::def_id::DefId; use rustc_data_structures::fx::FxHashMap; use session::config::OutputType; use std::cell::{Ref, RefCell}; @@ -57,7 +56,7 @@ impl DepGraph { self.data.thread.is_fully_enabled() } - pub fn query(&self) -> DepGraphQuery { + pub fn query(&self) -> DepGraphQuery { self.data.thread.query() } @@ -65,7 +64,7 @@ impl DepGraph { raii::IgnoreTask::new(&self.data.thread) } - pub fn in_task<'graph>(&'graph self, key: DepNode) -> Option> { + pub fn in_task<'graph>(&'graph self, key: DepNode) -> Option> { raii::DepTask::new(&self.data.thread, key) } @@ -103,14 +102,14 @@ impl DepGraph { /// `arg` parameter. /// /// [README]: README.md - pub fn with_task(&self, key: DepNode, cx: C, arg: A, task: fn(C, A) -> R) -> R + pub fn with_task(&self, key: DepNode, cx: C, arg: A, task: fn(C, A) -> R) -> R where C: DepGraphSafe, A: DepGraphSafe { let _task = self.in_task(key); task(cx, arg) } - pub fn read(&self, v: DepNode) { + pub fn read(&self, v: DepNode) { if self.data.thread.is_enqueue_enabled() { self.data.thread.enqueue(DepMessage::Read(v)); } diff --git a/src/librustc/dep_graph/mod.rs b/src/librustc/dep_graph/mod.rs index 809bed939f54..92b05f6a6558 100644 --- a/src/librustc/dep_graph/mod.rs +++ b/src/librustc/dep_graph/mod.rs @@ -28,3 +28,5 @@ pub use self::query::DepGraphQuery; pub use self::safe::AssertDepGraphSafe; pub use self::safe::DepGraphSafe; pub use self::raii::DepTask; + +pub use self::dep_node::{DepKind, DepConstructor}; diff --git a/src/librustc/dep_graph/query.rs b/src/librustc/dep_graph/query.rs index 4c791f965534..116c527bf46d 100644 --- a/src/librustc/dep_graph/query.rs +++ b/src/librustc/dep_graph/query.rs @@ -10,20 +10,18 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::graph::{Direction, INCOMING, Graph, NodeIndex, OUTGOING}; -use std::fmt::Debug; -use std::hash::Hash; use super::DepNode; -pub struct DepGraphQuery { - pub graph: Graph, ()>, - pub indices: FxHashMap, NodeIndex>, +pub struct DepGraphQuery { + pub graph: Graph, + pub indices: FxHashMap, } -impl DepGraphQuery { - pub fn new(nodes: &[DepNode], - edges: &[(DepNode, DepNode)]) - -> DepGraphQuery { +impl DepGraphQuery { + pub fn new(nodes: &[DepNode], + edges: &[(DepNode, DepNode)]) + -> DepGraphQuery { let mut graph = Graph::new(); let mut indices = FxHashMap(); for node in nodes { @@ -43,18 +41,18 @@ impl DepGraphQuery { } } - pub fn contains_node(&self, node: &DepNode) -> bool { + pub fn contains_node(&self, node: &DepNode) -> bool { self.indices.contains_key(&node) } - pub fn nodes(&self) -> Vec<&DepNode> { + pub fn nodes(&self) -> Vec<&DepNode> { self.graph.all_nodes() .iter() .map(|n| &n.data) .collect() } - pub fn edges(&self) -> Vec<(&DepNode,&DepNode)> { + pub fn edges(&self) -> Vec<(&DepNode,&DepNode)> { self.graph.all_edges() .iter() .map(|edge| (edge.source(), edge.target())) @@ -63,7 +61,7 @@ impl DepGraphQuery { .collect() } - fn reachable_nodes(&self, node: &DepNode, direction: Direction) -> Vec<&DepNode> { + fn reachable_nodes(&self, node: &DepNode, direction: Direction) -> Vec<&DepNode> { if let Some(&index) = self.indices.get(node) { self.graph.depth_traverse(index, direction) .map(|s| self.graph.node_data(s)) @@ -75,17 +73,17 @@ impl DepGraphQuery { /// All nodes reachable from `node`. In other words, things that /// will have to be recomputed if `node` changes. - pub fn transitive_successors(&self, node: &DepNode) -> Vec<&DepNode> { + pub fn transitive_successors(&self, node: &DepNode) -> Vec<&DepNode> { self.reachable_nodes(node, OUTGOING) } /// All nodes that can reach `node`. - pub fn transitive_predecessors(&self, node: &DepNode) -> Vec<&DepNode> { + pub fn transitive_predecessors(&self, node: &DepNode) -> Vec<&DepNode> { self.reachable_nodes(node, INCOMING) } /// Just the outgoing edges from `node`. - pub fn immediate_successors(&self, node: &DepNode) -> Vec<&DepNode> { + pub fn immediate_successors(&self, node: &DepNode) -> Vec<&DepNode> { if let Some(&index) = self.indices.get(&node) { self.graph.successor_nodes(index) .map(|s| self.graph.node_data(s)) diff --git a/src/librustc/dep_graph/raii.rs b/src/librustc/dep_graph/raii.rs index e39797599acf..b45f5de80271 100644 --- a/src/librustc/dep_graph/raii.rs +++ b/src/librustc/dep_graph/raii.rs @@ -8,17 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use hir::def_id::DefId; use super::DepNode; use super::thread::{DepGraphThreadData, DepMessage}; pub struct DepTask<'graph> { data: &'graph DepGraphThreadData, - key: Option>, + key: Option, } impl<'graph> DepTask<'graph> { - pub fn new(data: &'graph DepGraphThreadData, key: DepNode) + pub fn new(data: &'graph DepGraphThreadData, key: DepNode) -> Option> { if data.is_enqueue_enabled() { data.enqueue(DepMessage::PushTask(key.clone())); diff --git a/src/librustc/dep_graph/shadow.rs b/src/librustc/dep_graph/shadow.rs index bedb6ff2771f..8808ea5948da 100644 --- a/src/librustc/dep_graph/shadow.rs +++ b/src/librustc/dep_graph/shadow.rs @@ -26,7 +26,6 @@ //! specify an edge filter to be applied to each edge as it is //! created. See `./README.md` for details. -use hir::def_id::DefId; use std::cell::RefCell; use std::env; @@ -36,7 +35,7 @@ use super::debug::EdgeFilter; pub struct ShadowGraph { // if you push None onto the stack, that corresponds to an Ignore - stack: RefCell>>>, + stack: RefCell>>, forbidden_edge: Option, } @@ -114,8 +113,8 @@ impl ShadowGraph { } fn check_edge(&self, - source: Option>>, - target: Option>>) { + source: Option>, + target: Option>) { assert!(ENABLED); match (source, target) { // cannot happen, one side is always Some(Some(_)) @@ -141,9 +140,9 @@ impl ShadowGraph { // Do a little juggling: we get back a reference to an option at the // top of the stack, convert it to an optional reference. -fn top<'s>(stack: &'s Vec>>) -> Option>> { +fn top<'s>(stack: &'s Vec>) -> Option> { stack.last() - .map(|n: &'s Option>| -> Option<&'s DepNode> { + .map(|n: &'s Option| -> Option<&'s DepNode> { // (*) // (*) type annotation just there to clarify what would // otherwise be some *really* obscure code diff --git a/src/librustc/dep_graph/thread.rs b/src/librustc/dep_graph/thread.rs index d3a940c811b8..ad0abfe26f45 100644 --- a/src/librustc/dep_graph/thread.rs +++ b/src/librustc/dep_graph/thread.rs @@ -18,7 +18,6 @@ //! to accumulate more messages. This way we only ever have two vectors //! allocated (and both have a fairly large capacity). -use hir::def_id::DefId; use rustc_data_structures::veccell::VecCell; use std::sync::mpsc::{self, Sender, Receiver}; use std::thread; @@ -30,10 +29,10 @@ use super::shadow::ShadowGraph; #[derive(Debug)] pub enum DepMessage { - Read(DepNode), - Write(DepNode), - PushTask(DepNode), - PopTask(DepNode), + Read(DepNode), + Write(DepNode), + PushTask(DepNode), + PopTask(DepNode), PushIgnore, PopIgnore, Query, @@ -63,7 +62,7 @@ pub struct DepGraphThreadData { swap_out: Sender>, // where to receive query results - query_in: Receiver>, + query_in: Receiver, } const INITIAL_CAPACITY: usize = 2048; @@ -120,7 +119,7 @@ impl DepGraphThreadData { self.swap_out.send(old_messages).unwrap(); } - pub fn query(&self) -> DepGraphQuery { + pub fn query(&self) -> DepGraphQuery { assert!(self.is_fully_enabled(), "should never query if not fully enabled"); self.enqueue(DepMessage::Query); self.swap(); @@ -151,7 +150,7 @@ impl DepGraphThreadData { /// Definition of the depgraph thread. pub fn main(swap_in: Receiver>, swap_out: Sender>, - query_out: Sender>) { + query_out: Sender) { let mut edges = DepGraphEdges::new(); // the compiler thread always expects a fresh buffer to be diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 176760c255c0..a1875cd46a0c 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -15,7 +15,7 @@ pub use self::def_collector::{DefCollector, MacroInvocationData}; pub use self::definitions::{Definitions, DefKey, DefPath, DefPathData, DisambiguatedDefPathData, DefPathHash}; -use dep_graph::{DepGraph, DepNode}; +use dep_graph::{DepGraph, DepNode, DepKind}; use hir::def_id::{CRATE_DEF_INDEX, DefId, DefIndex, DefIndexAddressSpace}; @@ -235,7 +235,7 @@ impl Forest { } pub fn krate<'hir>(&'hir self) -> &'hir Crate { - self.dep_graph.read(DepNode::Krate); + self.dep_graph.read(DepNode::new_no_params(DepKind::Krate)); &self.krate } } @@ -280,7 +280,7 @@ impl<'hir> Map<'hir> { self.dep_graph.read(self.dep_node(id)); } - fn dep_node(&self, id0: NodeId) -> DepNode { + fn dep_node(&self, id0: NodeId) -> DepNode { let mut id = id0; let mut last_expr = None; loop { @@ -289,14 +289,16 @@ impl<'hir> Map<'hir> { EntryItem(..) | EntryTraitItem(..) | EntryImplItem(..) => { + let def_index = self.definitions.opt_def_index(id).unwrap(); + let def_path_hash = self.definitions.def_path_hash(def_index); + if let Some(last_id) = last_expr { // The body may have a separate dep node if entry.is_body_owner(last_id) { - let def_id = self.local_def_id(id); - return DepNode::HirBody(def_id); + return def_path_hash.to_dep_node(DepKind::HirBody); } } - return DepNode::Hir(self.local_def_id(id)); + return def_path_hash.to_dep_node(DepKind::Hir); } EntryVariant(p, v) => { @@ -305,8 +307,9 @@ impl<'hir> Map<'hir> { if last_expr.is_some() { if v.node.disr_expr.map(|e| e.node_id) == last_expr { // The enum parent holds both Hir and HirBody nodes. - let def_id = self.local_def_id(id); - return DepNode::HirBody(def_id); + let def_index = self.definitions.opt_def_index(id).unwrap(); + let def_path_hash = self.definitions.def_path_hash(def_index); + return def_path_hash.to_dep_node(DepKind::HirBody); } } } @@ -331,7 +334,8 @@ impl<'hir> Map<'hir> { } RootCrate => { - return DepNode::Hir(DefId::local(CRATE_DEF_INDEX)); + let def_path_hash = self.definitions.def_path_hash(CRATE_DEF_INDEX); + return def_path_hash.to_dep_node(DepKind::Hir); } NotPresent => @@ -339,8 +343,11 @@ impl<'hir> Map<'hir> { // present in the map for whatever reason, but // they *do* have def-ids. So if we encounter an // empty hole, check for that case. - return self.opt_local_def_id(id) - .map(|def_id| DepNode::Hir(def_id)) + return self.definitions.opt_def_index(id) + .map(|def_index| { + let def_path_hash = self.definitions.def_path_hash(def_index); + def_path_hash.to_dep_node(DepKind::Hir) + }) .unwrap_or_else(|| { bug!("Walking parents from `{}` \ led to `NotPresent` at `{}`", @@ -497,7 +504,7 @@ impl<'hir> Map<'hir> { } pub fn trait_impls(&self, trait_did: DefId) -> &'hir [NodeId] { - self.dep_graph.read(DepNode::AllLocalTraitImpls); + self.dep_graph.read(DepNode::new_no_params(DepKind::AllLocalTraitImpls)); // NB: intentionally bypass `self.forest.krate()` so that we // do not trigger a read of the whole krate here @@ -505,7 +512,7 @@ impl<'hir> Map<'hir> { } pub fn trait_default_impl(&self, trait_did: DefId) -> Option { - self.dep_graph.read(DepNode::AllLocalTraitImpls); + self.dep_graph.read(DepNode::new_no_params(DepKind::AllLocalTraitImpls)); // NB: intentionally bypass `self.forest.krate()` so that we // do not trigger a read of the whole krate here @@ -520,8 +527,9 @@ impl<'hir> Map<'hir> { /// invoking `krate.attrs` because it registers a tighter /// dep-graph access. pub fn krate_attrs(&self) -> &'hir [ast::Attribute] { - let crate_root_def_id = DefId::local(CRATE_DEF_INDEX); - self.dep_graph.read(DepNode::Hir(crate_root_def_id)); + let def_path_hash = self.definitions.def_path_hash(CRATE_DEF_INDEX); + + self.dep_graph.read(def_path_hash.to_dep_node(DepKind::Hir)); &self.forest.krate.attrs } @@ -754,11 +762,8 @@ impl<'hir> Map<'hir> { } } - pub fn get_inlined_body(&self, def_id: DefId) -> Option<&'hir Body> { - self.inlined_bodies.borrow().get(&def_id).map(|&body| { - self.dep_graph.read(DepNode::MetaData(def_id)); - body - }) + pub fn get_inlined_body_untracked(&self, def_id: DefId) -> Option<&'hir Body> { + self.inlined_bodies.borrow().get(&def_id).cloned() } pub fn intern_inlined_body(&self, def_id: DefId, body: Body) -> &'hir Body { diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 2022565d533b..06506e214ed3 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -25,7 +25,7 @@ //! for all lint attributes. use self::TargetLint::*; -use dep_graph::DepNode; +use dep_graph::{DepNode, DepKind}; use middle::privacy::AccessLevels; use ty::{self, TyCtxt}; use session::{config, early_error, Session}; @@ -1321,7 +1321,7 @@ fn check_lint_name_cmdline(sess: &Session, lint_cx: &LintStore, /// /// Consumes the `lint_store` field of the `Session`. pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { - let _task = tcx.dep_graph.in_task(DepNode::LateLintCheck); + let _task = tcx.dep_graph.in_task(DepNode::new_no_params(DepKind::LateLintCheck)); let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE); diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs index c2fe04534375..16ecc94b9476 100644 --- a/src/librustc/traits/fulfill.rs +++ b/src/librustc/traits/fulfill.rs @@ -183,7 +183,9 @@ impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> { assert!(!infcx.is_in_snapshot()); - if infcx.tcx.fulfilled_predicates.borrow().check_duplicate(&obligation.predicate) { + let tcx = infcx.tcx; + + if tcx.fulfilled_predicates.borrow().check_duplicate(tcx, &obligation.predicate) { debug!("register_predicate_obligation: duplicate"); return } @@ -373,7 +375,8 @@ fn process_predicate<'a, 'gcx, 'tcx>( match obligation.predicate { ty::Predicate::Trait(ref data) => { - if selcx.tcx().fulfilled_predicates.borrow().check_duplicate_trait(data) { + let tcx = selcx.tcx(); + if tcx.fulfilled_predicates.borrow().check_duplicate_trait(tcx, data) { return Ok(Some(vec![])); } @@ -607,22 +610,22 @@ impl<'a, 'gcx, 'tcx> GlobalFulfilledPredicates<'gcx> { } } - pub fn check_duplicate(&self, key: &ty::Predicate<'tcx>) -> bool { + pub fn check_duplicate(&self, tcx: TyCtxt, key: &ty::Predicate<'tcx>) -> bool { if let ty::Predicate::Trait(ref data) = *key { - self.check_duplicate_trait(data) + self.check_duplicate_trait(tcx, data) } else { false } } - pub fn check_duplicate_trait(&self, data: &ty::PolyTraitPredicate<'tcx>) -> bool { + pub fn check_duplicate_trait(&self, tcx: TyCtxt, data: &ty::PolyTraitPredicate<'tcx>) -> bool { // For the global predicate registry, when we find a match, it // may have been computed by some other task, so we want to // add a read from the node corresponding to the predicate // processing to make sure we get the transitive dependencies. if self.set.contains(data) { debug_assert!(data.is_global()); - self.dep_graph.read(data.dep_node()); + self.dep_graph.read(data.dep_node(tcx)); debug!("check_duplicate: global predicate `{:?}` already proved elsewhere", data); true diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 998201ad8d9f..10710d963a01 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -381,7 +381,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { assert!(!obligation.predicate.has_escaping_regions()); let tcx = self.tcx(); - let dep_node = obligation.predicate.dep_node(); + let dep_node = obligation.predicate.dep_node(tcx); let _task = tcx.dep_graph.in_task(dep_node); let stack = self.push_stack(TraitObligationStackList::empty(), obligation); @@ -514,11 +514,13 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { debug!("evaluate_predicate_recursively({:?})", obligation); + let tcx = self.tcx(); + // Check the cache from the tcx of predicates that we know // have been proven elsewhere. This cache only contains // predicates that are global in scope and hence unaffected by // the current environment. - if self.tcx().fulfilled_predicates.borrow().check_duplicate(&obligation.predicate) { + if tcx.fulfilled_predicates.borrow().check_duplicate(tcx, &obligation.predicate) { return EvaluatedToOk; } diff --git a/src/librustc/traits/trans/mod.rs b/src/librustc/traits/trans/mod.rs index 7ad2ef90f0d4..e3b7757ec5b7 100644 --- a/src/librustc/traits/trans/mod.rs +++ b/src/librustc/traits/trans/mod.rs @@ -13,7 +13,8 @@ // seems likely that they should eventually be merged into more // general routines. -use dep_graph::{DepGraph, DepNode, DepTrackingMap, DepTrackingMapConfig}; +use dep_graph::{DepGraph, DepNode, DepTrackingMap, DepTrackingMapConfig, + DepConstructor}; use hir::def_id::DefId; use infer::TransNormalize; use std::cell::RefCell; @@ -40,7 +41,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { // Remove any references to regions; this helps improve caching. let trait_ref = self.erase_regions(&trait_ref); - self.trans_trait_caches.trait_cache.memoize(trait_ref, || { + self.trans_trait_caches.trait_cache.memoize(self, trait_ref, || { debug!("trans::fulfill_obligation(trait_ref={:?}, def_id={:?})", trait_ref, trait_ref.def_id()); @@ -138,7 +139,7 @@ impl<'a, 'gcx> TypeFolder<'gcx, 'gcx> for AssociatedTypeNormalizer<'a, 'gcx> { if !ty.has_projection_types() { ty } else { - self.tcx.trans_trait_caches.project_cache.memoize(ty, || { + self.tcx.trans_trait_caches.project_cache.memoize(self.tcx, ty, || { debug!("AssociatedTypeNormalizer: ty={:?}", ty); self.tcx.normalize_associated_type(&ty) }) @@ -170,8 +171,8 @@ pub struct TraitSelectionCache<'tcx> { impl<'tcx> DepTrackingMapConfig for TraitSelectionCache<'tcx> { type Key = ty::PolyTraitRef<'tcx>; type Value = Vtable<'tcx, ()>; - fn to_dep_node(key: &ty::PolyTraitRef<'tcx>) -> DepNode { - key.to_poly_trait_predicate().dep_node() + fn to_dep_node(tcx: TyCtxt, key: &ty::PolyTraitRef<'tcx>) -> DepNode { + key.to_poly_trait_predicate().dep_node(tcx) } } @@ -184,7 +185,7 @@ pub struct ProjectionCache<'gcx> { impl<'gcx> DepTrackingMapConfig for ProjectionCache<'gcx> { type Key = Ty<'gcx>; type Value = Ty<'gcx>; - fn to_dep_node(key: &Self::Key) -> DepNode { + fn to_dep_node(tcx: TyCtxt, key: &Self::Key) -> DepNode { // Ideally, we'd just put `key` into the dep-node, but we // can't put full types in there. So just collect up all the // def-ids of structs/enums as well as any traits that we @@ -208,7 +209,7 @@ impl<'gcx> DepTrackingMapConfig for ProjectionCache<'gcx> { }) .collect(); - DepNode::ProjectionCache { def_ids: def_ids } + DepNode::new(tcx, DepConstructor::ProjectionCache { def_ids: def_ids }) } } diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index 7dca28df9da3..76103148ec3e 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use dep_graph::DepNode; +use dep_graph::DepConstructor; use hir::def_id::DefId; use ty::{self, Ty, TypeFoldable, Substs}; use util::ppaux; @@ -60,7 +60,8 @@ impl<'tcx> InstanceDef<'tcx> { tcx.get_attrs(self.def_id()) } - pub(crate) fn dep_node(&self) -> DepNode { + pub //(crate) + fn dep_node(&self) -> DepConstructor { // HACK: def-id binning, project-style; someone replace this with // real on-demand. let ty = match self { @@ -69,7 +70,7 @@ impl<'tcx> InstanceDef<'tcx> { _ => None }.into_iter(); - DepNode::MirShim( + DepConstructor::MirShim( Some(self.def_id()).into_iter().chain( ty.flat_map(|t| t.walk()).flat_map(|t| match t.sty { ty::TyAdt(adt_def, _) => Some(adt_def.did), diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs index b5adcc8ed757..162a734aa195 100644 --- a/src/librustc/ty/maps.rs +++ b/src/librustc/ty/maps.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use dep_graph::{DepNode, DepTrackingMapConfig}; +use dep_graph::{DepConstructor, DepNode, DepTrackingMapConfig}; use hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, LOCAL_CRATE}; use hir::def::Def; use hir; @@ -524,10 +524,10 @@ macro_rules! define_maps { type Value = $V; #[allow(unused)] - fn to_dep_node(key: &$K) -> DepNode { - use dep_graph::DepNode::*; + fn to_dep_node(tcx: TyCtxt, key: &$K) -> DepNode { + use dep_graph::DepConstructor::*; - $node(*key) + DepNode::new(tcx, $node(*key)) } } impl<'a, $tcx, 'lcx> queries::$name<$tcx> { @@ -554,7 +554,7 @@ macro_rules! define_maps { span = key.default_span(tcx) } - let _task = tcx.dep_graph.in_task(Self::to_dep_node(&key)); + let _task = tcx.dep_graph.in_task(Self::to_dep_node(tcx, &key)); let result = tcx.cycle_check(span, Query::$name(key), || { let provider = tcx.maps.providers[key.map_crate()].$name; @@ -569,7 +569,7 @@ macro_rules! define_maps { // We register the `read` here, but not in `force`, since // `force` does not give access to the value produced (and thus // we actually don't read it). - tcx.dep_graph.read(Self::to_dep_node(&key)); + tcx.dep_graph.read(Self::to_dep_node(tcx, &key)); Self::try_get_with(tcx, span, key, Clone::clone) } @@ -782,7 +782,7 @@ define_maps! { <'tcx> /// To avoid cycles within the predicates of a single item we compute /// per-type-parameter predicates for resolving `T::AssocTy`. - [] type_param_predicates: TypeParamPredicates((DefId, DefId)) + [] type_param_predicates: type_param_predicates((DefId, DefId)) -> ty::GenericPredicates<'tcx>, [] trait_def: ItemSignature(DefId) -> &'tcx ty::TraitDef, @@ -931,74 +931,81 @@ define_maps! { <'tcx> -> Result<&'tcx Layout, LayoutError<'tcx>>, } -fn coherent_trait_dep_node((_, def_id): (CrateNum, DefId)) -> DepNode { - DepNode::CoherenceCheckTrait(def_id) +fn type_param_predicates((item_id, param_id): (DefId, DefId)) -> DepConstructor { + DepConstructor::TypeParamPredicates { + item_id, + param_id + } } -fn crate_inherent_impls_dep_node(_: CrateNum) -> DepNode { - DepNode::Coherence +fn coherent_trait_dep_node((_, def_id): (CrateNum, DefId)) -> DepConstructor { + DepConstructor::CoherenceCheckTrait(def_id) } -fn reachability_dep_node(_: CrateNum) -> DepNode { - DepNode::Reachability +fn crate_inherent_impls_dep_node(_: CrateNum) -> DepConstructor { + DepConstructor::Coherence } -fn mir_shim_dep_node(instance: ty::InstanceDef) -> DepNode { +fn reachability_dep_node(_: CrateNum) -> DepConstructor { + DepConstructor::Reachability +} + +fn mir_shim_dep_node(instance: ty::InstanceDef) -> DepConstructor { instance.dep_node() } -fn symbol_name_dep_node(instance: ty::Instance) -> DepNode { +fn symbol_name_dep_node(instance: ty::Instance) -> DepConstructor { // symbol_name uses the substs only to traverse them to find the // hash, and that does not create any new dep-nodes. - DepNode::SymbolName(instance.def.def_id()) + DepConstructor::SymbolName(instance.def.def_id()) } -fn typeck_item_bodies_dep_node(_: CrateNum) -> DepNode { - DepNode::TypeckBodiesKrate +fn typeck_item_bodies_dep_node(_: CrateNum) -> DepConstructor { + DepConstructor::TypeckBodiesKrate } -fn const_eval_dep_node((def_id, _): (DefId, &Substs)) -> DepNode { - DepNode::ConstEval(def_id) +fn const_eval_dep_node((def_id, _): (DefId, &Substs)) -> DepConstructor { + DepConstructor::ConstEval(def_id) } -fn mir_keys(_: CrateNum) -> DepNode { - DepNode::MirKeys +fn mir_keys(_: CrateNum) -> DepConstructor { + DepConstructor::MirKeys } -fn crate_variances(_: CrateNum) -> DepNode { - DepNode::CrateVariances +fn crate_variances(_: CrateNum) -> DepConstructor { + DepConstructor::CrateVariances } -fn relevant_trait_impls_for((def_id, _): (DefId, SimplifiedType)) -> DepNode { - DepNode::TraitImpls(def_id) +fn relevant_trait_impls_for((def_id, _): (DefId, SimplifiedType)) -> DepConstructor { + DepConstructor::TraitImpls(def_id) } -fn is_copy_dep_node<'tcx>(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> DepNode { +fn is_copy_dep_node<'tcx>(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> DepConstructor { let def_id = ty::item_path::characteristic_def_id_of_type(key.value) .unwrap_or(DefId::local(CRATE_DEF_INDEX)); - DepNode::IsCopy(def_id) + DepConstructor::IsCopy(def_id) } -fn is_sized_dep_node<'tcx>(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> DepNode { +fn is_sized_dep_node<'tcx>(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> DepConstructor { let def_id = ty::item_path::characteristic_def_id_of_type(key.value) .unwrap_or(DefId::local(CRATE_DEF_INDEX)); - DepNode::IsSized(def_id) + DepConstructor::IsSized(def_id) } -fn is_freeze_dep_node<'tcx>(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> DepNode { +fn is_freeze_dep_node<'tcx>(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> DepConstructor { let def_id = ty::item_path::characteristic_def_id_of_type(key.value) .unwrap_or(DefId::local(CRATE_DEF_INDEX)); - DepNode::IsFreeze(def_id) + DepConstructor::IsFreeze(def_id) } -fn needs_drop_dep_node<'tcx>(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> DepNode { +fn needs_drop_dep_node<'tcx>(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> DepConstructor { let def_id = ty::item_path::characteristic_def_id_of_type(key.value) .unwrap_or(DefId::local(CRATE_DEF_INDEX)); - DepNode::NeedsDrop(def_id) + DepConstructor::NeedsDrop(def_id) } -fn layout_dep_node<'tcx>(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> DepNode { +fn layout_dep_node<'tcx>(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> DepConstructor { let def_id = ty::item_path::characteristic_def_id_of_type(key.value) .unwrap_or(DefId::local(CRATE_DEF_INDEX)); - DepNode::Layout(def_id) + DepConstructor::Layout(def_id) } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index afa2da3d561b..b09ab57cc41a 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -15,7 +15,7 @@ pub use self::IntVarValue::*; pub use self::LvaluePreference::*; pub use self::fold::TypeFoldable; -use dep_graph::DepNode; +use dep_graph::{DepNode, DepConstructor}; use hir::{map as hir_map, FreevarMap, TraitMap}; use hir::def::{Def, CtorKind, ExportMap}; use hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE}; @@ -918,7 +918,7 @@ impl<'tcx> TraitPredicate<'tcx> { } /// Creates the dep-node for selecting/evaluating this trait reference. - fn dep_node(&self) -> DepNode { + fn dep_node(&self, tcx: TyCtxt) -> DepNode { // Extact the trait-def and first def-id from inputs. See the // docs for `DepNode::TraitSelect` for more information. let trait_def_id = self.def_id(); @@ -931,10 +931,10 @@ impl<'tcx> TraitPredicate<'tcx> { }) .next() .unwrap_or(trait_def_id); - DepNode::TraitSelect { + DepNode::new(tcx, DepConstructor::TraitSelect { trait_def_id: trait_def_id, input_def_id: input_def_id - } + }) } pub fn input_types<'a>(&'a self) -> impl DoubleEndedIterator> + 'a { @@ -952,9 +952,9 @@ impl<'tcx> PolyTraitPredicate<'tcx> { self.0.def_id() } - pub fn dep_node(&self) -> DepNode { + pub fn dep_node(&self, tcx: TyCtxt) -> DepNode { // ok to skip binder since depnode does not care about regions - self.0.dep_node() + self.0.dep_node(tcx) } } diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs index 17564671a1e3..40ee3cd28f56 100644 --- a/src/librustc/util/common.rs +++ b/src/librustc/util/common.rs @@ -19,6 +19,8 @@ use std::iter::repeat; use std::path::Path; use std::time::{Duration, Instant}; +use ty::TyCtxt; + // The name of the associated type for `Fn` return types pub const FN_OUTPUT_NAME: &'static str = "Output"; @@ -209,7 +211,7 @@ pub trait MemoizationMap { /// needed in the `op` to ensure that the correct edges are /// added into the dep graph. See the `DepTrackingMap` impl for /// more details! - fn memoize(&self, key: Self::Key, op: OP) -> Self::Value + fn memoize(&self, tcx: TyCtxt, key: Self::Key, op: OP) -> Self::Value where OP: FnOnce() -> Self::Value; } @@ -219,7 +221,7 @@ impl MemoizationMap for RefCell> type Key = K; type Value = V; - fn memoize(&self, key: K, op: OP) -> V + fn memoize(&self, _tcx: TyCtxt, key: K, op: OP) -> V where OP: FnOnce() -> V { let result = self.borrow().get(&key).cloned(); diff --git a/src/librustc_incremental/assert_dep_graph.rs b/src/librustc_incremental/assert_dep_graph.rs index 39fe2188f68d..04192c35ef3a 100644 --- a/src/librustc_incremental/assert_dep_graph.rs +++ b/src/librustc_incremental/assert_dep_graph.rs @@ -44,7 +44,7 @@ //! ``` use graphviz as dot; -use rustc::dep_graph::{DepGraphQuery, DepNode}; +use rustc::dep_graph::{DepGraphQuery, DepNode, DepKind}; use rustc::dep_graph::debug::{DepNodeFilter, EdgeFilter}; use rustc::hir::def_id::DefId; use rustc::ty::TyCtxt; @@ -95,8 +95,8 @@ pub fn assert_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { check_paths(tcx, &if_this_changed, &then_this_would_need); } -type Sources = Vec<(Span, DefId, DepNode)>; -type Targets = Vec<(Span, ast::Name, ast::NodeId, DepNode)>; +type Sources = Vec<(Span, DefId, DepNode)>; +type Targets = Vec<(Span, ast::Name, ast::NodeId, DepNode)>; struct IfThisChanged<'a, 'tcx:'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, @@ -121,13 +121,14 @@ impl<'a, 'tcx> IfThisChanged<'a, 'tcx> { fn process_attrs(&mut self, node_id: ast::NodeId, attrs: &[ast::Attribute]) { let def_id = self.tcx.hir.local_def_id(node_id); + let def_path_hash = self.tcx.def_path_hash(def_id); for attr in attrs { if attr.check_name(ATTR_IF_THIS_CHANGED) { let dep_node_interned = self.argument(attr); let dep_node = match dep_node_interned { - None => DepNode::Hir(def_id), + None => def_path_hash.to_dep_node(DepKind::Hir), Some(n) => { - match DepNode::from_label_string(&n.as_str(), def_id) { + match DepNode::from_label_string(&n.as_str(), def_path_hash) { Ok(n) => n, Err(()) => { self.tcx.sess.span_fatal( @@ -142,7 +143,7 @@ impl<'a, 'tcx> IfThisChanged<'a, 'tcx> { let dep_node_interned = self.argument(attr); let dep_node = match dep_node_interned { Some(n) => { - match DepNode::from_label_string(&n.as_str(), def_id) { + match DepNode::from_label_string(&n.as_str(), def_path_hash) { Ok(n) => n, Err(()) => { self.tcx.sess.span_fatal( @@ -263,34 +264,34 @@ fn dump_graph(tcx: TyCtxt) { } } -pub struct GraphvizDepGraph<'q>(FxHashSet<&'q DepNode>, - Vec<(&'q DepNode, &'q DepNode)>); +pub struct GraphvizDepGraph<'q>(FxHashSet<&'q DepNode>, + Vec<(&'q DepNode, &'q DepNode)>); impl<'a, 'tcx, 'q> dot::GraphWalk<'a> for GraphvizDepGraph<'q> { - type Node = &'q DepNode; - type Edge = (&'q DepNode, &'q DepNode); - fn nodes(&self) -> dot::Nodes<&'q DepNode> { + type Node = &'q DepNode; + type Edge = (&'q DepNode, &'q DepNode); + fn nodes(&self) -> dot::Nodes<&'q DepNode> { let nodes: Vec<_> = self.0.iter().cloned().collect(); nodes.into_cow() } - fn edges(&self) -> dot::Edges<(&'q DepNode, &'q DepNode)> { + fn edges(&self) -> dot::Edges<(&'q DepNode, &'q DepNode)> { self.1[..].into_cow() } - fn source(&self, edge: &(&'q DepNode, &'q DepNode)) -> &'q DepNode { + fn source(&self, edge: &(&'q DepNode, &'q DepNode)) -> &'q DepNode { edge.0 } - fn target(&self, edge: &(&'q DepNode, &'q DepNode)) -> &'q DepNode { + fn target(&self, edge: &(&'q DepNode, &'q DepNode)) -> &'q DepNode { edge.1 } } impl<'a, 'tcx, 'q> dot::Labeller<'a> for GraphvizDepGraph<'q> { - type Node = &'q DepNode; - type Edge = (&'q DepNode, &'q DepNode); + type Node = &'q DepNode; + type Edge = (&'q DepNode, &'q DepNode); fn graph_id(&self) -> dot::Id { dot::Id::new("DependencyGraph").unwrap() } - fn node_id(&self, n: &&'q DepNode) -> dot::Id { + fn node_id(&self, n: &&'q DepNode) -> dot::Id { let s: String = format!("{:?}", n).chars() .map(|c| if c == '_' || c.is_alphanumeric() { c } else { '_' }) @@ -298,7 +299,7 @@ impl<'a, 'tcx, 'q> dot::Labeller<'a> for GraphvizDepGraph<'q> { debug!("n={:?} s={:?}", n, s); dot::Id::new(s).unwrap() } - fn node_label(&self, n: &&'q DepNode) -> dot::LabelText { + fn node_label(&self, n: &&'q DepNode) -> dot::LabelText { dot::LabelText::label(format!("{:?}", n)) } } @@ -306,8 +307,8 @@ impl<'a, 'tcx, 'q> dot::Labeller<'a> for GraphvizDepGraph<'q> { // Given an optional filter like `"x,y,z"`, returns either `None` (no // filter) or the set of nodes whose labels contain all of those // substrings. -fn node_set<'q>(query: &'q DepGraphQuery, filter: &DepNodeFilter) - -> Option>> +fn node_set<'q>(query: &'q DepGraphQuery, filter: &DepNodeFilter) + -> Option> { debug!("node_set(filter={:?})", filter); @@ -318,10 +319,10 @@ fn node_set<'q>(query: &'q DepGraphQuery, filter: &DepNodeFilter) Some(query.nodes().into_iter().filter(|n| filter.test(n)).collect()) } -fn filter_nodes<'q>(query: &'q DepGraphQuery, - sources: &Option>>, - targets: &Option>>) - -> FxHashSet<&'q DepNode> +fn filter_nodes<'q>(query: &'q DepGraphQuery, + sources: &Option>, + targets: &Option>) + -> FxHashSet<&'q DepNode> { if let &Some(ref sources) = sources { if let &Some(ref targets) = targets { @@ -336,10 +337,10 @@ fn filter_nodes<'q>(query: &'q DepGraphQuery, } } -fn walk_nodes<'q>(query: &'q DepGraphQuery, - starts: &FxHashSet<&'q DepNode>, +fn walk_nodes<'q>(query: &'q DepGraphQuery, + starts: &FxHashSet<&'q DepNode>, direction: Direction) - -> FxHashSet<&'q DepNode> + -> FxHashSet<&'q DepNode> { let mut set = FxHashSet(); for &start in starts { @@ -360,10 +361,10 @@ fn walk_nodes<'q>(query: &'q DepGraphQuery, set } -fn walk_between<'q>(query: &'q DepGraphQuery, - sources: &FxHashSet<&'q DepNode>, - targets: &FxHashSet<&'q DepNode>) - -> FxHashSet<&'q DepNode> +fn walk_between<'q>(query: &'q DepGraphQuery, + sources: &FxHashSet<&'q DepNode>, + targets: &FxHashSet<&'q DepNode>) + -> FxHashSet<&'q DepNode> { // This is a bit tricky. We want to include a node only if it is: // (a) reachable from a source and (b) will reach a target. And we @@ -391,7 +392,7 @@ fn walk_between<'q>(query: &'q DepGraphQuery, }) .collect(); - fn recurse(query: &DepGraphQuery, + fn recurse(query: &DepGraphQuery, node_states: &mut [State], node: NodeIndex) -> bool @@ -428,9 +429,9 @@ fn walk_between<'q>(query: &'q DepGraphQuery, } } -fn filter_edges<'q>(query: &'q DepGraphQuery, - nodes: &FxHashSet<&'q DepNode>) - -> Vec<(&'q DepNode, &'q DepNode)> +fn filter_edges<'q>(query: &'q DepGraphQuery, + nodes: &FxHashSet<&'q DepNode>) + -> Vec<(&'q DepNode, &'q DepNode)> { query.edges() .into_iter() diff --git a/src/librustc_incremental/calculate_svh/mod.rs b/src/librustc_incremental/calculate_svh/mod.rs index 7831ae3092f4..f30a0f553b98 100644 --- a/src/librustc_incremental/calculate_svh/mod.rs +++ b/src/librustc_incremental/calculate_svh/mod.rs @@ -29,7 +29,7 @@ use std::cell::RefCell; use std::hash::Hash; -use rustc::dep_graph::DepNode; +use rustc::dep_graph::{DepNode, DepKind}; use rustc::hir; use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId}; use rustc::hir::map::DefPathHash; @@ -44,7 +44,7 @@ use rustc_data_structures::accumulate_vec::AccumulateVec; pub type IchHasher = StableHasher; pub struct IncrementalHashesMap { - hashes: FxHashMap, Fingerprint>, + hashes: FxHashMap, // These are the metadata hashes for the current crate as they were stored // during the last compilation session. They are only loaded if @@ -62,16 +62,16 @@ impl IncrementalHashesMap { } } - pub fn get(&self, k: &DepNode) -> Option<&Fingerprint> { + pub fn get(&self, k: &DepNode) -> Option<&Fingerprint> { self.hashes.get(k) } - pub fn insert(&mut self, k: DepNode, v: Fingerprint) -> Option { - self.hashes.insert(k, v) + pub fn insert(&mut self, k: DepNode, v: Fingerprint) { + assert!(self.hashes.insert(k, v).is_none()); } pub fn iter<'a>(&'a self) - -> ::std::collections::hash_map::Iter<'a, DepNode, Fingerprint> { + -> ::std::collections::hash_map::Iter<'a, DepNode, Fingerprint> { self.hashes.iter() } @@ -80,10 +80,10 @@ impl IncrementalHashesMap { } } -impl<'a> ::std::ops::Index<&'a DepNode> for IncrementalHashesMap { +impl<'a> ::std::ops::Index<&'a DepNode> for IncrementalHashesMap { type Output = Fingerprint; - fn index(&self, index: &'a DepNode) -> &Fingerprint { + fn index(&self, index: &'a DepNode) -> &Fingerprint { match self.hashes.get(index) { Some(fingerprint) => fingerprint, None => { @@ -100,7 +100,7 @@ struct ComputeItemHashesVisitor<'a, 'tcx: 'a> { impl<'a, 'tcx: 'a> ComputeItemHashesVisitor<'a, 'tcx> { fn compute_and_store_ich_for_item_like(&mut self, - dep_node: DepNode, + dep_node: DepNode, hash_bodies: bool, item_like: T) where T: HashStable> @@ -143,36 +143,29 @@ impl<'a, 'tcx: 'a> ComputeItemHashesVisitor<'a, 'tcx> { // add each item (in some deterministic order) to the overall // crate hash. { - let hcx = &mut self.hcx; let mut item_hashes: Vec<_> = self.hashes.iter() - .filter_map(|(item_dep_node, &item_hash)| { + .filter_map(|(&item_dep_node, &item_hash)| { // This `match` determines what kinds of nodes // go into the SVH: - match *item_dep_node { - DepNode::Hir(_) | - DepNode::HirBody(_) => { + match item_dep_node.kind { + DepKind::Hir | + DepKind::HirBody => { // We want to incoporate these into the // SVH. } - DepNode::AllLocalTraitImpls => { + DepKind::AllLocalTraitImpls => { // These are already covered by hashing // the HIR. return None } ref other => { - bug!("Found unexpected DepNode during \ + bug!("Found unexpected DepKind during \ SVH computation: {:?}", other) } } - // Convert from a DepNode to a - // DepNode where the u64 is the hash of - // the def-id's def-path: - let item_dep_node = - item_dep_node.map_def(|&did| Some(hcx.def_path_hash(did))) - .unwrap(); Some((item_dep_node, item_hash)) }) .collect(); @@ -183,7 +176,7 @@ impl<'a, 'tcx: 'a> ComputeItemHashesVisitor<'a, 'tcx> { krate.attrs.hash_stable(&mut self.hcx, &mut crate_state); let crate_hash = crate_state.finish(); - self.hashes.insert(DepNode::Krate, crate_hash); + self.hashes.insert(DepNode::new_no_params(DepKind::Krate), crate_hash); debug!("calculate_crate_hash: crate_hash={:?}", crate_hash); } @@ -206,11 +199,11 @@ impl<'a, 'tcx: 'a> ComputeItemHashesVisitor<'a, 'tcx> { body_ids: _, } = *krate; - let def_id = DefId::local(CRATE_DEF_INDEX); - self.compute_and_store_ich_for_item_like(DepNode::Hir(def_id), + let def_path_hash = self.hcx.tcx().hir.definitions().def_path_hash(CRATE_DEF_INDEX); + self.compute_and_store_ich_for_item_like(def_path_hash.to_dep_node(DepKind::Hir), false, (module, (span, attrs))); - self.compute_and_store_ich_for_item_like(DepNode::HirBody(def_id), + self.compute_and_store_ich_for_item_like(def_path_hash.to_dep_node(DepKind::HirBody), true, (module, (span, attrs))); } @@ -255,27 +248,43 @@ impl<'a, 'tcx: 'a> ComputeItemHashesVisitor<'a, 'tcx> { let mut hasher = StableHasher::new(); impls.hash_stable(&mut self.hcx, &mut hasher); - self.hashes.insert(DepNode::AllLocalTraitImpls, hasher.finish()); + self.hashes.insert(DepNode::new_no_params(DepKind::AllLocalTraitImpls), + hasher.finish()); } } impl<'a, 'tcx: 'a> ItemLikeVisitor<'tcx> for ComputeItemHashesVisitor<'a, 'tcx> { fn visit_item(&mut self, item: &'tcx hir::Item) { let def_id = self.hcx.tcx().hir.local_def_id(item.id); - self.compute_and_store_ich_for_item_like(DepNode::Hir(def_id), false, item); - self.compute_and_store_ich_for_item_like(DepNode::HirBody(def_id), true, item); + let def_path_hash = self.hcx.tcx().def_path_hash(def_id); + self.compute_and_store_ich_for_item_like(def_path_hash.to_dep_node(DepKind::Hir), + false, + item); + self.compute_and_store_ich_for_item_like(def_path_hash.to_dep_node(DepKind::HirBody), + true, + item); } fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem) { let def_id = self.hcx.tcx().hir.local_def_id(item.id); - self.compute_and_store_ich_for_item_like(DepNode::Hir(def_id), false, item); - self.compute_and_store_ich_for_item_like(DepNode::HirBody(def_id), true, item); + let def_path_hash = self.hcx.tcx().def_path_hash(def_id); + self.compute_and_store_ich_for_item_like(def_path_hash.to_dep_node(DepKind::Hir), + false, + item); + self.compute_and_store_ich_for_item_like(def_path_hash.to_dep_node(DepKind::HirBody), + true, + item); } fn visit_impl_item(&mut self, item: &'tcx hir::ImplItem) { let def_id = self.hcx.tcx().hir.local_def_id(item.id); - self.compute_and_store_ich_for_item_like(DepNode::Hir(def_id), false, item); - self.compute_and_store_ich_for_item_like(DepNode::HirBody(def_id), true, item); + let def_path_hash = self.hcx.tcx().def_path_hash(def_id); + self.compute_and_store_ich_for_item_like(def_path_hash.to_dep_node(DepKind::Hir), + false, + item); + self.compute_and_store_ich_for_item_like(def_path_hash.to_dep_node(DepKind::HirBody), + true, + item); } } @@ -297,8 +306,13 @@ pub fn compute_incremental_hashes_map<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>) for macro_def in krate.exported_macros.iter() { let def_id = tcx.hir.local_def_id(macro_def.id); - visitor.compute_and_store_ich_for_item_like(DepNode::Hir(def_id), false, macro_def); - visitor.compute_and_store_ich_for_item_like(DepNode::HirBody(def_id), true, macro_def); + let def_path_hash = tcx.def_path_hash(def_id); + visitor.compute_and_store_ich_for_item_like(def_path_hash.to_dep_node(DepKind::Hir), + false, + macro_def); + visitor.compute_and_store_ich_for_item_like(def_path_hash.to_dep_node(DepKind::HirBody), + true, + macro_def); } visitor.compute_and_store_ich_for_trait_impls(krate); diff --git a/src/librustc_incremental/persist/data.rs b/src/librustc_incremental/persist/data.rs index 96b7de94daf6..c3cd9656afe5 100644 --- a/src/librustc_incremental/persist/data.rs +++ b/src/librustc_incremental/persist/data.rs @@ -22,7 +22,7 @@ use rustc_data_structures::indexed_vec::{IndexVec, Idx}; #[derive(Debug, RustcEncodable, RustcDecodable)] pub struct SerializedDepGraph { /// The set of all DepNodes in the graph - pub nodes: IndexVec>, + pub nodes: IndexVec, /// For each DepNode, stores the list of edges originating from that /// DepNode. Encoded as a [start, end) pair indexing into edge_list_data, /// which holds the actual DepNodeIndices of the target nodes. @@ -34,7 +34,7 @@ pub struct SerializedDepGraph { /// These are output nodes that have no incoming edges. We track /// these separately so that when we reload all edges, we don't /// lose track of these nodes. - pub bootstrap_outputs: Vec>, + pub bootstrap_outputs: Vec, /// These are hashes of two things: /// - the HIR nodes in this crate @@ -87,7 +87,7 @@ impl Idx for DepNodeIndex { #[derive(Debug, RustcEncodable, RustcDecodable)] pub struct SerializedHash { /// def-id of thing being hashed - pub dep_node: DepNode, + pub dep_node: DepNode, /// the hash as of previous compilation, computed by code in /// `hash` module diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs index 3a428bd7b8f7..01ec0d685268 100644 --- a/src/librustc_incremental/persist/dirty_clean.rs +++ b/src/librustc_incremental/persist/dirty_clean.rs @@ -41,7 +41,7 @@ //! use super::load::DirtyNodes; -use rustc::dep_graph::{DepGraphQuery, DepNode}; +use rustc::dep_graph::{DepGraphQuery, DepNode, DepKind}; use rustc::hir; use rustc::hir::def_id::DefId; use rustc::hir::itemlikevisit::ItemLikeVisitor; @@ -64,14 +64,10 @@ pub fn check_dirty_clean_annotations<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } let _ignore = tcx.dep_graph.in_ignore(); - let def_path_hash_to_def_id = tcx.def_path_hash_to_def_id.as_ref().unwrap(); - let dirty_inputs: FxHashSet> = + let dirty_inputs: FxHashSet = dirty_inputs.keys() - .filter_map(|dep_node| { - dep_node.map_def(|def_path_hash| { - def_path_hash_to_def_id.get(def_path_hash).cloned() - }) - }) + .filter(|dep_node| dep_node.extract_def_id(tcx).is_some()) + .cloned() .collect(); let query = tcx.dep_graph.query(); @@ -100,18 +96,19 @@ pub fn check_dirty_clean_annotations<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pub struct DirtyCleanVisitor<'a, 'tcx:'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, - query: &'a DepGraphQuery, - dirty_inputs: FxHashSet>, + query: &'a DepGraphQuery, + dirty_inputs: FxHashSet, checked_attrs: FxHashSet, } impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> { - fn dep_node(&self, attr: &Attribute, def_id: DefId) -> DepNode { + fn dep_node(&self, attr: &Attribute, def_id: DefId) -> DepNode { + let def_path_hash = self.tcx.def_path_hash(def_id); for item in attr.meta_item_list().unwrap_or_else(Vec::new) { if item.check_name(LABEL) { let value = expect_associated_value(self.tcx, &item); - match DepNode::from_label_string(&value.as_str(), def_id) { - Ok(def_id) => return def_id, + match DepNode::from_label_string(&value.as_str(), def_path_hash) { + Ok(dep_node) => return dep_node, Err(()) => { self.tcx.sess.span_fatal( item.span, @@ -124,24 +121,30 @@ impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> { self.tcx.sess.span_fatal(attr.span, "no `label` found"); } - fn dep_node_str(&self, dep_node: &DepNode) -> DepNode { - dep_node.map_def(|&def_id| Some(self.tcx.item_path_str(def_id))).unwrap() + fn dep_node_str(&self, dep_node: &DepNode) -> String { + if let Some(def_id) = dep_node.extract_def_id(self.tcx) { + format!("{:?}({})", + dep_node.kind, + self.tcx.item_path_str(def_id)) + } else { + format!("{:?}({:?})", dep_node.kind, dep_node.hash) + } } - fn assert_dirty(&self, item_span: Span, dep_node: DepNode) { + fn assert_dirty(&self, item_span: Span, dep_node: DepNode) { debug!("assert_dirty({:?})", dep_node); - match dep_node { - DepNode::Krate | - DepNode::Hir(_) | - DepNode::HirBody(_) => { + match dep_node.kind { + DepKind::Krate | + DepKind::Hir | + DepKind::HirBody => { // HIR nodes are inputs, so if we are asserting that the HIR node is // dirty, we check the dirty input set. if !self.dirty_inputs.contains(&dep_node) { let dep_node_str = self.dep_node_str(&dep_node); self.tcx.sess.span_err( item_span, - &format!("`{:?}` not found in dirty set, but should be dirty", + &format!("`{}` not found in dirty set, but should be dirty", dep_node_str)); } } @@ -152,25 +155,25 @@ impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> { let dep_node_str = self.dep_node_str(&dep_node); self.tcx.sess.span_err( item_span, - &format!("`{:?}` found in dep graph, but should be dirty", dep_node_str)); + &format!("`{}` found in dep graph, but should be dirty", dep_node_str)); } } } } - fn assert_clean(&self, item_span: Span, dep_node: DepNode) { + fn assert_clean(&self, item_span: Span, dep_node: DepNode) { debug!("assert_clean({:?})", dep_node); - match dep_node { - DepNode::Krate | - DepNode::Hir(_) | - DepNode::HirBody(_) => { + match dep_node.kind { + DepKind::Krate | + DepKind::Hir | + DepKind::HirBody => { // For HIR nodes, check the inputs. if self.dirty_inputs.contains(&dep_node) { let dep_node_str = self.dep_node_str(&dep_node); self.tcx.sess.span_err( item_span, - &format!("`{:?}` found in dirty-node set, but should be clean", + &format!("`{}` found in dirty-node set, but should be clean", dep_node_str)); } } @@ -180,7 +183,7 @@ impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> { let dep_node_str = self.dep_node_str(&dep_node); self.tcx.sess.span_err( item_span, - &format!("`{:?}` not found in dep graph, but should be clean", + &format!("`{}` not found in dep graph, but should be clean", dep_node_str)); } } diff --git a/src/librustc_incremental/persist/hash.rs b/src/librustc_incremental/persist/hash.rs index 4a2dd274aae5..0e8ffb9ee3c9 100644 --- a/src/librustc_incremental/persist/hash.rs +++ b/src/librustc_incremental/persist/hash.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use rustc::dep_graph::DepNode; +use rustc::dep_graph::{DepNode, DepKind}; use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use rustc::hir::svh::Svh; use rustc::ich::Fingerprint; @@ -45,31 +45,29 @@ impl<'a, 'tcx> HashContext<'a, 'tcx> { } } - pub fn is_hashable(dep_node: &DepNode) -> bool { - match *dep_node { - DepNode::Krate | - DepNode::Hir(_) | - DepNode::HirBody(_) => + pub fn is_hashable(tcx: TyCtxt, dep_node: &DepNode) -> bool { + match dep_node.kind { + DepKind::Krate | + DepKind::Hir | + DepKind::HirBody => true, - DepNode::MetaData(def_id) => !def_id.is_local(), + DepKind::MetaData => { + let def_id = dep_node.extract_def_id(tcx).unwrap(); + !def_id.is_local() + } _ => false, } } - pub fn hash(&mut self, dep_node: &DepNode) -> Option { - match *dep_node { - DepNode::Krate => { + pub fn hash(&mut self, dep_node: &DepNode) -> Option { + match dep_node.kind { + DepKind::Krate => { Some(self.incremental_hashes_map[dep_node]) } // HIR nodes (which always come from our crate) are an input: - DepNode::Hir(def_id) | - DepNode::HirBody(def_id) => { - assert!(def_id.is_local(), - "cannot hash HIR for non-local def-id {:?} => {:?}", - def_id, - self.tcx.item_path_str(def_id)); - + DepKind::Hir | + DepKind::HirBody => { Some(self.incremental_hashes_map[dep_node]) } @@ -77,10 +75,15 @@ impl<'a, 'tcx> HashContext<'a, 'tcx> { // MetaData nodes from *our* crates are an *output*; we // don't hash them, but we do compute a hash for them and // save it for others to use. - DepNode::MetaData(def_id) if !def_id.is_local() => { - Some(self.metadata_hash(def_id, + DepKind::MetaData => { + let def_id = dep_node.extract_def_id(self.tcx).unwrap(); + if !def_id.is_local() { + Some(self.metadata_hash(def_id, def_id.krate, |this| &mut this.metadata_hashes)) + } else { + None + } } _ => { diff --git a/src/librustc_incremental/persist/load.rs b/src/librustc_incremental/persist/load.rs index f2ecf4c74e78..53fccfaa3929 100644 --- a/src/librustc_incremental/persist/load.rs +++ b/src/librustc_incremental/persist/load.rs @@ -10,9 +10,8 @@ //! Code to save/load the dep-graph from files. -use rustc::dep_graph::{DepNode, WorkProductId}; +use rustc::dep_graph::{DepNode, WorkProductId, DepKind}; use rustc::hir::def_id::DefId; -use rustc::hir::map::DefPathHash; use rustc::hir::svh::Svh; use rustc::ich::Fingerprint; use rustc::session::Session; @@ -33,7 +32,7 @@ use super::work_product; // The key is a dirty node. The value is **some** base-input that we // can blame it on. -pub type DirtyNodes = FxHashMap, DepNode>; +pub type DirtyNodes = FxHashMap; /// If we are in incremental mode, and a previous dep-graph exists, /// then load up those nodes/edges that are still valid into the @@ -118,14 +117,20 @@ fn load_data(sess: &Session, path: &Path) -> Option> { None } -/// Try to convert a DepNode from the old dep-graph into a DepNode in the -/// current graph by mapping the DefPathHash to a valid DefId. This will fail -/// if the DefPathHash refers to something that has been removed (because -/// there is no DefId for that thing anymore). -fn retrace(tcx: TyCtxt, dep_node: &DepNode) -> Option> { - dep_node.map_def(|def_path_hash| { - tcx.def_path_hash_to_def_id.as_ref().unwrap().get(def_path_hash).cloned() - }) +/// Check if a DepNode from the previous dep-graph refers to something that +/// still exists in the current compilation session. Only works for DepNode +/// variants that represent inputs (HIR and imported Metadata). +fn does_still_exist(tcx: TyCtxt, dep_node: &DepNode) -> bool { + match dep_node.kind { + DepKind::Hir | + DepKind::HirBody | + DepKind::MetaData => { + dep_node.extract_def_id(tcx).is_some() + } + _ => { + bug!("unexpected Input DepNode: {:?}", dep_node) + } + } } /// Decode the dep graph and load the edges/nodes that are still clean @@ -161,7 +166,7 @@ pub fn decode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let serialized_dep_graph = SerializedDepGraph::decode(&mut dep_graph_decoder)?; - let edge_map: FxHashMap, Vec>> = { + let edge_map: FxHashMap> = { let capacity = serialized_dep_graph.edge_list_data.len(); let mut edge_map = FxHashMap::with_capacity_and_hasher(capacity, Default::default()); @@ -194,46 +199,26 @@ pub fn decode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Recreate the edges in the graph that are still clean. let mut clean_work_products = FxHashSet(); let mut dirty_work_products = FxHashSet(); // incomplete; just used to suppress debug output - let mut extra_edges = vec![]; for (source, targets) in &edge_map { for target in targets { - process_edges(tcx, source, target, &edge_map, &dirty_raw_nodes, - &mut clean_work_products, &mut dirty_work_products, &mut extra_edges); + process_edge(tcx, source, target, &dirty_raw_nodes, + &mut clean_work_products, &mut dirty_work_products); } } // Recreate bootstrap outputs, which are outputs that have no incoming edges (and hence cannot // be dirty). for bootstrap_output in &serialized_dep_graph.bootstrap_outputs { - if let Some(n) = retrace(tcx, bootstrap_output) { - if let DepNode::WorkProduct(ref wp) = n { - clean_work_products.insert(wp.clone()); - } - - tcx.dep_graph.with_task(n, (), (), create_node); - - fn create_node((): (), (): ()) { - // just create the node with no inputs - } + if let DepKind::WorkProduct = bootstrap_output.kind { + let wp_id = WorkProductId::from_fingerprint(bootstrap_output.hash); + clean_work_products.insert(wp_id); } - } - // Subtle. Sometimes we have intermediate nodes that we can't recreate in the new graph. - // This is pretty unusual but it arises in a scenario like this: - // - // Hir(X) -> Foo(Y) -> Bar - // - // Note that the `Hir(Y)` is not an input to `Foo(Y)` -- this - // almost never happens, but can happen in some obscure - // scenarios. In that case, if `Y` is removed, then we can't - // recreate `Foo(Y)` (the def-id `Y` no longer exists); what we do - // then is to push the edge `Hir(X) -> Bar` onto `extra_edges` - // (along with any other targets of `Foo(Y)`). We will then add - // the edge from `Hir(X)` to `Bar` (or, if `Bar` itself cannot be - // recreated, to the targets of `Bar`). - while let Some((source, target)) = extra_edges.pop() { - process_edges(tcx, source, target, &edge_map, &dirty_raw_nodes, - &mut clean_work_products, &mut dirty_work_products, &mut extra_edges); + tcx.dep_graph.with_task(*bootstrap_output, (), (), create_node); + + fn create_node((): (), (): ()) { + // just create the node with no inputs + } } // Add in work-products that are still clean, and delete those that are @@ -256,40 +241,37 @@ fn initial_dirty_nodes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let mut hcx = HashContext::new(tcx, incremental_hashes_map); let mut dirty_nodes = FxHashMap(); - let print_removed_message = |dep_node: &DepNode<_>| { - if tcx.sess.opts.debugging_opts.incremental_dump_hash { - println!("node {:?} is dirty as it was removed", dep_node); - } - - debug!("initial_dirty_nodes: {:?} is dirty as it was removed", dep_node); - }; - for hash in serialized_hashes { - if let Some(dep_node) = retrace(tcx, &hash.dep_node) { - if let Some(current_hash) = hcx.hash(&dep_node) { - if current_hash == hash.hash { - debug!("initial_dirty_nodes: {:?} is clean (hash={:?})", - dep_node.map_def(|&def_id| Some(tcx.def_path(def_id))).unwrap(), + let dep_node = hash.dep_node; + if does_still_exist(tcx, &dep_node) { + let current_hash = hcx.hash(&dep_node).unwrap_or_else(|| { + bug!("Cannot find current ICH for input that still exists?") + }); + + if current_hash == hash.hash { + debug!("initial_dirty_nodes: {:?} is clean (hash={:?})", + dep_node, current_hash); - continue; - } - - if tcx.sess.opts.debugging_opts.incremental_dump_hash { - println!("node {:?} is dirty as hash is {:?} was {:?}", - dep_node.map_def(|&def_id| Some(tcx.def_path(def_id))).unwrap(), - current_hash, - hash.hash); - } - - debug!("initial_dirty_nodes: {:?} is dirty as hash is {:?}, was {:?}", - dep_node.map_def(|&def_id| Some(tcx.def_path(def_id))).unwrap(), - current_hash, - hash.hash); - } else { - print_removed_message(&hash.dep_node); + continue; } + + if tcx.sess.opts.debugging_opts.incremental_dump_hash { + println!("node {:?} is dirty as hash is {:?}, was {:?}", + dep_node, + current_hash, + hash.hash); + } + + debug!("initial_dirty_nodes: {:?} is dirty as hash is {:?}, was {:?}", + dep_node, + current_hash, + hash.hash); } else { - print_removed_message(&hash.dep_node); + if tcx.sess.opts.debugging_opts.incremental_dump_hash { + println!("node {:?} is dirty as it was removed", dep_node); + } + + debug!("initial_dirty_nodes: {:?} is dirty as it was removed", dep_node); } dirty_nodes.insert(hash.dep_node.clone(), hash.dep_node.clone()); @@ -298,11 +280,11 @@ fn initial_dirty_nodes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, dirty_nodes } -fn transitive_dirty_nodes(edge_map: &FxHashMap, Vec>>, +fn transitive_dirty_nodes(edge_map: &FxHashMap>, mut dirty_nodes: DirtyNodes) -> DirtyNodes { - let mut stack: Vec<(DepNode, DepNode)> = vec![]; + let mut stack: Vec<(DepNode, DepNode)> = vec![]; stack.extend(dirty_nodes.iter().map(|(s, b)| (s.clone(), b.clone()))); while let Some((source, blame)) = stack.pop() { // we know the source is dirty (because of the node `blame`)... @@ -366,6 +348,7 @@ fn delete_dirty_work_product(tcx: TyCtxt, fn load_prev_metadata_hashes(tcx: TyCtxt, output: &mut FxHashMap) { if !tcx.sess.opts.debugging_opts.query_dep_graph { + // Previous metadata hashes are only needed for testing. return } @@ -417,71 +400,70 @@ fn load_prev_metadata_hashes(tcx: TyCtxt, serialized_hashes.index_map.len()); } -fn process_edges<'a, 'tcx, 'edges>( +fn process_edge<'a, 'tcx, 'edges>( tcx: TyCtxt<'a, 'tcx, 'tcx>, - source: &'edges DepNode, - target: &'edges DepNode, - edges: &'edges FxHashMap, Vec>>, + source: &'edges DepNode, + target: &'edges DepNode, dirty_raw_nodes: &DirtyNodes, clean_work_products: &mut FxHashSet, - dirty_work_products: &mut FxHashSet, - extra_edges: &mut Vec<(&'edges DepNode, &'edges DepNode)>) + dirty_work_products: &mut FxHashSet) { // If the target is dirty, skip the edge. If this is an edge // that targets a work-product, we can print the blame // information now. if let Some(blame) = dirty_raw_nodes.get(target) { - if let DepNode::WorkProduct(ref wp) = *target { + if let DepKind::WorkProduct = target.kind { if tcx.sess.opts.debugging_opts.incremental_info { - if dirty_work_products.insert(wp.clone()) { + let wp_id = WorkProductId::from_fingerprint(target.hash); + + if dirty_work_products.insert(wp_id) { // Try to reconstruct the human-readable version of the // DepNode. This cannot be done for things that where // removed. - let readable_blame = if let Some(dep_node) = retrace(tcx, blame) { - dep_node.map_def(|&def_id| Some(tcx.def_path(def_id).to_string(tcx))) - .unwrap() + let blame_str = if let Some(def_id) = blame.extract_def_id(tcx) { + format!("{:?}({})", + blame.kind, + tcx.def_path(def_id).to_string(tcx)) } else { - blame.map_def(|def_path_hash| Some(format!("{:?}", def_path_hash))) - .unwrap() + format!("{:?}", blame) }; println!("incremental: module {:?} is dirty because {:?} \ changed or was removed", - wp, - readable_blame); + wp_id, + blame_str); } } } return; } - // If the source is dirty, the target will be dirty. - assert!(!dirty_raw_nodes.contains_key(source)); + // At this point we have asserted that the target is clean -- otherwise, we + // would have hit the return above. We can do some further consistency + // checks based on this fact: - // Retrace the source -> target edges to def-ids and then create - // an edge in the graph. Retracing may yield none if some of the - // data happens to have been removed. - if let Some(source_node) = retrace(tcx, source) { - if let Some(target_node) = retrace(tcx, target) { - let _task = tcx.dep_graph.in_task(target_node); - tcx.dep_graph.read(source_node); - if let DepNode::WorkProduct(ref wp) = *target { - clean_work_products.insert(wp.clone()); - } - } else { - // As discussed in `decode_dep_graph` above, sometimes the - // target cannot be recreated again, in which case we add - // edges to go from `source` to the targets of `target`. - extra_edges.extend( - edges[target].iter().map(|t| (source, t))); + // We should never have an edge where the target is clean but the source + // was dirty. Otherwise something was wrong with the dirtying pass above: + debug_assert!(!dirty_raw_nodes.contains_key(source)); + + // We also never should encounter an edge going from a removed input to a + // clean target because removing the input would have dirtied the input + // node and transitively dirtied the target. + debug_assert!(match source.kind { + DepKind::Hir | DepKind::HirBody | DepKind::MetaData => { + does_still_exist(tcx, source) + } + _ => true, + }); + + if !dirty_raw_nodes.contains_key(target) { + let _task = tcx.dep_graph.in_task(*target); + tcx.dep_graph.read(*source); + + if let DepKind::WorkProduct = target.kind { + let wp_id = WorkProductId::from_fingerprint(target.hash); + clean_work_products.insert(wp_id); } - } else { - // It's also possible that the source can't be created! But we - // can ignore such cases, because (a) if `source` is a HIR - // node, it would be considered dirty; and (b) in other cases, - // there must be some input to this node that is clean, and so - // we'll re-create the edges over in the case where target is - // undefined. } } diff --git a/src/librustc_incremental/persist/preds/mod.rs b/src/librustc_incremental/persist/preds/mod.rs index e769641a4cad..0a259ad26858 100644 --- a/src/librustc_incremental/persist/preds/mod.rs +++ b/src/librustc_incremental/persist/preds/mod.rs @@ -8,8 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use rustc::dep_graph::{DepGraphQuery, DepNode}; -use rustc::hir::def_id::DefId; +use rustc::dep_graph::{DepGraphQuery, DepNode, DepKind}; use rustc::ich::Fingerprint; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::graph::{Graph, NodeIndex}; @@ -26,7 +25,7 @@ pub struct Predecessors<'query> { // nodes) and all of the "work-products" we may care about // later. Other nodes may be retained if it keeps the overall size // of the graph down. - pub reduced_graph: Graph<&'query DepNode, ()>, + pub reduced_graph: Graph<&'query DepNode, ()>, // These are output nodes that have no incoming edges. We have to // track these specially because, when we load the data back up @@ -34,32 +33,32 @@ pub struct Predecessors<'query> { // to recreate the nodes where all incoming edges are clean; but // since we ordinarily just serialize edges, we wind up just // forgetting that bootstrap outputs even exist in that case.) - pub bootstrap_outputs: Vec<&'query DepNode>, + pub bootstrap_outputs: Vec<&'query DepNode>, // For the inputs (hir/foreign-metadata), we include hashes. - pub hashes: FxHashMap<&'query DepNode, Fingerprint>, + pub hashes: FxHashMap<&'query DepNode, Fingerprint>, } impl<'q> Predecessors<'q> { - pub fn new(query: &'q DepGraphQuery, hcx: &mut HashContext) -> Self { + pub fn new(query: &'q DepGraphQuery, hcx: &mut HashContext) -> Self { let tcx = hcx.tcx; // Find the set of "start nodes". These are nodes that we will // possibly query later. - let is_output = |node: &DepNode| -> bool { - match *node { - DepNode::WorkProduct(_) => true, - DepNode::MetaData(ref def_id) => { + let is_output = |node: &DepNode| -> bool { + match node.kind { + DepKind::WorkProduct => true, + DepKind::MetaData => { // We do *not* create dep-nodes for the current crate's // metadata anymore, just for metadata that we import/read // from other crates. - debug_assert!(!def_id.is_local()); + debug_assert!(!node.extract_def_id(tcx).unwrap().is_local()); false } // if -Z query-dep-graph is passed, save more extended data // to enable better unit testing - DepNode::TypeckTables(_) | - DepNode::TransCrateItem(_) => tcx.sess.opts.debugging_opts.query_dep_graph, + DepKind::TypeckTables | + DepKind::TransCrateItem => tcx.sess.opts.debugging_opts.query_dep_graph, _ => false, } @@ -67,7 +66,9 @@ impl<'q> Predecessors<'q> { // Reduce the graph to the most important nodes. let compress::Reduction { graph, input_nodes } = - compress::reduce_graph(&query.graph, HashContext::is_hashable, |n| is_output(n)); + compress::reduce_graph(&query.graph, + |n| HashContext::is_hashable(tcx, n), + |n| is_output(n)); let mut hashes = FxHashMap(); for input_index in input_nodes { @@ -81,8 +82,8 @@ impl<'q> Predecessors<'q> { // Not all inputs might have been reachable from an output node, // but we still want their hash for our unit tests. let hir_nodes = query.graph.all_nodes().iter().filter_map(|node| { - match node.data { - DepNode::Hir(_) => Some(&node.data), + match node.data.kind { + DepKind::Hir => Some(&node.data), _ => None, } }); @@ -93,7 +94,7 @@ impl<'q> Predecessors<'q> { } } - let bootstrap_outputs: Vec<&'q DepNode> = + let bootstrap_outputs: Vec<&'q DepNode> = (0 .. graph.len_nodes()) .map(NodeIndex) .filter(|&n| graph.incoming_edges(n).next().is_none()) diff --git a/src/librustc_incremental/persist/save.rs b/src/librustc_incremental/persist/save.rs index 01db756f9de0..48742b424f1e 100644 --- a/src/librustc_incremental/persist/save.rs +++ b/src/librustc_incremental/persist/save.rs @@ -11,7 +11,6 @@ use rustc::dep_graph::DepNode; use rustc::hir::def_id::DefId; use rustc::hir::svh::Svh; -use rustc::hir::map::DefPathHash; use rustc::ich::Fingerprint; use rustc::middle::cstore::EncodedMetadataHashes; use rustc::session::Session; @@ -174,16 +173,12 @@ pub fn encode_dep_graph(tcx: TyCtxt, // First encode the commandline arguments hash tcx.sess.opts.dep_tracking_hash().encode(encoder)?; - let to_hash_based_node = |dep_node: &DepNode| { - dep_node.map_def(|&def_id| Some(tcx.def_path_hash(def_id))).unwrap() - }; - // NB: We rely on this Vec being indexable by reduced_graph's NodeIndex. - let nodes: IndexVec> = preds + let nodes: IndexVec = preds .reduced_graph .all_nodes() .iter() - .map(|node| to_hash_based_node(node.data)) + .map(|node| node.data.clone()) .collect(); let mut edge_list_indices = Vec::with_capacity(nodes.len()); @@ -206,18 +201,17 @@ pub fn encode_dep_graph(tcx: TyCtxt, // Check that we have a consistent number of edges. assert_eq!(edge_list_data.len(), preds.reduced_graph.len_edges()); - let bootstrap_outputs = preds - .bootstrap_outputs - .iter() - .map(|n| to_hash_based_node(n)) - .collect(); + let bootstrap_outputs = preds.bootstrap_outputs + .iter() + .map(|dep_node| (**dep_node).clone()) + .collect(); let hashes = preds .hashes .iter() .map(|(&dep_node, &hash)| { SerializedHash { - dep_node: to_hash_based_node(dep_node), + dep_node: dep_node.clone(), hash: hash, } }) diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs index ed67616e58f6..e572be9ffe7d 100644 --- a/src/librustc_metadata/cstore.rs +++ b/src/librustc_metadata/cstore.rs @@ -255,6 +255,13 @@ impl CStore { pub fn do_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option { self.extern_mod_crate_map.borrow().get(&emod_id).cloned() } + + pub fn read_dep_node(&self, def_id: DefId) { + use rustc::middle::cstore::CrateStore; + let def_path_hash = self.def_path_hash(def_id); + let dep_node = def_path_hash.to_dep_node(::rustc::dep_graph::DepKind::MetaData); + self.dep_graph.read(dep_node); + } } impl CrateMetadata { diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 60cc03f7b792..97f73b25c64d 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -22,8 +22,6 @@ use rustc::session::Session; use rustc::ty::{self, TyCtxt}; use rustc::ty::maps::Providers; use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE}; - -use rustc::dep_graph::{DepNode}; use rustc::hir::map::{DefKey, DefPath, DisambiguatedDefPathData, DefPathHash}; use rustc::hir::map::definitions::{DefPathTable, GlobalMetaDataKind}; use rustc::util::nodemap::{NodeSet, DefIdMap}; @@ -48,7 +46,10 @@ macro_rules! provide { DepTrackingMapConfig>::Value { assert!(!$def_id.is_local()); - $tcx.dep_graph.read(DepNode::MetaData($def_id)); + let def_path_hash = $tcx.def_path_hash($def_id); + let dep_node = def_path_hash.to_dep_node(::rustc::dep_graph::DepKind::MetaData); + + $tcx.dep_graph.read(dep_node); let $cdata = $tcx.sess.cstore.crate_data_as_rc_any($def_id.krate); let $cdata = $cdata.downcast_ref::() @@ -140,12 +141,12 @@ impl CrateStore for cstore::CStore { } fn visibility(&self, def: DefId) -> ty::Visibility { - self.dep_graph.read(DepNode::MetaData(def)); + self.read_dep_node(def); self.get_crate_data(def.krate).get_visibility(def.index) } fn item_generics_cloned(&self, def: DefId) -> ty::Generics { - self.dep_graph.read(DepNode::MetaData(def)); + self.read_dep_node(def); self.get_crate_data(def.krate).get_generics(def.index) } @@ -161,19 +162,19 @@ impl CrateStore for cstore::CStore { fn impl_defaultness(&self, def: DefId) -> hir::Defaultness { - self.dep_graph.read(DepNode::MetaData(def)); + self.read_dep_node(def); self.get_crate_data(def.krate).get_impl_defaultness(def.index) } fn associated_item_cloned(&self, def: DefId) -> ty::AssociatedItem { - self.dep_graph.read(DepNode::MetaData(def)); + self.read_dep_node(def); self.get_crate_data(def.krate).get_associated_item(def.index) } fn is_const_fn(&self, did: DefId) -> bool { - self.dep_graph.read(DepNode::MetaData(did)); + self.read_dep_node(did); self.get_crate_data(did.krate).is_const_fn(did.index) } @@ -344,13 +345,13 @@ impl CrateStore for cstore::CStore { fn struct_field_names(&self, def: DefId) -> Vec { - self.dep_graph.read(DepNode::MetaData(def)); + self.read_dep_node(def); self.get_crate_data(def.krate).get_struct_field_names(def.index) } fn item_children(&self, def_id: DefId) -> Vec { - self.dep_graph.read(DepNode::MetaData(def_id)); + self.read_dep_node(def_id); let mut result = vec![]; self.get_crate_data(def_id.krate) .each_child_of_item(def_id.index, |child| result.push(child)); @@ -398,11 +399,12 @@ impl CrateStore for cstore::CStore { tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx hir::Body { - if let Some(cached) = tcx.hir.get_inlined_body(def_id) { + self.read_dep_node(def_id); + + if let Some(cached) = tcx.hir.get_inlined_body_untracked(def_id) { return cached; } - self.dep_graph.read(DepNode::MetaData(def_id)); debug!("item_body({:?}): inlining item", def_id); self.get_crate_data(def_id.krate).item_body(tcx, def_id.index) diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index a095fdd50841..2a2010621fcc 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -13,7 +13,7 @@ use cstore::{self, CrateMetadata, MetadataBlob, NativeLibrary}; use schema::*; -use rustc::dep_graph::{DepGraph, DepNode}; +use rustc::dep_graph::{DepGraph, DepNode, DepKind}; use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash}; use rustc::hir::map::definitions::GlobalMetaDataKind; use rustc::hir; @@ -876,7 +876,8 @@ impl<'a, 'tcx> CrateMetadata { return Rc::new([]); } - dep_graph.read(DepNode::MetaData(self.local_def_id(node_id))); + let dep_node = self.def_path_hash(node_id).to_dep_node(DepKind::MetaData); + dep_graph.read(dep_node); if let Some(&Some(ref val)) = self.attribute_cache.borrow()[node_as].get(node_index) { @@ -1194,8 +1195,9 @@ impl<'a, 'tcx> CrateMetadata { self.codemap_import_info.borrow() } - pub fn metadata_dep_node(&self, kind: GlobalMetaDataKind) -> DepNode { + pub fn metadata_dep_node(&self, kind: GlobalMetaDataKind) -> DepNode { let def_index = kind.def_index(&self.def_path_table); - DepNode::MetaData(self.local_def_id(def_index)) + let def_path_hash = self.def_path_table.def_path_hash(def_index); + def_path_hash.to_dep_node(DepKind::MetaData) } } diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index 9180f9100ad7..1337f90efa74 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -203,7 +203,7 @@ impl Tracked { } } - pub fn get(&self, dep_graph: &DepGraph, dep_node: DepNode) -> &T { + pub fn get(&self, dep_graph: &DepGraph, dep_node: DepNode) -> &T { dep_graph.read(dep_node); &self.state } diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index e57cbb1c9101..e4939db5759a 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -23,7 +23,7 @@ use rustc::middle::dependency_format::Linkage; use CrateTranslation; use rustc::util::common::time; use rustc::util::fs::fix_windows_verbatim_for_gcc; -use rustc::dep_graph::DepNode; +use rustc::dep_graph::{DepKind, DepNode}; use rustc::hir::def_id::CrateNum; use rustc::hir::svh::Svh; use rustc_back::tempdir::TempDir; @@ -134,8 +134,9 @@ pub fn find_crate_name(sess: Option<&Session>, } pub fn build_link_meta(incremental_hashes_map: &IncrementalHashesMap) -> LinkMeta { + let krate_dep_node = &DepNode::new_no_params(DepKind::Krate); let r = LinkMeta { - crate_hash: Svh::new(incremental_hashes_map[&DepNode::Krate].to_smaller_hash()), + crate_hash: Svh::new(incremental_hashes_map[krate_dep_node].to_smaller_hash()), }; info!("{:?}", r); return r; diff --git a/src/librustc_trans/partitioning.rs b/src/librustc_trans/partitioning.rs index df8984e6d247..ead442d33882 100644 --- a/src/librustc_trans/partitioning.rs +++ b/src/librustc_trans/partitioning.rs @@ -167,8 +167,8 @@ impl<'tcx> CodegenUnit<'tcx> { WorkProductId::from_cgu_name(self.name()) } - pub fn work_product_dep_node(&self) -> DepNode { - DepNode::WorkProduct(self.work_product_id()) + pub fn work_product_dep_node(&self) -> DepNode { + self.work_product_id().to_dep_node() } pub fn compute_symbol_name_hash<'a>(&self, diff --git a/src/librustc_trans/trans_item.rs b/src/librustc_trans/trans_item.rs index 392ee71d52b4..2a36ef9358e4 100644 --- a/src/librustc_trans/trans_item.rs +++ b/src/librustc_trans/trans_item.rs @@ -23,7 +23,7 @@ use common; use declare; use llvm; use monomorphize::Instance; -use rustc::dep_graph::DepNode; +use rustc::dep_graph::DepKind; use rustc::hir; use rustc::hir::def_id::DefId; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; @@ -75,14 +75,16 @@ impl<'a, 'tcx> TransItem<'tcx> { match *self { TransItem::Static(node_id) => { - let def_id = ccx.tcx().hir.local_def_id(node_id); - let _task = ccx.tcx().dep_graph.in_task(DepNode::TransCrateItem(def_id)); // (*) - let item = ccx.tcx().hir.expect_item(node_id); + let tcx = ccx.tcx(); + let def_id = tcx.hir.local_def_id(node_id); + let dep_node = def_id.to_dep_node(tcx, DepKind::TransCrateItem); + let _task = ccx.tcx().dep_graph.in_task(dep_node); // (*) + let item = tcx.hir.expect_item(node_id); if let hir::ItemStatic(_, m, _) = item.node { match consts::trans_static(&ccx, m, item.id, &item.attrs) { Ok(_) => { /* Cool, everything's alright. */ }, Err(err) => { - err.report(ccx.tcx(), item.span, "static"); + err.report(tcx, item.span, "static"); } }; } else { @@ -99,7 +101,8 @@ impl<'a, 'tcx> TransItem<'tcx> { } TransItem::Fn(instance) => { let _task = ccx.tcx().dep_graph.in_task( - DepNode::TransCrateItem(instance.def_id())); // (*) + instance.def_id() + .to_dep_node(ccx.tcx(), DepKind::TransCrateItem)); // (*) base::trans_instance(&ccx, instance); } diff --git a/src/librustc_typeck/coherence/inherent_impls.rs b/src/librustc_typeck/coherence/inherent_impls.rs index f7ebc2104422..e24d76600218 100644 --- a/src/librustc_typeck/coherence/inherent_impls.rs +++ b/src/librustc_typeck/coherence/inherent_impls.rs @@ -17,7 +17,7 @@ //! `tcx.inherent_impls(def_id)`). That value, however, //! is computed by selecting an idea from this table. -use rustc::dep_graph::DepNode; +use rustc::dep_graph::DepKind; use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use rustc::hir; use rustc::hir::itemlikevisit::ItemLikeVisitor; @@ -79,7 +79,8 @@ pub fn inherent_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, }); for &impl_def_id in &result[..] { - tcx.dep_graph.read(DepNode::Hir(impl_def_id)); + let def_path_hash = tcx.def_path_hash(impl_def_id); + tcx.dep_graph.read(def_path_hash.to_dep_node(DepKind::Hir)); } result diff --git a/src/librustc_typeck/coherence/overlap.rs b/src/librustc_typeck/coherence/overlap.rs index ba1d7b18e8c7..781e323dea39 100644 --- a/src/librustc_typeck/coherence/overlap.rs +++ b/src/librustc_typeck/coherence/overlap.rs @@ -15,7 +15,7 @@ use rustc::traits; use rustc::ty::{self, TyCtxt, TypeFoldable}; use syntax::ast; -use rustc::dep_graph::DepNode; +use rustc::dep_graph::DepKind; use rustc::hir; use rustc::hir::itemlikevisit::ItemLikeVisitor; @@ -39,7 +39,8 @@ pub fn check_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, node_id: ast::NodeId) { } let _task = - tcx.dep_graph.in_task(DepNode::CoherenceOverlapCheck(trait_def_id)); + tcx.dep_graph.in_task(trait_def_id.to_dep_node(tcx, + DepKind::CoherenceOverlapCheck)); // Trigger building the specialization graph for the trait of this impl. // This will detect any overlap errors. diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index cb2ee7dd1bcd..c434edb1c31a 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -15,7 +15,7 @@ use hir::def_id::DefId; use middle::resolve_lifetime as rl; -use rustc::dep_graph::{AssertDepGraphSafe, DepNode}; +use rustc::dep_graph::{AssertDepGraphSafe, DepKind}; use rustc::ty::subst::Substs; use rustc::ty::{self, Ty, TyCtxt}; use rustc::hir::map as hir_map; @@ -104,7 +104,8 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ConstraintContext<'a, 'tcx> { hir::ItemEnum(..) | hir::ItemStruct(..) | hir::ItemUnion(..) => { - tcx.dep_graph.with_task(DepNode::ItemVarianceConstraints(def_id), + let dep_node = def_id.to_dep_node(tcx, DepKind::ItemVarianceConstraints); + tcx.dep_graph.with_task(dep_node, AssertDepGraphSafe(self), def_id, visit_item_task); diff --git a/src/librustc_typeck/variance/mod.rs b/src/librustc_typeck/variance/mod.rs index 1afe2725ac87..8f9f40ca40b0 100644 --- a/src/librustc_typeck/variance/mod.rs +++ b/src/librustc_typeck/variance/mod.rs @@ -12,7 +12,7 @@ //! parameters. See README.md for details. use arena; -use rustc::dep_graph::DepNode; +use rustc::dep_graph::DepKind; use rustc::hir; use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use rustc::ty::{self, CrateVariancesMap, TyCtxt}; @@ -72,12 +72,15 @@ fn variances_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_def_id: DefId) // Lacking red/green, we read the variances for all items here // but ignore the dependencies, then re-synthesize the ones we need. let crate_map = tcx.dep_graph.with_ignore(|| tcx.crate_variances(LOCAL_CRATE)); - tcx.dep_graph.read(DepNode::ItemVarianceConstraints(item_def_id)); + let dep_node = item_def_id.to_dep_node(tcx, DepKind::ItemVarianceConstraints); + tcx.dep_graph.read(dep_node); for &dep_def_id in crate_map.dependencies.less_than(&item_def_id) { if dep_def_id.is_local() { - tcx.dep_graph.read(DepNode::ItemVarianceConstraints(dep_def_id)); + let dep_node = dep_def_id.to_dep_node(tcx, DepKind::ItemVarianceConstraints); + tcx.dep_graph.read(dep_node); } else { - tcx.dep_graph.read(DepNode::ItemVariances(dep_def_id)); + let dep_node = dep_def_id.to_dep_node(tcx, DepKind::ItemVariances); + tcx.dep_graph.read(dep_node); } } diff --git a/src/test/incremental/dirty_clean.rs b/src/test/incremental/dirty_clean.rs index 9f20128de4f5..ce9865103dcc 100644 --- a/src/test/incremental/dirty_clean.rs +++ b/src/test/incremental/dirty_clean.rs @@ -38,8 +38,8 @@ mod y { #[rustc_clean(label="TypeckTables", cfg="cfail2")] #[rustc_clean(label="TransCrateItem", cfg="cfail2")] pub fn y() { - //[cfail2]~^ ERROR `TypeckTables("y::y")` not found in dep graph, but should be clean - //[cfail2]~| ERROR `TransCrateItem("y::y")` not found in dep graph, but should be clean + //[cfail2]~^ ERROR `TypeckTables(y::y)` not found in dep graph, but should be clean + //[cfail2]~| ERROR `TransCrateItem(y::y)` not found in dep graph, but should be clean x::x(); } } @@ -48,7 +48,7 @@ mod z { #[rustc_dirty(label="TypeckTables", cfg="cfail2")] #[rustc_dirty(label="TransCrateItem", cfg="cfail2")] pub fn z() { - //[cfail2]~^ ERROR `TypeckTables("z::z")` found in dep graph, but should be dirty - //[cfail2]~| ERROR `TransCrateItem("z::z")` found in dep graph, but should be dirty + //[cfail2]~^ ERROR `TypeckTables(z::z)` found in dep graph, but should be dirty + //[cfail2]~| ERROR `TransCrateItem(z::z)` found in dep graph, but should be dirty } } From 7f482808f9700259da6585597486166148576d96 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Fri, 9 Jun 2017 15:01:44 +0200 Subject: [PATCH 093/233] incr.comp.: Clean up and optimize dep-graph loading. --- src/librustc_incremental/persist/data.rs | 21 ++-- .../persist/dirty_clean.rs | 13 +- src/librustc_incremental/persist/load.rs | 114 ++++++++---------- src/librustc_incremental/persist/save.rs | 57 ++++++--- 4 files changed, 116 insertions(+), 89 deletions(-) diff --git a/src/librustc_incremental/persist/data.rs b/src/librustc_incremental/persist/data.rs index c3cd9656afe5..06acfb5d7780 100644 --- a/src/librustc_incremental/persist/data.rs +++ b/src/librustc_incremental/persist/data.rs @@ -26,7 +26,7 @@ pub struct SerializedDepGraph { /// For each DepNode, stores the list of edges originating from that /// DepNode. Encoded as a [start, end) pair indexing into edge_list_data, /// which holds the actual DepNodeIndices of the target nodes. - pub edge_list_indices: Vec<(u32, u32)>, + pub edge_list_indices: IndexVec, /// A flattened list of all edge targets in the graph. Edge sources are /// implicit in edge_list_indices. pub edge_list_data: Vec, @@ -55,7 +55,14 @@ pub struct SerializedDepGraph { /// will be different when we next compile) related to each node, /// but rather the `DefPathIndex`. This can then be retraced /// to find the current def-id. - pub hashes: Vec, + pub hashes: Vec<(DepNodeIndex, Fingerprint)>, +} + +impl SerializedDepGraph { + pub fn edge_targets_from(&self, source: DepNodeIndex) -> &[DepNodeIndex] { + let targets = self.edge_list_indices[source]; + &self.edge_list_data[targets.0 as usize .. targets.1 as usize] + } } /// The index of a DepNode in the SerializedDepGraph::nodes array. @@ -84,16 +91,6 @@ impl Idx for DepNodeIndex { } } -#[derive(Debug, RustcEncodable, RustcDecodable)] -pub struct SerializedHash { - /// def-id of thing being hashed - pub dep_node: DepNode, - - /// the hash as of previous compilation, computed by code in - /// `hash` module - pub hash: Fingerprint, -} - #[derive(Debug, RustcEncodable, RustcDecodable)] pub struct SerializedWorkProduct { /// node that produced the work-product diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs index 01ec0d685268..3f3dc10365c6 100644 --- a/src/librustc_incremental/persist/dirty_clean.rs +++ b/src/librustc_incremental/persist/dirty_clean.rs @@ -40,6 +40,7 @@ //! previous revision to compare things to. //! +use super::data::DepNodeIndex; use super::load::DirtyNodes; use rustc::dep_graph::{DepGraphQuery, DepNode, DepKind}; use rustc::hir; @@ -50,6 +51,7 @@ use rustc::ich::{Fingerprint, ATTR_DIRTY, ATTR_CLEAN, ATTR_DIRTY_METADATA, ATTR_CLEAN_METADATA}; use syntax::ast::{self, Attribute, NestedMetaItem}; use rustc_data_structures::fx::{FxHashSet, FxHashMap}; +use rustc_data_structures::indexed_vec::IndexVec; use syntax_pos::Span; use rustc::ty::TyCtxt; @@ -57,6 +59,7 @@ const LABEL: &'static str = "label"; const CFG: &'static str = "cfg"; pub fn check_dirty_clean_annotations<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + nodes: &IndexVec, dirty_inputs: &DirtyNodes) { // can't add `#[rustc_dirty]` etc without opting in to this feature if !tcx.sess.features.borrow().rustc_attrs { @@ -66,8 +69,14 @@ pub fn check_dirty_clean_annotations<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let _ignore = tcx.dep_graph.in_ignore(); let dirty_inputs: FxHashSet = dirty_inputs.keys() - .filter(|dep_node| dep_node.extract_def_id(tcx).is_some()) - .cloned() + .filter_map(|dep_node_index| { + let dep_node = nodes[*dep_node_index]; + if dep_node.extract_def_id(tcx).is_some() { + Some(dep_node) + } else { + None + } + }) .collect(); let query = tcx.dep_graph.query(); diff --git a/src/librustc_incremental/persist/load.rs b/src/librustc_incremental/persist/load.rs index 53fccfaa3929..28a00bf4aa6c 100644 --- a/src/librustc_incremental/persist/load.rs +++ b/src/librustc_incremental/persist/load.rs @@ -17,9 +17,9 @@ use rustc::ich::Fingerprint; use rustc::session::Session; use rustc::ty::TyCtxt; use rustc_data_structures::fx::{FxHashSet, FxHashMap}; +use rustc_data_structures::indexed_vec::IndexVec; use rustc_serialize::Decodable as RustcDecodable; use rustc_serialize::opaque::Decoder; -use std::default::Default; use std::path::{Path}; use IncrementalHashesMap; @@ -32,7 +32,7 @@ use super::work_product; // The key is a dirty node. The value is **some** base-input that we // can blame it on. -pub type DirtyNodes = FxHashMap; +pub type DirtyNodes = FxHashMap; /// If we are in incremental mode, and a previous dep-graph exists, /// then load up those nodes/edges that are still valid into the @@ -166,48 +166,35 @@ pub fn decode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let serialized_dep_graph = SerializedDepGraph::decode(&mut dep_graph_decoder)?; - let edge_map: FxHashMap> = { - let capacity = serialized_dep_graph.edge_list_data.len(); - let mut edge_map = FxHashMap::with_capacity_and_hasher(capacity, Default::default()); - - for (node_index, source) in serialized_dep_graph.nodes.iter().enumerate() { - let (start, end) = serialized_dep_graph.edge_list_indices[node_index]; - let targets = - (&serialized_dep_graph.edge_list_data[start as usize .. end as usize]) - .into_iter() - .map(|&node_index| serialized_dep_graph.nodes[node_index].clone()) - .collect(); - - edge_map.insert(source.clone(), targets); - } - - edge_map - }; - // Compute the set of nodes from the old graph where some input - // has changed or been removed. These are "raw" source nodes, - // which means that they still use the original `DefPathIndex` - // values from the encoding, rather than having been retraced to a - // `DefId`. The reason for this is that this way we can include - // nodes that have been removed (which no longer have a `DefId` in - // the current compilation). + // has changed or been removed. let dirty_raw_nodes = initial_dirty_nodes(tcx, incremental_hashes_map, + &serialized_dep_graph.nodes, &serialized_dep_graph.hashes); - let dirty_raw_nodes = transitive_dirty_nodes(&edge_map, dirty_raw_nodes); + let dirty_raw_nodes = transitive_dirty_nodes(&serialized_dep_graph, + dirty_raw_nodes); // Recreate the edges in the graph that are still clean. let mut clean_work_products = FxHashSet(); let mut dirty_work_products = FxHashSet(); // incomplete; just used to suppress debug output - for (source, targets) in &edge_map { - for target in targets { - process_edge(tcx, source, target, &dirty_raw_nodes, - &mut clean_work_products, &mut dirty_work_products); + for (source, targets) in serialized_dep_graph.edge_list_indices.iter_enumerated() { + let target_begin = targets.0 as usize; + let target_end = targets.1 as usize; + + for &target in &serialized_dep_graph.edge_list_data[target_begin .. target_end] { + process_edge(tcx, + source, + target, + &serialized_dep_graph.nodes, + &dirty_raw_nodes, + &mut clean_work_products, + &mut dirty_work_products); } } - // Recreate bootstrap outputs, which are outputs that have no incoming edges (and hence cannot - // be dirty). + // Recreate bootstrap outputs, which are outputs that have no incoming edges + // (and hence cannot be dirty). for bootstrap_output in &serialized_dep_graph.bootstrap_outputs { if let DepKind::WorkProduct = bootstrap_output.kind { let wp_id = WorkProductId::from_fingerprint(bootstrap_output.hash); @@ -225,7 +212,9 @@ pub fn decode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // dirty. reconcile_work_products(tcx, work_products, &clean_work_products); - dirty_clean::check_dirty_clean_annotations(tcx, &dirty_raw_nodes); + dirty_clean::check_dirty_clean_annotations(tcx, + &serialized_dep_graph.nodes, + &dirty_raw_nodes); load_prev_metadata_hashes(tcx, &mut *incremental_hashes_map.prev_metadata_hashes.borrow_mut()); @@ -236,19 +225,20 @@ pub fn decode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, /// a bit vector where the index is the DefPathIndex. fn initial_dirty_nodes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, incremental_hashes_map: &IncrementalHashesMap, - serialized_hashes: &[SerializedHash]) + nodes: &IndexVec, + serialized_hashes: &[(DepNodeIndex, Fingerprint)]) -> DirtyNodes { let mut hcx = HashContext::new(tcx, incremental_hashes_map); let mut dirty_nodes = FxHashMap(); - for hash in serialized_hashes { - let dep_node = hash.dep_node; + for &(dep_node_index, prev_hash) in serialized_hashes { + let dep_node = nodes[dep_node_index]; if does_still_exist(tcx, &dep_node) { let current_hash = hcx.hash(&dep_node).unwrap_or_else(|| { bug!("Cannot find current ICH for input that still exists?") }); - if current_hash == hash.hash { + if current_hash == prev_hash { debug!("initial_dirty_nodes: {:?} is clean (hash={:?})", dep_node, current_hash); @@ -259,13 +249,13 @@ fn initial_dirty_nodes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, println!("node {:?} is dirty as hash is {:?}, was {:?}", dep_node, current_hash, - hash.hash); + prev_hash); } debug!("initial_dirty_nodes: {:?} is dirty as hash is {:?}, was {:?}", dep_node, current_hash, - hash.hash); + prev_hash); } else { if tcx.sess.opts.debugging_opts.incremental_dump_hash { println!("node {:?} is dirty as it was removed", dep_node); @@ -273,30 +263,27 @@ fn initial_dirty_nodes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, debug!("initial_dirty_nodes: {:?} is dirty as it was removed", dep_node); } - - dirty_nodes.insert(hash.dep_node.clone(), hash.dep_node.clone()); + dirty_nodes.insert(dep_node_index, dep_node_index); } dirty_nodes } -fn transitive_dirty_nodes(edge_map: &FxHashMap>, +fn transitive_dirty_nodes(serialized_dep_graph: &SerializedDepGraph, mut dirty_nodes: DirtyNodes) -> DirtyNodes { - let mut stack: Vec<(DepNode, DepNode)> = vec![]; - stack.extend(dirty_nodes.iter().map(|(s, b)| (s.clone(), b.clone()))); + let mut stack: Vec<(DepNodeIndex, DepNodeIndex)> = vec![]; + stack.extend(dirty_nodes.iter().map(|(&s, &b)| (s, b))); while let Some((source, blame)) = stack.pop() { // we know the source is dirty (because of the node `blame`)... - assert!(dirty_nodes.contains_key(&source)); + debug_assert!(dirty_nodes.contains_key(&source)); // ...so we dirty all the targets (with the same blame) - if let Some(targets) = edge_map.get(&source) { - for target in targets { - if !dirty_nodes.contains_key(target) { - dirty_nodes.insert(target.clone(), blame.clone()); - stack.push((target.clone(), blame.clone())); - } + for &target in serialized_dep_graph.edge_targets_from(source) { + if !dirty_nodes.contains_key(&target) { + dirty_nodes.insert(target, blame); + stack.push((target, blame)); } } } @@ -402,8 +389,9 @@ fn load_prev_metadata_hashes(tcx: TyCtxt, fn process_edge<'a, 'tcx, 'edges>( tcx: TyCtxt<'a, 'tcx, 'tcx>, - source: &'edges DepNode, - target: &'edges DepNode, + source: DepNodeIndex, + target: DepNodeIndex, + nodes: &IndexVec, dirty_raw_nodes: &DirtyNodes, clean_work_products: &mut FxHashSet, dirty_work_products: &mut FxHashSet) @@ -411,7 +399,8 @@ fn process_edge<'a, 'tcx, 'edges>( // If the target is dirty, skip the edge. If this is an edge // that targets a work-product, we can print the blame // information now. - if let Some(blame) = dirty_raw_nodes.get(target) { + if let Some(&blame) = dirty_raw_nodes.get(&target) { + let target = nodes[target]; if let DepKind::WorkProduct = target.kind { if tcx.sess.opts.debugging_opts.incremental_info { let wp_id = WorkProductId::from_fingerprint(target.hash); @@ -420,6 +409,7 @@ fn process_edge<'a, 'tcx, 'edges>( // Try to reconstruct the human-readable version of the // DepNode. This cannot be done for things that where // removed. + let blame = nodes[blame]; let blame_str = if let Some(def_id) = blame.extract_def_id(tcx) { format!("{:?}({})", blame.kind, @@ -444,21 +434,23 @@ fn process_edge<'a, 'tcx, 'edges>( // We should never have an edge where the target is clean but the source // was dirty. Otherwise something was wrong with the dirtying pass above: - debug_assert!(!dirty_raw_nodes.contains_key(source)); + debug_assert!(!dirty_raw_nodes.contains_key(&source)); // We also never should encounter an edge going from a removed input to a // clean target because removing the input would have dirtied the input // node and transitively dirtied the target. - debug_assert!(match source.kind { + debug_assert!(match nodes[source].kind { DepKind::Hir | DepKind::HirBody | DepKind::MetaData => { - does_still_exist(tcx, source) + does_still_exist(tcx, &nodes[source]) } _ => true, }); - if !dirty_raw_nodes.contains_key(target) { - let _task = tcx.dep_graph.in_task(*target); - tcx.dep_graph.read(*source); + if !dirty_raw_nodes.contains_key(&target) { + let target = nodes[target]; + let source = nodes[source]; + let _task = tcx.dep_graph.in_task(target); + tcx.dep_graph.read(source); if let DepKind::WorkProduct = target.kind { let wp_id = WorkProductId::from_fingerprint(target.hash); diff --git a/src/librustc_incremental/persist/save.rs b/src/librustc_incremental/persist/save.rs index 48742b424f1e..867452d97e8f 100644 --- a/src/librustc_incremental/persist/save.rs +++ b/src/librustc_incremental/persist/save.rs @@ -174,14 +174,14 @@ pub fn encode_dep_graph(tcx: TyCtxt, tcx.sess.opts.dep_tracking_hash().encode(encoder)?; // NB: We rely on this Vec being indexable by reduced_graph's NodeIndex. - let nodes: IndexVec = preds + let mut nodes: IndexVec = preds .reduced_graph .all_nodes() .iter() .map(|node| node.data.clone()) .collect(); - let mut edge_list_indices = Vec::with_capacity(nodes.len()); + let mut edge_list_indices = IndexVec::with_capacity(nodes.len()); let mut edge_list_data = Vec::with_capacity(preds.reduced_graph.len_edges()); for node_index in 0 .. nodes.len() { @@ -196,7 +196,7 @@ pub fn encode_dep_graph(tcx: TyCtxt, edge_list_indices.push((start, end)); } - // Let's make we had no overflow there. + // Let's make sure we had no overflow there. assert!(edge_list_data.len() <= ::std::u32::MAX as usize); // Check that we have a consistent number of edges. assert_eq!(edge_list_data.len(), preds.reduced_graph.len_edges()); @@ -206,23 +206,52 @@ pub fn encode_dep_graph(tcx: TyCtxt, .map(|dep_node| (**dep_node).clone()) .collect(); - let hashes = preds - .hashes - .iter() - .map(|(&dep_node, &hash)| { - SerializedHash { - dep_node: dep_node.clone(), - hash: hash, - } - }) - .collect(); + // Next, build the map of content hashes. To this end, we need to transform + // the (DepNode -> Fingerprint) map that we have into a + // (DepNodeIndex -> Fingerprint) map. This may necessitate adding nodes back + // to the dep-graph that have been filtered out during reduction. + let content_hashes = { + // We have to build a (DepNode -> DepNodeIndex) map. We over-allocate a + // little because we expect some more nodes to be added. + let capacity = (nodes.len() * 120) / 100; + let mut node_to_index = FxHashMap::with_capacity_and_hasher(capacity, + Default::default()); + // Add the nodes we already have in the graph. + node_to_index.extend(nodes.iter_enumerated() + .map(|(index, &node)| (node, index))); + + let mut content_hashes = Vec::with_capacity(preds.hashes.len()); + + for (&&dep_node, &hash) in preds.hashes.iter() { + let dep_node_index = *node_to_index + .entry(dep_node) + .or_insert_with(|| { + // There is no DepNodeIndex for this DepNode yet. This + // happens when the DepNode got filtered out during graph + // reduction. Since we have a content hash for the DepNode, + // we add it back to the graph. + let next_index = nodes.len(); + nodes.push(dep_node); + + debug_assert_eq!(next_index, edge_list_indices.len()); + // Push an empty list of edges + edge_list_indices.push((0,0)); + + DepNodeIndex::new(next_index) + }); + + content_hashes.push((dep_node_index, hash)); + } + + content_hashes + }; let graph = SerializedDepGraph { nodes, edge_list_indices, edge_list_data, bootstrap_outputs, - hashes, + hashes: content_hashes, }; // Encode the graph data. From d7c0d7569b47298da4a45dfd96275b9a888fe58c Mon Sep 17 00:00:00 2001 From: gentoo90 Date: Fri, 9 Jun 2017 18:51:28 +0300 Subject: [PATCH 094/233] Pretty-printers tests: gdbr -> gdb --- src/test/debuginfo/pretty-std.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/debuginfo/pretty-std.rs b/src/test/debuginfo/pretty-std.rs index 88a3c76b8581..9596f0287bc5 100644 --- a/src/test/debuginfo/pretty-std.rs +++ b/src/test/debuginfo/pretty-std.rs @@ -38,11 +38,11 @@ // gdbg-check:$6 = None // gdbr-check:$6 = core::option::Option::None -// gdbr-command: print os_string -// gdbr-check:$7 = "IAMA OS string 😃" +// gdb-command: print os_string +// gdb-check:$7 = "IAMA OS string 😃" -// gdbr-command: print some_string -// gdbr-check:$8 = Some = {"IAMA optional string!"} +// gdb-command: print some_string +// gdb-check:$8 = Some = {"IAMA optional string!"} // === LLDB TESTS ================================================================================== From 63076ddbb8e9856e9996adb49fc0a67a29ca697b Mon Sep 17 00:00:00 2001 From: gentoo90 Date: Fri, 9 Jun 2017 19:09:02 +0300 Subject: [PATCH 095/233] Add compat_str() which works with unicode in both Python 2 and 3 GDB can be built with Python 2 or with Python 3 --- src/etc/debugger_pretty_printers_common.py | 5 +++++ src/etc/gdb_rust_pretty_printing.py | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/etc/debugger_pretty_printers_common.py b/src/etc/debugger_pretty_printers_common.py index 7eb008a05f61..4a38d4be083f 100644 --- a/src/etc/debugger_pretty_printers_common.py +++ b/src/etc/debugger_pretty_printers_common.py @@ -354,3 +354,8 @@ def extract_type_name(qualified_type_name): return qualified_type_name else: return qualified_type_name[index + 2:] + +try: + compat_str = unicode # Python 2 +except NameError: + compat_str = str diff --git a/src/etc/gdb_rust_pretty_printing.py b/src/etc/gdb_rust_pretty_printing.py index aab15d9ed1e3..822dc5814047 100755 --- a/src/etc/gdb_rust_pretty_printing.py +++ b/src/etc/gdb_rust_pretty_printing.py @@ -78,7 +78,7 @@ class GdbValue(rustpp.Value): def as_integer(self): if self.gdb_val.type.code == gdb.TYPE_CODE_PTR: - as_str = unicode(self.gdb_val).split()[0] + as_str = rustpp.compat_str(self.gdb_val).split()[0] return int(as_str, 0) return int(self.gdb_val) From 1cd077dd40e5bed789f803733db999015b66eda1 Mon Sep 17 00:00:00 2001 From: arthurprs Date: Fri, 9 Jun 2017 20:23:38 +0200 Subject: [PATCH 096/233] Revert "Update jemalloc to 4.5.0" This reverts commit 65d0be3b7b540145c22409b1a79f7d263422e19b. --- src/jemalloc | 2 +- src/liballoc_jemalloc/build.rs | 24 +++++++++++++++++++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/jemalloc b/src/jemalloc index 3288e0659c08..11bfb0dcf85f 160000 --- a/src/jemalloc +++ b/src/jemalloc @@ -1 +1 @@ -Subproject commit 3288e0659c08fb5006f6d6dd4b5675ed0c2c432a +Subproject commit 11bfb0dcf85f7aa92abd30524bb1e42e18d108c6 diff --git a/src/liballoc_jemalloc/build.rs b/src/liballoc_jemalloc/build.rs index 859e414a6fe7..f3a0eebe6984 100644 --- a/src/liballoc_jemalloc/build.rs +++ b/src/liballoc_jemalloc/build.rs @@ -93,7 +93,29 @@ fn main() { .env("AR", &ar) .env("RANLIB", format!("{} s", ar.display())); - if target.contains("ios") { + if target.contains("windows") { + // A bit of history here, this used to be --enable-lazy-lock added in + // #14006 which was filed with jemalloc in jemalloc/jemalloc#83 which + // was also reported to MinGW: + // + // http://sourceforge.net/p/mingw-w64/bugs/395/ + // + // When updating jemalloc to 4.0, however, it was found that binaries + // would exit with the status code STATUS_RESOURCE_NOT_OWNED indicating + // that a thread was unlocking a mutex it never locked. Disabling this + // "lazy lock" option seems to fix the issue, but it was enabled by + // default for MinGW targets in 13473c7 for jemalloc. + // + // As a result of all that, force disabling lazy lock on Windows, and + // after reading some code it at least *appears* that the initialization + // of mutexes is otherwise ok in jemalloc, so shouldn't cause problems + // hopefully... + // + // tl;dr: make windows behave like other platforms by disabling lazy + // locking, but requires passing an option due to a historical + // default with jemalloc. + cmd.arg("--disable-lazy-lock"); + } else if target.contains("ios") { cmd.arg("--disable-tls"); } else if target.contains("android") { // We force android to have prefixed symbols because apparently From 496bd63f33ac649a637259ed359da7b9f1a65f80 Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Fri, 9 Jun 2017 22:20:32 +0200 Subject: [PATCH 097/233] Simplify FromIterator example of Result --- src/libcore/result.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/libcore/result.rs b/src/libcore/result.rs index df7fff0df927..88a93492de96 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -1060,12 +1060,9 @@ impl> FromIterator> for Result { /// checking for overflow: /// /// ``` - /// use std::u32; - /// /// let v = vec![1, 2]; - /// let res: Result, &'static str> = v.iter().map(|&x: &u32| - /// if x == u32::MAX { Err("Overflow!") } - /// else { Ok(x + 1) } + /// let res: Result, &'static str> = v.iter().map(|x: &u32| + /// x.checked_add(1).ok_or("Overflow!") /// ).collect(); /// assert!(res == Ok(vec![2, 3])); /// ``` @@ -1126,4 +1123,4 @@ impl ops::Try for Result { fn from_error(v: E) -> Self { Err(v) } -} \ No newline at end of file +} From 577c059d5040465bb35afaf605d0f5e49556982f Mon Sep 17 00:00:00 2001 From: Oliver Middleton Date: Fri, 9 Jun 2017 23:03:08 +0100 Subject: [PATCH 098/233] rustdoc: Use `create_dir_all` to create output directory Currently rustdoc will fail if passed `-o foo/doc` if the `foo` directory doesn't exist. Also remove unneeded `mkdir` as `create_dir_all` can now handle concurrent invocations. --- src/librustdoc/html/render.rs | 25 ++++--------------- .../run-make/rustdoc-output-path/Makefile | 4 +++ src/test/run-make/rustdoc-output-path/foo.rs | 11 ++++++++ 3 files changed, 20 insertions(+), 20 deletions(-) create mode 100644 src/test/run-make/rustdoc-output-path/Makefile create mode 100644 src/test/run-make/rustdoc-output-path/foo.rs diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index fea059e2757d..2b8a18eeb680 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -492,7 +492,7 @@ pub fn run(mut krate: clean::Crate, } } } - try_err!(mkdir(&dst), &dst); + try_err!(fs::create_dir_all(&dst), &dst); krate = render_sources(&dst, &mut scx, krate)?; let cx = Context { current: Vec::new(), @@ -658,7 +658,7 @@ fn write_shared(cx: &Context, // Write out the shared files. Note that these are shared among all rustdoc // docs placed in the output directory, so this needs to be a synchronized // operation with respect to all other rustdocs running around. - try_err!(mkdir(&cx.dst), &cx.dst); + try_err!(fs::create_dir_all(&cx.dst), &cx.dst); let _lock = flock::Lock::panicking_new(&cx.dst.join(".lock"), true, true, true); // Add all the static files. These may already exist, but we just @@ -808,10 +808,8 @@ fn write_shared(cx: &Context, fn render_sources(dst: &Path, scx: &mut SharedContext, krate: clean::Crate) -> Result { info!("emitting source files"); - let dst = dst.join("src"); - try_err!(mkdir(&dst), &dst); - let dst = dst.join(&krate.name); - try_err!(mkdir(&dst), &dst); + let dst = dst.join("src").join(&krate.name); + try_err!(fs::create_dir_all(&dst), &dst); let mut folder = SourceCollector { dst: dst, scx: scx, @@ -825,19 +823,6 @@ fn write(dst: PathBuf, contents: &[u8]) -> Result<(), Error> { Ok(try_err!(try_err!(File::create(&dst), &dst).write_all(contents), &dst)) } -/// Makes a directory on the filesystem, failing the thread if an error occurs -/// and skipping if the directory already exists. -/// -/// Note that this also handles races as rustdoc is likely to be run -/// concurrently against another invocation. -fn mkdir(path: &Path) -> io::Result<()> { - match fs::create_dir(path) { - Ok(()) => Ok(()), - Err(ref e) if e.kind() == io::ErrorKind::AlreadyExists => Ok(()), - Err(e) => Err(e) - } -} - /// Takes a path to a source file and cleans the path to it. This canonicalizes /// things like ".." to components which preserve the "top down" hierarchy of a /// static HTML tree. Each component in the cleaned path will be passed as an @@ -951,7 +936,7 @@ impl<'a> SourceCollector<'a> { let mut href = String::new(); clean_srcpath(&self.scx.src_root, &p, false, |component| { cur.push(component); - mkdir(&cur).unwrap(); + fs::create_dir_all(&cur).unwrap(); root_path.push_str("../"); href.push_str(component); href.push('/'); diff --git a/src/test/run-make/rustdoc-output-path/Makefile b/src/test/run-make/rustdoc-output-path/Makefile new file mode 100644 index 000000000000..4e570718a62f --- /dev/null +++ b/src/test/run-make/rustdoc-output-path/Makefile @@ -0,0 +1,4 @@ +-include ../tools.mk + +all: + $(HOST_RPATH_ENV) '$(RUSTDOC)' -o "$(TMPDIR)/foo/bar/doc" foo.rs diff --git a/src/test/run-make/rustdoc-output-path/foo.rs b/src/test/run-make/rustdoc-output-path/foo.rs new file mode 100644 index 000000000000..11fc2cd2b8d1 --- /dev/null +++ b/src/test/run-make/rustdoc-output-path/foo.rs @@ -0,0 +1,11 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub struct Foo; From b9c8e99955c03c61b514cc870d1462029ef956ff Mon Sep 17 00:00:00 2001 From: Clar Charr Date: Wed, 7 Jun 2017 21:59:57 -0400 Subject: [PATCH 099/233] Move Fn to module. --- src/libcore/ops/function.rs | 194 ++++++++++++++++++ src/libcore/ops/mod.rs | 189 +---------------- .../item-collection/function-as-argument.rs | 4 +- .../trait-method-as-argument.rs | 12 +- 4 files changed, 206 insertions(+), 193 deletions(-) create mode 100644 src/libcore/ops/function.rs diff --git a/src/libcore/ops/function.rs b/src/libcore/ops/function.rs new file mode 100644 index 000000000000..62bf69336a39 --- /dev/null +++ b/src/libcore/ops/function.rs @@ -0,0 +1,194 @@ +// 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. + +/// A version of the call operator that takes an immutable receiver. +/// +/// # Examples +/// +/// Closures automatically implement this trait, which allows them to be +/// invoked. Note, however, that `Fn` takes an immutable reference to any +/// captured variables. To take a mutable capture, implement [`FnMut`], and to +/// consume the capture, implement [`FnOnce`]. +/// +/// [`FnMut`]: trait.FnMut.html +/// [`FnOnce`]: trait.FnOnce.html +/// +/// ``` +/// let square = |x| x * x; +/// assert_eq!(square(5), 25); +/// ``` +/// +/// Closures can also be passed to higher-level functions through a `Fn` +/// parameter (or a `FnMut` or `FnOnce` parameter, which are supertraits of +/// `Fn`). +/// +/// ``` +/// fn call_with_one(func: F) -> usize +/// where F: Fn(usize) -> usize { +/// func(1) +/// } +/// +/// let double = |x| x * 2; +/// assert_eq!(call_with_one(double), 2); +/// ``` +#[lang = "fn"] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_paren_sugar] +#[fundamental] // so that regex can rely that `&str: !FnMut` +pub trait Fn : FnMut { + /// This is called when the call operator is used. + #[unstable(feature = "fn_traits", issue = "29625")] + extern "rust-call" fn call(&self, args: Args) -> Self::Output; +} + +/// A version of the call operator that takes a mutable receiver. +/// +/// # Examples +/// +/// Closures that mutably capture variables automatically implement this trait, +/// which allows them to be invoked. +/// +/// ``` +/// let mut x = 5; +/// { +/// let mut square_x = || x *= x; +/// square_x(); +/// } +/// assert_eq!(x, 25); +/// ``` +/// +/// Closures can also be passed to higher-level functions through a `FnMut` +/// parameter (or a `FnOnce` parameter, which is a supertrait of `FnMut`). +/// +/// ``` +/// fn do_twice(mut func: F) +/// where F: FnMut() +/// { +/// func(); +/// func(); +/// } +/// +/// let mut x: usize = 1; +/// { +/// let add_two_to_x = || x += 2; +/// do_twice(add_two_to_x); +/// } +/// +/// assert_eq!(x, 5); +/// ``` +#[lang = "fn_mut"] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_paren_sugar] +#[fundamental] // so that regex can rely that `&str: !FnMut` +pub trait FnMut : FnOnce { + /// This is called when the call operator is used. + #[unstable(feature = "fn_traits", issue = "29625")] + extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output; +} + +/// A version of the call operator that takes a by-value receiver. +/// +/// # Examples +/// +/// By-value closures automatically implement this trait, which allows them to +/// be invoked. +/// +/// ``` +/// let x = 5; +/// let square_x = move || x * x; +/// assert_eq!(square_x(), 25); +/// ``` +/// +/// By-value Closures can also be passed to higher-level functions through a +/// `FnOnce` parameter. +/// +/// ``` +/// fn consume_with_relish(func: F) +/// where F: FnOnce() -> String +/// { +/// // `func` consumes its captured variables, so it cannot be run more +/// // than once +/// println!("Consumed: {}", func()); +/// +/// println!("Delicious!"); +/// +/// // Attempting to invoke `func()` again will throw a `use of moved +/// // value` error for `func` +/// } +/// +/// let x = String::from("x"); +/// let consume_and_return_x = move || x; +/// consume_with_relish(consume_and_return_x); +/// +/// // `consume_and_return_x` can no longer be invoked at this point +/// ``` +#[lang = "fn_once"] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_paren_sugar] +#[fundamental] // so that regex can rely that `&str: !FnMut` +pub trait FnOnce { + /// The returned type after the call operator is used. + #[stable(feature = "fn_once_output", since = "1.12.0")] + type Output; + + /// This is called when the call operator is used. + #[unstable(feature = "fn_traits", issue = "29625")] + extern "rust-call" fn call_once(self, args: Args) -> Self::Output; +} + +mod impls { + #[stable(feature = "rust1", since = "1.0.0")] + impl<'a,A,F:?Sized> Fn for &'a F + where F : Fn + { + extern "rust-call" fn call(&self, args: A) -> F::Output { + (**self).call(args) + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl<'a,A,F:?Sized> FnMut for &'a F + where F : Fn + { + extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output { + (**self).call(args) + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl<'a,A,F:?Sized> FnOnce for &'a F + where F : Fn + { + type Output = F::Output; + + extern "rust-call" fn call_once(self, args: A) -> F::Output { + (*self).call(args) + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl<'a,A,F:?Sized> FnMut for &'a mut F + where F : FnMut + { + extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output { + (*self).call_mut(args) + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl<'a,A,F:?Sized> FnOnce for &'a mut F + where F : FnMut + { + type Output = F::Output; + extern "rust-call" fn call_once(mut self, args: A) -> F::Output { + (*self).call_mut(args) + } + } +} diff --git a/src/libcore/ops/mod.rs b/src/libcore/ops/mod.rs index e67add65ab36..7f452fd791fb 100644 --- a/src/libcore/ops/mod.rs +++ b/src/libcore/ops/mod.rs @@ -147,8 +147,12 @@ #![stable(feature = "rust1", since = "1.0.0")] +mod function; mod range; +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::function::{Fn, FnMut, FnOnce}; + #[stable(feature = "rust1", since = "1.0.0")] pub use self::range::{Range, RangeFrom, RangeFull, RangeTo}; @@ -2200,191 +2204,6 @@ impl<'a, T: ?Sized> DerefMut for &'a mut T { fn deref_mut(&mut self) -> &mut T { *self } } -/// A version of the call operator that takes an immutable receiver. -/// -/// # Examples -/// -/// Closures automatically implement this trait, which allows them to be -/// invoked. Note, however, that `Fn` takes an immutable reference to any -/// captured variables. To take a mutable capture, implement [`FnMut`], and to -/// consume the capture, implement [`FnOnce`]. -/// -/// [`FnMut`]: trait.FnMut.html -/// [`FnOnce`]: trait.FnOnce.html -/// -/// ``` -/// let square = |x| x * x; -/// assert_eq!(square(5), 25); -/// ``` -/// -/// Closures can also be passed to higher-level functions through a `Fn` -/// parameter (or a `FnMut` or `FnOnce` parameter, which are supertraits of -/// `Fn`). -/// -/// ``` -/// fn call_with_one(func: F) -> usize -/// where F: Fn(usize) -> usize { -/// func(1) -/// } -/// -/// let double = |x| x * 2; -/// assert_eq!(call_with_one(double), 2); -/// ``` -#[lang = "fn"] -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_paren_sugar] -#[fundamental] // so that regex can rely that `&str: !FnMut` -pub trait Fn : FnMut { - /// This is called when the call operator is used. - #[unstable(feature = "fn_traits", issue = "29625")] - extern "rust-call" fn call(&self, args: Args) -> Self::Output; -} - -/// A version of the call operator that takes a mutable receiver. -/// -/// # Examples -/// -/// Closures that mutably capture variables automatically implement this trait, -/// which allows them to be invoked. -/// -/// ``` -/// let mut x = 5; -/// { -/// let mut square_x = || x *= x; -/// square_x(); -/// } -/// assert_eq!(x, 25); -/// ``` -/// -/// Closures can also be passed to higher-level functions through a `FnMut` -/// parameter (or a `FnOnce` parameter, which is a supertrait of `FnMut`). -/// -/// ``` -/// fn do_twice(mut func: F) -/// where F: FnMut() -/// { -/// func(); -/// func(); -/// } -/// -/// let mut x: usize = 1; -/// { -/// let add_two_to_x = || x += 2; -/// do_twice(add_two_to_x); -/// } -/// -/// assert_eq!(x, 5); -/// ``` -#[lang = "fn_mut"] -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_paren_sugar] -#[fundamental] // so that regex can rely that `&str: !FnMut` -pub trait FnMut : FnOnce { - /// This is called when the call operator is used. - #[unstable(feature = "fn_traits", issue = "29625")] - extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output; -} - -/// A version of the call operator that takes a by-value receiver. -/// -/// # Examples -/// -/// By-value closures automatically implement this trait, which allows them to -/// be invoked. -/// -/// ``` -/// let x = 5; -/// let square_x = move || x * x; -/// assert_eq!(square_x(), 25); -/// ``` -/// -/// By-value Closures can also be passed to higher-level functions through a -/// `FnOnce` parameter. -/// -/// ``` -/// fn consume_with_relish(func: F) -/// where F: FnOnce() -> String -/// { -/// // `func` consumes its captured variables, so it cannot be run more -/// // than once -/// println!("Consumed: {}", func()); -/// -/// println!("Delicious!"); -/// -/// // Attempting to invoke `func()` again will throw a `use of moved -/// // value` error for `func` -/// } -/// -/// let x = String::from("x"); -/// let consume_and_return_x = move || x; -/// consume_with_relish(consume_and_return_x); -/// -/// // `consume_and_return_x` can no longer be invoked at this point -/// ``` -#[lang = "fn_once"] -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_paren_sugar] -#[fundamental] // so that regex can rely that `&str: !FnMut` -pub trait FnOnce { - /// The returned type after the call operator is used. - #[stable(feature = "fn_once_output", since = "1.12.0")] - type Output; - - /// This is called when the call operator is used. - #[unstable(feature = "fn_traits", issue = "29625")] - extern "rust-call" fn call_once(self, args: Args) -> Self::Output; -} - -mod impls { - #[stable(feature = "rust1", since = "1.0.0")] - impl<'a,A,F:?Sized> Fn for &'a F - where F : Fn - { - extern "rust-call" fn call(&self, args: A) -> F::Output { - (**self).call(args) - } - } - - #[stable(feature = "rust1", since = "1.0.0")] - impl<'a,A,F:?Sized> FnMut for &'a F - where F : Fn - { - extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output { - (**self).call(args) - } - } - - #[stable(feature = "rust1", since = "1.0.0")] - impl<'a,A,F:?Sized> FnOnce for &'a F - where F : Fn - { - type Output = F::Output; - - extern "rust-call" fn call_once(self, args: A) -> F::Output { - (*self).call(args) - } - } - - #[stable(feature = "rust1", since = "1.0.0")] - impl<'a,A,F:?Sized> FnMut for &'a mut F - where F : FnMut - { - extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output { - (*self).call_mut(args) - } - } - - #[stable(feature = "rust1", since = "1.0.0")] - impl<'a,A,F:?Sized> FnOnce for &'a mut F - where F : FnMut - { - type Output = F::Output; - extern "rust-call" fn call_once(mut self, args: A) -> F::Output { - (*self).call_mut(args) - } - } -} - /// Trait that indicates that this is a pointer or a wrapper for one, /// where unsizing can be performed on the pointee. /// diff --git a/src/test/codegen-units/item-collection/function-as-argument.rs b/src/test/codegen-units/item-collection/function-as-argument.rs index c4aed7465bcb..c3d46ff5314f 100644 --- a/src/test/codegen-units/item-collection/function-as-argument.rs +++ b/src/test/codegen-units/item-collection/function-as-argument.rs @@ -28,12 +28,12 @@ fn main() { //~ TRANS_ITEM fn function_as_argument::take_fn_once[0] //~ TRANS_ITEM fn function_as_argument::function[0] - //~ TRANS_ITEM fn core::ops[0]::FnOnce[0]::call_once[0] + //~ TRANS_ITEM fn core::ops[0]::function[0]::FnOnce[0]::call_once[0] take_fn_once(function, 0u32, "abc"); //~ TRANS_ITEM fn function_as_argument::take_fn_once[0] //~ TRANS_ITEM fn function_as_argument::function[0] - //~ TRANS_ITEM fn core::ops[0]::FnOnce[0]::call_once[0] + //~ TRANS_ITEM fn core::ops[0]::function[0]::FnOnce[0]::call_once[0] take_fn_once(function, 'c', 0f64); //~ TRANS_ITEM fn function_as_argument::take_fn_pointer[0] diff --git a/src/test/codegen-units/item-collection/trait-method-as-argument.rs b/src/test/codegen-units/item-collection/trait-method-as-argument.rs index f095b637a84e..21c9c254e51c 100644 --- a/src/test/codegen-units/item-collection/trait-method-as-argument.rs +++ b/src/test/codegen-units/item-collection/trait-method-as-argument.rs @@ -40,27 +40,27 @@ fn take_foo_mut T>(mut f: F, arg: T) -> T { fn main() { //~ TRANS_ITEM fn trait_method_as_argument::take_foo_once[0] u32> //~ TRANS_ITEM fn trait_method_as_argument::{{impl}}[0]::foo[0] - //~ TRANS_ITEM fn core::ops[0]::FnOnce[0]::call_once[0] u32, (u32)> + //~ TRANS_ITEM fn core::ops[0]::function[0]::FnOnce[0]::call_once[0] u32, (u32)> take_foo_once(Trait::foo, 0u32); //~ TRANS_ITEM fn trait_method_as_argument::take_foo_once[0] char> //~ TRANS_ITEM fn trait_method_as_argument::Trait[0]::foo[0] - //~ TRANS_ITEM fn core::ops[0]::FnOnce[0]::call_once[0] char, (char)> + //~ TRANS_ITEM fn core::ops[0]::function[0]::FnOnce[0]::call_once[0] char, (char)> take_foo_once(Trait::foo, 'c'); //~ TRANS_ITEM fn trait_method_as_argument::take_foo[0] u32> - //~ TRANS_ITEM fn core::ops[0]::Fn[0]::call[0] u32, (u32)> + //~ TRANS_ITEM fn core::ops[0]::function[0]::Fn[0]::call[0] u32, (u32)> take_foo(Trait::foo, 0u32); //~ TRANS_ITEM fn trait_method_as_argument::take_foo[0] char> - //~ TRANS_ITEM fn core::ops[0]::Fn[0]::call[0] char, (char)> + //~ TRANS_ITEM fn core::ops[0]::function[0]::Fn[0]::call[0] char, (char)> take_foo(Trait::foo, 'c'); //~ TRANS_ITEM fn trait_method_as_argument::take_foo_mut[0] u32> - //~ TRANS_ITEM fn core::ops[0]::FnMut[0]::call_mut[0] char, (char)> + //~ TRANS_ITEM fn core::ops[0]::function[0]::FnMut[0]::call_mut[0] char, (char)> take_foo_mut(Trait::foo, 0u32); //~ TRANS_ITEM fn trait_method_as_argument::take_foo_mut[0] char> - //~ TRANS_ITEM fn core::ops[0]::FnMut[0]::call_mut[0] u32, (u32)> + //~ TRANS_ITEM fn core::ops[0]::function[0]::FnMut[0]::call_mut[0] u32, (u32)> take_foo_mut(Trait::foo, 'c'); } From 75677e0646a3e110c22b56145b5c586c1f87a741 Mon Sep 17 00:00:00 2001 From: Clar Charr Date: Wed, 7 Jun 2017 22:04:46 -0400 Subject: [PATCH 100/233] Move arithmetic ops to module. --- src/libcore/ops/arith.rs | 873 +++++++++++++++++++++++++++++++++++++++ src/libcore/ops/mod.rs | 871 +------------------------------------- 2 files changed, 880 insertions(+), 864 deletions(-) create mode 100644 src/libcore/ops/arith.rs diff --git a/src/libcore/ops/arith.rs b/src/libcore/ops/arith.rs new file mode 100644 index 000000000000..c6fb75f6acef --- /dev/null +++ b/src/libcore/ops/arith.rs @@ -0,0 +1,873 @@ +// 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. + +/// The addition operator `+`. +/// +/// # Examples +/// +/// This example creates a `Point` struct that implements the `Add` trait, and +/// then demonstrates adding two `Point`s. +/// +/// ``` +/// use std::ops::Add; +/// +/// #[derive(Debug)] +/// struct Point { +/// x: i32, +/// y: i32, +/// } +/// +/// impl Add for Point { +/// type Output = Point; +/// +/// fn add(self, other: Point) -> Point { +/// Point { +/// x: self.x + other.x, +/// y: self.y + other.y, +/// } +/// } +/// } +/// +/// impl PartialEq for Point { +/// fn eq(&self, other: &Self) -> bool { +/// self.x == other.x && self.y == other.y +/// } +/// } +/// +/// fn main() { +/// assert_eq!(Point { x: 1, y: 0 } + Point { x: 2, y: 3 }, +/// Point { x: 3, y: 3 }); +/// } +/// ``` +/// +/// Here is an example of the same `Point` struct implementing the `Add` trait +/// using generics. +/// +/// ``` +/// use std::ops::Add; +/// +/// #[derive(Debug)] +/// struct Point { +/// x: T, +/// y: T, +/// } +/// +/// // Notice that the implementation uses the `Output` associated type +/// impl> Add for Point { +/// type Output = Point; +/// +/// fn add(self, other: Point) -> Point { +/// Point { +/// x: self.x + other.x, +/// y: self.y + other.y, +/// } +/// } +/// } +/// +/// impl PartialEq for Point { +/// fn eq(&self, other: &Self) -> bool { +/// self.x == other.x && self.y == other.y +/// } +/// } +/// +/// fn main() { +/// assert_eq!(Point { x: 1, y: 0 } + Point { x: 2, y: 3 }, +/// Point { x: 3, y: 3 }); +/// } +/// ``` +/// +/// Note that `RHS = Self` by default, but this is not mandatory. For example, +/// [std::time::SystemTime] implements `Add`, which permits +/// operations of the form `SystemTime = SystemTime + Duration`. +/// +/// [std::time::SystemTime]: ../../std/time/struct.SystemTime.html +#[lang = "add"] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} + {RHS}`"] +pub trait Add { + /// The resulting type after applying the `+` operator + #[stable(feature = "rust1", since = "1.0.0")] + type Output; + + /// The method for the `+` operator + #[stable(feature = "rust1", since = "1.0.0")] + fn add(self, rhs: RHS) -> Self::Output; +} + +macro_rules! add_impl { + ($($t:ty)*) => ($( + #[stable(feature = "rust1", since = "1.0.0")] + impl Add for $t { + type Output = $t; + + #[inline] + #[rustc_inherit_overflow_checks] + fn add(self, other: $t) -> $t { self + other } + } + + forward_ref_binop! { impl Add, add for $t, $t } + )*) +} + +add_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } + +/// The subtraction operator `-`. +/// +/// # Examples +/// +/// This example creates a `Point` struct that implements the `Sub` trait, and +/// then demonstrates subtracting two `Point`s. +/// +/// ``` +/// use std::ops::Sub; +/// +/// #[derive(Debug)] +/// struct Point { +/// x: i32, +/// y: i32, +/// } +/// +/// impl Sub for Point { +/// type Output = Point; +/// +/// fn sub(self, other: Point) -> Point { +/// Point { +/// x: self.x - other.x, +/// y: self.y - other.y, +/// } +/// } +/// } +/// +/// impl PartialEq for Point { +/// fn eq(&self, other: &Self) -> bool { +/// self.x == other.x && self.y == other.y +/// } +/// } +/// +/// fn main() { +/// assert_eq!(Point { x: 3, y: 3 } - Point { x: 2, y: 3 }, +/// Point { x: 1, y: 0 }); +/// } +/// ``` +/// +/// Note that `RHS = Self` by default, but this is not mandatory. For example, +/// [std::time::SystemTime] implements `Sub`, which permits +/// operations of the form `SystemTime = SystemTime - Duration`. +/// +/// [std::time::SystemTime]: ../../std/time/struct.SystemTime.html +#[lang = "sub"] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} - {RHS}`"] +pub trait Sub { + /// The resulting type after applying the `-` operator + #[stable(feature = "rust1", since = "1.0.0")] + type Output; + + /// The method for the `-` operator + #[stable(feature = "rust1", since = "1.0.0")] + fn sub(self, rhs: RHS) -> Self::Output; +} + +macro_rules! sub_impl { + ($($t:ty)*) => ($( + #[stable(feature = "rust1", since = "1.0.0")] + impl Sub for $t { + type Output = $t; + + #[inline] + #[rustc_inherit_overflow_checks] + fn sub(self, other: $t) -> $t { self - other } + } + + forward_ref_binop! { impl Sub, sub for $t, $t } + )*) +} + +sub_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } + +/// The multiplication operator `*`. +/// +/// # Examples +/// +/// Implementing a `Mul`tipliable rational number struct: +/// +/// ``` +/// use std::ops::Mul; +/// +/// // The uniqueness of rational numbers in lowest terms is a consequence of +/// // the fundamental theorem of arithmetic. +/// #[derive(Eq)] +/// #[derive(PartialEq, Debug)] +/// struct Rational { +/// nominator: usize, +/// denominator: usize, +/// } +/// +/// impl Rational { +/// fn new(nominator: usize, denominator: usize) -> Self { +/// if denominator == 0 { +/// panic!("Zero is an invalid denominator!"); +/// } +/// +/// // Reduce to lowest terms by dividing by the greatest common +/// // divisor. +/// let gcd = gcd(nominator, denominator); +/// Rational { +/// nominator: nominator / gcd, +/// denominator: denominator / gcd, +/// } +/// } +/// } +/// +/// impl Mul for Rational { +/// // The multiplication of rational numbers is a closed operation. +/// type Output = Self; +/// +/// fn mul(self, rhs: Self) -> Self { +/// let nominator = self.nominator * rhs.nominator; +/// let denominator = self.denominator * rhs.denominator; +/// Rational::new(nominator, denominator) +/// } +/// } +/// +/// // Euclid's two-thousand-year-old algorithm for finding the greatest common +/// // divisor. +/// fn gcd(x: usize, y: usize) -> usize { +/// let mut x = x; +/// let mut y = y; +/// while y != 0 { +/// let t = y; +/// y = x % y; +/// x = t; +/// } +/// x +/// } +/// +/// assert_eq!(Rational::new(1, 2), Rational::new(2, 4)); +/// assert_eq!(Rational::new(2, 3) * Rational::new(3, 4), +/// Rational::new(1, 2)); +/// ``` +/// +/// Note that `RHS = Self` by default, but this is not mandatory. Here is an +/// implementation which enables multiplication of vectors by scalars, as is +/// done in linear algebra. +/// +/// ``` +/// use std::ops::Mul; +/// +/// struct Scalar {value: usize}; +/// +/// #[derive(Debug)] +/// struct Vector {value: Vec}; +/// +/// impl Mul for Scalar { +/// type Output = Vector; +/// +/// fn mul(self, rhs: Vector) -> Vector { +/// Vector {value: rhs.value.iter().map(|v| self.value * v).collect()} +/// } +/// } +/// +/// impl PartialEq for Vector { +/// fn eq(&self, other: &Self) -> bool { +/// self.value == other.value +/// } +/// } +/// +/// let scalar = Scalar{value: 3}; +/// let vector = Vector{value: vec![2, 4, 6]}; +/// assert_eq!(scalar * vector, Vector{value: vec![6, 12, 18]}); +/// ``` +#[lang = "mul"] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} * {RHS}`"] +pub trait Mul { + /// The resulting type after applying the `*` operator + #[stable(feature = "rust1", since = "1.0.0")] + type Output; + + /// The method for the `*` operator + #[stable(feature = "rust1", since = "1.0.0")] + fn mul(self, rhs: RHS) -> Self::Output; +} + +macro_rules! mul_impl { + ($($t:ty)*) => ($( + #[stable(feature = "rust1", since = "1.0.0")] + impl Mul for $t { + type Output = $t; + + #[inline] + #[rustc_inherit_overflow_checks] + fn mul(self, other: $t) -> $t { self * other } + } + + forward_ref_binop! { impl Mul, mul for $t, $t } + )*) +} + +mul_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } + +/// The division operator `/`. +/// +/// # Examples +/// +/// Implementing a `Div`idable rational number struct: +/// +/// ``` +/// use std::ops::Div; +/// +/// // The uniqueness of rational numbers in lowest terms is a consequence of +/// // the fundamental theorem of arithmetic. +/// #[derive(Eq)] +/// #[derive(PartialEq, Debug)] +/// struct Rational { +/// nominator: usize, +/// denominator: usize, +/// } +/// +/// impl Rational { +/// fn new(nominator: usize, denominator: usize) -> Self { +/// if denominator == 0 { +/// panic!("Zero is an invalid denominator!"); +/// } +/// +/// // Reduce to lowest terms by dividing by the greatest common +/// // divisor. +/// let gcd = gcd(nominator, denominator); +/// Rational { +/// nominator: nominator / gcd, +/// denominator: denominator / gcd, +/// } +/// } +/// } +/// +/// impl Div for Rational { +/// // The division of rational numbers is a closed operation. +/// type Output = Self; +/// +/// fn div(self, rhs: Self) -> Self { +/// if rhs.nominator == 0 { +/// panic!("Cannot divide by zero-valued `Rational`!"); +/// } +/// +/// let nominator = self.nominator * rhs.denominator; +/// let denominator = self.denominator * rhs.nominator; +/// Rational::new(nominator, denominator) +/// } +/// } +/// +/// // Euclid's two-thousand-year-old algorithm for finding the greatest common +/// // divisor. +/// fn gcd(x: usize, y: usize) -> usize { +/// let mut x = x; +/// let mut y = y; +/// while y != 0 { +/// let t = y; +/// y = x % y; +/// x = t; +/// } +/// x +/// } +/// +/// fn main() { +/// assert_eq!(Rational::new(1, 2), Rational::new(2, 4)); +/// assert_eq!(Rational::new(1, 2) / Rational::new(3, 4), +/// Rational::new(2, 3)); +/// } +/// ``` +/// +/// Note that `RHS = Self` by default, but this is not mandatory. Here is an +/// implementation which enables division of vectors by scalars, as is done in +/// linear algebra. +/// +/// ``` +/// use std::ops::Div; +/// +/// struct Scalar {value: f32}; +/// +/// #[derive(Debug)] +/// struct Vector {value: Vec}; +/// +/// impl Div for Vector { +/// type Output = Vector; +/// +/// fn div(self, rhs: Scalar) -> Vector { +/// Vector {value: self.value.iter().map(|v| v / rhs.value).collect()} +/// } +/// } +/// +/// impl PartialEq for Vector { +/// fn eq(&self, other: &Self) -> bool { +/// self.value == other.value +/// } +/// } +/// +/// let scalar = Scalar{value: 2f32}; +/// let vector = Vector{value: vec![2f32, 4f32, 6f32]}; +/// assert_eq!(vector / scalar, Vector{value: vec![1f32, 2f32, 3f32]}); +/// ``` +#[lang = "div"] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} / {RHS}`"] +pub trait Div { + /// The resulting type after applying the `/` operator + #[stable(feature = "rust1", since = "1.0.0")] + type Output; + + /// The method for the `/` operator + #[stable(feature = "rust1", since = "1.0.0")] + fn div(self, rhs: RHS) -> Self::Output; +} + +macro_rules! div_impl_integer { + ($($t:ty)*) => ($( + /// This operation rounds towards zero, truncating any + /// fractional part of the exact result. + #[stable(feature = "rust1", since = "1.0.0")] + impl Div for $t { + type Output = $t; + + #[inline] + fn div(self, other: $t) -> $t { self / other } + } + + forward_ref_binop! { impl Div, div for $t, $t } + )*) +} + +div_impl_integer! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } + +macro_rules! div_impl_float { + ($($t:ty)*) => ($( + #[stable(feature = "rust1", since = "1.0.0")] + impl Div for $t { + type Output = $t; + + #[inline] + fn div(self, other: $t) -> $t { self / other } + } + + forward_ref_binop! { impl Div, div for $t, $t } + )*) +} + +div_impl_float! { f32 f64 } + +/// The remainder operator `%`. +/// +/// # Examples +/// +/// This example implements `Rem` on a `SplitSlice` object. After `Rem` is +/// implemented, one can use the `%` operator to find out what the remaining +/// elements of the slice would be after splitting it into equal slices of a +/// given length. +/// +/// ``` +/// use std::ops::Rem; +/// +/// #[derive(PartialEq, Debug)] +/// struct SplitSlice<'a, T: 'a> { +/// slice: &'a [T], +/// } +/// +/// impl<'a, T> Rem for SplitSlice<'a, T> { +/// type Output = SplitSlice<'a, T>; +/// +/// fn rem(self, modulus: usize) -> Self { +/// let len = self.slice.len(); +/// let rem = len % modulus; +/// let start = len - rem; +/// SplitSlice {slice: &self.slice[start..]} +/// } +/// } +/// +/// // If we were to divide &[0, 1, 2, 3, 4, 5, 6, 7] into slices of size 3, +/// // the remainder would be &[6, 7] +/// assert_eq!(SplitSlice { slice: &[0, 1, 2, 3, 4, 5, 6, 7] } % 3, +/// SplitSlice { slice: &[6, 7] }); +/// ``` +#[lang = "rem"] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} % {RHS}`"] +pub trait Rem { + /// The resulting type after applying the `%` operator + #[stable(feature = "rust1", since = "1.0.0")] + type Output = Self; + + /// The method for the `%` operator + #[stable(feature = "rust1", since = "1.0.0")] + fn rem(self, rhs: RHS) -> Self::Output; +} + +macro_rules! rem_impl_integer { + ($($t:ty)*) => ($( + /// This operation satisfies `n % d == n - (n / d) * d`. The + /// result has the same sign as the left operand. + #[stable(feature = "rust1", since = "1.0.0")] + impl Rem for $t { + type Output = $t; + + #[inline] + fn rem(self, other: $t) -> $t { self % other } + } + + forward_ref_binop! { impl Rem, rem for $t, $t } + )*) +} + +rem_impl_integer! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } + + +macro_rules! rem_impl_float { + ($($t:ty)*) => ($( + #[stable(feature = "rust1", since = "1.0.0")] + impl Rem for $t { + type Output = $t; + + #[inline] + fn rem(self, other: $t) -> $t { self % other } + } + + forward_ref_binop! { impl Rem, rem for $t, $t } + )*) +} + +rem_impl_float! { f32 f64 } + +/// The unary negation operator `-`. +/// +/// # Examples +/// +/// An implementation of `Neg` for `Sign`, which allows the use of `-` to +/// negate its value. +/// +/// ``` +/// use std::ops::Neg; +/// +/// #[derive(Debug, PartialEq)] +/// enum Sign { +/// Negative, +/// Zero, +/// Positive, +/// } +/// +/// impl Neg for Sign { +/// type Output = Sign; +/// +/// fn neg(self) -> Sign { +/// match self { +/// Sign::Negative => Sign::Positive, +/// Sign::Zero => Sign::Zero, +/// Sign::Positive => Sign::Negative, +/// } +/// } +/// } +/// +/// // a negative positive is a negative +/// assert_eq!(-Sign::Positive, Sign::Negative); +/// // a double negative is a positive +/// assert_eq!(-Sign::Negative, Sign::Positive); +/// // zero is its own negation +/// assert_eq!(-Sign::Zero, Sign::Zero); +/// ``` +#[lang = "neg"] +#[stable(feature = "rust1", since = "1.0.0")] +pub trait Neg { + /// The resulting type after applying the `-` operator + #[stable(feature = "rust1", since = "1.0.0")] + type Output; + + /// The method for the unary `-` operator + #[stable(feature = "rust1", since = "1.0.0")] + fn neg(self) -> Self::Output; +} + + + +macro_rules! neg_impl_core { + ($id:ident => $body:expr, $($t:ty)*) => ($( + #[stable(feature = "rust1", since = "1.0.0")] + impl Neg for $t { + type Output = $t; + + #[inline] + #[rustc_inherit_overflow_checks] + fn neg(self) -> $t { let $id = self; $body } + } + + forward_ref_unop! { impl Neg, neg for $t } + )*) +} + +macro_rules! neg_impl_numeric { + ($($t:ty)*) => { neg_impl_core!{ x => -x, $($t)*} } +} + +#[allow(unused_macros)] +macro_rules! neg_impl_unsigned { + ($($t:ty)*) => { + neg_impl_core!{ x => { + !x.wrapping_add(1) + }, $($t)*} } +} + +// neg_impl_unsigned! { usize u8 u16 u32 u64 } +neg_impl_numeric! { isize i8 i16 i32 i64 i128 f32 f64 } + +/// The addition assignment operator `+=`. +/// +/// # Examples +/// +/// This example creates a `Point` struct that implements the `AddAssign` +/// trait, and then demonstrates add-assigning to a mutable `Point`. +/// +/// ``` +/// use std::ops::AddAssign; +/// +/// #[derive(Debug)] +/// struct Point { +/// x: i32, +/// y: i32, +/// } +/// +/// impl AddAssign for Point { +/// fn add_assign(&mut self, other: Point) { +/// *self = Point { +/// x: self.x + other.x, +/// y: self.y + other.y, +/// }; +/// } +/// } +/// +/// impl PartialEq for Point { +/// fn eq(&self, other: &Self) -> bool { +/// self.x == other.x && self.y == other.y +/// } +/// } +/// +/// let mut point = Point { x: 1, y: 0 }; +/// point += Point { x: 2, y: 3 }; +/// assert_eq!(point, Point { x: 3, y: 3 }); +/// ``` +#[lang = "add_assign"] +#[stable(feature = "op_assign_traits", since = "1.8.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} += {Rhs}`"] +pub trait AddAssign { + /// The method for the `+=` operator + #[stable(feature = "op_assign_traits", since = "1.8.0")] + fn add_assign(&mut self, rhs: Rhs); +} + +macro_rules! add_assign_impl { + ($($t:ty)+) => ($( + #[stable(feature = "op_assign_traits", since = "1.8.0")] + impl AddAssign for $t { + #[inline] + #[rustc_inherit_overflow_checks] + fn add_assign(&mut self, other: $t) { *self += other } + } + )+) +} + +add_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } + +/// The subtraction assignment operator `-=`. +/// +/// # Examples +/// +/// This example creates a `Point` struct that implements the `SubAssign` +/// trait, and then demonstrates sub-assigning to a mutable `Point`. +/// +/// ``` +/// use std::ops::SubAssign; +/// +/// #[derive(Debug)] +/// struct Point { +/// x: i32, +/// y: i32, +/// } +/// +/// impl SubAssign for Point { +/// fn sub_assign(&mut self, other: Point) { +/// *self = Point { +/// x: self.x - other.x, +/// y: self.y - other.y, +/// }; +/// } +/// } +/// +/// impl PartialEq for Point { +/// fn eq(&self, other: &Self) -> bool { +/// self.x == other.x && self.y == other.y +/// } +/// } +/// +/// let mut point = Point { x: 3, y: 3 }; +/// point -= Point { x: 2, y: 3 }; +/// assert_eq!(point, Point {x: 1, y: 0}); +/// ``` +#[lang = "sub_assign"] +#[stable(feature = "op_assign_traits", since = "1.8.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} -= {Rhs}`"] +pub trait SubAssign { + /// The method for the `-=` operator + #[stable(feature = "op_assign_traits", since = "1.8.0")] + fn sub_assign(&mut self, rhs: Rhs); +} + +macro_rules! sub_assign_impl { + ($($t:ty)+) => ($( + #[stable(feature = "op_assign_traits", since = "1.8.0")] + impl SubAssign for $t { + #[inline] + #[rustc_inherit_overflow_checks] + fn sub_assign(&mut self, other: $t) { *self -= other } + } + )+) +} + +sub_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } + +/// The multiplication assignment operator `*=`. +/// +/// # Examples +/// +/// A trivial implementation of `MulAssign`. When `Foo *= Foo` happens, it ends up +/// calling `mul_assign`, and therefore, `main` prints `Multiplying!`. +/// +/// ``` +/// use std::ops::MulAssign; +/// +/// struct Foo; +/// +/// impl MulAssign for Foo { +/// fn mul_assign(&mut self, _rhs: Foo) { +/// println!("Multiplying!"); +/// } +/// } +/// +/// # #[allow(unused_assignments)] +/// fn main() { +/// let mut foo = Foo; +/// foo *= Foo; +/// } +/// ``` +#[lang = "mul_assign"] +#[stable(feature = "op_assign_traits", since = "1.8.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} *= {Rhs}`"] +pub trait MulAssign { + /// The method for the `*=` operator + #[stable(feature = "op_assign_traits", since = "1.8.0")] + fn mul_assign(&mut self, rhs: Rhs); +} + +macro_rules! mul_assign_impl { + ($($t:ty)+) => ($( + #[stable(feature = "op_assign_traits", since = "1.8.0")] + impl MulAssign for $t { + #[inline] + #[rustc_inherit_overflow_checks] + fn mul_assign(&mut self, other: $t) { *self *= other } + } + )+) +} + +mul_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } + +/// The division assignment operator `/=`. +/// +/// # Examples +/// +/// A trivial implementation of `DivAssign`. When `Foo /= Foo` happens, it ends up +/// calling `div_assign`, and therefore, `main` prints `Dividing!`. +/// +/// ``` +/// use std::ops::DivAssign; +/// +/// struct Foo; +/// +/// impl DivAssign for Foo { +/// fn div_assign(&mut self, _rhs: Foo) { +/// println!("Dividing!"); +/// } +/// } +/// +/// # #[allow(unused_assignments)] +/// fn main() { +/// let mut foo = Foo; +/// foo /= Foo; +/// } +/// ``` +#[lang = "div_assign"] +#[stable(feature = "op_assign_traits", since = "1.8.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} /= {Rhs}`"] +pub trait DivAssign { + /// The method for the `/=` operator + #[stable(feature = "op_assign_traits", since = "1.8.0")] + fn div_assign(&mut self, rhs: Rhs); +} + +macro_rules! div_assign_impl { + ($($t:ty)+) => ($( + #[stable(feature = "op_assign_traits", since = "1.8.0")] + impl DivAssign for $t { + #[inline] + fn div_assign(&mut self, other: $t) { *self /= other } + } + )+) +} + +div_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } + +/// The remainder assignment operator `%=`. +/// +/// # Examples +/// +/// A trivial implementation of `RemAssign`. When `Foo %= Foo` happens, it ends up +/// calling `rem_assign`, and therefore, `main` prints `Remainder-ing!`. +/// +/// ``` +/// use std::ops::RemAssign; +/// +/// struct Foo; +/// +/// impl RemAssign for Foo { +/// fn rem_assign(&mut self, _rhs: Foo) { +/// println!("Remainder-ing!"); +/// } +/// } +/// +/// # #[allow(unused_assignments)] +/// fn main() { +/// let mut foo = Foo; +/// foo %= Foo; +/// } +/// ``` +#[lang = "rem_assign"] +#[stable(feature = "op_assign_traits", since = "1.8.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} %= {Rhs}`"] +pub trait RemAssign { + /// The method for the `%=` operator + #[stable(feature = "op_assign_traits", since = "1.8.0")] + fn rem_assign(&mut self, rhs: Rhs); +} + +macro_rules! rem_assign_impl { + ($($t:ty)+) => ($( + #[stable(feature = "op_assign_traits", since = "1.8.0")] + impl RemAssign for $t { + #[inline] + fn rem_assign(&mut self, other: $t) { *self %= other } + } + )+) +} + +rem_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } diff --git a/src/libcore/ops/mod.rs b/src/libcore/ops/mod.rs index 7f452fd791fb..7d10c35d5e0b 100644 --- a/src/libcore/ops/mod.rs +++ b/src/libcore/ops/mod.rs @@ -147,9 +147,16 @@ #![stable(feature = "rust1", since = "1.0.0")] +mod arith; mod function; mod range; +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::arith::{Add, Sub, Mul, Div, Rem, Neg}; + +#[stable(feature = "op_assign_traits", since = "1.8.0")] +pub use self::arith::{AddAssign, SubAssign, MulAssign, DivAssign, RemAssign}; + #[stable(feature = "rust1", since = "1.0.0")] pub use self::function::{Fn, FnMut, FnOnce}; @@ -251,620 +258,6 @@ pub trait Drop { fn drop(&mut self); } -/// The addition operator `+`. -/// -/// # Examples -/// -/// This example creates a `Point` struct that implements the `Add` trait, and -/// then demonstrates adding two `Point`s. -/// -/// ``` -/// use std::ops::Add; -/// -/// #[derive(Debug)] -/// struct Point { -/// x: i32, -/// y: i32, -/// } -/// -/// impl Add for Point { -/// type Output = Point; -/// -/// fn add(self, other: Point) -> Point { -/// Point { -/// x: self.x + other.x, -/// y: self.y + other.y, -/// } -/// } -/// } -/// -/// impl PartialEq for Point { -/// fn eq(&self, other: &Self) -> bool { -/// self.x == other.x && self.y == other.y -/// } -/// } -/// -/// fn main() { -/// assert_eq!(Point { x: 1, y: 0 } + Point { x: 2, y: 3 }, -/// Point { x: 3, y: 3 }); -/// } -/// ``` -/// -/// Here is an example of the same `Point` struct implementing the `Add` trait -/// using generics. -/// -/// ``` -/// use std::ops::Add; -/// -/// #[derive(Debug)] -/// struct Point { -/// x: T, -/// y: T, -/// } -/// -/// // Notice that the implementation uses the `Output` associated type -/// impl> Add for Point { -/// type Output = Point; -/// -/// fn add(self, other: Point) -> Point { -/// Point { -/// x: self.x + other.x, -/// y: self.y + other.y, -/// } -/// } -/// } -/// -/// impl PartialEq for Point { -/// fn eq(&self, other: &Self) -> bool { -/// self.x == other.x && self.y == other.y -/// } -/// } -/// -/// fn main() { -/// assert_eq!(Point { x: 1, y: 0 } + Point { x: 2, y: 3 }, -/// Point { x: 3, y: 3 }); -/// } -/// ``` -/// -/// Note that `RHS = Self` by default, but this is not mandatory. For example, -/// [std::time::SystemTime] implements `Add`, which permits -/// operations of the form `SystemTime = SystemTime + Duration`. -/// -/// [std::time::SystemTime]: ../../std/time/struct.SystemTime.html -#[lang = "add"] -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} + {RHS}`"] -pub trait Add { - /// The resulting type after applying the `+` operator - #[stable(feature = "rust1", since = "1.0.0")] - type Output; - - /// The method for the `+` operator - #[stable(feature = "rust1", since = "1.0.0")] - fn add(self, rhs: RHS) -> Self::Output; -} - -macro_rules! add_impl { - ($($t:ty)*) => ($( - #[stable(feature = "rust1", since = "1.0.0")] - impl Add for $t { - type Output = $t; - - #[inline] - #[rustc_inherit_overflow_checks] - fn add(self, other: $t) -> $t { self + other } - } - - forward_ref_binop! { impl Add, add for $t, $t } - )*) -} - -add_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } - -/// The subtraction operator `-`. -/// -/// # Examples -/// -/// This example creates a `Point` struct that implements the `Sub` trait, and -/// then demonstrates subtracting two `Point`s. -/// -/// ``` -/// use std::ops::Sub; -/// -/// #[derive(Debug)] -/// struct Point { -/// x: i32, -/// y: i32, -/// } -/// -/// impl Sub for Point { -/// type Output = Point; -/// -/// fn sub(self, other: Point) -> Point { -/// Point { -/// x: self.x - other.x, -/// y: self.y - other.y, -/// } -/// } -/// } -/// -/// impl PartialEq for Point { -/// fn eq(&self, other: &Self) -> bool { -/// self.x == other.x && self.y == other.y -/// } -/// } -/// -/// fn main() { -/// assert_eq!(Point { x: 3, y: 3 } - Point { x: 2, y: 3 }, -/// Point { x: 1, y: 0 }); -/// } -/// ``` -/// -/// Note that `RHS = Self` by default, but this is not mandatory. For example, -/// [std::time::SystemTime] implements `Sub`, which permits -/// operations of the form `SystemTime = SystemTime - Duration`. -/// -/// [std::time::SystemTime]: ../../std/time/struct.SystemTime.html -#[lang = "sub"] -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} - {RHS}`"] -pub trait Sub { - /// The resulting type after applying the `-` operator - #[stable(feature = "rust1", since = "1.0.0")] - type Output; - - /// The method for the `-` operator - #[stable(feature = "rust1", since = "1.0.0")] - fn sub(self, rhs: RHS) -> Self::Output; -} - -macro_rules! sub_impl { - ($($t:ty)*) => ($( - #[stable(feature = "rust1", since = "1.0.0")] - impl Sub for $t { - type Output = $t; - - #[inline] - #[rustc_inherit_overflow_checks] - fn sub(self, other: $t) -> $t { self - other } - } - - forward_ref_binop! { impl Sub, sub for $t, $t } - )*) -} - -sub_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } - -/// The multiplication operator `*`. -/// -/// # Examples -/// -/// Implementing a `Mul`tipliable rational number struct: -/// -/// ``` -/// use std::ops::Mul; -/// -/// // The uniqueness of rational numbers in lowest terms is a consequence of -/// // the fundamental theorem of arithmetic. -/// #[derive(Eq)] -/// #[derive(PartialEq, Debug)] -/// struct Rational { -/// nominator: usize, -/// denominator: usize, -/// } -/// -/// impl Rational { -/// fn new(nominator: usize, denominator: usize) -> Self { -/// if denominator == 0 { -/// panic!("Zero is an invalid denominator!"); -/// } -/// -/// // Reduce to lowest terms by dividing by the greatest common -/// // divisor. -/// let gcd = gcd(nominator, denominator); -/// Rational { -/// nominator: nominator / gcd, -/// denominator: denominator / gcd, -/// } -/// } -/// } -/// -/// impl Mul for Rational { -/// // The multiplication of rational numbers is a closed operation. -/// type Output = Self; -/// -/// fn mul(self, rhs: Self) -> Self { -/// let nominator = self.nominator * rhs.nominator; -/// let denominator = self.denominator * rhs.denominator; -/// Rational::new(nominator, denominator) -/// } -/// } -/// -/// // Euclid's two-thousand-year-old algorithm for finding the greatest common -/// // divisor. -/// fn gcd(x: usize, y: usize) -> usize { -/// let mut x = x; -/// let mut y = y; -/// while y != 0 { -/// let t = y; -/// y = x % y; -/// x = t; -/// } -/// x -/// } -/// -/// assert_eq!(Rational::new(1, 2), Rational::new(2, 4)); -/// assert_eq!(Rational::new(2, 3) * Rational::new(3, 4), -/// Rational::new(1, 2)); -/// ``` -/// -/// Note that `RHS = Self` by default, but this is not mandatory. Here is an -/// implementation which enables multiplication of vectors by scalars, as is -/// done in linear algebra. -/// -/// ``` -/// use std::ops::Mul; -/// -/// struct Scalar {value: usize}; -/// -/// #[derive(Debug)] -/// struct Vector {value: Vec}; -/// -/// impl Mul for Scalar { -/// type Output = Vector; -/// -/// fn mul(self, rhs: Vector) -> Vector { -/// Vector {value: rhs.value.iter().map(|v| self.value * v).collect()} -/// } -/// } -/// -/// impl PartialEq for Vector { -/// fn eq(&self, other: &Self) -> bool { -/// self.value == other.value -/// } -/// } -/// -/// let scalar = Scalar{value: 3}; -/// let vector = Vector{value: vec![2, 4, 6]}; -/// assert_eq!(scalar * vector, Vector{value: vec![6, 12, 18]}); -/// ``` -#[lang = "mul"] -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} * {RHS}`"] -pub trait Mul { - /// The resulting type after applying the `*` operator - #[stable(feature = "rust1", since = "1.0.0")] - type Output; - - /// The method for the `*` operator - #[stable(feature = "rust1", since = "1.0.0")] - fn mul(self, rhs: RHS) -> Self::Output; -} - -macro_rules! mul_impl { - ($($t:ty)*) => ($( - #[stable(feature = "rust1", since = "1.0.0")] - impl Mul for $t { - type Output = $t; - - #[inline] - #[rustc_inherit_overflow_checks] - fn mul(self, other: $t) -> $t { self * other } - } - - forward_ref_binop! { impl Mul, mul for $t, $t } - )*) -} - -mul_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } - -/// The division operator `/`. -/// -/// # Examples -/// -/// Implementing a `Div`idable rational number struct: -/// -/// ``` -/// use std::ops::Div; -/// -/// // The uniqueness of rational numbers in lowest terms is a consequence of -/// // the fundamental theorem of arithmetic. -/// #[derive(Eq)] -/// #[derive(PartialEq, Debug)] -/// struct Rational { -/// nominator: usize, -/// denominator: usize, -/// } -/// -/// impl Rational { -/// fn new(nominator: usize, denominator: usize) -> Self { -/// if denominator == 0 { -/// panic!("Zero is an invalid denominator!"); -/// } -/// -/// // Reduce to lowest terms by dividing by the greatest common -/// // divisor. -/// let gcd = gcd(nominator, denominator); -/// Rational { -/// nominator: nominator / gcd, -/// denominator: denominator / gcd, -/// } -/// } -/// } -/// -/// impl Div for Rational { -/// // The division of rational numbers is a closed operation. -/// type Output = Self; -/// -/// fn div(self, rhs: Self) -> Self { -/// if rhs.nominator == 0 { -/// panic!("Cannot divide by zero-valued `Rational`!"); -/// } -/// -/// let nominator = self.nominator * rhs.denominator; -/// let denominator = self.denominator * rhs.nominator; -/// Rational::new(nominator, denominator) -/// } -/// } -/// -/// // Euclid's two-thousand-year-old algorithm for finding the greatest common -/// // divisor. -/// fn gcd(x: usize, y: usize) -> usize { -/// let mut x = x; -/// let mut y = y; -/// while y != 0 { -/// let t = y; -/// y = x % y; -/// x = t; -/// } -/// x -/// } -/// -/// fn main() { -/// assert_eq!(Rational::new(1, 2), Rational::new(2, 4)); -/// assert_eq!(Rational::new(1, 2) / Rational::new(3, 4), -/// Rational::new(2, 3)); -/// } -/// ``` -/// -/// Note that `RHS = Self` by default, but this is not mandatory. Here is an -/// implementation which enables division of vectors by scalars, as is done in -/// linear algebra. -/// -/// ``` -/// use std::ops::Div; -/// -/// struct Scalar {value: f32}; -/// -/// #[derive(Debug)] -/// struct Vector {value: Vec}; -/// -/// impl Div for Vector { -/// type Output = Vector; -/// -/// fn div(self, rhs: Scalar) -> Vector { -/// Vector {value: self.value.iter().map(|v| v / rhs.value).collect()} -/// } -/// } -/// -/// impl PartialEq for Vector { -/// fn eq(&self, other: &Self) -> bool { -/// self.value == other.value -/// } -/// } -/// -/// let scalar = Scalar{value: 2f32}; -/// let vector = Vector{value: vec![2f32, 4f32, 6f32]}; -/// assert_eq!(vector / scalar, Vector{value: vec![1f32, 2f32, 3f32]}); -/// ``` -#[lang = "div"] -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} / {RHS}`"] -pub trait Div { - /// The resulting type after applying the `/` operator - #[stable(feature = "rust1", since = "1.0.0")] - type Output; - - /// The method for the `/` operator - #[stable(feature = "rust1", since = "1.0.0")] - fn div(self, rhs: RHS) -> Self::Output; -} - -macro_rules! div_impl_integer { - ($($t:ty)*) => ($( - /// This operation rounds towards zero, truncating any - /// fractional part of the exact result. - #[stable(feature = "rust1", since = "1.0.0")] - impl Div for $t { - type Output = $t; - - #[inline] - fn div(self, other: $t) -> $t { self / other } - } - - forward_ref_binop! { impl Div, div for $t, $t } - )*) -} - -div_impl_integer! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } - -macro_rules! div_impl_float { - ($($t:ty)*) => ($( - #[stable(feature = "rust1", since = "1.0.0")] - impl Div for $t { - type Output = $t; - - #[inline] - fn div(self, other: $t) -> $t { self / other } - } - - forward_ref_binop! { impl Div, div for $t, $t } - )*) -} - -div_impl_float! { f32 f64 } - -/// The remainder operator `%`. -/// -/// # Examples -/// -/// This example implements `Rem` on a `SplitSlice` object. After `Rem` is -/// implemented, one can use the `%` operator to find out what the remaining -/// elements of the slice would be after splitting it into equal slices of a -/// given length. -/// -/// ``` -/// use std::ops::Rem; -/// -/// #[derive(PartialEq, Debug)] -/// struct SplitSlice<'a, T: 'a> { -/// slice: &'a [T], -/// } -/// -/// impl<'a, T> Rem for SplitSlice<'a, T> { -/// type Output = SplitSlice<'a, T>; -/// -/// fn rem(self, modulus: usize) -> Self { -/// let len = self.slice.len(); -/// let rem = len % modulus; -/// let start = len - rem; -/// SplitSlice {slice: &self.slice[start..]} -/// } -/// } -/// -/// // If we were to divide &[0, 1, 2, 3, 4, 5, 6, 7] into slices of size 3, -/// // the remainder would be &[6, 7] -/// assert_eq!(SplitSlice { slice: &[0, 1, 2, 3, 4, 5, 6, 7] } % 3, -/// SplitSlice { slice: &[6, 7] }); -/// ``` -#[lang = "rem"] -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} % {RHS}`"] -pub trait Rem { - /// The resulting type after applying the `%` operator - #[stable(feature = "rust1", since = "1.0.0")] - type Output = Self; - - /// The method for the `%` operator - #[stable(feature = "rust1", since = "1.0.0")] - fn rem(self, rhs: RHS) -> Self::Output; -} - -macro_rules! rem_impl_integer { - ($($t:ty)*) => ($( - /// This operation satisfies `n % d == n - (n / d) * d`. The - /// result has the same sign as the left operand. - #[stable(feature = "rust1", since = "1.0.0")] - impl Rem for $t { - type Output = $t; - - #[inline] - fn rem(self, other: $t) -> $t { self % other } - } - - forward_ref_binop! { impl Rem, rem for $t, $t } - )*) -} - -rem_impl_integer! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } - - -macro_rules! rem_impl_float { - ($($t:ty)*) => ($( - #[stable(feature = "rust1", since = "1.0.0")] - impl Rem for $t { - type Output = $t; - - #[inline] - fn rem(self, other: $t) -> $t { self % other } - } - - forward_ref_binop! { impl Rem, rem for $t, $t } - )*) -} - -rem_impl_float! { f32 f64 } - -/// The unary negation operator `-`. -/// -/// # Examples -/// -/// An implementation of `Neg` for `Sign`, which allows the use of `-` to -/// negate its value. -/// -/// ``` -/// use std::ops::Neg; -/// -/// #[derive(Debug, PartialEq)] -/// enum Sign { -/// Negative, -/// Zero, -/// Positive, -/// } -/// -/// impl Neg for Sign { -/// type Output = Sign; -/// -/// fn neg(self) -> Sign { -/// match self { -/// Sign::Negative => Sign::Positive, -/// Sign::Zero => Sign::Zero, -/// Sign::Positive => Sign::Negative, -/// } -/// } -/// } -/// -/// // a negative positive is a negative -/// assert_eq!(-Sign::Positive, Sign::Negative); -/// // a double negative is a positive -/// assert_eq!(-Sign::Negative, Sign::Positive); -/// // zero is its own negation -/// assert_eq!(-Sign::Zero, Sign::Zero); -/// ``` -#[lang = "neg"] -#[stable(feature = "rust1", since = "1.0.0")] -pub trait Neg { - /// The resulting type after applying the `-` operator - #[stable(feature = "rust1", since = "1.0.0")] - type Output; - - /// The method for the unary `-` operator - #[stable(feature = "rust1", since = "1.0.0")] - fn neg(self) -> Self::Output; -} - - - -macro_rules! neg_impl_core { - ($id:ident => $body:expr, $($t:ty)*) => ($( - #[stable(feature = "rust1", since = "1.0.0")] - impl Neg for $t { - type Output = $t; - - #[inline] - #[rustc_inherit_overflow_checks] - fn neg(self) -> $t { let $id = self; $body } - } - - forward_ref_unop! { impl Neg, neg for $t } - )*) -} - -macro_rules! neg_impl_numeric { - ($($t:ty)*) => { neg_impl_core!{ x => -x, $($t)*} } -} - -#[allow(unused_macros)] -macro_rules! neg_impl_unsigned { - ($($t:ty)*) => { - neg_impl_core!{ x => { - !x.wrapping_add(1) - }, $($t)*} } -} - -// neg_impl_unsigned! { usize u8 u16 u32 u64 } -neg_impl_numeric! { isize i8 i16 i32 i64 i128 f32 f64 } - /// The unary logical negation operator `!`. /// /// # Examples @@ -1386,256 +779,6 @@ macro_rules! shr_impl_all { shr_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize } -/// The addition assignment operator `+=`. -/// -/// # Examples -/// -/// This example creates a `Point` struct that implements the `AddAssign` -/// trait, and then demonstrates add-assigning to a mutable `Point`. -/// -/// ``` -/// use std::ops::AddAssign; -/// -/// #[derive(Debug)] -/// struct Point { -/// x: i32, -/// y: i32, -/// } -/// -/// impl AddAssign for Point { -/// fn add_assign(&mut self, other: Point) { -/// *self = Point { -/// x: self.x + other.x, -/// y: self.y + other.y, -/// }; -/// } -/// } -/// -/// impl PartialEq for Point { -/// fn eq(&self, other: &Self) -> bool { -/// self.x == other.x && self.y == other.y -/// } -/// } -/// -/// let mut point = Point { x: 1, y: 0 }; -/// point += Point { x: 2, y: 3 }; -/// assert_eq!(point, Point { x: 3, y: 3 }); -/// ``` -#[lang = "add_assign"] -#[stable(feature = "op_assign_traits", since = "1.8.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} += {Rhs}`"] -pub trait AddAssign { - /// The method for the `+=` operator - #[stable(feature = "op_assign_traits", since = "1.8.0")] - fn add_assign(&mut self, rhs: Rhs); -} - -macro_rules! add_assign_impl { - ($($t:ty)+) => ($( - #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl AddAssign for $t { - #[inline] - #[rustc_inherit_overflow_checks] - fn add_assign(&mut self, other: $t) { *self += other } - } - )+) -} - -add_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } - -/// The subtraction assignment operator `-=`. -/// -/// # Examples -/// -/// This example creates a `Point` struct that implements the `SubAssign` -/// trait, and then demonstrates sub-assigning to a mutable `Point`. -/// -/// ``` -/// use std::ops::SubAssign; -/// -/// #[derive(Debug)] -/// struct Point { -/// x: i32, -/// y: i32, -/// } -/// -/// impl SubAssign for Point { -/// fn sub_assign(&mut self, other: Point) { -/// *self = Point { -/// x: self.x - other.x, -/// y: self.y - other.y, -/// }; -/// } -/// } -/// -/// impl PartialEq for Point { -/// fn eq(&self, other: &Self) -> bool { -/// self.x == other.x && self.y == other.y -/// } -/// } -/// -/// let mut point = Point { x: 3, y: 3 }; -/// point -= Point { x: 2, y: 3 }; -/// assert_eq!(point, Point {x: 1, y: 0}); -/// ``` -#[lang = "sub_assign"] -#[stable(feature = "op_assign_traits", since = "1.8.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} -= {Rhs}`"] -pub trait SubAssign { - /// The method for the `-=` operator - #[stable(feature = "op_assign_traits", since = "1.8.0")] - fn sub_assign(&mut self, rhs: Rhs); -} - -macro_rules! sub_assign_impl { - ($($t:ty)+) => ($( - #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl SubAssign for $t { - #[inline] - #[rustc_inherit_overflow_checks] - fn sub_assign(&mut self, other: $t) { *self -= other } - } - )+) -} - -sub_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } - -/// The multiplication assignment operator `*=`. -/// -/// # Examples -/// -/// A trivial implementation of `MulAssign`. When `Foo *= Foo` happens, it ends up -/// calling `mul_assign`, and therefore, `main` prints `Multiplying!`. -/// -/// ``` -/// use std::ops::MulAssign; -/// -/// struct Foo; -/// -/// impl MulAssign for Foo { -/// fn mul_assign(&mut self, _rhs: Foo) { -/// println!("Multiplying!"); -/// } -/// } -/// -/// # #[allow(unused_assignments)] -/// fn main() { -/// let mut foo = Foo; -/// foo *= Foo; -/// } -/// ``` -#[lang = "mul_assign"] -#[stable(feature = "op_assign_traits", since = "1.8.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} *= {Rhs}`"] -pub trait MulAssign { - /// The method for the `*=` operator - #[stable(feature = "op_assign_traits", since = "1.8.0")] - fn mul_assign(&mut self, rhs: Rhs); -} - -macro_rules! mul_assign_impl { - ($($t:ty)+) => ($( - #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl MulAssign for $t { - #[inline] - #[rustc_inherit_overflow_checks] - fn mul_assign(&mut self, other: $t) { *self *= other } - } - )+) -} - -mul_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } - -/// The division assignment operator `/=`. -/// -/// # Examples -/// -/// A trivial implementation of `DivAssign`. When `Foo /= Foo` happens, it ends up -/// calling `div_assign`, and therefore, `main` prints `Dividing!`. -/// -/// ``` -/// use std::ops::DivAssign; -/// -/// struct Foo; -/// -/// impl DivAssign for Foo { -/// fn div_assign(&mut self, _rhs: Foo) { -/// println!("Dividing!"); -/// } -/// } -/// -/// # #[allow(unused_assignments)] -/// fn main() { -/// let mut foo = Foo; -/// foo /= Foo; -/// } -/// ``` -#[lang = "div_assign"] -#[stable(feature = "op_assign_traits", since = "1.8.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} /= {Rhs}`"] -pub trait DivAssign { - /// The method for the `/=` operator - #[stable(feature = "op_assign_traits", since = "1.8.0")] - fn div_assign(&mut self, rhs: Rhs); -} - -macro_rules! div_assign_impl { - ($($t:ty)+) => ($( - #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl DivAssign for $t { - #[inline] - fn div_assign(&mut self, other: $t) { *self /= other } - } - )+) -} - -div_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } - -/// The remainder assignment operator `%=`. -/// -/// # Examples -/// -/// A trivial implementation of `RemAssign`. When `Foo %= Foo` happens, it ends up -/// calling `rem_assign`, and therefore, `main` prints `Remainder-ing!`. -/// -/// ``` -/// use std::ops::RemAssign; -/// -/// struct Foo; -/// -/// impl RemAssign for Foo { -/// fn rem_assign(&mut self, _rhs: Foo) { -/// println!("Remainder-ing!"); -/// } -/// } -/// -/// # #[allow(unused_assignments)] -/// fn main() { -/// let mut foo = Foo; -/// foo %= Foo; -/// } -/// ``` -#[lang = "rem_assign"] -#[stable(feature = "op_assign_traits", since = "1.8.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} %= {Rhs}`"] -pub trait RemAssign { - /// The method for the `%=` operator - #[stable(feature = "op_assign_traits", since = "1.8.0")] - fn rem_assign(&mut self, rhs: Rhs); -} - -macro_rules! rem_assign_impl { - ($($t:ty)+) => ($( - #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl RemAssign for $t { - #[inline] - fn rem_assign(&mut self, other: $t) { *self %= other } - } - )+) -} - -rem_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } - /// The bitwise AND assignment operator `&=`. /// /// # Examples From d460aca7204b8252f20b970937838bf70b466efe Mon Sep 17 00:00:00 2001 From: Clar Charr Date: Wed, 7 Jun 2017 22:08:14 -0400 Subject: [PATCH 101/233] Move bit ops to module. --- src/libcore/ops/bit.rs | 839 +++++++++++++++++++++++++++++++++++++++++ src/libcore/ops/mod.rs | 837 +--------------------------------------- 2 files changed, 846 insertions(+), 830 deletions(-) create mode 100644 src/libcore/ops/bit.rs diff --git a/src/libcore/ops/bit.rs b/src/libcore/ops/bit.rs new file mode 100644 index 000000000000..8743be3557cc --- /dev/null +++ b/src/libcore/ops/bit.rs @@ -0,0 +1,839 @@ +// 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. + +/// The unary logical negation operator `!`. +/// +/// # Examples +/// +/// An implementation of `Not` for `Answer`, which enables the use of `!` to +/// invert its value. +/// +/// ``` +/// use std::ops::Not; +/// +/// #[derive(Debug, PartialEq)] +/// enum Answer { +/// Yes, +/// No, +/// } +/// +/// impl Not for Answer { +/// type Output = Answer; +/// +/// fn not(self) -> Answer { +/// match self { +/// Answer::Yes => Answer::No, +/// Answer::No => Answer::Yes +/// } +/// } +/// } +/// +/// assert_eq!(!Answer::Yes, Answer::No); +/// assert_eq!(!Answer::No, Answer::Yes); +/// ``` +#[lang = "not"] +#[stable(feature = "rust1", since = "1.0.0")] +pub trait Not { + /// The resulting type after applying the `!` operator + #[stable(feature = "rust1", since = "1.0.0")] + type Output; + + /// The method for the unary `!` operator + #[stable(feature = "rust1", since = "1.0.0")] + fn not(self) -> Self::Output; +} + +macro_rules! not_impl { + ($($t:ty)*) => ($( + #[stable(feature = "rust1", since = "1.0.0")] + impl Not for $t { + type Output = $t; + + #[inline] + fn not(self) -> $t { !self } + } + + forward_ref_unop! { impl Not, not for $t } + )*) +} + +not_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } + +/// The bitwise AND operator `&`. +/// +/// # Examples +/// +/// In this example, the `&` operator is lifted to a trivial `Scalar` type. +/// +/// ``` +/// use std::ops::BitAnd; +/// +/// #[derive(Debug, PartialEq)] +/// struct Scalar(bool); +/// +/// impl BitAnd for Scalar { +/// type Output = Self; +/// +/// // rhs is the "right-hand side" of the expression `a & b` +/// fn bitand(self, rhs: Self) -> Self { +/// Scalar(self.0 & rhs.0) +/// } +/// } +/// +/// fn main() { +/// assert_eq!(Scalar(true) & Scalar(true), Scalar(true)); +/// assert_eq!(Scalar(true) & Scalar(false), Scalar(false)); +/// assert_eq!(Scalar(false) & Scalar(true), Scalar(false)); +/// assert_eq!(Scalar(false) & Scalar(false), Scalar(false)); +/// } +/// ``` +/// +/// In this example, the `BitAnd` trait is implemented for a `BooleanVector` +/// struct. +/// +/// ``` +/// use std::ops::BitAnd; +/// +/// #[derive(Debug, PartialEq)] +/// struct BooleanVector(Vec); +/// +/// impl BitAnd for BooleanVector { +/// type Output = Self; +/// +/// fn bitand(self, BooleanVector(rhs): Self) -> Self { +/// let BooleanVector(lhs) = self; +/// assert_eq!(lhs.len(), rhs.len()); +/// BooleanVector(lhs.iter().zip(rhs.iter()).map(|(x, y)| *x && *y).collect()) +/// } +/// } +/// +/// fn main() { +/// let bv1 = BooleanVector(vec![true, true, false, false]); +/// let bv2 = BooleanVector(vec![true, false, true, false]); +/// let expected = BooleanVector(vec![true, false, false, false]); +/// assert_eq!(bv1 & bv2, expected); +/// } +/// ``` +#[lang = "bitand"] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} & {RHS}`"] +pub trait BitAnd { + /// The resulting type after applying the `&` operator + #[stable(feature = "rust1", since = "1.0.0")] + type Output; + + /// The method for the `&` operator + #[stable(feature = "rust1", since = "1.0.0")] + fn bitand(self, rhs: RHS) -> Self::Output; +} + +macro_rules! bitand_impl { + ($($t:ty)*) => ($( + #[stable(feature = "rust1", since = "1.0.0")] + impl BitAnd for $t { + type Output = $t; + + #[inline] + fn bitand(self, rhs: $t) -> $t { self & rhs } + } + + forward_ref_binop! { impl BitAnd, bitand for $t, $t } + )*) +} + +bitand_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } + +/// The bitwise OR operator `|`. +/// +/// # Examples +/// +/// In this example, the `|` operator is lifted to a trivial `Scalar` type. +/// +/// ``` +/// use std::ops::BitOr; +/// +/// #[derive(Debug, PartialEq)] +/// struct Scalar(bool); +/// +/// impl BitOr for Scalar { +/// type Output = Self; +/// +/// // rhs is the "right-hand side" of the expression `a | b` +/// fn bitor(self, rhs: Self) -> Self { +/// Scalar(self.0 | rhs.0) +/// } +/// } +/// +/// fn main() { +/// assert_eq!(Scalar(true) | Scalar(true), Scalar(true)); +/// assert_eq!(Scalar(true) | Scalar(false), Scalar(true)); +/// assert_eq!(Scalar(false) | Scalar(true), Scalar(true)); +/// assert_eq!(Scalar(false) | Scalar(false), Scalar(false)); +/// } +/// ``` +/// +/// In this example, the `BitOr` trait is implemented for a `BooleanVector` +/// struct. +/// +/// ``` +/// use std::ops::BitOr; +/// +/// #[derive(Debug, PartialEq)] +/// struct BooleanVector(Vec); +/// +/// impl BitOr for BooleanVector { +/// type Output = Self; +/// +/// fn bitor(self, BooleanVector(rhs): Self) -> Self { +/// let BooleanVector(lhs) = self; +/// assert_eq!(lhs.len(), rhs.len()); +/// BooleanVector(lhs.iter().zip(rhs.iter()).map(|(x, y)| *x || *y).collect()) +/// } +/// } +/// +/// fn main() { +/// let bv1 = BooleanVector(vec![true, true, false, false]); +/// let bv2 = BooleanVector(vec![true, false, true, false]); +/// let expected = BooleanVector(vec![true, true, true, false]); +/// assert_eq!(bv1 | bv2, expected); +/// } +/// ``` +#[lang = "bitor"] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} | {RHS}`"] +pub trait BitOr { + /// The resulting type after applying the `|` operator + #[stable(feature = "rust1", since = "1.0.0")] + type Output; + + /// The method for the `|` operator + #[stable(feature = "rust1", since = "1.0.0")] + fn bitor(self, rhs: RHS) -> Self::Output; +} + +macro_rules! bitor_impl { + ($($t:ty)*) => ($( + #[stable(feature = "rust1", since = "1.0.0")] + impl BitOr for $t { + type Output = $t; + + #[inline] + fn bitor(self, rhs: $t) -> $t { self | rhs } + } + + forward_ref_binop! { impl BitOr, bitor for $t, $t } + )*) +} + +bitor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } + +/// The bitwise XOR operator `^`. +/// +/// # Examples +/// +/// In this example, the `^` operator is lifted to a trivial `Scalar` type. +/// +/// ``` +/// use std::ops::BitXor; +/// +/// #[derive(Debug, PartialEq)] +/// struct Scalar(bool); +/// +/// impl BitXor for Scalar { +/// type Output = Self; +/// +/// // rhs is the "right-hand side" of the expression `a ^ b` +/// fn bitxor(self, rhs: Self) -> Self { +/// Scalar(self.0 ^ rhs.0) +/// } +/// } +/// +/// fn main() { +/// assert_eq!(Scalar(true) ^ Scalar(true), Scalar(false)); +/// assert_eq!(Scalar(true) ^ Scalar(false), Scalar(true)); +/// assert_eq!(Scalar(false) ^ Scalar(true), Scalar(true)); +/// assert_eq!(Scalar(false) ^ Scalar(false), Scalar(false)); +/// } +/// ``` +/// +/// In this example, the `BitXor` trait is implemented for a `BooleanVector` +/// struct. +/// +/// ``` +/// use std::ops::BitXor; +/// +/// #[derive(Debug, PartialEq)] +/// struct BooleanVector(Vec); +/// +/// impl BitXor for BooleanVector { +/// type Output = Self; +/// +/// fn bitxor(self, BooleanVector(rhs): Self) -> Self { +/// let BooleanVector(lhs) = self; +/// assert_eq!(lhs.len(), rhs.len()); +/// BooleanVector(lhs.iter() +/// .zip(rhs.iter()) +/// .map(|(x, y)| (*x || *y) && !(*x && *y)) +/// .collect()) +/// } +/// } +/// +/// fn main() { +/// let bv1 = BooleanVector(vec![true, true, false, false]); +/// let bv2 = BooleanVector(vec![true, false, true, false]); +/// let expected = BooleanVector(vec![false, true, true, false]); +/// assert_eq!(bv1 ^ bv2, expected); +/// } +/// ``` +#[lang = "bitxor"] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} ^ {RHS}`"] +pub trait BitXor { + /// The resulting type after applying the `^` operator + #[stable(feature = "rust1", since = "1.0.0")] + type Output; + + /// The method for the `^` operator + #[stable(feature = "rust1", since = "1.0.0")] + fn bitxor(self, rhs: RHS) -> Self::Output; +} + +macro_rules! bitxor_impl { + ($($t:ty)*) => ($( + #[stable(feature = "rust1", since = "1.0.0")] + impl BitXor for $t { + type Output = $t; + + #[inline] + fn bitxor(self, other: $t) -> $t { self ^ other } + } + + forward_ref_binop! { impl BitXor, bitxor for $t, $t } + )*) +} + +bitxor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } + +/// The left shift operator `<<`. +/// +/// # Examples +/// +/// An implementation of `Shl` that lifts the `<<` operation on integers to a +/// `Scalar` struct. +/// +/// ``` +/// use std::ops::Shl; +/// +/// #[derive(PartialEq, Debug)] +/// struct Scalar(usize); +/// +/// impl Shl for Scalar { +/// type Output = Self; +/// +/// fn shl(self, Scalar(rhs): Self) -> Scalar { +/// let Scalar(lhs) = self; +/// Scalar(lhs << rhs) +/// } +/// } +/// fn main() { +/// assert_eq!(Scalar(4) << Scalar(2), Scalar(16)); +/// } +/// ``` +/// +/// An implementation of `Shl` that spins a vector leftward by a given amount. +/// +/// ``` +/// use std::ops::Shl; +/// +/// #[derive(PartialEq, Debug)] +/// struct SpinVector { +/// vec: Vec, +/// } +/// +/// impl Shl for SpinVector { +/// type Output = Self; +/// +/// fn shl(self, rhs: usize) -> SpinVector { +/// // rotate the vector by `rhs` places +/// let (a, b) = self.vec.split_at(rhs); +/// let mut spun_vector: Vec = vec![]; +/// spun_vector.extend_from_slice(b); +/// spun_vector.extend_from_slice(a); +/// SpinVector { vec: spun_vector } +/// } +/// } +/// +/// fn main() { +/// assert_eq!(SpinVector { vec: vec![0, 1, 2, 3, 4] } << 2, +/// SpinVector { vec: vec![2, 3, 4, 0, 1] }); +/// } +/// ``` +#[lang = "shl"] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} << {RHS}`"] +pub trait Shl { + /// The resulting type after applying the `<<` operator + #[stable(feature = "rust1", since = "1.0.0")] + type Output; + + /// The method for the `<<` operator + #[stable(feature = "rust1", since = "1.0.0")] + fn shl(self, rhs: RHS) -> Self::Output; +} + +macro_rules! shl_impl { + ($t:ty, $f:ty) => ( + #[stable(feature = "rust1", since = "1.0.0")] + impl Shl<$f> for $t { + type Output = $t; + + #[inline] + #[rustc_inherit_overflow_checks] + fn shl(self, other: $f) -> $t { + self << other + } + } + + forward_ref_binop! { impl Shl, shl for $t, $f } + ) +} + +macro_rules! shl_impl_all { + ($($t:ty)*) => ($( + shl_impl! { $t, u8 } + shl_impl! { $t, u16 } + shl_impl! { $t, u32 } + shl_impl! { $t, u64 } + shl_impl! { $t, u128 } + shl_impl! { $t, usize } + + shl_impl! { $t, i8 } + shl_impl! { $t, i16 } + shl_impl! { $t, i32 } + shl_impl! { $t, i64 } + shl_impl! { $t, i128 } + shl_impl! { $t, isize } + )*) +} + +shl_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 isize i128 } + +/// The right shift operator `>>`. +/// +/// # Examples +/// +/// An implementation of `Shr` that lifts the `>>` operation on integers to a +/// `Scalar` struct. +/// +/// ``` +/// use std::ops::Shr; +/// +/// #[derive(PartialEq, Debug)] +/// struct Scalar(usize); +/// +/// impl Shr for Scalar { +/// type Output = Self; +/// +/// fn shr(self, Scalar(rhs): Self) -> Scalar { +/// let Scalar(lhs) = self; +/// Scalar(lhs >> rhs) +/// } +/// } +/// fn main() { +/// assert_eq!(Scalar(16) >> Scalar(2), Scalar(4)); +/// } +/// ``` +/// +/// An implementation of `Shr` that spins a vector rightward by a given amount. +/// +/// ``` +/// use std::ops::Shr; +/// +/// #[derive(PartialEq, Debug)] +/// struct SpinVector { +/// vec: Vec, +/// } +/// +/// impl Shr for SpinVector { +/// type Output = Self; +/// +/// fn shr(self, rhs: usize) -> SpinVector { +/// // rotate the vector by `rhs` places +/// let (a, b) = self.vec.split_at(self.vec.len() - rhs); +/// let mut spun_vector: Vec = vec![]; +/// spun_vector.extend_from_slice(b); +/// spun_vector.extend_from_slice(a); +/// SpinVector { vec: spun_vector } +/// } +/// } +/// +/// fn main() { +/// assert_eq!(SpinVector { vec: vec![0, 1, 2, 3, 4] } >> 2, +/// SpinVector { vec: vec![3, 4, 0, 1, 2] }); +/// } +/// ``` +#[lang = "shr"] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} >> {RHS}`"] +pub trait Shr { + /// The resulting type after applying the `>>` operator + #[stable(feature = "rust1", since = "1.0.0")] + type Output; + + /// The method for the `>>` operator + #[stable(feature = "rust1", since = "1.0.0")] + fn shr(self, rhs: RHS) -> Self::Output; +} + +macro_rules! shr_impl { + ($t:ty, $f:ty) => ( + #[stable(feature = "rust1", since = "1.0.0")] + impl Shr<$f> for $t { + type Output = $t; + + #[inline] + #[rustc_inherit_overflow_checks] + fn shr(self, other: $f) -> $t { + self >> other + } + } + + forward_ref_binop! { impl Shr, shr for $t, $f } + ) +} + +macro_rules! shr_impl_all { + ($($t:ty)*) => ($( + shr_impl! { $t, u8 } + shr_impl! { $t, u16 } + shr_impl! { $t, u32 } + shr_impl! { $t, u64 } + shr_impl! { $t, u128 } + shr_impl! { $t, usize } + + shr_impl! { $t, i8 } + shr_impl! { $t, i16 } + shr_impl! { $t, i32 } + shr_impl! { $t, i64 } + shr_impl! { $t, i128 } + shr_impl! { $t, isize } + )*) +} + +shr_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize } + +/// The bitwise AND assignment operator `&=`. +/// +/// # Examples +/// +/// In this example, the `&=` operator is lifted to a trivial `Scalar` type. +/// +/// ``` +/// use std::ops::BitAndAssign; +/// +/// #[derive(Debug, PartialEq)] +/// struct Scalar(bool); +/// +/// impl BitAndAssign for Scalar { +/// // rhs is the "right-hand side" of the expression `a &= b` +/// fn bitand_assign(&mut self, rhs: Self) { +/// *self = Scalar(self.0 & rhs.0) +/// } +/// } +/// +/// fn main() { +/// let mut scalar = Scalar(true); +/// scalar &= Scalar(true); +/// assert_eq!(scalar, Scalar(true)); +/// +/// let mut scalar = Scalar(true); +/// scalar &= Scalar(false); +/// assert_eq!(scalar, Scalar(false)); +/// +/// let mut scalar = Scalar(false); +/// scalar &= Scalar(true); +/// assert_eq!(scalar, Scalar(false)); +/// +/// let mut scalar = Scalar(false); +/// scalar &= Scalar(false); +/// assert_eq!(scalar, Scalar(false)); +/// } +/// ``` +/// +/// In this example, the `BitAndAssign` trait is implemented for a +/// `BooleanVector` struct. +/// +/// ``` +/// use std::ops::BitAndAssign; +/// +/// #[derive(Debug, PartialEq)] +/// struct BooleanVector(Vec); +/// +/// impl BitAndAssign for BooleanVector { +/// // rhs is the "right-hand side" of the expression `a &= b` +/// fn bitand_assign(&mut self, rhs: Self) { +/// assert_eq!(self.0.len(), rhs.0.len()); +/// *self = BooleanVector(self.0 +/// .iter() +/// .zip(rhs.0.iter()) +/// .map(|(x, y)| *x && *y) +/// .collect()); +/// } +/// } +/// +/// fn main() { +/// let mut bv = BooleanVector(vec![true, true, false, false]); +/// bv &= BooleanVector(vec![true, false, true, false]); +/// let expected = BooleanVector(vec![true, false, false, false]); +/// assert_eq!(bv, expected); +/// } +/// ``` +#[lang = "bitand_assign"] +#[stable(feature = "op_assign_traits", since = "1.8.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} &= {Rhs}`"] +pub trait BitAndAssign { + /// The method for the `&=` operator + #[stable(feature = "op_assign_traits", since = "1.8.0")] + fn bitand_assign(&mut self, rhs: Rhs); +} + +macro_rules! bitand_assign_impl { + ($($t:ty)+) => ($( + #[stable(feature = "op_assign_traits", since = "1.8.0")] + impl BitAndAssign for $t { + #[inline] + fn bitand_assign(&mut self, other: $t) { *self &= other } + } + )+) +} + +bitand_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } + +/// The bitwise OR assignment operator `|=`. +/// +/// # Examples +/// +/// A trivial implementation of `BitOrAssign`. When `Foo |= Foo` happens, it ends up +/// calling `bitor_assign`, and therefore, `main` prints `Bitwise Or-ing!`. +/// +/// ``` +/// use std::ops::BitOrAssign; +/// +/// struct Foo; +/// +/// impl BitOrAssign for Foo { +/// fn bitor_assign(&mut self, _rhs: Foo) { +/// println!("Bitwise Or-ing!"); +/// } +/// } +/// +/// # #[allow(unused_assignments)] +/// fn main() { +/// let mut foo = Foo; +/// foo |= Foo; +/// } +/// ``` +#[lang = "bitor_assign"] +#[stable(feature = "op_assign_traits", since = "1.8.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} |= {Rhs}`"] +pub trait BitOrAssign { + /// The method for the `|=` operator + #[stable(feature = "op_assign_traits", since = "1.8.0")] + fn bitor_assign(&mut self, rhs: Rhs); +} + +macro_rules! bitor_assign_impl { + ($($t:ty)+) => ($( + #[stable(feature = "op_assign_traits", since = "1.8.0")] + impl BitOrAssign for $t { + #[inline] + fn bitor_assign(&mut self, other: $t) { *self |= other } + } + )+) +} + +bitor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } + +/// The bitwise XOR assignment operator `^=`. +/// +/// # Examples +/// +/// A trivial implementation of `BitXorAssign`. When `Foo ^= Foo` happens, it ends up +/// calling `bitxor_assign`, and therefore, `main` prints `Bitwise Xor-ing!`. +/// +/// ``` +/// use std::ops::BitXorAssign; +/// +/// struct Foo; +/// +/// impl BitXorAssign for Foo { +/// fn bitxor_assign(&mut self, _rhs: Foo) { +/// println!("Bitwise Xor-ing!"); +/// } +/// } +/// +/// # #[allow(unused_assignments)] +/// fn main() { +/// let mut foo = Foo; +/// foo ^= Foo; +/// } +/// ``` +#[lang = "bitxor_assign"] +#[stable(feature = "op_assign_traits", since = "1.8.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} ^= {Rhs}`"] +pub trait BitXorAssign { + /// The method for the `^=` operator + #[stable(feature = "op_assign_traits", since = "1.8.0")] + fn bitxor_assign(&mut self, rhs: Rhs); +} + +macro_rules! bitxor_assign_impl { + ($($t:ty)+) => ($( + #[stable(feature = "op_assign_traits", since = "1.8.0")] + impl BitXorAssign for $t { + #[inline] + fn bitxor_assign(&mut self, other: $t) { *self ^= other } + } + )+) +} + +bitxor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } + +/// The left shift assignment operator `<<=`. +/// +/// # Examples +/// +/// A trivial implementation of `ShlAssign`. When `Foo <<= Foo` happens, it ends up +/// calling `shl_assign`, and therefore, `main` prints `Shifting left!`. +/// +/// ``` +/// use std::ops::ShlAssign; +/// +/// struct Foo; +/// +/// impl ShlAssign for Foo { +/// fn shl_assign(&mut self, _rhs: Foo) { +/// println!("Shifting left!"); +/// } +/// } +/// +/// # #[allow(unused_assignments)] +/// fn main() { +/// let mut foo = Foo; +/// foo <<= Foo; +/// } +/// ``` +#[lang = "shl_assign"] +#[stable(feature = "op_assign_traits", since = "1.8.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} <<= {Rhs}`"] +pub trait ShlAssign { + /// The method for the `<<=` operator + #[stable(feature = "op_assign_traits", since = "1.8.0")] + fn shl_assign(&mut self, rhs: Rhs); +} + +macro_rules! shl_assign_impl { + ($t:ty, $f:ty) => ( + #[stable(feature = "op_assign_traits", since = "1.8.0")] + impl ShlAssign<$f> for $t { + #[inline] + #[rustc_inherit_overflow_checks] + fn shl_assign(&mut self, other: $f) { + *self <<= other + } + } + ) +} + +macro_rules! shl_assign_impl_all { + ($($t:ty)*) => ($( + shl_assign_impl! { $t, u8 } + shl_assign_impl! { $t, u16 } + shl_assign_impl! { $t, u32 } + shl_assign_impl! { $t, u64 } + shl_assign_impl! { $t, u128 } + shl_assign_impl! { $t, usize } + + shl_assign_impl! { $t, i8 } + shl_assign_impl! { $t, i16 } + shl_assign_impl! { $t, i32 } + shl_assign_impl! { $t, i64 } + shl_assign_impl! { $t, i128 } + shl_assign_impl! { $t, isize } + )*) +} + +shl_assign_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize } + +/// The right shift assignment operator `>>=`. +/// +/// # Examples +/// +/// A trivial implementation of `ShrAssign`. When `Foo >>= Foo` happens, it ends up +/// calling `shr_assign`, and therefore, `main` prints `Shifting right!`. +/// +/// ``` +/// use std::ops::ShrAssign; +/// +/// struct Foo; +/// +/// impl ShrAssign for Foo { +/// fn shr_assign(&mut self, _rhs: Foo) { +/// println!("Shifting right!"); +/// } +/// } +/// +/// # #[allow(unused_assignments)] +/// fn main() { +/// let mut foo = Foo; +/// foo >>= Foo; +/// } +/// ``` +#[lang = "shr_assign"] +#[stable(feature = "op_assign_traits", since = "1.8.0")] +#[rustc_on_unimplemented = "no implementation for `{Self} >>= {Rhs}`"] +pub trait ShrAssign { + /// The method for the `>>=` operator + #[stable(feature = "op_assign_traits", since = "1.8.0")] + fn shr_assign(&mut self, rhs: Rhs); +} + +macro_rules! shr_assign_impl { + ($t:ty, $f:ty) => ( + #[stable(feature = "op_assign_traits", since = "1.8.0")] + impl ShrAssign<$f> for $t { + #[inline] + #[rustc_inherit_overflow_checks] + fn shr_assign(&mut self, other: $f) { + *self >>= other + } + } + ) +} + +macro_rules! shr_assign_impl_all { + ($($t:ty)*) => ($( + shr_assign_impl! { $t, u8 } + shr_assign_impl! { $t, u16 } + shr_assign_impl! { $t, u32 } + shr_assign_impl! { $t, u64 } + shr_assign_impl! { $t, u128 } + shr_assign_impl! { $t, usize } + + shr_assign_impl! { $t, i8 } + shr_assign_impl! { $t, i16 } + shr_assign_impl! { $t, i32 } + shr_assign_impl! { $t, i64 } + shr_assign_impl! { $t, i128 } + shr_assign_impl! { $t, isize } + )*) +} + +shr_assign_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize } diff --git a/src/libcore/ops/mod.rs b/src/libcore/ops/mod.rs index 7d10c35d5e0b..fdc1b5fc2359 100644 --- a/src/libcore/ops/mod.rs +++ b/src/libcore/ops/mod.rs @@ -148,6 +148,7 @@ #![stable(feature = "rust1", since = "1.0.0")] mod arith; +mod bit; mod function; mod range; @@ -157,6 +158,12 @@ pub use self::arith::{Add, Sub, Mul, Div, Rem, Neg}; #[stable(feature = "op_assign_traits", since = "1.8.0")] pub use self::arith::{AddAssign, SubAssign, MulAssign, DivAssign, RemAssign}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::bit::{Not, BitAnd, BitOr, BitXor, Shl, Shr}; + +#[stable(feature = "op_assign_traits", since = "1.8.0")] +pub use self::bit::{BitAndAssign, BitOrAssign, BitXorAssign, ShlAssign, ShrAssign}; + #[stable(feature = "rust1", since = "1.0.0")] pub use self::function::{Fn, FnMut, FnOnce}; @@ -258,836 +265,6 @@ pub trait Drop { fn drop(&mut self); } -/// The unary logical negation operator `!`. -/// -/// # Examples -/// -/// An implementation of `Not` for `Answer`, which enables the use of `!` to -/// invert its value. -/// -/// ``` -/// use std::ops::Not; -/// -/// #[derive(Debug, PartialEq)] -/// enum Answer { -/// Yes, -/// No, -/// } -/// -/// impl Not for Answer { -/// type Output = Answer; -/// -/// fn not(self) -> Answer { -/// match self { -/// Answer::Yes => Answer::No, -/// Answer::No => Answer::Yes -/// } -/// } -/// } -/// -/// assert_eq!(!Answer::Yes, Answer::No); -/// assert_eq!(!Answer::No, Answer::Yes); -/// ``` -#[lang = "not"] -#[stable(feature = "rust1", since = "1.0.0")] -pub trait Not { - /// The resulting type after applying the `!` operator - #[stable(feature = "rust1", since = "1.0.0")] - type Output; - - /// The method for the unary `!` operator - #[stable(feature = "rust1", since = "1.0.0")] - fn not(self) -> Self::Output; -} - -macro_rules! not_impl { - ($($t:ty)*) => ($( - #[stable(feature = "rust1", since = "1.0.0")] - impl Not for $t { - type Output = $t; - - #[inline] - fn not(self) -> $t { !self } - } - - forward_ref_unop! { impl Not, not for $t } - )*) -} - -not_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } - -/// The bitwise AND operator `&`. -/// -/// # Examples -/// -/// In this example, the `&` operator is lifted to a trivial `Scalar` type. -/// -/// ``` -/// use std::ops::BitAnd; -/// -/// #[derive(Debug, PartialEq)] -/// struct Scalar(bool); -/// -/// impl BitAnd for Scalar { -/// type Output = Self; -/// -/// // rhs is the "right-hand side" of the expression `a & b` -/// fn bitand(self, rhs: Self) -> Self { -/// Scalar(self.0 & rhs.0) -/// } -/// } -/// -/// fn main() { -/// assert_eq!(Scalar(true) & Scalar(true), Scalar(true)); -/// assert_eq!(Scalar(true) & Scalar(false), Scalar(false)); -/// assert_eq!(Scalar(false) & Scalar(true), Scalar(false)); -/// assert_eq!(Scalar(false) & Scalar(false), Scalar(false)); -/// } -/// ``` -/// -/// In this example, the `BitAnd` trait is implemented for a `BooleanVector` -/// struct. -/// -/// ``` -/// use std::ops::BitAnd; -/// -/// #[derive(Debug, PartialEq)] -/// struct BooleanVector(Vec); -/// -/// impl BitAnd for BooleanVector { -/// type Output = Self; -/// -/// fn bitand(self, BooleanVector(rhs): Self) -> Self { -/// let BooleanVector(lhs) = self; -/// assert_eq!(lhs.len(), rhs.len()); -/// BooleanVector(lhs.iter().zip(rhs.iter()).map(|(x, y)| *x && *y).collect()) -/// } -/// } -/// -/// fn main() { -/// let bv1 = BooleanVector(vec![true, true, false, false]); -/// let bv2 = BooleanVector(vec![true, false, true, false]); -/// let expected = BooleanVector(vec![true, false, false, false]); -/// assert_eq!(bv1 & bv2, expected); -/// } -/// ``` -#[lang = "bitand"] -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} & {RHS}`"] -pub trait BitAnd { - /// The resulting type after applying the `&` operator - #[stable(feature = "rust1", since = "1.0.0")] - type Output; - - /// The method for the `&` operator - #[stable(feature = "rust1", since = "1.0.0")] - fn bitand(self, rhs: RHS) -> Self::Output; -} - -macro_rules! bitand_impl { - ($($t:ty)*) => ($( - #[stable(feature = "rust1", since = "1.0.0")] - impl BitAnd for $t { - type Output = $t; - - #[inline] - fn bitand(self, rhs: $t) -> $t { self & rhs } - } - - forward_ref_binop! { impl BitAnd, bitand for $t, $t } - )*) -} - -bitand_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } - -/// The bitwise OR operator `|`. -/// -/// # Examples -/// -/// In this example, the `|` operator is lifted to a trivial `Scalar` type. -/// -/// ``` -/// use std::ops::BitOr; -/// -/// #[derive(Debug, PartialEq)] -/// struct Scalar(bool); -/// -/// impl BitOr for Scalar { -/// type Output = Self; -/// -/// // rhs is the "right-hand side" of the expression `a | b` -/// fn bitor(self, rhs: Self) -> Self { -/// Scalar(self.0 | rhs.0) -/// } -/// } -/// -/// fn main() { -/// assert_eq!(Scalar(true) | Scalar(true), Scalar(true)); -/// assert_eq!(Scalar(true) | Scalar(false), Scalar(true)); -/// assert_eq!(Scalar(false) | Scalar(true), Scalar(true)); -/// assert_eq!(Scalar(false) | Scalar(false), Scalar(false)); -/// } -/// ``` -/// -/// In this example, the `BitOr` trait is implemented for a `BooleanVector` -/// struct. -/// -/// ``` -/// use std::ops::BitOr; -/// -/// #[derive(Debug, PartialEq)] -/// struct BooleanVector(Vec); -/// -/// impl BitOr for BooleanVector { -/// type Output = Self; -/// -/// fn bitor(self, BooleanVector(rhs): Self) -> Self { -/// let BooleanVector(lhs) = self; -/// assert_eq!(lhs.len(), rhs.len()); -/// BooleanVector(lhs.iter().zip(rhs.iter()).map(|(x, y)| *x || *y).collect()) -/// } -/// } -/// -/// fn main() { -/// let bv1 = BooleanVector(vec![true, true, false, false]); -/// let bv2 = BooleanVector(vec![true, false, true, false]); -/// let expected = BooleanVector(vec![true, true, true, false]); -/// assert_eq!(bv1 | bv2, expected); -/// } -/// ``` -#[lang = "bitor"] -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} | {RHS}`"] -pub trait BitOr { - /// The resulting type after applying the `|` operator - #[stable(feature = "rust1", since = "1.0.0")] - type Output; - - /// The method for the `|` operator - #[stable(feature = "rust1", since = "1.0.0")] - fn bitor(self, rhs: RHS) -> Self::Output; -} - -macro_rules! bitor_impl { - ($($t:ty)*) => ($( - #[stable(feature = "rust1", since = "1.0.0")] - impl BitOr for $t { - type Output = $t; - - #[inline] - fn bitor(self, rhs: $t) -> $t { self | rhs } - } - - forward_ref_binop! { impl BitOr, bitor for $t, $t } - )*) -} - -bitor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } - -/// The bitwise XOR operator `^`. -/// -/// # Examples -/// -/// In this example, the `^` operator is lifted to a trivial `Scalar` type. -/// -/// ``` -/// use std::ops::BitXor; -/// -/// #[derive(Debug, PartialEq)] -/// struct Scalar(bool); -/// -/// impl BitXor for Scalar { -/// type Output = Self; -/// -/// // rhs is the "right-hand side" of the expression `a ^ b` -/// fn bitxor(self, rhs: Self) -> Self { -/// Scalar(self.0 ^ rhs.0) -/// } -/// } -/// -/// fn main() { -/// assert_eq!(Scalar(true) ^ Scalar(true), Scalar(false)); -/// assert_eq!(Scalar(true) ^ Scalar(false), Scalar(true)); -/// assert_eq!(Scalar(false) ^ Scalar(true), Scalar(true)); -/// assert_eq!(Scalar(false) ^ Scalar(false), Scalar(false)); -/// } -/// ``` -/// -/// In this example, the `BitXor` trait is implemented for a `BooleanVector` -/// struct. -/// -/// ``` -/// use std::ops::BitXor; -/// -/// #[derive(Debug, PartialEq)] -/// struct BooleanVector(Vec); -/// -/// impl BitXor for BooleanVector { -/// type Output = Self; -/// -/// fn bitxor(self, BooleanVector(rhs): Self) -> Self { -/// let BooleanVector(lhs) = self; -/// assert_eq!(lhs.len(), rhs.len()); -/// BooleanVector(lhs.iter() -/// .zip(rhs.iter()) -/// .map(|(x, y)| (*x || *y) && !(*x && *y)) -/// .collect()) -/// } -/// } -/// -/// fn main() { -/// let bv1 = BooleanVector(vec![true, true, false, false]); -/// let bv2 = BooleanVector(vec![true, false, true, false]); -/// let expected = BooleanVector(vec![false, true, true, false]); -/// assert_eq!(bv1 ^ bv2, expected); -/// } -/// ``` -#[lang = "bitxor"] -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} ^ {RHS}`"] -pub trait BitXor { - /// The resulting type after applying the `^` operator - #[stable(feature = "rust1", since = "1.0.0")] - type Output; - - /// The method for the `^` operator - #[stable(feature = "rust1", since = "1.0.0")] - fn bitxor(self, rhs: RHS) -> Self::Output; -} - -macro_rules! bitxor_impl { - ($($t:ty)*) => ($( - #[stable(feature = "rust1", since = "1.0.0")] - impl BitXor for $t { - type Output = $t; - - #[inline] - fn bitxor(self, other: $t) -> $t { self ^ other } - } - - forward_ref_binop! { impl BitXor, bitxor for $t, $t } - )*) -} - -bitxor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } - -/// The left shift operator `<<`. -/// -/// # Examples -/// -/// An implementation of `Shl` that lifts the `<<` operation on integers to a -/// `Scalar` struct. -/// -/// ``` -/// use std::ops::Shl; -/// -/// #[derive(PartialEq, Debug)] -/// struct Scalar(usize); -/// -/// impl Shl for Scalar { -/// type Output = Self; -/// -/// fn shl(self, Scalar(rhs): Self) -> Scalar { -/// let Scalar(lhs) = self; -/// Scalar(lhs << rhs) -/// } -/// } -/// fn main() { -/// assert_eq!(Scalar(4) << Scalar(2), Scalar(16)); -/// } -/// ``` -/// -/// An implementation of `Shl` that spins a vector leftward by a given amount. -/// -/// ``` -/// use std::ops::Shl; -/// -/// #[derive(PartialEq, Debug)] -/// struct SpinVector { -/// vec: Vec, -/// } -/// -/// impl Shl for SpinVector { -/// type Output = Self; -/// -/// fn shl(self, rhs: usize) -> SpinVector { -/// // rotate the vector by `rhs` places -/// let (a, b) = self.vec.split_at(rhs); -/// let mut spun_vector: Vec = vec![]; -/// spun_vector.extend_from_slice(b); -/// spun_vector.extend_from_slice(a); -/// SpinVector { vec: spun_vector } -/// } -/// } -/// -/// fn main() { -/// assert_eq!(SpinVector { vec: vec![0, 1, 2, 3, 4] } << 2, -/// SpinVector { vec: vec![2, 3, 4, 0, 1] }); -/// } -/// ``` -#[lang = "shl"] -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} << {RHS}`"] -pub trait Shl { - /// The resulting type after applying the `<<` operator - #[stable(feature = "rust1", since = "1.0.0")] - type Output; - - /// The method for the `<<` operator - #[stable(feature = "rust1", since = "1.0.0")] - fn shl(self, rhs: RHS) -> Self::Output; -} - -macro_rules! shl_impl { - ($t:ty, $f:ty) => ( - #[stable(feature = "rust1", since = "1.0.0")] - impl Shl<$f> for $t { - type Output = $t; - - #[inline] - #[rustc_inherit_overflow_checks] - fn shl(self, other: $f) -> $t { - self << other - } - } - - forward_ref_binop! { impl Shl, shl for $t, $f } - ) -} - -macro_rules! shl_impl_all { - ($($t:ty)*) => ($( - shl_impl! { $t, u8 } - shl_impl! { $t, u16 } - shl_impl! { $t, u32 } - shl_impl! { $t, u64 } - shl_impl! { $t, u128 } - shl_impl! { $t, usize } - - shl_impl! { $t, i8 } - shl_impl! { $t, i16 } - shl_impl! { $t, i32 } - shl_impl! { $t, i64 } - shl_impl! { $t, i128 } - shl_impl! { $t, isize } - )*) -} - -shl_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 isize i128 } - -/// The right shift operator `>>`. -/// -/// # Examples -/// -/// An implementation of `Shr` that lifts the `>>` operation on integers to a -/// `Scalar` struct. -/// -/// ``` -/// use std::ops::Shr; -/// -/// #[derive(PartialEq, Debug)] -/// struct Scalar(usize); -/// -/// impl Shr for Scalar { -/// type Output = Self; -/// -/// fn shr(self, Scalar(rhs): Self) -> Scalar { -/// let Scalar(lhs) = self; -/// Scalar(lhs >> rhs) -/// } -/// } -/// fn main() { -/// assert_eq!(Scalar(16) >> Scalar(2), Scalar(4)); -/// } -/// ``` -/// -/// An implementation of `Shr` that spins a vector rightward by a given amount. -/// -/// ``` -/// use std::ops::Shr; -/// -/// #[derive(PartialEq, Debug)] -/// struct SpinVector { -/// vec: Vec, -/// } -/// -/// impl Shr for SpinVector { -/// type Output = Self; -/// -/// fn shr(self, rhs: usize) -> SpinVector { -/// // rotate the vector by `rhs` places -/// let (a, b) = self.vec.split_at(self.vec.len() - rhs); -/// let mut spun_vector: Vec = vec![]; -/// spun_vector.extend_from_slice(b); -/// spun_vector.extend_from_slice(a); -/// SpinVector { vec: spun_vector } -/// } -/// } -/// -/// fn main() { -/// assert_eq!(SpinVector { vec: vec![0, 1, 2, 3, 4] } >> 2, -/// SpinVector { vec: vec![3, 4, 0, 1, 2] }); -/// } -/// ``` -#[lang = "shr"] -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} >> {RHS}`"] -pub trait Shr { - /// The resulting type after applying the `>>` operator - #[stable(feature = "rust1", since = "1.0.0")] - type Output; - - /// The method for the `>>` operator - #[stable(feature = "rust1", since = "1.0.0")] - fn shr(self, rhs: RHS) -> Self::Output; -} - -macro_rules! shr_impl { - ($t:ty, $f:ty) => ( - #[stable(feature = "rust1", since = "1.0.0")] - impl Shr<$f> for $t { - type Output = $t; - - #[inline] - #[rustc_inherit_overflow_checks] - fn shr(self, other: $f) -> $t { - self >> other - } - } - - forward_ref_binop! { impl Shr, shr for $t, $f } - ) -} - -macro_rules! shr_impl_all { - ($($t:ty)*) => ($( - shr_impl! { $t, u8 } - shr_impl! { $t, u16 } - shr_impl! { $t, u32 } - shr_impl! { $t, u64 } - shr_impl! { $t, u128 } - shr_impl! { $t, usize } - - shr_impl! { $t, i8 } - shr_impl! { $t, i16 } - shr_impl! { $t, i32 } - shr_impl! { $t, i64 } - shr_impl! { $t, i128 } - shr_impl! { $t, isize } - )*) -} - -shr_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize } - -/// The bitwise AND assignment operator `&=`. -/// -/// # Examples -/// -/// In this example, the `&=` operator is lifted to a trivial `Scalar` type. -/// -/// ``` -/// use std::ops::BitAndAssign; -/// -/// #[derive(Debug, PartialEq)] -/// struct Scalar(bool); -/// -/// impl BitAndAssign for Scalar { -/// // rhs is the "right-hand side" of the expression `a &= b` -/// fn bitand_assign(&mut self, rhs: Self) { -/// *self = Scalar(self.0 & rhs.0) -/// } -/// } -/// -/// fn main() { -/// let mut scalar = Scalar(true); -/// scalar &= Scalar(true); -/// assert_eq!(scalar, Scalar(true)); -/// -/// let mut scalar = Scalar(true); -/// scalar &= Scalar(false); -/// assert_eq!(scalar, Scalar(false)); -/// -/// let mut scalar = Scalar(false); -/// scalar &= Scalar(true); -/// assert_eq!(scalar, Scalar(false)); -/// -/// let mut scalar = Scalar(false); -/// scalar &= Scalar(false); -/// assert_eq!(scalar, Scalar(false)); -/// } -/// ``` -/// -/// In this example, the `BitAndAssign` trait is implemented for a -/// `BooleanVector` struct. -/// -/// ``` -/// use std::ops::BitAndAssign; -/// -/// #[derive(Debug, PartialEq)] -/// struct BooleanVector(Vec); -/// -/// impl BitAndAssign for BooleanVector { -/// // rhs is the "right-hand side" of the expression `a &= b` -/// fn bitand_assign(&mut self, rhs: Self) { -/// assert_eq!(self.0.len(), rhs.0.len()); -/// *self = BooleanVector(self.0 -/// .iter() -/// .zip(rhs.0.iter()) -/// .map(|(x, y)| *x && *y) -/// .collect()); -/// } -/// } -/// -/// fn main() { -/// let mut bv = BooleanVector(vec![true, true, false, false]); -/// bv &= BooleanVector(vec![true, false, true, false]); -/// let expected = BooleanVector(vec![true, false, false, false]); -/// assert_eq!(bv, expected); -/// } -/// ``` -#[lang = "bitand_assign"] -#[stable(feature = "op_assign_traits", since = "1.8.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} &= {Rhs}`"] -pub trait BitAndAssign { - /// The method for the `&=` operator - #[stable(feature = "op_assign_traits", since = "1.8.0")] - fn bitand_assign(&mut self, rhs: Rhs); -} - -macro_rules! bitand_assign_impl { - ($($t:ty)+) => ($( - #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl BitAndAssign for $t { - #[inline] - fn bitand_assign(&mut self, other: $t) { *self &= other } - } - )+) -} - -bitand_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } - -/// The bitwise OR assignment operator `|=`. -/// -/// # Examples -/// -/// A trivial implementation of `BitOrAssign`. When `Foo |= Foo` happens, it ends up -/// calling `bitor_assign`, and therefore, `main` prints `Bitwise Or-ing!`. -/// -/// ``` -/// use std::ops::BitOrAssign; -/// -/// struct Foo; -/// -/// impl BitOrAssign for Foo { -/// fn bitor_assign(&mut self, _rhs: Foo) { -/// println!("Bitwise Or-ing!"); -/// } -/// } -/// -/// # #[allow(unused_assignments)] -/// fn main() { -/// let mut foo = Foo; -/// foo |= Foo; -/// } -/// ``` -#[lang = "bitor_assign"] -#[stable(feature = "op_assign_traits", since = "1.8.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} |= {Rhs}`"] -pub trait BitOrAssign { - /// The method for the `|=` operator - #[stable(feature = "op_assign_traits", since = "1.8.0")] - fn bitor_assign(&mut self, rhs: Rhs); -} - -macro_rules! bitor_assign_impl { - ($($t:ty)+) => ($( - #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl BitOrAssign for $t { - #[inline] - fn bitor_assign(&mut self, other: $t) { *self |= other } - } - )+) -} - -bitor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } - -/// The bitwise XOR assignment operator `^=`. -/// -/// # Examples -/// -/// A trivial implementation of `BitXorAssign`. When `Foo ^= Foo` happens, it ends up -/// calling `bitxor_assign`, and therefore, `main` prints `Bitwise Xor-ing!`. -/// -/// ``` -/// use std::ops::BitXorAssign; -/// -/// struct Foo; -/// -/// impl BitXorAssign for Foo { -/// fn bitxor_assign(&mut self, _rhs: Foo) { -/// println!("Bitwise Xor-ing!"); -/// } -/// } -/// -/// # #[allow(unused_assignments)] -/// fn main() { -/// let mut foo = Foo; -/// foo ^= Foo; -/// } -/// ``` -#[lang = "bitxor_assign"] -#[stable(feature = "op_assign_traits", since = "1.8.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} ^= {Rhs}`"] -pub trait BitXorAssign { - /// The method for the `^=` operator - #[stable(feature = "op_assign_traits", since = "1.8.0")] - fn bitxor_assign(&mut self, rhs: Rhs); -} - -macro_rules! bitxor_assign_impl { - ($($t:ty)+) => ($( - #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl BitXorAssign for $t { - #[inline] - fn bitxor_assign(&mut self, other: $t) { *self ^= other } - } - )+) -} - -bitxor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } - -/// The left shift assignment operator `<<=`. -/// -/// # Examples -/// -/// A trivial implementation of `ShlAssign`. When `Foo <<= Foo` happens, it ends up -/// calling `shl_assign`, and therefore, `main` prints `Shifting left!`. -/// -/// ``` -/// use std::ops::ShlAssign; -/// -/// struct Foo; -/// -/// impl ShlAssign for Foo { -/// fn shl_assign(&mut self, _rhs: Foo) { -/// println!("Shifting left!"); -/// } -/// } -/// -/// # #[allow(unused_assignments)] -/// fn main() { -/// let mut foo = Foo; -/// foo <<= Foo; -/// } -/// ``` -#[lang = "shl_assign"] -#[stable(feature = "op_assign_traits", since = "1.8.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} <<= {Rhs}`"] -pub trait ShlAssign { - /// The method for the `<<=` operator - #[stable(feature = "op_assign_traits", since = "1.8.0")] - fn shl_assign(&mut self, rhs: Rhs); -} - -macro_rules! shl_assign_impl { - ($t:ty, $f:ty) => ( - #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl ShlAssign<$f> for $t { - #[inline] - #[rustc_inherit_overflow_checks] - fn shl_assign(&mut self, other: $f) { - *self <<= other - } - } - ) -} - -macro_rules! shl_assign_impl_all { - ($($t:ty)*) => ($( - shl_assign_impl! { $t, u8 } - shl_assign_impl! { $t, u16 } - shl_assign_impl! { $t, u32 } - shl_assign_impl! { $t, u64 } - shl_assign_impl! { $t, u128 } - shl_assign_impl! { $t, usize } - - shl_assign_impl! { $t, i8 } - shl_assign_impl! { $t, i16 } - shl_assign_impl! { $t, i32 } - shl_assign_impl! { $t, i64 } - shl_assign_impl! { $t, i128 } - shl_assign_impl! { $t, isize } - )*) -} - -shl_assign_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize } - -/// The right shift assignment operator `>>=`. -/// -/// # Examples -/// -/// A trivial implementation of `ShrAssign`. When `Foo >>= Foo` happens, it ends up -/// calling `shr_assign`, and therefore, `main` prints `Shifting right!`. -/// -/// ``` -/// use std::ops::ShrAssign; -/// -/// struct Foo; -/// -/// impl ShrAssign for Foo { -/// fn shr_assign(&mut self, _rhs: Foo) { -/// println!("Shifting right!"); -/// } -/// } -/// -/// # #[allow(unused_assignments)] -/// fn main() { -/// let mut foo = Foo; -/// foo >>= Foo; -/// } -/// ``` -#[lang = "shr_assign"] -#[stable(feature = "op_assign_traits", since = "1.8.0")] -#[rustc_on_unimplemented = "no implementation for `{Self} >>= {Rhs}`"] -pub trait ShrAssign { - /// The method for the `>>=` operator - #[stable(feature = "op_assign_traits", since = "1.8.0")] - fn shr_assign(&mut self, rhs: Rhs); -} - -macro_rules! shr_assign_impl { - ($t:ty, $f:ty) => ( - #[stable(feature = "op_assign_traits", since = "1.8.0")] - impl ShrAssign<$f> for $t { - #[inline] - #[rustc_inherit_overflow_checks] - fn shr_assign(&mut self, other: $f) { - *self >>= other - } - } - ) -} - -macro_rules! shr_assign_impl_all { - ($($t:ty)*) => ($( - shr_assign_impl! { $t, u8 } - shr_assign_impl! { $t, u16 } - shr_assign_impl! { $t, u32 } - shr_assign_impl! { $t, u64 } - shr_assign_impl! { $t, u128 } - shr_assign_impl! { $t, usize } - - shr_assign_impl! { $t, i8 } - shr_assign_impl! { $t, i16 } - shr_assign_impl! { $t, i32 } - shr_assign_impl! { $t, i64 } - shr_assign_impl! { $t, i128 } - shr_assign_impl! { $t, isize } - )*) -} - -shr_assign_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize } - /// The `Index` trait is used to specify the functionality of indexing operations /// like `container[index]` when used in an immutable context. /// From f774cddcf2c1935f101bcfb931495e411e58e52b Mon Sep 17 00:00:00 2001 From: Clar Charr Date: Wed, 7 Jun 2017 22:10:21 -0400 Subject: [PATCH 102/233] Move placement new operators to module. --- src/libcore/ops/mod.rs | 123 ++------------------------------------ src/libcore/ops/place.rs | 126 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 130 insertions(+), 119 deletions(-) create mode 100644 src/libcore/ops/place.rs diff --git a/src/libcore/ops/mod.rs b/src/libcore/ops/mod.rs index fdc1b5fc2359..d05365a8fddd 100644 --- a/src/libcore/ops/mod.rs +++ b/src/libcore/ops/mod.rs @@ -150,17 +150,16 @@ mod arith; mod bit; mod function; +mod place; mod range; #[stable(feature = "rust1", since = "1.0.0")] pub use self::arith::{Add, Sub, Mul, Div, Rem, Neg}; - #[stable(feature = "op_assign_traits", since = "1.8.0")] pub use self::arith::{AddAssign, SubAssign, MulAssign, DivAssign, RemAssign}; #[stable(feature = "rust1", since = "1.0.0")] pub use self::bit::{Not, BitAnd, BitOr, BitXor, Shl, Shr}; - #[stable(feature = "op_assign_traits", since = "1.8.0")] pub use self::bit::{BitAndAssign, BitOrAssign, BitXorAssign, ShlAssign, ShrAssign}; @@ -173,6 +172,9 @@ pub use self::range::{Range, RangeFrom, RangeFull, RangeTo}; #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] pub use self::range::{RangeInclusive, RangeToInclusive}; +#[unstable(feature = "placement_new_protocol", issue = "27779")] +pub use self::place::{Place, Placer, InPlace, Boxed, BoxPlace}; + use marker::Unsize; /// The `Drop` trait is used to run some code when a value goes out of scope. @@ -592,123 +594,6 @@ impl, U: ?Sized> CoerceUnsized<*const U> for *mut T {} #[unstable(feature = "coerce_unsized", issue = "27732")] impl, U: ?Sized> CoerceUnsized<*const U> for *const T {} -/// Both `PLACE <- EXPR` and `box EXPR` desugar into expressions -/// that allocate an intermediate "place" that holds uninitialized -/// state. The desugaring evaluates EXPR, and writes the result at -/// the address returned by the `pointer` method of this trait. -/// -/// A `Place` can be thought of as a special representation for a -/// hypothetical `&uninit` reference (which Rust cannot currently -/// express directly). That is, it represents a pointer to -/// uninitialized storage. -/// -/// The client is responsible for two steps: First, initializing the -/// payload (it can access its address via `pointer`). Second, -/// converting the agent to an instance of the owning pointer, via the -/// appropriate `finalize` method (see the `InPlace`. -/// -/// If evaluating EXPR fails, then it is up to the destructor for the -/// implementation of Place to clean up any intermediate state -/// (e.g. deallocate box storage, pop a stack, etc). -#[unstable(feature = "placement_new_protocol", issue = "27779")] -pub trait Place { - /// Returns the address where the input value will be written. - /// Note that the data at this address is generally uninitialized, - /// and thus one should use `ptr::write` for initializing it. - fn pointer(&mut self) -> *mut Data; -} - -/// Interface to implementations of `PLACE <- EXPR`. -/// -/// `PLACE <- EXPR` effectively desugars into: -/// -/// ```rust,ignore -/// let p = PLACE; -/// let mut place = Placer::make_place(p); -/// let raw_place = Place::pointer(&mut place); -/// let value = EXPR; -/// unsafe { -/// std::ptr::write(raw_place, value); -/// InPlace::finalize(place) -/// } -/// ``` -/// -/// The type of `PLACE <- EXPR` is derived from the type of `PLACE`; -/// if the type of `PLACE` is `P`, then the final type of the whole -/// expression is `P::Place::Owner` (see the `InPlace` and `Boxed` -/// traits). -/// -/// Values for types implementing this trait usually are transient -/// intermediate values (e.g. the return value of `Vec::emplace_back`) -/// or `Copy`, since the `make_place` method takes `self` by value. -#[unstable(feature = "placement_new_protocol", issue = "27779")] -pub trait Placer { - /// `Place` is the intermedate agent guarding the - /// uninitialized state for `Data`. - type Place: InPlace; - - /// Creates a fresh place from `self`. - fn make_place(self) -> Self::Place; -} - -/// Specialization of `Place` trait supporting `PLACE <- EXPR`. -#[unstable(feature = "placement_new_protocol", issue = "27779")] -pub trait InPlace: Place { - /// `Owner` is the type of the end value of `PLACE <- EXPR` - /// - /// Note that when `PLACE <- EXPR` is solely used for - /// side-effecting an existing data-structure, - /// e.g. `Vec::emplace_back`, then `Owner` need not carry any - /// information at all (e.g. it can be the unit type `()` in that - /// case). - type Owner; - - /// Converts self into the final value, shifting - /// deallocation/cleanup responsibilities (if any remain), over to - /// the returned instance of `Owner` and forgetting self. - unsafe fn finalize(self) -> Self::Owner; -} - -/// Core trait for the `box EXPR` form. -/// -/// `box EXPR` effectively desugars into: -/// -/// ```rust,ignore -/// let mut place = BoxPlace::make_place(); -/// let raw_place = Place::pointer(&mut place); -/// let value = EXPR; -/// unsafe { -/// ::std::ptr::write(raw_place, value); -/// Boxed::finalize(place) -/// } -/// ``` -/// -/// The type of `box EXPR` is supplied from its surrounding -/// context; in the above expansion, the result type `T` is used -/// to determine which implementation of `Boxed` to use, and that -/// `` in turn dictates determines which -/// implementation of `BoxPlace` to use, namely: -/// `<::Place as BoxPlace>`. -#[unstable(feature = "placement_new_protocol", issue = "27779")] -pub trait Boxed { - /// The kind of data that is stored in this kind of box. - type Data; /* (`Data` unused b/c cannot yet express below bound.) */ - /// The place that will negotiate the storage of the data. - type Place: BoxPlace; - - /// Converts filled place into final owning value, shifting - /// deallocation/cleanup responsibilities (if any remain), over to - /// returned instance of `Self` and forgetting `filled`. - unsafe fn finalize(filled: Self::Place) -> Self; -} - -/// Specialization of `Place` trait supporting `box EXPR`. -#[unstable(feature = "placement_new_protocol", issue = "27779")] -pub trait BoxPlace : Place { - /// Creates a globally fresh place. - fn make_place() -> Self; -} - /// This trait has been superseded by the `Try` trait, but must remain /// here as `?` is still lowered to it in stage0 . #[cfg(stage0)] diff --git a/src/libcore/ops/place.rs b/src/libcore/ops/place.rs new file mode 100644 index 000000000000..996a741c96f9 --- /dev/null +++ b/src/libcore/ops/place.rs @@ -0,0 +1,126 @@ +// 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. + +/// Both `PLACE <- EXPR` and `box EXPR` desugar into expressions +/// that allocate an intermediate "place" that holds uninitialized +/// state. The desugaring evaluates EXPR, and writes the result at +/// the address returned by the `pointer` method of this trait. +/// +/// A `Place` can be thought of as a special representation for a +/// hypothetical `&uninit` reference (which Rust cannot currently +/// express directly). That is, it represents a pointer to +/// uninitialized storage. +/// +/// The client is responsible for two steps: First, initializing the +/// payload (it can access its address via `pointer`). Second, +/// converting the agent to an instance of the owning pointer, via the +/// appropriate `finalize` method (see the `InPlace`. +/// +/// If evaluating EXPR fails, then it is up to the destructor for the +/// implementation of Place to clean up any intermediate state +/// (e.g. deallocate box storage, pop a stack, etc). +#[unstable(feature = "placement_new_protocol", issue = "27779")] +pub trait Place { + /// Returns the address where the input value will be written. + /// Note that the data at this address is generally uninitialized, + /// and thus one should use `ptr::write` for initializing it. + fn pointer(&mut self) -> *mut Data; +} + +/// Interface to implementations of `PLACE <- EXPR`. +/// +/// `PLACE <- EXPR` effectively desugars into: +/// +/// ```rust,ignore +/// let p = PLACE; +/// let mut place = Placer::make_place(p); +/// let raw_place = Place::pointer(&mut place); +/// let value = EXPR; +/// unsafe { +/// std::ptr::write(raw_place, value); +/// InPlace::finalize(place) +/// } +/// ``` +/// +/// The type of `PLACE <- EXPR` is derived from the type of `PLACE`; +/// if the type of `PLACE` is `P`, then the final type of the whole +/// expression is `P::Place::Owner` (see the `InPlace` and `Boxed` +/// traits). +/// +/// Values for types implementing this trait usually are transient +/// intermediate values (e.g. the return value of `Vec::emplace_back`) +/// or `Copy`, since the `make_place` method takes `self` by value. +#[unstable(feature = "placement_new_protocol", issue = "27779")] +pub trait Placer { + /// `Place` is the intermedate agent guarding the + /// uninitialized state for `Data`. + type Place: InPlace; + + /// Creates a fresh place from `self`. + fn make_place(self) -> Self::Place; +} + +/// Specialization of `Place` trait supporting `PLACE <- EXPR`. +#[unstable(feature = "placement_new_protocol", issue = "27779")] +pub trait InPlace: Place { + /// `Owner` is the type of the end value of `PLACE <- EXPR` + /// + /// Note that when `PLACE <- EXPR` is solely used for + /// side-effecting an existing data-structure, + /// e.g. `Vec::emplace_back`, then `Owner` need not carry any + /// information at all (e.g. it can be the unit type `()` in that + /// case). + type Owner; + + /// Converts self into the final value, shifting + /// deallocation/cleanup responsibilities (if any remain), over to + /// the returned instance of `Owner` and forgetting self. + unsafe fn finalize(self) -> Self::Owner; +} + +/// Core trait for the `box EXPR` form. +/// +/// `box EXPR` effectively desugars into: +/// +/// ```rust,ignore +/// let mut place = BoxPlace::make_place(); +/// let raw_place = Place::pointer(&mut place); +/// let value = EXPR; +/// unsafe { +/// ::std::ptr::write(raw_place, value); +/// Boxed::finalize(place) +/// } +/// ``` +/// +/// The type of `box EXPR` is supplied from its surrounding +/// context; in the above expansion, the result type `T` is used +/// to determine which implementation of `Boxed` to use, and that +/// `` in turn dictates determines which +/// implementation of `BoxPlace` to use, namely: +/// `<::Place as BoxPlace>`. +#[unstable(feature = "placement_new_protocol", issue = "27779")] +pub trait Boxed { + /// The kind of data that is stored in this kind of box. + type Data; /* (`Data` unused b/c cannot yet express below bound.) */ + /// The place that will negotiate the storage of the data. + type Place: BoxPlace; + + /// Converts filled place into final owning value, shifting + /// deallocation/cleanup responsibilities (if any remain), over to + /// returned instance of `Self` and forgetting `filled`. + unsafe fn finalize(filled: Self::Place) -> Self; +} + +/// Specialization of `Place` trait supporting `box EXPR`. +#[unstable(feature = "placement_new_protocol", issue = "27779")] +pub trait BoxPlace : Place { + /// Creates a globally fresh place. + fn make_place() -> Self; +} From bc9dc0ab3e26171da27fccf5775538e55c2a8e06 Mon Sep 17 00:00:00 2001 From: Clar Charr Date: Wed, 7 Jun 2017 22:12:18 -0400 Subject: [PATCH 103/233] Move Try to module. --- src/libcore/ops/mod.rs | 109 +++------------------------------------- src/libcore/ops/try.rs | 111 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 118 insertions(+), 102 deletions(-) create mode 100644 src/libcore/ops/try.rs diff --git a/src/libcore/ops/mod.rs b/src/libcore/ops/mod.rs index d05365a8fddd..ae6fcf52cd76 100644 --- a/src/libcore/ops/mod.rs +++ b/src/libcore/ops/mod.rs @@ -152,6 +152,7 @@ mod bit; mod function; mod place; mod range; +mod try; #[stable(feature = "rust1", since = "1.0.0")] pub use self::arith::{Add, Sub, Mul, Div, Rem, Neg}; @@ -172,6 +173,12 @@ pub use self::range::{Range, RangeFrom, RangeFull, RangeTo}; #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] pub use self::range::{RangeInclusive, RangeToInclusive}; +#[unstable(feature = "question_mark_carrier", issue = "31436")] +#[cfg(stage0)] +pub use self::try::Carrier; +#[unstable(feature = "try_trait", issue = "42327")] +pub use self::try::Try; + #[unstable(feature = "placement_new_protocol", issue = "27779")] pub use self::place::{Place, Placer, InPlace, Boxed, BoxPlace}; @@ -593,105 +600,3 @@ impl, U: ?Sized> CoerceUnsized<*const U> for *mut T {} // *const T -> *const U #[unstable(feature = "coerce_unsized", issue = "27732")] impl, U: ?Sized> CoerceUnsized<*const U> for *const T {} - -/// This trait has been superseded by the `Try` trait, but must remain -/// here as `?` is still lowered to it in stage0 . -#[cfg(stage0)] -#[unstable(feature = "question_mark_carrier", issue = "31436")] -pub trait Carrier { - /// The type of the value when computation succeeds. - type Success; - /// The type of the value when computation errors out. - type Error; - - /// Create a `Carrier` from a success value. - fn from_success(_: Self::Success) -> Self; - - /// Create a `Carrier` from an error value. - fn from_error(_: Self::Error) -> Self; - - /// Translate this `Carrier` to another implementation of `Carrier` with the - /// same associated types. - fn translate(self) -> T where T: Carrier; -} - -#[cfg(stage0)] -#[unstable(feature = "question_mark_carrier", issue = "31436")] -impl Carrier for Result { - type Success = U; - type Error = V; - - fn from_success(u: U) -> Result { - Ok(u) - } - - fn from_error(e: V) -> Result { - Err(e) - } - - fn translate(self) -> T - where T: Carrier - { - match self { - Ok(u) => T::from_success(u), - Err(e) => T::from_error(e), - } - } -} - -struct _DummyErrorType; - -impl Try for _DummyErrorType { - type Ok = (); - type Error = (); - - fn into_result(self) -> Result { - Ok(()) - } - - fn from_ok(_: ()) -> _DummyErrorType { - _DummyErrorType - } - - fn from_error(_: ()) -> _DummyErrorType { - _DummyErrorType - } -} - -/// A trait for customizing the behaviour of the `?` operator. -/// -/// A type implementing `Try` is one that has a canonical way to view it -/// in terms of a success/failure dichotomy. This trait allows both -/// extracting those success or failure values from an existing instance and -/// creating a new instance from a success or failure value. -#[unstable(feature = "try_trait", issue = "42327")] -pub trait Try { - /// The type of this value when viewed as successful. - #[unstable(feature = "try_trait", issue = "42327")] - type Ok; - /// The type of this value when viewed as failed. - #[unstable(feature = "try_trait", issue = "42327")] - type Error; - - /// Applies the "?" operator. A return of `Ok(t)` means that the - /// execution should continue normally, and the result of `?` is the - /// value `t`. A return of `Err(e)` means that execution should branch - /// to the innermost enclosing `catch`, or return from the function. - /// - /// If an `Err(e)` result is returned, the value `e` will be "wrapped" - /// in the return type of the enclosing scope (which must itself implement - /// `Try`). Specifically, the value `X::from_error(From::from(e))` - /// is returned, where `X` is the return type of the enclosing function. - #[unstable(feature = "try_trait", issue = "42327")] - fn into_result(self) -> Result; - - /// Wrap an error value to construct the composite result. For example, - /// `Result::Err(x)` and `Result::from_error(x)` are equivalent. - #[unstable(feature = "try_trait", issue = "42327")] - fn from_error(v: Self::Error) -> Self; - - /// Wrap an OK value to construct the composite result. For example, - /// `Result::Ok(x)` and `Result::from_ok(x)` are equivalent. - #[unstable(feature = "try_trait", issue = "42327")] - fn from_ok(v: Self::Ok) -> Self; -} diff --git a/src/libcore/ops/try.rs b/src/libcore/ops/try.rs new file mode 100644 index 000000000000..cf75cf79fae6 --- /dev/null +++ b/src/libcore/ops/try.rs @@ -0,0 +1,111 @@ +// 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. + +/// This trait has been superseded by the `Try` trait, but must remain +/// here as `?` is still lowered to it in stage0 . +#[cfg(stage0)] +#[unstable(feature = "question_mark_carrier", issue = "31436")] +pub trait Carrier { + /// The type of the value when computation succeeds. + type Success; + /// The type of the value when computation errors out. + type Error; + + /// Create a `Carrier` from a success value. + fn from_success(_: Self::Success) -> Self; + + /// Create a `Carrier` from an error value. + fn from_error(_: Self::Error) -> Self; + + /// Translate this `Carrier` to another implementation of `Carrier` with the + /// same associated types. + fn translate(self) -> T where T: Carrier; +} + +#[cfg(stage0)] +#[unstable(feature = "question_mark_carrier", issue = "31436")] +impl Carrier for Result { + type Success = U; + type Error = V; + + fn from_success(u: U) -> Result { + Ok(u) + } + + fn from_error(e: V) -> Result { + Err(e) + } + + fn translate(self) -> T + where T: Carrier + { + match self { + Ok(u) => T::from_success(u), + Err(e) => T::from_error(e), + } + } +} + +struct _DummyErrorType; + +impl Try for _DummyErrorType { + type Ok = (); + type Error = (); + + fn into_result(self) -> Result { + Ok(()) + } + + fn from_ok(_: ()) -> _DummyErrorType { + _DummyErrorType + } + + fn from_error(_: ()) -> _DummyErrorType { + _DummyErrorType + } +} + +/// A trait for customizing the behaviour of the `?` operator. +/// +/// A type implementing `Try` is one that has a canonical way to view it +/// in terms of a success/failure dichotomy. This trait allows both +/// extracting those success or failure values from an existing instance and +/// creating a new instance from a success or failure value. +#[unstable(feature = "try_trait", issue = "42327")] +pub trait Try { + /// The type of this value when viewed as successful. + #[unstable(feature = "try_trait", issue = "42327")] + type Ok; + /// The type of this value when viewed as failed. + #[unstable(feature = "try_trait", issue = "42327")] + type Error; + + /// Applies the "?" operator. A return of `Ok(t)` means that the + /// execution should continue normally, and the result of `?` is the + /// value `t`. A return of `Err(e)` means that execution should branch + /// to the innermost enclosing `catch`, or return from the function. + /// + /// If an `Err(e)` result is returned, the value `e` will be "wrapped" + /// in the return type of the enclosing scope (which must itself implement + /// `Try`). Specifically, the value `X::from_error(From::from(e))` + /// is returned, where `X` is the return type of the enclosing function. + #[unstable(feature = "try_trait", issue = "42327")] + fn into_result(self) -> Result; + + /// Wrap an error value to construct the composite result. For example, + /// `Result::Err(x)` and `Result::from_error(x)` are equivalent. + #[unstable(feature = "try_trait", issue = "42327")] + fn from_error(v: Self::Error) -> Self; + + /// Wrap an OK value to construct the composite result. For example, + /// `Result::Ok(x)` and `Result::from_ok(x)` are equivalent. + #[unstable(feature = "try_trait", issue = "42327")] + fn from_ok(v: Self::Ok) -> Self; +} From fefa521e5082fa610b7e5eebcdd98b56dc6b523b Mon Sep 17 00:00:00 2001 From: Clar Charr Date: Wed, 7 Jun 2017 22:13:31 -0400 Subject: [PATCH 104/233] Move Deref to module. --- src/libcore/ops/deref.rs | 119 +++++++++++++++++++++++++++++++++++++++ src/libcore/ops/mod.rs | 114 ++----------------------------------- 2 files changed, 123 insertions(+), 110 deletions(-) create mode 100644 src/libcore/ops/deref.rs diff --git a/src/libcore/ops/deref.rs b/src/libcore/ops/deref.rs new file mode 100644 index 000000000000..3f4dabbbc0ce --- /dev/null +++ b/src/libcore/ops/deref.rs @@ -0,0 +1,119 @@ +// 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. + +/// The `Deref` trait is used to specify the functionality of dereferencing +/// operations, like `*v`. +/// +/// `Deref` also enables ['`Deref` coercions'][coercions]. +/// +/// [coercions]: ../../book/deref-coercions.html +/// +/// # Examples +/// +/// A struct with a single field which is accessible via dereferencing the +/// struct. +/// +/// ``` +/// use std::ops::Deref; +/// +/// struct DerefExample { +/// value: T +/// } +/// +/// impl Deref for DerefExample { +/// type Target = T; +/// +/// fn deref(&self) -> &T { +/// &self.value +/// } +/// } +/// +/// fn main() { +/// let x = DerefExample { value: 'a' }; +/// assert_eq!('a', *x); +/// } +/// ``` +#[lang = "deref"] +#[stable(feature = "rust1", since = "1.0.0")] +pub trait Deref { + /// The resulting type after dereferencing + #[stable(feature = "rust1", since = "1.0.0")] + type Target: ?Sized; + + /// The method called to dereference a value + #[stable(feature = "rust1", since = "1.0.0")] + fn deref(&self) -> &Self::Target; +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T: ?Sized> Deref for &'a T { + type Target = T; + + fn deref(&self) -> &T { *self } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T: ?Sized> Deref for &'a mut T { + type Target = T; + + fn deref(&self) -> &T { *self } +} + +/// The `DerefMut` trait is used to specify the functionality of dereferencing +/// mutably like `*v = 1;` +/// +/// `DerefMut` also enables ['`Deref` coercions'][coercions]. +/// +/// [coercions]: ../../book/deref-coercions.html +/// +/// # Examples +/// +/// A struct with a single field which is modifiable via dereferencing the +/// struct. +/// +/// ``` +/// use std::ops::{Deref, DerefMut}; +/// +/// struct DerefMutExample { +/// value: T +/// } +/// +/// impl Deref for DerefMutExample { +/// type Target = T; +/// +/// fn deref(&self) -> &T { +/// &self.value +/// } +/// } +/// +/// impl DerefMut for DerefMutExample { +/// fn deref_mut(&mut self) -> &mut T { +/// &mut self.value +/// } +/// } +/// +/// fn main() { +/// let mut x = DerefMutExample { value: 'a' }; +/// *x = 'b'; +/// assert_eq!('b', *x); +/// } +/// ``` +#[lang = "deref_mut"] +#[stable(feature = "rust1", since = "1.0.0")] +pub trait DerefMut: Deref { + /// The method called to mutably dereference a value + #[stable(feature = "rust1", since = "1.0.0")] + fn deref_mut(&mut self) -> &mut Self::Target; +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T: ?Sized> DerefMut for &'a mut T { + fn deref_mut(&mut self) -> &mut T { *self } +} diff --git a/src/libcore/ops/mod.rs b/src/libcore/ops/mod.rs index ae6fcf52cd76..22e5695a8780 100644 --- a/src/libcore/ops/mod.rs +++ b/src/libcore/ops/mod.rs @@ -149,6 +149,7 @@ mod arith; mod bit; +mod deref; mod function; mod place; mod range; @@ -164,6 +165,9 @@ pub use self::bit::{Not, BitAnd, BitOr, BitXor, Shl, Shr}; #[stable(feature = "op_assign_traits", since = "1.8.0")] pub use self::bit::{BitAndAssign, BitOrAssign, BitXorAssign, ShlAssign, ShrAssign}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::deref::{Deref, DerefMut}; + #[stable(feature = "rust1", since = "1.0.0")] pub use self::function::{Fn, FnMut, FnOnce}; @@ -423,116 +427,6 @@ pub trait IndexMut: Index { fn index_mut(&mut self, index: Idx) -> &mut Self::Output; } -/// The `Deref` trait is used to specify the functionality of dereferencing -/// operations, like `*v`. -/// -/// `Deref` also enables ['`Deref` coercions'][coercions]. -/// -/// [coercions]: ../../book/deref-coercions.html -/// -/// # Examples -/// -/// A struct with a single field which is accessible via dereferencing the -/// struct. -/// -/// ``` -/// use std::ops::Deref; -/// -/// struct DerefExample { -/// value: T -/// } -/// -/// impl Deref for DerefExample { -/// type Target = T; -/// -/// fn deref(&self) -> &T { -/// &self.value -/// } -/// } -/// -/// fn main() { -/// let x = DerefExample { value: 'a' }; -/// assert_eq!('a', *x); -/// } -/// ``` -#[lang = "deref"] -#[stable(feature = "rust1", since = "1.0.0")] -pub trait Deref { - /// The resulting type after dereferencing - #[stable(feature = "rust1", since = "1.0.0")] - type Target: ?Sized; - - /// The method called to dereference a value - #[stable(feature = "rust1", since = "1.0.0")] - fn deref(&self) -> &Self::Target; -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T: ?Sized> Deref for &'a T { - type Target = T; - - fn deref(&self) -> &T { *self } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T: ?Sized> Deref for &'a mut T { - type Target = T; - - fn deref(&self) -> &T { *self } -} - -/// The `DerefMut` trait is used to specify the functionality of dereferencing -/// mutably like `*v = 1;` -/// -/// `DerefMut` also enables ['`Deref` coercions'][coercions]. -/// -/// [coercions]: ../../book/deref-coercions.html -/// -/// # Examples -/// -/// A struct with a single field which is modifiable via dereferencing the -/// struct. -/// -/// ``` -/// use std::ops::{Deref, DerefMut}; -/// -/// struct DerefMutExample { -/// value: T -/// } -/// -/// impl Deref for DerefMutExample { -/// type Target = T; -/// -/// fn deref(&self) -> &T { -/// &self.value -/// } -/// } -/// -/// impl DerefMut for DerefMutExample { -/// fn deref_mut(&mut self) -> &mut T { -/// &mut self.value -/// } -/// } -/// -/// fn main() { -/// let mut x = DerefMutExample { value: 'a' }; -/// *x = 'b'; -/// assert_eq!('b', *x); -/// } -/// ``` -#[lang = "deref_mut"] -#[stable(feature = "rust1", since = "1.0.0")] -pub trait DerefMut: Deref { - /// The method called to mutably dereference a value - #[stable(feature = "rust1", since = "1.0.0")] - fn deref_mut(&mut self) -> &mut Self::Target; -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T: ?Sized> DerefMut for &'a mut T { - fn deref_mut(&mut self) -> &mut T { *self } -} - /// Trait that indicates that this is a pointer or a wrapper for one, /// where unsizing can be performed on the pointee. /// From 6693b4d50548198c1534eac592b1eac674b57a39 Mon Sep 17 00:00:00 2001 From: Clar Charr Date: Wed, 7 Jun 2017 22:14:13 -0400 Subject: [PATCH 105/233] Move Index to module. --- src/libcore/ops/index.rs | 158 +++++++++++++++++++++++++++++++++++++++ src/libcore/ops/mod.rs | 153 +------------------------------------ 2 files changed, 162 insertions(+), 149 deletions(-) create mode 100644 src/libcore/ops/index.rs diff --git a/src/libcore/ops/index.rs b/src/libcore/ops/index.rs new file mode 100644 index 000000000000..b16b95677874 --- /dev/null +++ b/src/libcore/ops/index.rs @@ -0,0 +1,158 @@ +// 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. + +/// The `Index` trait is used to specify the functionality of indexing operations +/// like `container[index]` when used in an immutable context. +/// +/// `container[index]` is actually syntactic sugar for `*container.index(index)`, +/// but only when used as an immutable value. If a mutable value is requested, +/// [`IndexMut`] is used instead. This allows nice things such as +/// `let value = v[index]` if `value` implements [`Copy`]. +/// +/// [`IndexMut`]: ../../std/ops/trait.IndexMut.html +/// [`Copy`]: ../../std/marker/trait.Copy.html +/// +/// # Examples +/// +/// The following example implements `Index` on a read-only `NucleotideCount` +/// container, enabling individual counts to be retrieved with index syntax. +/// +/// ``` +/// use std::ops::Index; +/// +/// enum Nucleotide { +/// A, +/// C, +/// G, +/// T, +/// } +/// +/// struct NucleotideCount { +/// a: usize, +/// c: usize, +/// g: usize, +/// t: usize, +/// } +/// +/// impl Index for NucleotideCount { +/// type Output = usize; +/// +/// fn index(&self, nucleotide: Nucleotide) -> &usize { +/// match nucleotide { +/// Nucleotide::A => &self.a, +/// Nucleotide::C => &self.c, +/// Nucleotide::G => &self.g, +/// Nucleotide::T => &self.t, +/// } +/// } +/// } +/// +/// let nucleotide_count = NucleotideCount {a: 14, c: 9, g: 10, t: 12}; +/// assert_eq!(nucleotide_count[Nucleotide::A], 14); +/// assert_eq!(nucleotide_count[Nucleotide::C], 9); +/// assert_eq!(nucleotide_count[Nucleotide::G], 10); +/// assert_eq!(nucleotide_count[Nucleotide::T], 12); +/// ``` +#[lang = "index"] +#[rustc_on_unimplemented = "the type `{Self}` cannot be indexed by `{Idx}`"] +#[stable(feature = "rust1", since = "1.0.0")] +pub trait Index { + /// The returned type after indexing + #[stable(feature = "rust1", since = "1.0.0")] + type Output: ?Sized; + + /// The method for the indexing (`container[index]`) operation + #[stable(feature = "rust1", since = "1.0.0")] + fn index(&self, index: Idx) -> &Self::Output; +} + +/// The `IndexMut` trait is used to specify the functionality of indexing +/// operations like `container[index]` when used in a mutable context. +/// +/// `container[index]` is actually syntactic sugar for +/// `*container.index_mut(index)`, but only when used as a mutable value. If +/// an immutable value is requested, the [`Index`] trait is used instead. This +/// allows nice things such as `v[index] = value` if `value` implements [`Copy`]. +/// +/// [`Index`]: ../../std/ops/trait.Index.html +/// [`Copy`]: ../../std/marker/trait.Copy.html +/// +/// # Examples +/// +/// A very simple implementation of a `Balance` struct that has two sides, where +/// each can be indexed mutably and immutably. +/// +/// ``` +/// use std::ops::{Index,IndexMut}; +/// +/// #[derive(Debug)] +/// enum Side { +/// Left, +/// Right, +/// } +/// +/// #[derive(Debug, PartialEq)] +/// enum Weight { +/// Kilogram(f32), +/// Pound(f32), +/// } +/// +/// struct Balance { +/// pub left: Weight, +/// pub right:Weight, +/// } +/// +/// impl Index for Balance { +/// type Output = Weight; +/// +/// fn index<'a>(&'a self, index: Side) -> &'a Weight { +/// println!("Accessing {:?}-side of balance immutably", index); +/// match index { +/// Side::Left => &self.left, +/// Side::Right => &self.right, +/// } +/// } +/// } +/// +/// impl IndexMut for Balance { +/// fn index_mut<'a>(&'a mut self, index: Side) -> &'a mut Weight { +/// println!("Accessing {:?}-side of balance mutably", index); +/// match index { +/// Side::Left => &mut self.left, +/// Side::Right => &mut self.right, +/// } +/// } +/// } +/// +/// fn main() { +/// let mut balance = Balance { +/// right: Weight::Kilogram(2.5), +/// left: Weight::Pound(1.5), +/// }; +/// +/// // In this case balance[Side::Right] is sugar for +/// // *balance.index(Side::Right), since we are only reading +/// // balance[Side::Right], not writing it. +/// assert_eq!(balance[Side::Right],Weight::Kilogram(2.5)); +/// +/// // However in this case balance[Side::Left] is sugar for +/// // *balance.index_mut(Side::Left), since we are writing +/// // balance[Side::Left]. +/// balance[Side::Left] = Weight::Kilogram(3.0); +/// } +/// ``` +#[lang = "index_mut"] +#[rustc_on_unimplemented = "the type `{Self}` cannot be mutably indexed by `{Idx}`"] +#[stable(feature = "rust1", since = "1.0.0")] +pub trait IndexMut: Index { + /// The method for the mutable indexing (`container[index]`) operation + #[stable(feature = "rust1", since = "1.0.0")] + fn index_mut(&mut self, index: Idx) -> &mut Self::Output; +} diff --git a/src/libcore/ops/mod.rs b/src/libcore/ops/mod.rs index 22e5695a8780..b209a9e4a2d0 100644 --- a/src/libcore/ops/mod.rs +++ b/src/libcore/ops/mod.rs @@ -151,6 +151,7 @@ mod arith; mod bit; mod deref; mod function; +mod index; mod place; mod range; mod try; @@ -171,6 +172,9 @@ pub use self::deref::{Deref, DerefMut}; #[stable(feature = "rust1", since = "1.0.0")] pub use self::function::{Fn, FnMut, FnOnce}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::index::{Index, IndexMut}; + #[stable(feature = "rust1", since = "1.0.0")] pub use self::range::{Range, RangeFrom, RangeFull, RangeTo}; @@ -278,155 +282,6 @@ pub trait Drop { fn drop(&mut self); } -/// The `Index` trait is used to specify the functionality of indexing operations -/// like `container[index]` when used in an immutable context. -/// -/// `container[index]` is actually syntactic sugar for `*container.index(index)`, -/// but only when used as an immutable value. If a mutable value is requested, -/// [`IndexMut`] is used instead. This allows nice things such as -/// `let value = v[index]` if `value` implements [`Copy`]. -/// -/// [`IndexMut`]: ../../std/ops/trait.IndexMut.html -/// [`Copy`]: ../../std/marker/trait.Copy.html -/// -/// # Examples -/// -/// The following example implements `Index` on a read-only `NucleotideCount` -/// container, enabling individual counts to be retrieved with index syntax. -/// -/// ``` -/// use std::ops::Index; -/// -/// enum Nucleotide { -/// A, -/// C, -/// G, -/// T, -/// } -/// -/// struct NucleotideCount { -/// a: usize, -/// c: usize, -/// g: usize, -/// t: usize, -/// } -/// -/// impl Index for NucleotideCount { -/// type Output = usize; -/// -/// fn index(&self, nucleotide: Nucleotide) -> &usize { -/// match nucleotide { -/// Nucleotide::A => &self.a, -/// Nucleotide::C => &self.c, -/// Nucleotide::G => &self.g, -/// Nucleotide::T => &self.t, -/// } -/// } -/// } -/// -/// let nucleotide_count = NucleotideCount {a: 14, c: 9, g: 10, t: 12}; -/// assert_eq!(nucleotide_count[Nucleotide::A], 14); -/// assert_eq!(nucleotide_count[Nucleotide::C], 9); -/// assert_eq!(nucleotide_count[Nucleotide::G], 10); -/// assert_eq!(nucleotide_count[Nucleotide::T], 12); -/// ``` -#[lang = "index"] -#[rustc_on_unimplemented = "the type `{Self}` cannot be indexed by `{Idx}`"] -#[stable(feature = "rust1", since = "1.0.0")] -pub trait Index { - /// The returned type after indexing - #[stable(feature = "rust1", since = "1.0.0")] - type Output: ?Sized; - - /// The method for the indexing (`container[index]`) operation - #[stable(feature = "rust1", since = "1.0.0")] - fn index(&self, index: Idx) -> &Self::Output; -} - -/// The `IndexMut` trait is used to specify the functionality of indexing -/// operations like `container[index]` when used in a mutable context. -/// -/// `container[index]` is actually syntactic sugar for -/// `*container.index_mut(index)`, but only when used as a mutable value. If -/// an immutable value is requested, the [`Index`] trait is used instead. This -/// allows nice things such as `v[index] = value` if `value` implements [`Copy`]. -/// -/// [`Index`]: ../../std/ops/trait.Index.html -/// [`Copy`]: ../../std/marker/trait.Copy.html -/// -/// # Examples -/// -/// A very simple implementation of a `Balance` struct that has two sides, where -/// each can be indexed mutably and immutably. -/// -/// ``` -/// use std::ops::{Index,IndexMut}; -/// -/// #[derive(Debug)] -/// enum Side { -/// Left, -/// Right, -/// } -/// -/// #[derive(Debug, PartialEq)] -/// enum Weight { -/// Kilogram(f32), -/// Pound(f32), -/// } -/// -/// struct Balance { -/// pub left: Weight, -/// pub right:Weight, -/// } -/// -/// impl Index for Balance { -/// type Output = Weight; -/// -/// fn index<'a>(&'a self, index: Side) -> &'a Weight { -/// println!("Accessing {:?}-side of balance immutably", index); -/// match index { -/// Side::Left => &self.left, -/// Side::Right => &self.right, -/// } -/// } -/// } -/// -/// impl IndexMut for Balance { -/// fn index_mut<'a>(&'a mut self, index: Side) -> &'a mut Weight { -/// println!("Accessing {:?}-side of balance mutably", index); -/// match index { -/// Side::Left => &mut self.left, -/// Side::Right => &mut self.right, -/// } -/// } -/// } -/// -/// fn main() { -/// let mut balance = Balance { -/// right: Weight::Kilogram(2.5), -/// left: Weight::Pound(1.5), -/// }; -/// -/// // In this case balance[Side::Right] is sugar for -/// // *balance.index(Side::Right), since we are only reading -/// // balance[Side::Right], not writing it. -/// assert_eq!(balance[Side::Right],Weight::Kilogram(2.5)); -/// -/// // However in this case balance[Side::Left] is sugar for -/// // *balance.index_mut(Side::Left), since we are writing -/// // balance[Side::Left]. -/// balance[Side::Left] = Weight::Kilogram(3.0); -/// } -/// ``` -#[lang = "index_mut"] -#[rustc_on_unimplemented = "the type `{Self}` cannot be mutably indexed by `{Idx}`"] -#[stable(feature = "rust1", since = "1.0.0")] -pub trait IndexMut: Index { - /// The method for the mutable indexing (`container[index]`) operation - #[stable(feature = "rust1", since = "1.0.0")] - fn index_mut(&mut self, index: Idx) -> &mut Self::Output; -} - /// Trait that indicates that this is a pointer or a wrapper for one, /// where unsizing can be performed on the pointee. /// From b099e0e7867b7c2269c48f44892abf6e348ebda3 Mon Sep 17 00:00:00 2001 From: Clar Charr Date: Wed, 7 Jun 2017 22:15:05 -0400 Subject: [PATCH 106/233] Move CoerceUnsized to module. --- src/libcore/ops/mod.rs | 72 ++--------------------------------- src/libcore/ops/unsize.rs | 79 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+), 69 deletions(-) create mode 100644 src/libcore/ops/unsize.rs diff --git a/src/libcore/ops/mod.rs b/src/libcore/ops/mod.rs index b209a9e4a2d0..c725e9d04651 100644 --- a/src/libcore/ops/mod.rs +++ b/src/libcore/ops/mod.rs @@ -155,6 +155,7 @@ mod index; mod place; mod range; mod try; +mod unsize; #[stable(feature = "rust1", since = "1.0.0")] pub use self::arith::{Add, Sub, Mul, Div, Rem, Neg}; @@ -190,7 +191,8 @@ pub use self::try::Try; #[unstable(feature = "placement_new_protocol", issue = "27779")] pub use self::place::{Place, Placer, InPlace, Boxed, BoxPlace}; -use marker::Unsize; +#[unstable(feature = "coerce_unsized", issue = "27732")] +pub use self::unsize::CoerceUnsized; /// The `Drop` trait is used to run some code when a value goes out of scope. /// This is sometimes called a 'destructor'. @@ -281,71 +283,3 @@ pub trait Drop { #[stable(feature = "rust1", since = "1.0.0")] fn drop(&mut self); } - -/// Trait that indicates that this is a pointer or a wrapper for one, -/// where unsizing can be performed on the pointee. -/// -/// See the [DST coercion RfC][dst-coerce] and [the nomicon entry on coercion][nomicon-coerce] -/// for more details. -/// -/// For builtin pointer types, pointers to `T` will coerce to pointers to `U` if `T: Unsize` -/// by converting from a thin pointer to a fat pointer. -/// -/// For custom types, the coercion here works by coercing `Foo` to `Foo` -/// provided an impl of `CoerceUnsized> for Foo` exists. -/// Such an impl can only be written if `Foo` has only a single non-phantomdata -/// field involving `T`. If the type of that field is `Bar`, an implementation -/// of `CoerceUnsized> for Bar` must exist. The coercion will work by -/// by coercing the `Bar` field into `Bar` and filling in the rest of the fields -/// from `Foo` to create a `Foo`. This will effectively drill down to a pointer -/// field and coerce that. -/// -/// Generally, for smart pointers you will implement -/// `CoerceUnsized> for Ptr where T: Unsize, U: ?Sized`, with an -/// optional `?Sized` bound on `T` itself. For wrapper types that directly embed `T` -/// like `Cell` and `RefCell`, you -/// can directly implement `CoerceUnsized> for Wrap where T: CoerceUnsized`. -/// This will let coercions of types like `Cell>` work. -/// -/// [`Unsize`][unsize] is used to mark types which can be coerced to DSTs if behind -/// pointers. It is implemented automatically by the compiler. -/// -/// [dst-coerce]: https://github.com/rust-lang/rfcs/blob/master/text/0982-dst-coercion.md -/// [unsize]: ../marker/trait.Unsize.html -/// [nomicon-coerce]: ../../nomicon/coercions.html -#[unstable(feature = "coerce_unsized", issue = "27732")] -#[lang="coerce_unsized"] -pub trait CoerceUnsized { - // Empty. -} - -// &mut T -> &mut U -#[unstable(feature = "coerce_unsized", issue = "27732")] -impl<'a, T: ?Sized+Unsize, U: ?Sized> CoerceUnsized<&'a mut U> for &'a mut T {} -// &mut T -> &U -#[unstable(feature = "coerce_unsized", issue = "27732")] -impl<'a, 'b: 'a, T: ?Sized+Unsize, U: ?Sized> CoerceUnsized<&'a U> for &'b mut T {} -// &mut T -> *mut U -#[unstable(feature = "coerce_unsized", issue = "27732")] -impl<'a, T: ?Sized+Unsize, U: ?Sized> CoerceUnsized<*mut U> for &'a mut T {} -// &mut T -> *const U -#[unstable(feature = "coerce_unsized", issue = "27732")] -impl<'a, T: ?Sized+Unsize, U: ?Sized> CoerceUnsized<*const U> for &'a mut T {} - -// &T -> &U -#[unstable(feature = "coerce_unsized", issue = "27732")] -impl<'a, 'b: 'a, T: ?Sized+Unsize, U: ?Sized> CoerceUnsized<&'a U> for &'b T {} -// &T -> *const U -#[unstable(feature = "coerce_unsized", issue = "27732")] -impl<'a, T: ?Sized+Unsize, U: ?Sized> CoerceUnsized<*const U> for &'a T {} - -// *mut T -> *mut U -#[unstable(feature = "coerce_unsized", issue = "27732")] -impl, U: ?Sized> CoerceUnsized<*mut U> for *mut T {} -// *mut T -> *const U -#[unstable(feature = "coerce_unsized", issue = "27732")] -impl, U: ?Sized> CoerceUnsized<*const U> for *mut T {} - -// *const T -> *const U -#[unstable(feature = "coerce_unsized", issue = "27732")] -impl, U: ?Sized> CoerceUnsized<*const U> for *const T {} diff --git a/src/libcore/ops/unsize.rs b/src/libcore/ops/unsize.rs new file mode 100644 index 000000000000..1914216e9f08 --- /dev/null +++ b/src/libcore/ops/unsize.rs @@ -0,0 +1,79 @@ +// 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. + +use marker::Unsize; + +/// Trait that indicates that this is a pointer or a wrapper for one, +/// where unsizing can be performed on the pointee. +/// +/// See the [DST coercion RfC][dst-coerce] and [the nomicon entry on coercion][nomicon-coerce] +/// for more details. +/// +/// For builtin pointer types, pointers to `T` will coerce to pointers to `U` if `T: Unsize` +/// by converting from a thin pointer to a fat pointer. +/// +/// For custom types, the coercion here works by coercing `Foo` to `Foo` +/// provided an impl of `CoerceUnsized> for Foo` exists. +/// Such an impl can only be written if `Foo` has only a single non-phantomdata +/// field involving `T`. If the type of that field is `Bar`, an implementation +/// of `CoerceUnsized> for Bar` must exist. The coercion will work by +/// by coercing the `Bar` field into `Bar` and filling in the rest of the fields +/// from `Foo` to create a `Foo`. This will effectively drill down to a pointer +/// field and coerce that. +/// +/// Generally, for smart pointers you will implement +/// `CoerceUnsized> for Ptr where T: Unsize, U: ?Sized`, with an +/// optional `?Sized` bound on `T` itself. For wrapper types that directly embed `T` +/// like `Cell` and `RefCell`, you +/// can directly implement `CoerceUnsized> for Wrap where T: CoerceUnsized`. +/// This will let coercions of types like `Cell>` work. +/// +/// [`Unsize`][unsize] is used to mark types which can be coerced to DSTs if behind +/// pointers. It is implemented automatically by the compiler. +/// +/// [dst-coerce]: https://github.com/rust-lang/rfcs/blob/master/text/0982-dst-coercion.md +/// [unsize]: ../marker/trait.Unsize.html +/// [nomicon-coerce]: ../../nomicon/coercions.html +#[unstable(feature = "coerce_unsized", issue = "27732")] +#[lang="coerce_unsized"] +pub trait CoerceUnsized { + // Empty. +} + +// &mut T -> &mut U +#[unstable(feature = "coerce_unsized", issue = "27732")] +impl<'a, T: ?Sized+Unsize, U: ?Sized> CoerceUnsized<&'a mut U> for &'a mut T {} +// &mut T -> &U +#[unstable(feature = "coerce_unsized", issue = "27732")] +impl<'a, 'b: 'a, T: ?Sized+Unsize, U: ?Sized> CoerceUnsized<&'a U> for &'b mut T {} +// &mut T -> *mut U +#[unstable(feature = "coerce_unsized", issue = "27732")] +impl<'a, T: ?Sized+Unsize, U: ?Sized> CoerceUnsized<*mut U> for &'a mut T {} +// &mut T -> *const U +#[unstable(feature = "coerce_unsized", issue = "27732")] +impl<'a, T: ?Sized+Unsize, U: ?Sized> CoerceUnsized<*const U> for &'a mut T {} + +// &T -> &U +#[unstable(feature = "coerce_unsized", issue = "27732")] +impl<'a, 'b: 'a, T: ?Sized+Unsize, U: ?Sized> CoerceUnsized<&'a U> for &'b T {} +// &T -> *const U +#[unstable(feature = "coerce_unsized", issue = "27732")] +impl<'a, T: ?Sized+Unsize, U: ?Sized> CoerceUnsized<*const U> for &'a T {} + +// *mut T -> *mut U +#[unstable(feature = "coerce_unsized", issue = "27732")] +impl, U: ?Sized> CoerceUnsized<*mut U> for *mut T {} +// *mut T -> *const U +#[unstable(feature = "coerce_unsized", issue = "27732")] +impl, U: ?Sized> CoerceUnsized<*const U> for *mut T {} + +// *const T -> *const U +#[unstable(feature = "coerce_unsized", issue = "27732")] +impl, U: ?Sized> CoerceUnsized<*const U> for *const T {} From f8d5f90adee5e43ecf4cd0e191086f8bd45e1285 Mon Sep 17 00:00:00 2001 From: Clar Charr Date: Wed, 7 Jun 2017 22:16:16 -0400 Subject: [PATCH 107/233] Move Drop to module. --- src/libcore/ops/drop.rs | 99 +++++++++++++++++++++++++++++++++++++++++ src/libcore/ops/mod.rs | 94 ++------------------------------------ 2 files changed, 103 insertions(+), 90 deletions(-) create mode 100644 src/libcore/ops/drop.rs diff --git a/src/libcore/ops/drop.rs b/src/libcore/ops/drop.rs new file mode 100644 index 000000000000..92f3cb256c83 --- /dev/null +++ b/src/libcore/ops/drop.rs @@ -0,0 +1,99 @@ +// 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. + +/// The `Drop` trait is used to run some code when a value goes out of scope. +/// This is sometimes called a 'destructor'. +/// +/// When a value goes out of scope, if it implements this trait, it will have +/// its `drop` method called. Then any fields the value contains will also +/// be dropped recursively. +/// +/// Because of the recursive dropping, you do not need to implement this trait +/// unless your type needs its own destructor logic. +/// +/// # Examples +/// +/// A trivial implementation of `Drop`. The `drop` method is called when `_x` +/// goes out of scope, and therefore `main` prints `Dropping!`. +/// +/// ``` +/// struct HasDrop; +/// +/// impl Drop for HasDrop { +/// fn drop(&mut self) { +/// println!("Dropping!"); +/// } +/// } +/// +/// fn main() { +/// let _x = HasDrop; +/// } +/// ``` +/// +/// Showing the recursive nature of `Drop`. When `outer` goes out of scope, the +/// `drop` method will be called first for `Outer`, then for `Inner`. Therefore +/// `main` prints `Dropping Outer!` and then `Dropping Inner!`. +/// +/// ``` +/// struct Inner; +/// struct Outer(Inner); +/// +/// impl Drop for Inner { +/// fn drop(&mut self) { +/// println!("Dropping Inner!"); +/// } +/// } +/// +/// impl Drop for Outer { +/// fn drop(&mut self) { +/// println!("Dropping Outer!"); +/// } +/// } +/// +/// fn main() { +/// let _x = Outer(Inner); +/// } +/// ``` +/// +/// Because variables are dropped in the reverse order they are declared, +/// `main` will print `Declared second!` and then `Declared first!`. +/// +/// ``` +/// struct PrintOnDrop(&'static str); +/// +/// fn main() { +/// let _first = PrintOnDrop("Declared first!"); +/// let _second = PrintOnDrop("Declared second!"); +/// } +/// ``` +#[lang = "drop"] +#[stable(feature = "rust1", since = "1.0.0")] +pub trait Drop { + /// A method called when the value goes out of scope. + /// + /// When this method has been called, `self` has not yet been deallocated. + /// If it were, `self` would be a dangling reference. + /// + /// After this function is over, the memory of `self` will be deallocated. + /// + /// This function cannot be called explicitly. This is compiler error + /// [E0040]. However, the [`std::mem::drop`] function in the prelude can be + /// used to call the argument's `Drop` implementation. + /// + /// [E0040]: ../../error-index.html#E0040 + /// [`std::mem::drop`]: ../../std/mem/fn.drop.html + /// + /// # Panics + /// + /// Given that a `panic!` will call `drop()` as it unwinds, any `panic!` in + /// a `drop()` implementation will likely abort. + #[stable(feature = "rust1", since = "1.0.0")] + fn drop(&mut self); +} diff --git a/src/libcore/ops/mod.rs b/src/libcore/ops/mod.rs index c725e9d04651..4e0389e5de4e 100644 --- a/src/libcore/ops/mod.rs +++ b/src/libcore/ops/mod.rs @@ -150,6 +150,7 @@ mod arith; mod bit; mod deref; +mod drop; mod function; mod index; mod place; @@ -170,6 +171,9 @@ pub use self::bit::{BitAndAssign, BitOrAssign, BitXorAssign, ShlAssign, ShrAssig #[stable(feature = "rust1", since = "1.0.0")] pub use self::deref::{Deref, DerefMut}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::drop::Drop; + #[stable(feature = "rust1", since = "1.0.0")] pub use self::function::{Fn, FnMut, FnOnce}; @@ -193,93 +197,3 @@ pub use self::place::{Place, Placer, InPlace, Boxed, BoxPlace}; #[unstable(feature = "coerce_unsized", issue = "27732")] pub use self::unsize::CoerceUnsized; - -/// The `Drop` trait is used to run some code when a value goes out of scope. -/// This is sometimes called a 'destructor'. -/// -/// When a value goes out of scope, if it implements this trait, it will have -/// its `drop` method called. Then any fields the value contains will also -/// be dropped recursively. -/// -/// Because of the recursive dropping, you do not need to implement this trait -/// unless your type needs its own destructor logic. -/// -/// # Examples -/// -/// A trivial implementation of `Drop`. The `drop` method is called when `_x` -/// goes out of scope, and therefore `main` prints `Dropping!`. -/// -/// ``` -/// struct HasDrop; -/// -/// impl Drop for HasDrop { -/// fn drop(&mut self) { -/// println!("Dropping!"); -/// } -/// } -/// -/// fn main() { -/// let _x = HasDrop; -/// } -/// ``` -/// -/// Showing the recursive nature of `Drop`. When `outer` goes out of scope, the -/// `drop` method will be called first for `Outer`, then for `Inner`. Therefore -/// `main` prints `Dropping Outer!` and then `Dropping Inner!`. -/// -/// ``` -/// struct Inner; -/// struct Outer(Inner); -/// -/// impl Drop for Inner { -/// fn drop(&mut self) { -/// println!("Dropping Inner!"); -/// } -/// } -/// -/// impl Drop for Outer { -/// fn drop(&mut self) { -/// println!("Dropping Outer!"); -/// } -/// } -/// -/// fn main() { -/// let _x = Outer(Inner); -/// } -/// ``` -/// -/// Because variables are dropped in the reverse order they are declared, -/// `main` will print `Declared second!` and then `Declared first!`. -/// -/// ``` -/// struct PrintOnDrop(&'static str); -/// -/// fn main() { -/// let _first = PrintOnDrop("Declared first!"); -/// let _second = PrintOnDrop("Declared second!"); -/// } -/// ``` -#[lang = "drop"] -#[stable(feature = "rust1", since = "1.0.0")] -pub trait Drop { - /// A method called when the value goes out of scope. - /// - /// When this method has been called, `self` has not yet been deallocated. - /// If it were, `self` would be a dangling reference. - /// - /// After this function is over, the memory of `self` will be deallocated. - /// - /// This function cannot be called explicitly. This is compiler error - /// [E0040]. However, the [`std::mem::drop`] function in the prelude can be - /// used to call the argument's `Drop` implementation. - /// - /// [E0040]: ../../error-index.html#E0040 - /// [`std::mem::drop`]: ../../std/mem/fn.drop.html - /// - /// # Panics - /// - /// Given that a `panic!` will call `drop()` as it unwinds, any `panic!` in - /// a `drop()` implementation will likely abort. - #[stable(feature = "rust1", since = "1.0.0")] - fn drop(&mut self); -} From f52ac18840d29c93881b0d3ea100dcf4e55348dd Mon Sep 17 00:00:00 2001 From: Dylan Maccora Date: Sat, 10 Jun 2017 16:19:28 +1000 Subject: [PATCH 108/233] env docs completion. --- src/libstd/env.rs | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/libstd/env.rs b/src/libstd/env.rs index 5d2bb9daf17e..4bb0f26014c0 100644 --- a/src/libstd/env.rs +++ b/src/libstd/env.rs @@ -367,7 +367,7 @@ fn _remove_var(k: &OsStr) { /// An iterator that splits an environment variable into paths according to /// platform-specific conventions. /// -/// This structure is created by the [`std::env::split_paths`] function See its +/// This structure is created by the [`std::env::split_paths`] function. See its /// documentation for more. /// /// [`std::env::split_paths`]: fn.split_paths.html @@ -605,14 +605,15 @@ pub fn current_exe() -> io::Result { os_imp::current_exe() } -/// An iterator over the arguments of a process, yielding a [`String`] value -/// for each argument. +/// An iterator over the arguments of a process, yielding a [`String`] value for +/// each argument. /// -/// This structure is created through the [`std::env::args`] function. +/// This struct is created by the [`std::env::args`] function. See its +/// documentation for more. /// /// The first element is traditionally the path of the executable, but it can be -/// set to arbitrary text, and may not even exist. This means this property should -/// not be relied upon for security purposes. +/// set to arbitrary text, and may not even exist. This means this property +/// should not be relied upon for security purposes. /// /// [`String`]: ../string/struct.String.html /// [`std::env::args`]: ./fn.args.html @@ -622,11 +623,12 @@ pub struct Args { inner: ArgsOs } /// An iterator over the arguments of a process, yielding an [`OsString`] value /// for each argument. /// -/// This structure is created through the [`std::env::args_os`] function. +/// This struct is created by the [`std::env::args_os`] function. See its +/// documentation for more. /// /// The first element is traditionally the path of the executable, but it can be -/// set to arbitrary text, and may not even exist. This means this property should -/// not be relied upon for security purposes. +/// set to arbitrary text, and may not even exist. This means this property +/// should not be relied upon for security purposes. /// /// [`OsString`]: ../ffi/struct.OsString.html /// [`std::env::args_os`]: ./fn.args_os.html From 70fa1fbea7786425471b0d43aae320920fd4e917 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 10 Jun 2017 12:21:24 +0200 Subject: [PATCH 109/233] Added a `StableHasherResult` impl for `u128`. --- src/librustc_data_structures/stable_hasher.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/librustc_data_structures/stable_hasher.rs b/src/librustc_data_structures/stable_hasher.rs index 634d3041bf4a..f3572d3e25b3 100644 --- a/src/librustc_data_structures/stable_hasher.rs +++ b/src/librustc_data_structures/stable_hasher.rs @@ -78,6 +78,17 @@ impl StableHasherResult for [u8; 20] { } } +impl StableHasherResult for u128 { + fn finish(mut hasher: StableHasher) -> Self { + let hash_bytes: &[u8] = hasher.finalize(); + assert!(hash_bytes.len() >= mem::size_of::() * 2); + + unsafe { + ::std::ptr::read_unaligned(hash_bytes.as_ptr() as *const u128) + } + } +} + impl StableHasherResult for u64 { fn finish(mut hasher: StableHasher) -> Self { hasher.state.finalize(); From 1f874ded52acaecd47b39e90e93d7d7a31c90dae Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 8 Jun 2017 23:57:01 +0300 Subject: [PATCH 110/233] rustc: do not depend on infcx.tables in MemCategorizationContext. --- src/librustc/infer/mod.rs | 143 ++---------------- src/librustc/middle/expr_use_visitor.rs | 41 +++-- src/librustc/middle/mem_categorization.rs | 94 +++++++----- src/librustc/traits/error_reporting.rs | 14 +- src/librustc_borrowck/borrowck/check_loans.rs | 5 +- .../borrowck/gather_loans/mod.rs | 10 +- src/librustc_const_eval/check_match.rs | 5 +- src/librustc_mir/build/mod.rs | 2 +- src/librustc_mir/hair/cx/mod.rs | 6 +- src/librustc_passes/consts.rs | 5 +- src/librustc_typeck/check/mod.rs | 2 +- src/librustc_typeck/check/regionck.rs | 53 +++---- src/librustc_typeck/check/upvar.rs | 6 +- 13 files changed, 146 insertions(+), 240 deletions(-) diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 6e9d028aa647..3e2d26aa518a 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -19,11 +19,8 @@ pub use self::freshen::TypeFreshener; pub use self::region_inference::{GenericKind, VerifyBound}; use hir::def_id::DefId; -use hir; use middle::free_region::{FreeRegionMap, RegionRelations}; use middle::region::RegionMaps; -use middle::mem_categorization as mc; -use middle::mem_categorization::McResult; use middle::lang_items; use mir::tcx::LvalueTy; use ty::subst::{Kind, Subst, Substs}; @@ -36,7 +33,6 @@ use traits::{self, ObligationCause, PredicateObligations, Reveal}; use rustc_data_structures::unify::{self, UnificationTable}; use std::cell::{Cell, RefCell, Ref, RefMut}; use std::fmt; -use std::ops::Deref; use syntax::ast; use errors::DiagnosticBuilder; use syntax_pos::{self, Span, DUMMY_SP}; @@ -80,55 +76,23 @@ pub type FixupResult = Result; // "fixup result" /// `InProgress` (during typeck) or `Interned` (result of typeck). /// Only the `InProgress` version supports `borrow_mut`. #[derive(Copy, Clone)] -pub enum InferTables<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { - Interned(&'a ty::TypeckTables<'gcx>), +pub enum InferTables<'a, 'tcx: 'a> { InProgress(&'a RefCell>), Missing } -pub enum InferTablesRef<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { - Interned(&'a ty::TypeckTables<'gcx>), - InProgress(Ref<'a, ty::TypeckTables<'tcx>>) -} - -impl<'a, 'gcx, 'tcx> Deref for InferTablesRef<'a, 'gcx, 'tcx> { - type Target = ty::TypeckTables<'tcx>; - fn deref(&self) -> &Self::Target { - match *self { - InferTablesRef::Interned(tables) => tables, - InferTablesRef::InProgress(ref tables) => tables - } - } -} - -impl<'a, 'gcx, 'tcx> InferTables<'a, 'gcx, 'tcx> { - pub fn borrow(self) -> InferTablesRef<'a, 'gcx, 'tcx> { +impl<'a, 'tcx> InferTables<'a, 'tcx> { + pub fn borrow(self) -> Ref<'a, ty::TypeckTables<'tcx>> { match self { - InferTables::Interned(tables) => InferTablesRef::Interned(tables), - InferTables::InProgress(tables) => InferTablesRef::InProgress(tables.borrow()), + InferTables::InProgress(tables) => tables.borrow(), InferTables::Missing => { bug!("InferTables: infcx.tables.borrow() with no tables") } } } - pub fn expect_interned(self) -> &'a ty::TypeckTables<'gcx> { - match self { - InferTables::Interned(tables) => tables, - InferTables::InProgress(_) => { - bug!("InferTables: infcx.tables.expect_interned() during type-checking"); - } - InferTables::Missing => { - bug!("InferTables: infcx.tables.expect_interned() with no tables") - } - } - } - pub fn borrow_mut(self) -> RefMut<'a, ty::TypeckTables<'tcx>> { match self { - InferTables::Interned(_) => { - bug!("InferTables: infcx.tables.borrow_mut() outside of type-checking"); - } InferTables::InProgress(tables) => tables.borrow_mut(), InferTables::Missing => { bug!("InferTables: infcx.tables.borrow_mut() with no tables") @@ -140,7 +104,7 @@ impl<'a, 'gcx, 'tcx> InferTables<'a, 'gcx, 'tcx> { pub struct InferCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { pub tcx: TyCtxt<'a, 'gcx, 'tcx>, - pub tables: InferTables<'a, 'gcx, 'tcx>, + pub tables: InferTables<'a, 'tcx>, // Cache for projections. This cache is snapshotted along with the // infcx. @@ -397,41 +361,18 @@ impl fmt::Display for FixupError { } pub trait InferEnv<'a, 'tcx> { - fn to_parts(self, tcx: TyCtxt<'a, 'tcx, 'tcx>) - -> (Option<&'a ty::TypeckTables<'tcx>>, - Option>); + fn fresh_tables(self) -> Option>; } impl<'a, 'tcx> InferEnv<'a, 'tcx> for () { - fn to_parts(self, _: TyCtxt<'a, 'tcx, 'tcx>) - -> (Option<&'a ty::TypeckTables<'tcx>>, - Option>) { - (None, None) - } -} - -impl<'a, 'tcx> InferEnv<'a, 'tcx> for &'a ty::TypeckTables<'tcx> { - fn to_parts(self, _: TyCtxt<'a, 'tcx, 'tcx>) - -> (Option<&'a ty::TypeckTables<'tcx>>, - Option>) { - (Some(self), None) + fn fresh_tables(self) -> Option> { + None } } impl<'a, 'tcx> InferEnv<'a, 'tcx> for ty::TypeckTables<'tcx> { - fn to_parts(self, _: TyCtxt<'a, 'tcx, 'tcx>) - -> (Option<&'a ty::TypeckTables<'tcx>>, - Option>) { - (None, Some(self)) - } -} - -impl<'a, 'tcx> InferEnv<'a, 'tcx> for hir::BodyId { - fn to_parts(self, tcx: TyCtxt<'a, 'tcx, 'tcx>) - -> (Option<&'a ty::TypeckTables<'tcx>>, - Option>) { - let def_id = tcx.hir.body_owner_def_id(self); - (Some(tcx.typeck_tables_of(def_id)), None) + fn fresh_tables(self) -> Option> { + Some(self) } } @@ -442,29 +383,24 @@ pub struct InferCtxtBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { global_tcx: TyCtxt<'a, 'gcx, 'gcx>, arena: DroplessArena, fresh_tables: Option>>, - tables: Option<&'a ty::TypeckTables<'gcx>>, } impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> { pub fn infer_ctxt>(self, env: E) -> InferCtxtBuilder<'a, 'gcx, 'tcx> { - let (tables, fresh_tables) = env.to_parts(self); InferCtxtBuilder { global_tcx: self, arena: DroplessArena::new(), - fresh_tables: fresh_tables.map(RefCell::new), - tables: tables, + fresh_tables: env.fresh_tables().map(RefCell::new), } } /// Fake InferCtxt with the global tcx. Used by pre-MIR borrowck /// for MemCategorizationContext/ExprUseVisitor. /// If any inference functionality is used, ICEs will occur. - pub fn borrowck_fake_infer_ctxt(self, body: hir::BodyId) - -> InferCtxt<'a, 'gcx, 'gcx> { - let (tables, _) = body.to_parts(self); + pub fn borrowck_fake_infer_ctxt(self) -> InferCtxt<'a, 'gcx, 'gcx> { InferCtxt { tcx: self, - tables: InferTables::Interned(tables.unwrap()), + tables: InferTables::Missing, type_variables: RefCell::new(type_variable::TypeVariableTable::new()), int_unification_table: RefCell::new(UnificationTable::new()), float_unification_table: RefCell::new(UnificationTable::new()), @@ -488,11 +424,9 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> { global_tcx, ref arena, ref fresh_tables, - tables, } = *self; - let tables = tables.map(InferTables::Interned).unwrap_or_else(|| { - fresh_tables.as_ref().map_or(InferTables::Missing, InferTables::InProgress) - }); + let tables = fresh_tables.as_ref() + .map_or(InferTables::Missing, InferTables::InProgress); global_tcx.enter_local(arena, |tcx| f(InferCtxt { tcx: tcx, tables: tables, @@ -1190,28 +1124,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { self.tainted_by_errors_flag.set(true) } - pub fn node_type(&self, id: ast::NodeId) -> Ty<'tcx> { - match self.tables.borrow().node_types.get(&id) { - Some(&t) => t, - // FIXME - None if self.is_tainted_by_errors() => - self.tcx.types.err, - None => { - bug!("no type for node {}: {} in fcx", - id, self.tcx.hir.node_to_string(id)); - } - } - } - - pub fn expr_ty(&self, ex: &hir::Expr) -> Ty<'tcx> { - match self.tables.borrow().node_types.get(&ex.id) { - Some(&t) => t, - None => { - bug!("no type for expr in fcx"); - } - } - } - pub fn resolve_regions_and_report_errors(&self, region_context: DefId, region_map: &RegionMaps, @@ -1310,21 +1222,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { value.fold_with(&mut r) } - /// Resolves all type variables in `t` and then, if any were left - /// unresolved, substitutes an error type. This is used after the - /// main checking when doing a second pass before writeback. The - /// justification is that writeback will produce an error for - /// these unconstrained type variables. - fn resolve_type_vars_or_error(&self, t: &Ty<'tcx>) -> mc::McResult> { - let ty = self.resolve_type_vars_if_possible(t); - if ty.references_error() || ty.is_ty_var() { - debug!("resolve_type_vars_or_error: error from {:?}", ty); - Err(()) - } else { - Ok(ty) - } - } - pub fn fully_resolve>(&self, value: &T) -> FixupResult { /*! * Attempts to resolve all type/region variables in @@ -1484,16 +1381,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { self.region_vars.verify_generic_bound(origin, kind, a, bound); } - pub fn node_ty(&self, id: ast::NodeId) -> McResult> { - let ty = self.node_type(id); - self.resolve_type_vars_or_error(&ty) - } - - pub fn expr_ty_adjusted(&self, expr: &hir::Expr) -> McResult> { - let ty = self.tables.borrow().expr_ty_adjusted(expr); - self.resolve_type_vars_or_error(&ty) - } - pub fn type_moves_by_default(&self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>, diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 4075d28a396a..b24b2a616b06 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -235,17 +235,14 @@ impl OverloadedCallType { /////////////////////////////////////////////////////////////////////////// // The ExprUseVisitor type // -// This is the code that actually walks the tree. Like -// mem_categorization, it requires a TYPER, which is a type that -// supplies types from the tree. After type checking is complete, you -// can just use the tcx as the typer. +// This is the code that actually walks the tree. pub struct ExprUseVisitor<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { mc: mc::MemCategorizationContext<'a, 'gcx, 'tcx>, delegate: &'a mut Delegate<'tcx>, param_env: ty::ParamEnv<'tcx>, } -// If the TYPER results in an error, it's because the type check +// If the MC results in an error, it's because the type check // failed (or will fail, when the error is uncovered and reported // during writeback). In this case, we just ignore this part of the // code. @@ -266,13 +263,14 @@ macro_rules! return_if_err { impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { pub fn new(delegate: &'a mut (Delegate<'tcx>+'a), - region_maps: &'a RegionMaps, infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, - param_env: ty::ParamEnv<'tcx>) + param_env: ty::ParamEnv<'tcx>, + region_maps: &'a RegionMaps, + tables: &'a ty::TypeckTables<'tcx>) -> Self { ExprUseVisitor { - mc: mc::MemCategorizationContext::new(infcx, region_maps), + mc: mc::MemCategorizationContext::new(infcx, region_maps, tables), delegate, param_env, } @@ -282,7 +280,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { debug!("consume_body(body={:?})", body); for arg in &body.arguments { - let arg_ty = return_if_err!(self.mc.infcx.node_ty(arg.pat.id)); + let arg_ty = return_if_err!(self.mc.node_ty(arg.pat.id)); let fn_body_scope_r = self.tcx().node_scope_region(body.value.id); let arg_cmt = self.mc.cat_rvalue( @@ -427,7 +425,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { hir::ExprAddrOf(m, ref base) => { // &base // make sure that the thing we are pointing out stays valid // for the lifetime `scope_r` of the resulting ptr: - let expr_ty = return_if_err!(self.mc.infcx.node_ty(expr.id)); + let expr_ty = return_if_err!(self.mc.expr_ty(expr)); if let ty::TyRef(r, _) = expr_ty.sty { let bk = ty::BorrowKind::from_mutbl(m); self.borrow_expr(&base, r, bk, AddrOf); @@ -491,7 +489,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { } hir::ExprAssignOp(_, ref lhs, ref rhs) => { - if self.mc.infcx.tables.borrow().is_method_call(expr) { + if self.mc.tables.is_method_call(expr) { self.consume_expr(lhs); } else { self.mutate_expr(expr, &lhs, MutateMode::WriteAndRead); @@ -514,7 +512,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { } fn walk_callee(&mut self, call: &hir::Expr, callee: &hir::Expr) { - let callee_ty = return_if_err!(self.mc.infcx.expr_ty_adjusted(callee)); + let callee_ty = return_if_err!(self.mc.expr_ty_adjusted(callee)); debug!("walk_callee: callee={:?} callee_ty={:?}", callee, callee_ty); match callee_ty.sty { @@ -523,7 +521,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { } ty::TyError => { } _ => { - let def_id = self.mc.infcx.tables.borrow().type_dependent_defs[&call.id].def_id(); + let def_id = self.mc.tables.type_dependent_defs[&call.id].def_id(); match OverloadedCallType::from_method_id(self.tcx(), def_id) { FnMutOverloadedCall => { let call_scope_r = self.tcx().node_scope_region(call.id); @@ -664,8 +662,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { // consumed or borrowed as part of the automatic adjustment // process. fn walk_adjustment(&mut self, expr: &hir::Expr) { - let tables = self.mc.infcx.tables.borrow(); - let adjustments = tables.expr_adjustments(expr); + let adjustments = self.mc.tables.expr_adjustments(expr); let mut cmt = return_if_err!(self.mc.cat_expr_unadjusted(expr)); for adjustment in adjustments { debug!("walk_adjustment expr={:?} adj={:?}", expr, adjustment); @@ -782,7 +779,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { mode: &mut TrackMatchMode) { debug!("determine_pat_move_mode cmt_discr={:?} pat={:?}", cmt_discr, pat); - return_if_err!(self.mc.cat_pattern(cmt_discr, pat, |_mc, cmt_pat, pat| { + return_if_err!(self.mc.cat_pattern(cmt_discr, pat, |cmt_pat, pat| { match pat.node { PatKind::Binding(hir::BindByRef(..), ..) => mode.lub(BorrowingMatch), @@ -806,12 +803,12 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { let tcx = self.tcx(); let infcx = self.mc.infcx; let ExprUseVisitor { ref mc, ref mut delegate, param_env } = *self; - return_if_err!(mc.cat_pattern(cmt_discr.clone(), pat, |mc, cmt_pat, pat| { + return_if_err!(mc.cat_pattern(cmt_discr.clone(), pat, |cmt_pat, pat| { if let PatKind::Binding(bmode, def_id, ..) = pat.node { debug!("binding cmt_pat={:?} pat={:?} match_mode={:?}", cmt_pat, pat, match_mode); // pat_ty: the type of the binding being produced. - let pat_ty = return_if_err!(infcx.node_ty(pat.id)); + let pat_ty = return_if_err!(mc.node_ty(pat.id)); // Each match binding is effectively an assignment to the // binding being produced. @@ -841,14 +838,14 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { // the interior nodes (enum variants and structs), as opposed // to the above loop's visit of than the bindings that form // the leaves of the pattern tree structure. - return_if_err!(mc.cat_pattern(cmt_discr, pat, |mc, cmt_pat, pat| { + return_if_err!(mc.cat_pattern(cmt_discr, pat, |cmt_pat, pat| { let qpath = match pat.node { PatKind::Path(ref qpath) | PatKind::TupleStruct(ref qpath, ..) | PatKind::Struct(ref qpath, ..) => qpath, _ => return }; - let def = infcx.tables.borrow().qpath_def(qpath, pat.id); + let def = mc.tables.qpath_def(qpath, pat.id); match def { Def::Variant(variant_did) | Def::VariantCtor(variant_did, ..) => { @@ -882,7 +879,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { let id_var = self.tcx().hir.as_local_node_id(def_id).unwrap(); let upvar_id = ty::UpvarId { var_id: id_var, closure_expr_id: closure_expr.id }; - let upvar_capture = self.mc.infcx.tables.borrow().upvar_capture(upvar_id); + let upvar_capture = self.mc.tables.upvar_capture(upvar_id); let cmt_var = return_if_err!(self.cat_captured_var(closure_expr.id, fn_decl_span, freevar.def)); @@ -915,7 +912,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { // Create the cmt for the variable being borrowed, from the // caller's perspective let var_id = self.tcx().hir.as_local_node_id(upvar_def.def_id()).unwrap(); - let var_ty = self.mc.infcx.node_ty(var_id)?; + let var_ty = self.mc.node_ty(var_id)?; self.mc.cat_def(closure_id, closure_span, var_ty, upvar_def) } } diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index ddbc7f91097d..66de8bc58032 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -76,6 +76,7 @@ use infer::InferCtxt; use hir::def::{Def, CtorKind}; use ty::adjustment; use ty::{self, Ty, TyCtxt}; +use ty::fold::TypeFoldable; use hir::{MutImmutable, MutMutable, PatKind}; use hir::pat_util::EnumerateAndAdjustIterator; @@ -283,6 +284,7 @@ impl ast_node for hir::Pat { pub struct MemCategorizationContext<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { pub infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, pub region_maps: &'a RegionMaps, + pub tables: &'a ty::TypeckTables<'tcx>, } pub type McResult = Result; @@ -386,35 +388,63 @@ impl MutabilityCategory { impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { /// Context should be the `DefId` we use to fetch region-maps. pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, - region_maps: &'a RegionMaps) + region_maps: &'a RegionMaps, + tables: &'a ty::TypeckTables<'tcx>) -> MemCategorizationContext<'a, 'gcx, 'tcx> { - MemCategorizationContext { infcx, region_maps } + MemCategorizationContext { infcx, region_maps, tables } } fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> { self.infcx.tcx } - fn expr_ty(&self, expr: &hir::Expr) -> McResult> { - match self.infcx.node_ty(expr.id) { - Ok(t) => Ok(t), - Err(()) => { - debug!("expr_ty({:?}) yielded Err", expr); - Err(()) + fn resolve_type_vars_if_possible(&self, value: &T) -> T + where T: TypeFoldable<'tcx> + { + self.infcx.resolve_type_vars_if_possible(value) + } + + fn is_tainted_by_errors(&self) -> bool { + self.infcx.is_tainted_by_errors() + } + + fn resolve_type_vars_or_error(&self, + id: ast::NodeId, + ty: Option>) + -> McResult> { + match ty { + Some(ty) => { + let ty = self.resolve_type_vars_if_possible(&ty); + if ty.references_error() || ty.is_ty_var() { + debug!("resolve_type_vars_or_error: error from {:?}", ty); + Err(()) + } else { + Ok(ty) + } + } + // FIXME + None if self.is_tainted_by_errors() => Err(()), + None => { + bug!("no type for node {}: {} in mem_categorization", + id, self.tcx().hir.node_to_string(id)); } } } - fn expr_ty_adjusted(&self, expr: &hir::Expr) -> McResult> { - self.infcx.expr_ty_adjusted(expr) + pub fn node_ty(&self, id: ast::NodeId) -> McResult> { + self.resolve_type_vars_or_error(id, self.tables.node_id_to_type_opt(id)) } - fn node_ty(&self, id: ast::NodeId) -> McResult> { - self.infcx.node_ty(id) + pub fn expr_ty(&self, expr: &hir::Expr) -> McResult> { + self.resolve_type_vars_or_error(expr.id, self.tables.expr_ty_opt(expr)) + } + + pub fn expr_ty_adjusted(&self, expr: &hir::Expr) -> McResult> { + self.resolve_type_vars_or_error(expr.id, self.tables.expr_ty_adjusted_opt(expr)) } fn pat_ty(&self, pat: &hir::Pat) -> McResult> { - let base_ty = self.infcx.node_ty(pat.id)?; + let base_ty = self.node_ty(pat.id)?; // FIXME (Issue #18207): This code detects whether we are // looking at a `ref x`, and if so, figures out what the type // *being borrowed* is. But ideally we would put in a more @@ -454,7 +484,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { } } - helper(self, expr, self.infcx.tables.borrow().expr_adjustments(expr)) + helper(self, expr, self.tables.expr_adjustments(expr)) } pub fn cat_expr_adjusted(&self, expr: &hir::Expr, @@ -471,7 +501,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { where F: FnOnce() -> McResult> { debug!("cat_expr_adjusted_with({:?}): {:?}", adjustment, expr); - let target = self.infcx.resolve_type_vars_if_possible(&adjustment.target); + let target = self.resolve_type_vars_if_possible(&adjustment.target); match adjustment.kind { adjustment::Adjust::Deref(overloaded) => { // Equivalent to *expr or something similar. @@ -506,7 +536,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { let expr_ty = self.expr_ty(expr)?; match expr.node { hir::ExprUnary(hir::UnDeref, ref e_base) => { - if self.infcx.tables.borrow().is_method_call(expr) { + if self.tables.is_method_call(expr) { self.cat_overloaded_lvalue(expr, e_base, false) } else { let base_cmt = self.cat_expr(&e_base)?; @@ -529,7 +559,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { } hir::ExprIndex(ref base, _) => { - if self.infcx.tables.borrow().is_method_call(expr) { + if self.tables.is_method_call(expr) { // If this is an index implemented by a method call, then it // will include an implicit deref of the result. // The call to index() returns a `&T` value, which @@ -543,7 +573,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { } hir::ExprPath(ref qpath) => { - let def = self.infcx.tables.borrow().qpath_def(qpath, expr.id); + let def = self.tables.qpath_def(qpath, expr.id); self.cat_def(expr.id, expr.span, expr_ty, def) } @@ -595,15 +625,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { Def::Upvar(def_id, _, fn_node_id) => { let var_id = self.tcx().hir.as_local_node_id(def_id).unwrap(); - let closure_id = self.tcx().hir.local_def_id(fn_node_id); - match self.infcx.closure_kind(closure_id) { - Some(kind) => { - self.cat_upvar(id, span, var_id, fn_node_id, kind) - } - None => { - span_bug!(span, "No closure kind for {:?}", closure_id); - } - } + self.cat_upvar(id, span, var_id, fn_node_id) } Def::Local(def_id) => { @@ -628,8 +650,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { id: ast::NodeId, span: Span, var_id: ast::NodeId, - fn_node_id: ast::NodeId, - kind: ty::ClosureKind) + fn_node_id: ast::NodeId) -> McResult> { // An upvar can have up to 3 components. We translate first to a @@ -655,6 +676,11 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { // FnMut | copied -> &'env mut | upvar -> &'env mut -> &'up bk // FnOnce | copied | upvar -> &'up bk + let kind = match self.tables.closure_kinds.get(&fn_node_id) { + Some(&(kind, _)) => kind, + None => span_bug!(span, "missing closure kind") + }; + let upvar_id = ty::UpvarId { var_id: var_id, closure_expr_id: fn_node_id }; let var_ty = self.node_ty(var_id)?; @@ -694,7 +720,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { // for that. let upvar_id = ty::UpvarId { var_id: var_id, closure_expr_id: fn_node_id }; - let upvar_capture = self.infcx.tables.borrow().upvar_capture(upvar_id); + let upvar_capture = self.tables.upvar_capture(upvar_id); let cmt_result = match upvar_capture { ty::UpvarCapture::ByValue => { cmt_result @@ -1000,14 +1026,14 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { } pub fn cat_pattern(&self, cmt: cmt<'tcx>, pat: &hir::Pat, mut op: F) -> McResult<()> - where F: FnMut(&MemCategorizationContext<'a, 'gcx, 'tcx>, cmt<'tcx>, &hir::Pat), + where F: FnMut(cmt<'tcx>, &hir::Pat), { self.cat_pattern_(cmt, pat, &mut op) } // FIXME(#19596) This is a workaround, but there should be a better way to do this fn cat_pattern_(&self, cmt: cmt<'tcx>, pat: &hir::Pat, op: &mut F) -> McResult<()> - where F : FnMut(&MemCategorizationContext<'a, 'gcx, 'tcx>, cmt<'tcx>, &hir::Pat) + where F : FnMut(cmt<'tcx>, &hir::Pat) { // Here, `cmt` is the categorization for the value being // matched and pat is the pattern it is being matched against. @@ -1056,7 +1082,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { debug!("cat_pattern: {:?} cmt={:?}", pat, cmt); - op(self, cmt.clone(), pat); + op(cmt.clone(), pat); // Note: This goes up here (rather than within the PatKind::TupleStruct arm // alone) because PatKind::Struct can also refer to variants. @@ -1087,7 +1113,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { match pat.node { PatKind::TupleStruct(ref qpath, ref subpats, ddpos) => { - let def = self.infcx.tables.borrow().qpath_def(qpath, pat.id); + let def = self.tables.qpath_def(qpath, pat.id); let expected_len = match def { Def::VariantCtor(def_id, CtorKind::Fn) => { let enum_def = self.tcx().parent_def_id(def_id).unwrap(); diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index c8e99c0354ab..74bfd9771488 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -29,7 +29,7 @@ use hir::{self, intravisit, Local, Pat, Body}; use hir::intravisit::{Visitor, NestedVisitorMap}; use hir::map::NodeExpr; use hir::def_id::DefId; -use infer::{self, InferCtxt, InferTables, InferTablesRef}; +use infer::{self, InferCtxt, InferTables}; use infer::type_variable::TypeVariableOrigin; use rustc::lint::builtin::EXTRA_REQUIREMENT_IN_IMPL; use std::fmt; @@ -652,18 +652,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { obligation.cause.span, format!("the requirement to implement `{}` derives from here", kind)); - let infer_tables = match self.tables { - InferTables::Interned(tables) => - Some(InferTablesRef::Interned(tables)), - InferTables::InProgress(tables) => - Some(InferTablesRef::InProgress(tables.borrow())), - InferTables::Missing => None, - }; - // Additional context information explaining why the closure only implements // a particular trait. - if let Some(tables) = infer_tables { - match tables.closure_kinds.get(&node_id) { + if let InferTables::InProgress(tables) = self.tables { + match tables.borrow().closure_kinds.get(&node_id) { Some(&(ty::ClosureKind::FnOnce, Some((span, name)))) => { err.span_note(span, &format!( "closure is `FnOnce` because it moves the \ diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs index 122a37ee32ae..a47ec35d265b 100644 --- a/src/librustc_borrowck/borrowck/check_loans.rs +++ b/src/librustc_borrowck/borrowck/check_loans.rs @@ -192,7 +192,6 @@ pub fn check_loans<'a, 'b, 'c, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, debug!("check_loans(body id={})", body.value.id); let def_id = bccx.tcx.hir.body_owner_def_id(body.id()); - let infcx = bccx.tcx.borrowck_fake_infer_ctxt(body.id()); let param_env = bccx.tcx.param_env(def_id); let mut clcx = CheckLoanCtxt { bccx: bccx, @@ -201,7 +200,9 @@ pub fn check_loans<'a, 'b, 'c, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, all_loans: all_loans, param_env, }; - euv::ExprUseVisitor::new(&mut clcx, &bccx.region_maps, &infcx, param_env).consume_body(body); + let infcx = bccx.tcx.borrowck_fake_infer_ctxt(); + euv::ExprUseVisitor::new(&mut clcx, &infcx, param_env, &bccx.region_maps, bccx.tables) + .consume_body(body); } #[derive(PartialEq)] diff --git a/src/librustc_borrowck/borrowck/gather_loans/mod.rs b/src/librustc_borrowck/borrowck/gather_loans/mod.rs index 85a09969ac81..ae68fb651f61 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/mod.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/mod.rs @@ -18,7 +18,6 @@ use borrowck::*; use borrowck::move_data::MoveData; -use rustc::infer::InferCtxt; use rustc::middle::expr_use_visitor as euv; use rustc::middle::mem_categorization as mc; use rustc::middle::mem_categorization::Categorization; @@ -40,11 +39,9 @@ pub fn gather_loans_in_fn<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, body: hir::BodyId) -> (Vec>, move_data::MoveData<'tcx>) { let def_id = bccx.tcx.hir.body_owner_def_id(body); - let infcx = bccx.tcx.borrowck_fake_infer_ctxt(body); let param_env = bccx.tcx.param_env(def_id); let mut glcx = GatherLoanCtxt { bccx: bccx, - infcx: &infcx, all_loans: Vec::new(), item_ub: region::CodeExtent::Misc(body.node_id), move_data: MoveData::new(), @@ -52,7 +49,9 @@ pub fn gather_loans_in_fn<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, }; let body = glcx.bccx.tcx.hir.body(body); - euv::ExprUseVisitor::new(&mut glcx, &bccx.region_maps, &infcx, param_env).consume_body(body); + let infcx = bccx.tcx.borrowck_fake_infer_ctxt(); + euv::ExprUseVisitor::new(&mut glcx, &infcx, param_env, &bccx.region_maps, bccx.tables) + .consume_body(body); glcx.report_potential_errors(); let GatherLoanCtxt { all_loans, move_data, .. } = glcx; @@ -61,7 +60,6 @@ pub fn gather_loans_in_fn<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, struct GatherLoanCtxt<'a, 'tcx: 'a> { bccx: &'a BorrowckCtxt<'a, 'tcx>, - infcx: &'a InferCtxt<'a, 'tcx, 'tcx>, move_data: move_data::MoveData<'tcx>, move_error_collector: move_error::MoveErrorCollector<'tcx>, all_loans: Vec>, @@ -158,7 +156,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for GatherLoanCtxt<'a, 'tcx> { } fn decl_without_init(&mut self, id: ast::NodeId, _span: Span) { - let ty = self.infcx.tables.borrow().node_id_to_type(id); + let ty = self.bccx.tables.node_id_to_type(id); gather_moves::gather_decl(self.bccx, &self.move_data, id, ty); } } diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs index 7c3076fda4fe..17cb60792c69 100644 --- a/src/librustc_const_eval/check_match.rs +++ b/src/librustc_const_eval/check_match.rs @@ -493,11 +493,12 @@ fn check_legality_of_move_bindings(cx: &MatchVisitor, /// /// FIXME: this should be done by borrowck. fn check_for_mutation_in_guard(cx: &MatchVisitor, guard: &hir::Expr) { - cx.tcx.infer_ctxt(cx.tables).enter(|infcx| { + cx.tcx.infer_ctxt(()).enter(|infcx| { let mut checker = MutationChecker { cx: cx, }; - ExprUseVisitor::new(&mut checker, cx.region_maps, &infcx, cx.param_env).walk_expr(guard); + ExprUseVisitor::new(&mut checker, &infcx, cx.param_env, cx.region_maps, cx.tables) + .walk_expr(guard); }); } diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 7490ee60e1f9..8d549154e11d 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -83,7 +83,7 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'t }; let src = MirSource::from_node(tcx, id); - tcx.infer_ctxt(body_id).enter(|infcx| { + tcx.infer_ctxt(()).enter(|infcx| { let cx = Cx::new(&infcx, src); let mut mir = if cx.tables().tainted_by_errors { build::construct_error(cx, body_id) diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index 5b7b52a72b0a..2bb6b39966a8 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -37,6 +37,7 @@ pub struct Cx<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, pub param_env: ty::ParamEnv<'tcx>, pub region_maps: Rc, + pub tables: &'a ty::TypeckTables<'gcx>, /// This is `Constness::Const` if we are compiling a `static`, /// `const`, or the body of a `const fn`. @@ -67,6 +68,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { let param_env = tcx.param_env(src_def_id); let region_maps = tcx.region_maps(src_def_id); + let tables = tcx.typeck_tables_of(src_def_id); let attrs = tcx.hir.attrs(src_id); @@ -82,7 +84,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { // Constants and const fn's always need overflow checks. check_overflow |= constness == hir::Constness::Const; - Cx { tcx, infcx, param_env, region_maps, constness, src, check_overflow } + Cx { tcx, infcx, param_env, region_maps, tables, constness, src, check_overflow } } } @@ -184,7 +186,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { } pub fn tables(&self) -> &'a ty::TypeckTables<'gcx> { - self.infcx.tables.expect_interned() + self.tables } pub fn check_overflow(&self) -> bool { diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs index 65a9334bbae1..f78893856883 100644 --- a/src/librustc_passes/consts.rs +++ b/src/librustc_passes/consts.rs @@ -138,11 +138,12 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckCrateVisitor<'a, 'tcx> { self.check_const_eval(&body.value); } - let outer_penv = self.tcx.infer_ctxt(body_id).enter(|infcx| { + let outer_penv = self.tcx.infer_ctxt(()).enter(|infcx| { let param_env = self.tcx.param_env(item_def_id); let outer_penv = mem::replace(&mut self.param_env, param_env); let region_maps = &self.tcx.region_maps(item_def_id); - euv::ExprUseVisitor::new(self, region_maps, &infcx, param_env).consume_body(body); + euv::ExprUseVisitor::new(self, &infcx, param_env, region_maps, self.tables) + .consume_body(body); outer_penv }); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 04469dcaf2bd..f2fdc59762b1 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4186,7 +4186,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { hir::StmtSemi(ref e, _) => e, _ => return, }; - let last_expr_ty = self.expr_ty(last_expr); + let last_expr_ty = self.node_ty(last_expr.id); if self.can_sub(self.param_env, last_expr_ty, expected_ty).is_err() { return; } diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 9c3e5cd1f400..616de1fc4122 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -824,15 +824,21 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { } } + /// Create a temporary `MemCategorizationContext` and pass it to the closure. + fn with_mc(&self, f: F) -> R + where F: for<'b> FnOnce(mc::MemCategorizationContext<'b, 'gcx, 'tcx>) -> R + { + f(mc::MemCategorizationContext::new(&self.infcx, + &self.region_maps, + &self.tables.borrow())) + } + /// Invoked on any adjustments that occur. Checks that if this is a region pointer being /// dereferenced, the lifetime of the pointer includes the deref expr. fn constrain_adjustments(&mut self, expr: &hir::Expr) -> mc::McResult> { debug!("constrain_adjustments(expr={:?})", expr); - let mut cmt = { - let mc = mc::MemCategorizationContext::new(self, &self.region_maps); - mc.cat_expr_unadjusted(expr)? - }; + let mut cmt = self.with_mc(|mc| mc.cat_expr_unadjusted(expr))?; let tables = self.tables.borrow(); let adjustments = tables.expr_adjustments(&expr); @@ -886,10 +892,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { expr.id, expr_region); } - { - let mc = mc::MemCategorizationContext::new(self, &self.region_maps); - cmt = mc.cat_expr_adjusted(expr, cmt, &adjustment)?; - } + cmt = self.with_mc(|mc| mc.cat_expr_adjusted(expr, cmt, &adjustment))?; if let Categorization::Deref(_, mc::BorrowedPtr(_, r_ptr)) = cmt.cat { self.mk_subregion_due_to_dereference(expr.span, @@ -981,10 +984,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { mutability: hir::Mutability, base: &hir::Expr) { debug!("link_addr_of(expr={:?}, base={:?})", expr, base); - let cmt = { - let mc = mc::MemCategorizationContext::new(self, &self.region_maps); - ignore_err!(mc.cat_expr(base)) - }; + let cmt = ignore_err!(self.with_mc(|mc| mc.cat_expr(base))); debug!("link_addr_of: cmt={:?}", cmt); @@ -1000,9 +1000,8 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { None => { return; } Some(ref expr) => &**expr, }; - let mc = &mc::MemCategorizationContext::new(self, &self.region_maps); - let discr_cmt = ignore_err!(mc.cat_expr(init_expr)); - self.link_pattern(mc, discr_cmt, &local.pat); + let discr_cmt = ignore_err!(self.with_mc(|mc| mc.cat_expr(init_expr))); + self.link_pattern(discr_cmt, &local.pat); } /// Computes the guarantors for any ref bindings in a match and @@ -1010,12 +1009,11 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { /// linked to the lifetime of its guarantor (if any). fn link_match(&self, discr: &hir::Expr, arms: &[hir::Arm]) { debug!("regionck::for_match()"); - let mc = &mc::MemCategorizationContext::new(self, &self.region_maps); - let discr_cmt = ignore_err!(mc.cat_expr(discr)); + let discr_cmt = ignore_err!(self.with_mc(|mc| mc.cat_expr(discr))); debug!("discr_cmt={:?}", discr_cmt); for arm in arms { for root_pat in &arm.pats { - self.link_pattern(mc, discr_cmt.clone(), &root_pat); + self.link_pattern(discr_cmt.clone(), &root_pat); } } } @@ -1025,30 +1023,28 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { /// linked to the lifetime of its guarantor (if any). fn link_fn_args(&self, body_scope: CodeExtent, args: &[hir::Arg]) { debug!("regionck::link_fn_args(body_scope={:?})", body_scope); - let mc = &mc::MemCategorizationContext::new(self, &self.region_maps); for arg in args { let arg_ty = self.node_ty(arg.id); let re_scope = self.tcx.mk_region(ty::ReScope(body_scope)); - let arg_cmt = mc.cat_rvalue( - arg.id, arg.pat.span, re_scope, arg_ty); + let arg_cmt = self.with_mc(|mc| { + mc.cat_rvalue(arg.id, arg.pat.span, re_scope, arg_ty) + }); debug!("arg_ty={:?} arg_cmt={:?} arg={:?}", arg_ty, arg_cmt, arg); - self.link_pattern(mc, arg_cmt, &arg.pat); + self.link_pattern(arg_cmt, &arg.pat); } } /// Link lifetimes of any ref bindings in `root_pat` to the pointers found /// in the discriminant, if needed. - fn link_pattern<'t>(&self, - mc: &mc::MemCategorizationContext<'a, 'gcx, 'tcx>, - discr_cmt: mc::cmt<'tcx>, - root_pat: &hir::Pat) { + fn link_pattern(&self, discr_cmt: mc::cmt<'tcx>, root_pat: &hir::Pat) { debug!("link_pattern(discr_cmt={:?}, root_pat={:?})", discr_cmt, root_pat); - let _ = mc.cat_pattern(discr_cmt, root_pat, |_, sub_cmt, sub_pat| { + let _ = self.with_mc(|mc| { + mc.cat_pattern(discr_cmt, root_pat, |sub_cmt, sub_pat| { match sub_pat.node { // `ref x` pattern PatKind::Binding(hir::BindByRef(mutbl), ..) => { @@ -1057,7 +1053,8 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { } _ => {} } - }); + }) + }); } /// Link lifetime of borrowed pointer resulting from autoref to lifetimes in the value being diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs index 1f0911bb234e..400ca59e1438 100644 --- a/src/librustc_typeck/check/upvar.rs +++ b/src/librustc_typeck/check/upvar.rs @@ -142,7 +142,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { adjust_closure_kinds: NodeMap(), adjust_upvar_captures: ty::UpvarCaptureMap::default(), }; - euv::ExprUseVisitor::new(&mut delegate, region_maps, self, self.param_env) + euv::ExprUseVisitor::new(&mut delegate, + &self.infcx, + self.param_env, + region_maps, + &self.tables.borrow()) .consume_body(body); // Write the adjusted values back into the main tables. From 3d2cff0c94a8a882eeca464ef638b0c912cc4f97 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 10 Jun 2017 13:39:39 +0200 Subject: [PATCH 111/233] Added source hashes to FileMap We can use these to perform lazy loading of source files belonging to external crates. That way we will be able to show the source code of external spans that have been translated. --- src/librustc/ich/impls_syntax.rs | 3 +++ src/librustc_metadata/decoder.rs | 2 ++ src/libsyntax/codemap.rs | 10 ++++++++++ src/libsyntax_pos/lib.rs | 13 ++++++++++--- 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs index 995f797df2fb..cba5ca148d0e 100644 --- a/src/librustc/ich/impls_syntax.rs +++ b/src/librustc/ich/impls_syntax.rs @@ -336,6 +336,7 @@ impl<'a, 'gcx, 'tcx> HashStable> for FileMa crate_of_origin, // Do not hash the source as it is not encoded src: _, + src_hash, start_pos, end_pos: _, ref lines, @@ -350,6 +351,8 @@ impl<'a, 'gcx, 'tcx> HashStable> for FileMa index: CRATE_DEF_INDEX, }.hash_stable(hcx, hasher); + src_hash.hash_stable(hcx, hasher); + // We only hash the relative position within this filemap let lines = lines.borrow(); lines.len().hash_stable(hcx, hasher); diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index d4baaa39d5d8..cd50fc4d5276 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -1148,6 +1148,7 @@ impl<'a, 'tcx> CrateMetadata { // containing the information we need. let syntax_pos::FileMap { name, name_was_remapped, + src_hash, start_pos, end_pos, lines, @@ -1173,6 +1174,7 @@ impl<'a, 'tcx> CrateMetadata { let local_version = local_codemap.new_imported_filemap(name, name_was_remapped, self.cnum.as_u32(), + src_hash, source_length, lines, multibyte_chars); diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index 830a457df748..0935ec1b01c9 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -27,9 +27,12 @@ use std::rc::Rc; use std::env; use std::fs; +use std::hash::Hasher; use std::io::{self, Read}; use errors::CodeMapper; +use rustc_data_structures::stable_hasher::StableHasher; + /// Return the span itself if it doesn't come from a macro expansion, /// otherwise return the call site span up to the `enclosing_sp` by /// following the `expn_info` chain. @@ -171,11 +174,16 @@ impl CodeMap { let (filename, was_remapped) = self.path_mapping.map_prefix(filename); + let mut hasher: StableHasher = StableHasher::new(); + hasher.write(src.as_bytes()); + let src_hash = hasher.finish(); + let filemap = Rc::new(FileMap { name: filename, name_was_remapped: was_remapped, crate_of_origin: 0, src: Some(Rc::new(src)), + src_hash: src_hash, start_pos: Pos::from_usize(start_pos), end_pos: Pos::from_usize(end_pos), lines: RefCell::new(Vec::new()), @@ -210,6 +218,7 @@ impl CodeMap { filename: FileName, name_was_remapped: bool, crate_of_origin: u32, + src_hash: u128, source_len: usize, mut file_local_lines: Vec, mut file_local_multibyte_chars: Vec) @@ -233,6 +242,7 @@ impl CodeMap { name_was_remapped: name_was_remapped, crate_of_origin: crate_of_origin, src: None, + src_hash: src_hash, start_pos: start_pos, end_pos: end_pos, lines: RefCell::new(file_local_lines), diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index 25f74aeecf40..caea14971816 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -24,6 +24,7 @@ #![feature(const_fn)] #![feature(custom_attribute)] +#![feature(i128_type)] #![feature(optin_builtin_traits)] #![allow(unused_attributes)] #![feature(specialization)] @@ -36,7 +37,6 @@ use std::cell::{Cell, RefCell}; use std::ops::{Add, Sub}; use std::rc::Rc; use std::cmp; - use std::fmt; use serialize::{Encodable, Decodable, Encoder, Decoder}; @@ -382,6 +382,8 @@ pub struct FileMap { pub crate_of_origin: u32, /// The complete source code pub src: Option>, + /// The source code's hash + pub src_hash: u128, /// The start position of this source in the CodeMap pub start_pos: BytePos, /// The end position of this source in the CodeMap @@ -394,9 +396,10 @@ pub struct FileMap { impl Encodable for FileMap { fn encode(&self, s: &mut S) -> Result<(), S::Error> { - s.emit_struct("FileMap", 6, |s| { + s.emit_struct("FileMap", 7, |s| { s.emit_struct_field("name", 0, |s| self.name.encode(s))?; s.emit_struct_field("name_was_remapped", 1, |s| self.name_was_remapped.encode(s))?; + s.emit_struct_field("src_hash", 6, |s| self.src_hash.encode(s))?; s.emit_struct_field("start_pos", 2, |s| self.start_pos.encode(s))?; s.emit_struct_field("end_pos", 3, |s| self.end_pos.encode(s))?; s.emit_struct_field("lines", 4, |s| { @@ -459,7 +462,10 @@ impl Decodable for FileMap { let name: String = d.read_struct_field("name", 0, |d| Decodable::decode(d))?; let name_was_remapped: bool = d.read_struct_field("name_was_remapped", 1, |d| Decodable::decode(d))?; - let start_pos: BytePos = d.read_struct_field("start_pos", 2, |d| Decodable::decode(d))?; + let src_hash: u128 = + d.read_struct_field("src_hash", 6, |d| Decodable::decode(d))?; + let start_pos: BytePos = + d.read_struct_field("start_pos", 2, |d| Decodable::decode(d))?; let end_pos: BytePos = d.read_struct_field("end_pos", 3, |d| Decodable::decode(d))?; let lines: Vec = d.read_struct_field("lines", 4, |d| { let num_lines: u32 = Decodable::decode(d)?; @@ -501,6 +507,7 @@ impl Decodable for FileMap { start_pos: start_pos, end_pos: end_pos, src: None, + src_hash: src_hash, lines: RefCell::new(lines), multibyte_chars: RefCell::new(multibyte_chars) }) From b89db83e6c6dd8186875188de049057d9743ba8a Mon Sep 17 00:00:00 2001 From: Tommy Ip Date: Sat, 10 Jun 2017 10:55:19 +0100 Subject: [PATCH 112/233] Only emit one error for `use foo::self;` Currently `use foo::self;` would emit both E0429 and E0432. This commit silence the latter one (assuming `foo` is a valid module). Fixes #42559 --- src/librustc_resolve/resolve_imports.rs | 10 ++++++++++ src/test/compile-fail/E0429.rs | 1 - src/test/compile-fail/use-keyword.rs | 5 ++--- src/test/compile-fail/use-mod-4.rs | 3 +++ 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index a892f9df6a64..405b2ed6ba9c 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -482,6 +482,16 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { if let Some(err) = self.finalize_import(import) { errors = true; + if let SingleImport { source, ref result, .. } = import.subclass { + if source.name == "self" { + // Silence `unresolved import` error if E0429 is already emitted + match result.value_ns.get() { + Err(Determined) => continue, + _ => {}, + } + } + } + // If the error is a single failed import then create a "fake" import // resolution for it so that later resolve stages won't complain. self.import_dummy_binding(import); diff --git a/src/test/compile-fail/E0429.rs b/src/test/compile-fail/E0429.rs index a7d19744f3fc..f1cad200be61 100644 --- a/src/test/compile-fail/E0429.rs +++ b/src/test/compile-fail/E0429.rs @@ -9,7 +9,6 @@ // except according to those terms. use std::fmt::self; //~ ERROR E0429 - //~^ ERROR E0432 fn main () { } diff --git a/src/test/compile-fail/use-keyword.rs b/src/test/compile-fail/use-keyword.rs index 6df20d414a78..aff54f18c19a 100644 --- a/src/test/compile-fail/use-keyword.rs +++ b/src/test/compile-fail/use-keyword.rs @@ -13,9 +13,8 @@ mod a { mod b { - use self as A; //~ ERROR `self` imports are only allowed within a { } list - //~^ ERROR unresolved import `self` [E0432] - //~| no `self` in the root + use self as A; + //~^ ERROR `self` imports are only allowed within a { } list use super as B; //~^ ERROR unresolved import `super` [E0432] //~| no `super` in the root diff --git a/src/test/compile-fail/use-mod-4.rs b/src/test/compile-fail/use-mod-4.rs index 146d37f41d63..f102a68c2c5e 100644 --- a/src/test/compile-fail/use-mod-4.rs +++ b/src/test/compile-fail/use-mod-4.rs @@ -11,4 +11,7 @@ use foo::self; //~ ERROR unresolved import `foo::self` //~^ ERROR `self` imports are only allowed within a { } list +use std::mem::self; +//~^ ERROR `self` imports are only allowed within a { } list + fn main() {} From 63481a57dcb4a12501621f5bc915999d4af0e8a0 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 8 Jun 2017 23:57:16 +0300 Subject: [PATCH 113/233] rustc: make InferCtxt optional in MemCategorizationContext. --- src/librustc/infer/mod.rs | 21 ----- src/librustc/middle/expr_use_visitor.rs | 37 ++++++--- src/librustc/middle/mem_categorization.rs | 81 ++++++++++++------- src/librustc_borrowck/borrowck/check_loans.rs | 3 +- .../borrowck/gather_loans/mod.rs | 3 +- src/librustc_const_eval/check_match.rs | 18 ++--- src/librustc_passes/consts.rs | 17 ++-- src/librustc_typeck/check/regionck.rs | 6 +- src/librustc_typeck/check/upvar.rs | 10 +-- 9 files changed, 105 insertions(+), 91 deletions(-) diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 3e2d26aa518a..b3e5f13de2c4 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -393,27 +393,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> { fresh_tables: env.fresh_tables().map(RefCell::new), } } - - /// Fake InferCtxt with the global tcx. Used by pre-MIR borrowck - /// for MemCategorizationContext/ExprUseVisitor. - /// If any inference functionality is used, ICEs will occur. - pub fn borrowck_fake_infer_ctxt(self) -> InferCtxt<'a, 'gcx, 'gcx> { - InferCtxt { - tcx: self, - tables: InferTables::Missing, - type_variables: RefCell::new(type_variable::TypeVariableTable::new()), - int_unification_table: RefCell::new(UnificationTable::new()), - float_unification_table: RefCell::new(UnificationTable::new()), - region_vars: RegionVarBindings::new(self), - selection_cache: traits::SelectionCache::new(), - evaluation_cache: traits::EvaluationCache::new(), - projection_cache: RefCell::new(traits::ProjectionCache::new()), - reported_trait_errors: RefCell::new(FxHashSet()), - tainted_by_errors_flag: Cell::new(false), - err_count_on_creation: self.sess.err_count(), - in_snapshot: Cell::new(false), - } - } } impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> { diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index b24b2a616b06..58e77f40d981 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -261,16 +261,32 @@ macro_rules! return_if_err { ) } -impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { +impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx, 'tcx> { pub fn new(delegate: &'a mut (Delegate<'tcx>+'a), - infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, + tcx: TyCtxt<'a, 'tcx, 'tcx>, param_env: ty::ParamEnv<'tcx>, region_maps: &'a RegionMaps, tables: &'a ty::TypeckTables<'tcx>) -> Self { ExprUseVisitor { - mc: mc::MemCategorizationContext::new(infcx, region_maps, tables), + mc: mc::MemCategorizationContext::new(tcx, region_maps, tables), + delegate, + param_env, + } + } +} + +impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { + pub fn with_infer(delegate: &'a mut (Delegate<'tcx>+'a), + infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, + param_env: ty::ParamEnv<'tcx>, + region_maps: &'a RegionMaps, + tables: &'a ty::TypeckTables<'tcx>) + -> Self + { + ExprUseVisitor { + mc: mc::MemCategorizationContext::with_infer(infcx, region_maps, tables), delegate, param_env, } @@ -296,7 +312,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { } fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> { - self.mc.infcx.tcx + self.mc.tcx } fn delegate_consume(&mut self, @@ -306,7 +322,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { debug!("delegate_consume(consume_id={}, cmt={:?})", consume_id, cmt); - let mode = copy_or_move(self.mc.infcx, self.param_env, &cmt, DirectRefMove); + let mode = copy_or_move(&self.mc, self.param_env, &cmt, DirectRefMove); self.delegate.consume(consume_id, consume_span, cmt, mode); } @@ -784,7 +800,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { PatKind::Binding(hir::BindByRef(..), ..) => mode.lub(BorrowingMatch), PatKind::Binding(hir::BindByValue(..), ..) => { - match copy_or_move(self.mc.infcx, self.param_env, &cmt_pat, PatBindingMove) { + match copy_or_move(&self.mc, self.param_env, &cmt_pat, PatBindingMove) { Copy => mode.lub(CopyingMatch), Move(..) => mode.lub(MovingMatch), } @@ -801,7 +817,6 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { debug!("walk_pat cmt_discr={:?} pat={:?}", cmt_discr, pat); let tcx = self.tcx(); - let infcx = self.mc.infcx; let ExprUseVisitor { ref mc, ref mut delegate, param_env } = *self; return_if_err!(mc.cat_pattern(cmt_discr.clone(), pat, |cmt_pat, pat| { if let PatKind::Binding(bmode, def_id, ..) = pat.node { @@ -826,7 +841,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { } } hir::BindByValue(..) => { - let mode = copy_or_move(infcx, param_env, &cmt_pat, PatBindingMove); + let mode = copy_or_move(mc, param_env, &cmt_pat, PatBindingMove); debug!("walk_pat binding consuming pat"); delegate.consume_pat(pat, cmt_pat, mode); } @@ -885,7 +900,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { freevar.def)); match upvar_capture { ty::UpvarCapture::ByValue => { - let mode = copy_or_move(self.mc.infcx, + let mode = copy_or_move(&self.mc, self.param_env, &cmt_var, CaptureMove); @@ -917,13 +932,13 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { } } -fn copy_or_move<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, +fn copy_or_move<'a, 'gcx, 'tcx>(mc: &mc::MemCategorizationContext<'a, 'gcx, 'tcx>, param_env: ty::ParamEnv<'tcx>, cmt: &mc::cmt<'tcx>, move_reason: MoveReason) -> ConsumeMode { - if infcx.type_moves_by_default(param_env, cmt.ty, cmt.span) { + if mc.type_moves_by_default(param_env, cmt.ty, cmt.span) { Move(move_reason) } else { Copy diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 66de8bc58032..259079cf1604 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -282,9 +282,10 @@ impl ast_node for hir::Pat { #[derive(Clone)] pub struct MemCategorizationContext<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { - pub infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, + pub tcx: TyCtxt<'a, 'gcx, 'tcx>, pub region_maps: &'a RegionMaps, pub tables: &'a ty::TypeckTables<'tcx>, + infcx: Option<&'a InferCtxt<'a, 'gcx, 'tcx>>, } pub type McResult = Result; @@ -385,27 +386,51 @@ impl MutabilityCategory { } } -impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { - /// Context should be the `DefId` we use to fetch region-maps. - pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, +impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx, 'tcx> { + pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, region_maps: &'a RegionMaps, tables: &'a ty::TypeckTables<'tcx>) - -> MemCategorizationContext<'a, 'gcx, 'tcx> { - MemCategorizationContext { infcx, region_maps, tables } + -> MemCategorizationContext<'a, 'tcx, 'tcx> { + MemCategorizationContext { tcx, region_maps, tables, infcx: None } + } +} + +impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { + pub fn with_infer(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, + region_maps: &'a RegionMaps, + tables: &'a ty::TypeckTables<'tcx>) + -> MemCategorizationContext<'a, 'gcx, 'tcx> { + MemCategorizationContext { + tcx: infcx.tcx, + region_maps, + tables, + infcx: Some(infcx), + } } - fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> { - self.infcx.tcx + pub fn type_moves_by_default(&self, + param_env: ty::ParamEnv<'tcx>, + ty: Ty<'tcx>, + span: Span) + -> bool { + self.infcx.map(|infcx| infcx.type_moves_by_default(param_env, ty, span)) + .or_else(|| { + self.tcx.lift_to_global(&(param_env, ty)).map(|(param_env, ty)| { + ty.moves_by_default(self.tcx.global_tcx(), param_env, span) + }) + }) + .unwrap_or(true) } fn resolve_type_vars_if_possible(&self, value: &T) -> T where T: TypeFoldable<'tcx> { - self.infcx.resolve_type_vars_if_possible(value) + self.infcx.map(|infcx| infcx.resolve_type_vars_if_possible(value)) + .unwrap_or_else(|| value.clone()) } fn is_tainted_by_errors(&self) -> bool { - self.infcx.is_tainted_by_errors() + self.infcx.map_or(false, |infcx| infcx.is_tainted_by_errors()) } fn resolve_type_vars_or_error(&self, @@ -426,7 +451,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { None if self.is_tainted_by_errors() => Err(()), None => { bug!("no type for node {}: {} in mem_categorization", - id, self.tcx().hir.node_to_string(id)); + id, self.tcx.hir.node_to_string(id)); } } } @@ -506,7 +531,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { adjustment::Adjust::Deref(overloaded) => { // Equivalent to *expr or something similar. let base = if let Some(deref) = overloaded { - let ref_ty = self.tcx().mk_ref(deref.region, ty::TypeAndMut { + let ref_ty = self.tcx.mk_ref(deref.region, ty::TypeAndMut { ty: target, mutbl: deref.mutbl, }); @@ -624,17 +649,17 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { } Def::Upvar(def_id, _, fn_node_id) => { - let var_id = self.tcx().hir.as_local_node_id(def_id).unwrap(); + let var_id = self.tcx.hir.as_local_node_id(def_id).unwrap(); self.cat_upvar(id, span, var_id, fn_node_id) } Def::Local(def_id) => { - let vid = self.tcx().hir.as_local_node_id(def_id).unwrap(); + let vid = self.tcx.hir.as_local_node_id(def_id).unwrap(); Ok(Rc::new(cmt_ { id: id, span: span, cat: Categorization::Local(vid), - mutbl: MutabilityCategory::from_local(self.tcx(), vid), + mutbl: MutabilityCategory::from_local(self.tcx, vid), ty: expr_ty, note: NoteNone })) @@ -686,7 +711,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { let var_ty = self.node_ty(var_id)?; // Mutability of original variable itself - let var_mutbl = MutabilityCategory::from_local(self.tcx(), var_id); + let var_mutbl = MutabilityCategory::from_local(self.tcx, var_id); // Construct the upvar. This represents access to the field // from the environment (perhaps we should eventually desugar @@ -753,11 +778,11 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { -> cmt_<'tcx> { // Region of environment pointer - let env_region = self.tcx().mk_region(ty::ReFree(ty::FreeRegion { + let env_region = self.tcx.mk_region(ty::ReFree(ty::FreeRegion { // The environment of a closure is guaranteed to // outlive any bindings introduced in the body of the // closure itself. - scope: self.tcx().hir.local_def_id(upvar_id.closure_expr_id), + scope: self.tcx.hir.local_def_id(upvar_id.closure_expr_id), bound_region: ty::BrEnv })); @@ -774,7 +799,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { // one. let cmt_result = cmt_ { mutbl: McImmutable, - ty: self.tcx().types.err, + ty: self.tcx.types.err, ..cmt_result }; @@ -806,7 +831,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { pub fn temporary_scope(&self, id: ast::NodeId) -> ty::Region<'tcx> { let scope = self.region_maps.temporary_scope(id); - self.tcx().mk_region(match scope { + self.tcx.mk_region(match scope { Some(scope) => ty::ReScope(scope), None => ty::ReStatic }) @@ -817,20 +842,20 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { span: Span, expr_ty: Ty<'tcx>) -> cmt<'tcx> { - let promotable = self.tcx().rvalue_promotable_to_static.borrow().get(&id).cloned() + let promotable = self.tcx.rvalue_promotable_to_static.borrow().get(&id).cloned() .unwrap_or(false); // When the corresponding feature isn't toggled, only promote `[T; 0]`. let promotable = match expr_ty.sty { ty::TyArray(_, 0) => true, - _ => promotable && self.tcx().sess.features.borrow().rvalue_static_promotion, + _ => promotable && self.tcx.sess.features.borrow().rvalue_static_promotion, }; // Compute maximum lifetime of this rvalue. This is 'static if // we can promote to a constant, otherwise equal to enclosing temp // lifetime. let re = if promotable { - self.tcx().types.re_static + self.tcx.types.re_static } else { self.temporary_scope(id) }; @@ -911,7 +936,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { span_bug!(expr.span, "cat_overloaded_lvalue: base is not a reference") } }; - let ref_ty = self.tcx().mk_ref(region, ty::TypeAndMut { + let ref_ty = self.tcx.mk_ref(region, ty::TypeAndMut { ty: lvalue_ty, mutbl, }); @@ -1098,8 +1123,8 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { Def::Variant(variant_did) | Def::VariantCtor(variant_did, ..) => { // univariant enums do not need downcasts - let enum_did = self.tcx().parent_def_id(variant_did).unwrap(); - if !self.tcx().adt_def(enum_did).is_univariant() { + let enum_did = self.tcx.parent_def_id(variant_did).unwrap(); + if !self.tcx.adt_def(enum_did).is_univariant() { self.cat_downcast(pat, cmt.clone(), cmt.ty, variant_did) } else { cmt @@ -1116,8 +1141,8 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { let def = self.tables.qpath_def(qpath, pat.id); let expected_len = match def { Def::VariantCtor(def_id, CtorKind::Fn) => { - let enum_def = self.tcx().parent_def_id(def_id).unwrap(); - self.tcx().adt_def(enum_def).variant_with_id(def_id).fields.len() + let enum_def = self.tcx.parent_def_id(def_id).unwrap(); + self.tcx.adt_def(enum_def).variant_with_id(def_id).fields.len() } Def::StructCtor(_, CtorKind::Fn) => { match self.pat_ty(&pat)?.sty { diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs index a47ec35d265b..ae2be28c198b 100644 --- a/src/librustc_borrowck/borrowck/check_loans.rs +++ b/src/librustc_borrowck/borrowck/check_loans.rs @@ -200,8 +200,7 @@ pub fn check_loans<'a, 'b, 'c, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, all_loans: all_loans, param_env, }; - let infcx = bccx.tcx.borrowck_fake_infer_ctxt(); - euv::ExprUseVisitor::new(&mut clcx, &infcx, param_env, &bccx.region_maps, bccx.tables) + euv::ExprUseVisitor::new(&mut clcx, bccx.tcx, param_env, &bccx.region_maps, bccx.tables) .consume_body(body); } diff --git a/src/librustc_borrowck/borrowck/gather_loans/mod.rs b/src/librustc_borrowck/borrowck/gather_loans/mod.rs index ae68fb651f61..7dcb6ce76a40 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/mod.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/mod.rs @@ -49,8 +49,7 @@ pub fn gather_loans_in_fn<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, }; let body = glcx.bccx.tcx.hir.body(body); - let infcx = bccx.tcx.borrowck_fake_infer_ctxt(); - euv::ExprUseVisitor::new(&mut glcx, &infcx, param_env, &bccx.region_maps, bccx.tables) + euv::ExprUseVisitor::new(&mut glcx, bccx.tcx, param_env, &bccx.region_maps, bccx.tables) .consume_body(body); glcx.report_potential_errors(); diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs index 17cb60792c69..fcdabf89e3cd 100644 --- a/src/librustc_const_eval/check_match.rs +++ b/src/librustc_const_eval/check_match.rs @@ -493,20 +493,18 @@ fn check_legality_of_move_bindings(cx: &MatchVisitor, /// /// FIXME: this should be done by borrowck. fn check_for_mutation_in_guard(cx: &MatchVisitor, guard: &hir::Expr) { - cx.tcx.infer_ctxt(()).enter(|infcx| { - let mut checker = MutationChecker { - cx: cx, - }; - ExprUseVisitor::new(&mut checker, &infcx, cx.param_env, cx.region_maps, cx.tables) - .walk_expr(guard); - }); + let mut checker = MutationChecker { + cx: cx, + }; + ExprUseVisitor::new(&mut checker, cx.tcx, cx.param_env, cx.region_maps, cx.tables) + .walk_expr(guard); } -struct MutationChecker<'a, 'gcx: 'a> { - cx: &'a MatchVisitor<'a, 'gcx>, +struct MutationChecker<'a, 'tcx: 'a> { + cx: &'a MatchVisitor<'a, 'tcx>, } -impl<'a, 'gcx, 'tcx> Delegate<'tcx> for MutationChecker<'a, 'gcx> { +impl<'a, 'tcx> Delegate<'tcx> for MutationChecker<'a, 'tcx> { fn matched_pat(&mut self, _: &Pat, _: cmt, _: euv::MatchMode) {} fn consume(&mut self, _: ast::NodeId, _: Span, _: cmt, _: ConsumeMode) {} fn consume_pat(&mut self, _: &Pat, _: cmt, _: ConsumeMode) {} diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs index f78893856883..e539cc1ae8bf 100644 --- a/src/librustc_passes/consts.rs +++ b/src/librustc_passes/consts.rs @@ -51,7 +51,6 @@ use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; use std::collections::hash_map::Entry; use std::cmp::Ordering; -use std::mem; struct CheckCrateVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, @@ -138,14 +137,14 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckCrateVisitor<'a, 'tcx> { self.check_const_eval(&body.value); } - let outer_penv = self.tcx.infer_ctxt(()).enter(|infcx| { - let param_env = self.tcx.param_env(item_def_id); - let outer_penv = mem::replace(&mut self.param_env, param_env); - let region_maps = &self.tcx.region_maps(item_def_id); - euv::ExprUseVisitor::new(self, &infcx, param_env, region_maps, self.tables) - .consume_body(body); - outer_penv - }); + let outer_penv = self.param_env; + self.param_env = self.tcx.param_env(item_def_id); + + let tcx = self.tcx; + let param_env = self.param_env; + let region_maps = self.tcx.region_maps(item_def_id); + euv::ExprUseVisitor::new(self, tcx, param_env, ®ion_maps, self.tables) + .consume_body(body); self.visit_body(body); diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 616de1fc4122..952321c946bf 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -828,9 +828,9 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { fn with_mc(&self, f: F) -> R where F: for<'b> FnOnce(mc::MemCategorizationContext<'b, 'gcx, 'tcx>) -> R { - f(mc::MemCategorizationContext::new(&self.infcx, - &self.region_maps, - &self.tables.borrow())) + f(mc::MemCategorizationContext::with_infer(&self.infcx, + &self.region_maps, + &self.tables.borrow())) } /// Invoked on any adjustments that occur. Checks that if this is a region pointer being diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs index 400ca59e1438..59ca896b347f 100644 --- a/src/librustc_typeck/check/upvar.rs +++ b/src/librustc_typeck/check/upvar.rs @@ -142,11 +142,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { adjust_closure_kinds: NodeMap(), adjust_upvar_captures: ty::UpvarCaptureMap::default(), }; - euv::ExprUseVisitor::new(&mut delegate, - &self.infcx, - self.param_env, - region_maps, - &self.tables.borrow()) + euv::ExprUseVisitor::with_infer(&mut delegate, + &self.infcx, + self.param_env, + region_maps, + &self.tables.borrow()) .consume_body(body); // Write the adjusted values back into the main tables. From fc5c31c48cf19757ebf4b750efa34e7cb5f995e3 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 9 Jun 2017 10:55:16 +0300 Subject: [PATCH 114/233] rustc: make the comon case of tcx.infer_ctxt(()) nicer. --- src/librustc/infer/mod.rs | 100 ++++++------------ src/librustc/traits/error_reporting.rs | 19 ++-- src/librustc/traits/mod.rs | 4 +- src/librustc/traits/specialize/mod.rs | 4 +- .../traits/specialize/specialization_graph.rs | 2 +- src/librustc/traits/trans/mod.rs | 2 +- src/librustc/ty/util.rs | 8 +- src/librustc_const_eval/eval.rs | 2 +- src/librustc_driver/test.rs | 2 +- src/librustc_lint/builtin.rs | 2 +- src/librustc_mir/build/mod.rs | 4 +- src/librustc_mir/transform/qualify_consts.rs | 2 +- src/librustc_mir/transform/type_check.rs | 2 +- src/librustc_typeck/check/compare_method.rs | 4 +- src/librustc_typeck/check/dropck.rs | 2 +- src/librustc_typeck/check/mod.rs | 49 +++++++-- src/librustc_typeck/coherence/builtin.rs | 2 +- .../coherence/inherent_impls_overlap.rs | 2 +- src/librustc_typeck/lib.rs | 2 +- 19 files changed, 102 insertions(+), 112 deletions(-) diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index b3e5f13de2c4..4bc0005d568a 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -31,7 +31,7 @@ use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; use ty::relate::RelateResult; use traits::{self, ObligationCause, PredicateObligations, Reveal}; use rustc_data_structures::unify::{self, UnificationTable}; -use std::cell::{Cell, RefCell, Ref, RefMut}; +use std::cell::{Cell, RefCell, Ref}; use std::fmt; use syntax::ast; use errors::DiagnosticBuilder; @@ -72,39 +72,14 @@ pub type Bound = Option; pub type UnitResult<'tcx> = RelateResult<'tcx, ()>; // "unify result" pub type FixupResult = Result; // "fixup result" -/// A version of &ty::TypeckTables which can be `Missing` (not needed), -/// `InProgress` (during typeck) or `Interned` (result of typeck). -/// Only the `InProgress` version supports `borrow_mut`. -#[derive(Copy, Clone)] -pub enum InferTables<'a, 'tcx: 'a> { - InProgress(&'a RefCell>), - Missing -} - -impl<'a, 'tcx> InferTables<'a, 'tcx> { - pub fn borrow(self) -> Ref<'a, ty::TypeckTables<'tcx>> { - match self { - InferTables::InProgress(tables) => tables.borrow(), - InferTables::Missing => { - bug!("InferTables: infcx.tables.borrow() with no tables") - } - } - } - - pub fn borrow_mut(self) -> RefMut<'a, ty::TypeckTables<'tcx>> { - match self { - InferTables::InProgress(tables) => tables.borrow_mut(), - InferTables::Missing => { - bug!("InferTables: infcx.tables.borrow_mut() with no tables") - } - } - } -} - pub struct InferCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { pub tcx: TyCtxt<'a, 'gcx, 'tcx>, - pub tables: InferTables<'a, 'tcx>, + /// During type-checking/inference of a body, `in_progress_tables` + /// contains a reference to the tables being built up, which are + /// used for reading closure kinds/signatures as they are inferred, + /// and for error reporting logic to read arbitrary node types. + pub in_progress_tables: Option<&'a RefCell>>, // Cache for projections. This cache is snapshotted along with the // infcx. @@ -360,23 +335,7 @@ impl fmt::Display for FixupError { } } -pub trait InferEnv<'a, 'tcx> { - fn fresh_tables(self) -> Option>; -} - -impl<'a, 'tcx> InferEnv<'a, 'tcx> for () { - fn fresh_tables(self) -> Option> { - None - } -} - -impl<'a, 'tcx> InferEnv<'a, 'tcx> for ty::TypeckTables<'tcx> { - fn fresh_tables(self) -> Option> { - Some(self) - } -} - -/// Helper type of a temporary returned by tcx.infer_ctxt(...). +/// Helper type of a temporary returned by tcx.infer_ctxt(). /// Necessary because we can't write the following bound: /// F: for<'b, 'tcx> where 'gcx: 'tcx FnOnce(InferCtxt<'b, 'gcx, 'tcx>). pub struct InferCtxtBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { @@ -386,16 +345,23 @@ pub struct InferCtxtBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { } impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> { - pub fn infer_ctxt>(self, env: E) -> InferCtxtBuilder<'a, 'gcx, 'tcx> { + pub fn infer_ctxt(self) -> InferCtxtBuilder<'a, 'gcx, 'tcx> { InferCtxtBuilder { global_tcx: self, arena: DroplessArena::new(), - fresh_tables: env.fresh_tables().map(RefCell::new), + fresh_tables: None, } } } impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> { + /// Used only by `rustc_typeck` during body type-checking/inference, + /// will initialize `in_progress_tables` with fresh `TypeckTables`. + pub fn with_fresh_in_progress_tables(mut self) -> Self { + self.fresh_tables = Some(RefCell::new(ty::TypeckTables::empty())); + self + } + pub fn enter(&'tcx mut self, f: F) -> R where F: for<'b> FnOnce(InferCtxt<'b, 'gcx, 'tcx>) -> R { @@ -404,11 +370,10 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> { ref arena, ref fresh_tables, } = *self; - let tables = fresh_tables.as_ref() - .map_or(InferTables::Missing, InferTables::InProgress); + let in_progress_tables = fresh_tables.as_ref(); global_tcx.enter_local(arena, |tcx| f(InferCtxt { - tcx: tcx, - tables: tables, + tcx, + in_progress_tables, projection_cache: RefCell::new(traits::ProjectionCache::new()), type_variables: RefCell::new(type_variable::TypeVariableTable::new()), int_unification_table: RefCell::new(UnificationTable::new()), @@ -531,7 +496,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { return value; } - self.infer_ctxt(()).enter(|infcx| { + self.infer_ctxt().enter(|infcx| { value.trans_normalize(&infcx, param_env) }) } @@ -553,7 +518,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { return value; } - self.infer_ctxt(()).enter(|infcx| { + self.infer_ctxt().enter(|infcx| { value.trans_normalize(&infcx, env.reveal_all()) }) } @@ -757,10 +722,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { was_in_snapshot: in_snapshot, // Borrow tables "in progress" (i.e. during typeck) // to ban writes from within a snapshot to them. - _in_progress_tables: match self.tables { - InferTables::InProgress(ref tables) => tables.try_borrow().ok(), - _ => None - } + _in_progress_tables: self.in_progress_tables.map(|tables| { + tables.borrow() + }) } } @@ -1366,14 +1330,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { span: Span) -> bool { let ty = self.resolve_type_vars_if_possible(&ty); - if let Some((param_env, ty)) = self.tcx.lift_to_global(&(param_env, ty)) { - // Even if the type may have no inference variables, during - // type-checking closure types are in local tables only. - let local_closures = match self.tables { - InferTables::InProgress(_) => ty.has_closure_types(), - _ => false - }; - if !local_closures { + // Even if the type may have no inference variables, during + // type-checking closure types are in local tables only. + if !self.in_progress_tables.is_some() || !ty.has_closure_types() { + if let Some((param_env, ty)) = self.tcx.lift_to_global(&(param_env, ty)) { return ty.moves_by_default(self.tcx.global_tcx(), param_env, span); } } @@ -1391,7 +1351,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { def_id: DefId) -> Option { - if let InferTables::InProgress(tables) = self.tables { + if let Some(tables) = self.in_progress_tables { if let Some(id) = self.tcx.hir.as_local_node_id(def_id) { return tables.borrow() .closure_kinds @@ -1409,7 +1369,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } pub fn closure_type(&self, def_id: DefId) -> ty::PolyFnSig<'tcx> { - if let InferTables::InProgress(tables) = self.tables { + if let Some(tables) = self.in_progress_tables { if let Some(id) = self.tcx.hir.as_local_node_id(def_id) { if let Some(&ty) = tables.borrow().closure_tys.get(&id) { return ty; diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 74bfd9771488..64438f586d7f 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -29,7 +29,7 @@ use hir::{self, intravisit, Local, Pat, Body}; use hir::intravisit::{Visitor, NestedVisitorMap}; use hir::map::NodeExpr; use hir::def_id::DefId; -use infer::{self, InferCtxt, InferTables}; +use infer::{self, InferCtxt}; use infer::type_variable::TypeVariableOrigin; use rustc::lint::builtin::EXTRA_REQUIREMENT_IN_IMPL; use std::fmt; @@ -72,9 +72,12 @@ struct FindLocalByTypeVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { } impl<'a, 'gcx, 'tcx> FindLocalByTypeVisitor<'a, 'gcx, 'tcx> { - fn node_matches_type(&mut self, node_id: &'gcx NodeId) -> bool { - match self.infcx.tables.borrow().node_types.get(node_id) { - Some(&ty) => { + fn node_matches_type(&mut self, node_id: NodeId) -> bool { + let ty_opt = self.infcx.in_progress_tables.and_then(|tables| { + tables.borrow().node_id_to_type_opt(node_id) + }); + match ty_opt { + Some(ty) => { let ty = self.infcx.resolve_type_vars_if_possible(&ty); ty.walk().any(|inner_ty| { inner_ty == *self.target_ty || match (&inner_ty.sty, &self.target_ty.sty) { @@ -88,7 +91,7 @@ impl<'a, 'gcx, 'tcx> FindLocalByTypeVisitor<'a, 'gcx, 'tcx> { } }) } - _ => false, + None => false, } } } @@ -99,7 +102,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for FindLocalByTypeVisitor<'a, 'gcx, 'tcx> { } fn visit_local(&mut self, local: &'gcx Local) { - if self.found_local_pattern.is_none() && self.node_matches_type(&local.id) { + if self.found_local_pattern.is_none() && self.node_matches_type(local.id) { self.found_local_pattern = Some(&*local.pat); } intravisit::walk_local(self, local); @@ -107,7 +110,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for FindLocalByTypeVisitor<'a, 'gcx, 'tcx> { fn visit_body(&mut self, body: &'gcx Body) { for argument in &body.arguments { - if self.found_arg_pattern.is_none() && self.node_matches_type(&argument.id) { + if self.found_arg_pattern.is_none() && self.node_matches_type(argument.id) { self.found_arg_pattern = Some(&*argument.pat); } } @@ -654,7 +657,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // Additional context information explaining why the closure only implements // a particular trait. - if let InferTables::InProgress(tables) = self.tables { + if let Some(tables) = self.in_progress_tables { match tables.borrow().closure_kinds.get(&node_id) { Some(&(ty::ClosureKind::FnOnce, Some((span, name)))) => { err.span_note(span, &format!( diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index c51974e6e670..3ce7ee847cca 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -484,7 +484,7 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let elaborated_env = ty::ParamEnv::new(tcx.intern_predicates(&predicates), unnormalized_env.reveal); - tcx.infer_ctxt(()).enter(|infcx| { + tcx.infer_ctxt().enter(|infcx| { let predicates = match fully_normalize( &infcx, cause, @@ -598,7 +598,7 @@ pub fn normalize_and_test_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, debug!("normalize_and_test_predicates(predicates={:?})", predicates); - tcx.infer_ctxt(()).enter(|infcx| { + tcx.infer_ctxt().enter(|infcx| { let param_env = ty::ParamEnv::empty(Reveal::All); let mut selcx = SelectionContext::new(&infcx); let mut fulfill_cx = FulfillmentContext::new(); diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index 689f06a35973..18734e2dbc3f 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -125,7 +125,7 @@ pub fn find_associated_item<'a, 'tcx>( let ancestors = trait_def.ancestors(tcx, impl_data.impl_def_id); match ancestors.defs(tcx, item.name, item.kind).next() { Some(node_item) => { - let substs = tcx.infer_ctxt(()).enter(|infcx| { + let substs = tcx.infer_ctxt().enter(|infcx| { let param_env = ty::ParamEnv::empty(Reveal::All); let substs = substs.rebase_onto(tcx, trait_def_id, impl_data.substs); let substs = translate_substs(&infcx, param_env, impl_data.impl_def_id, @@ -188,7 +188,7 @@ pub fn specializes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let impl1_trait_ref = tcx.impl_trait_ref(impl1_def_id).unwrap(); // Create a infcx, taking the predicates of impl1 as assumptions: - let result = tcx.infer_ctxt(()).enter(|infcx| { + let result = tcx.infer_ctxt().enter(|infcx| { // Normalize the trait reference. The WF rules ought to ensure // that this always succeeds. let impl1_trait_ref = diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs index 702c5035a18b..f80caeec460f 100644 --- a/src/librustc/traits/specialize/specialization_graph.rs +++ b/src/librustc/traits/specialize/specialization_graph.rs @@ -109,7 +109,7 @@ impl<'a, 'gcx, 'tcx> Children { let possible_sibling = *slot; let tcx = tcx.global_tcx(); - let (le, ge) = tcx.infer_ctxt(()).enter(|infcx| { + let (le, ge) = tcx.infer_ctxt().enter(|infcx| { let overlap = traits::overlapping_impls(&infcx, possible_sibling, impl_def_id); diff --git a/src/librustc/traits/trans/mod.rs b/src/librustc/traits/trans/mod.rs index 7ad2ef90f0d4..734ba2a2d390 100644 --- a/src/librustc/traits/trans/mod.rs +++ b/src/librustc/traits/trans/mod.rs @@ -46,7 +46,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { // Do the initial selection for the obligation. This yields the // shallow result we are looking for -- that is, what specific impl. - self.infer_ctxt(()).enter(|infcx| { + self.infer_ctxt().enter(|infcx| { let mut selcx = SelectionContext::new(&infcx); let param_env = ty::ParamEnv::empty(Reveal::All); diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index ec4ca54d6f5e..a7029ac5fa9f 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -175,7 +175,7 @@ impl<'tcx> ty::ParamEnv<'tcx> { self_type: Ty<'tcx>, span: Span) -> Result<(), CopyImplementationError<'tcx>> { // FIXME: (@jroesch) float this code up - tcx.infer_ctxt(()).enter(|infcx| { + tcx.infer_ctxt().enter(|infcx| { let (adt, substs) = match self_type.sty { ty::TyAdt(adt, substs) => (adt, substs), _ => return Err(CopyImplementationError::NotAnAdt), @@ -977,7 +977,7 @@ fn is_copy_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, { let (param_env, ty) = query.into_parts(); let trait_def_id = tcx.require_lang_item(lang_items::CopyTraitLangItem); - tcx.infer_ctxt(()) + tcx.infer_ctxt() .enter(|infcx| traits::type_known_to_meet_bound(&infcx, param_env, ty, @@ -991,7 +991,7 @@ fn is_sized_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, { let (param_env, ty) = query.into_parts(); let trait_def_id = tcx.require_lang_item(lang_items::SizedTraitLangItem); - tcx.infer_ctxt(()) + tcx.infer_ctxt() .enter(|infcx| traits::type_known_to_meet_bound(&infcx, param_env, ty, @@ -1005,7 +1005,7 @@ fn is_freeze_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, { let (param_env, ty) = query.into_parts(); let trait_def_id = tcx.require_lang_item(lang_items::FreezeTraitLangItem); - tcx.infer_ctxt(()) + tcx.infer_ctxt() .enter(|infcx| traits::type_known_to_meet_bound(&infcx, param_env, ty, diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index 3d07ffc2bc77..ec7510546a04 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -483,7 +483,7 @@ fn resolve_trait_associated_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, debug!("resolve_trait_associated_const: trait_ref={:?}", trait_ref); - tcx.infer_ctxt(()).enter(|infcx| { + tcx.infer_ctxt().enter(|infcx| { let param_env = ty::ParamEnv::empty(Reveal::UserFacing); let mut selcx = traits::SelectionContext::new(&infcx); let obligation = traits::Obligation::new(traits::ObligationCause::dummy(), diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index 2b74d0a812b4..62e20a90f8a0 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -154,7 +154,7 @@ fn test_env(source_string: &str, index, "test_crate", |tcx| { - tcx.infer_ctxt(()).enter(|infcx| { + tcx.infer_ctxt().enter(|infcx| { let mut region_maps = RegionMaps::new(); body(Env { infcx: &infcx, diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index bccdac91423c..9800012917c5 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -956,7 +956,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion { cx.param_env, trait_ref.to_poly_trait_predicate()); - tcx.infer_ctxt(()).enter(|infcx| { + tcx.infer_ctxt().enter(|infcx| { let mut selcx = traits::SelectionContext::new(&infcx); match selcx.select(&obligation) { // The method comes from a `T: Trait` bound. diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 8d549154e11d..56c0e18d6f91 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -83,7 +83,7 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'t }; let src = MirSource::from_node(tcx, id); - tcx.infer_ctxt(()).enter(|infcx| { + tcx.infer_ctxt().enter(|infcx| { let cx = Cx::new(&infcx, src); let mut mir = if cx.tables().tainted_by_errors { build::construct_error(cx, body_id) @@ -171,7 +171,7 @@ fn create_constructor_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, { let span = tcx.hir.span(ctor_id); if let hir::VariantData::Tuple(ref fields, ctor_id) = *v { - tcx.infer_ctxt(()).enter(|infcx| { + tcx.infer_ctxt().enter(|infcx| { let (mut mir, src) = shim::build_adt_ctor(&infcx, ctor_id, fields, span); diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 793cffdec89e..d60e761bc0b9 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -998,7 +998,7 @@ impl MirPass for QualifyAndPromoteConstants { // Statics must be Sync. if mode == Mode::Static { let ty = mir.return_ty; - tcx.infer_ctxt(()).enter(|infcx| { + tcx.infer_ctxt().enter(|infcx| { let param_env = ty::ParamEnv::empty(Reveal::UserFacing); let cause = traits::ObligationCause::new(mir.span, id, traits::SharedStatic); let mut fulfillment_cx = traits::FulfillmentContext::new(); diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs index da8e3b5a42ba..e23f0705b6a0 100644 --- a/src/librustc_mir/transform/type_check.rs +++ b/src/librustc_mir/transform/type_check.rs @@ -759,7 +759,7 @@ impl MirPass for TypeckMir { return; } let param_env = tcx.param_env(def_id); - tcx.infer_ctxt(()).enter(|infcx| { + tcx.infer_ctxt().enter(|infcx| { let mut checker = TypeChecker::new(&infcx, item_id, param_env); { let mut verifier = TypeVerifier::new(&mut checker, mir); diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index 8b76431fd2e6..29742469f84d 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -219,7 +219,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, param_env, normalize_cause.clone()); - tcx.infer_ctxt(()).enter(|infcx| { + tcx.infer_ctxt().enter(|infcx| { let inh = Inherited::new(infcx, impl_m.def_id); let infcx = &inh.infcx; @@ -726,7 +726,7 @@ pub fn compare_const_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_trait_ref: ty::TraitRef<'tcx>) { debug!("compare_const_impl(impl_trait_ref={:?})", impl_trait_ref); - tcx.infer_ctxt(()).enter(|infcx| { + tcx.infer_ctxt().enter(|infcx| { let param_env = ty::ParamEnv::empty(Reveal::UserFacing); let inh = Inherited::new(infcx, impl_c.def_id); let infcx = &inh.infcx; diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index bff9289de505..93057f91997d 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -79,7 +79,7 @@ fn ensure_drop_params_and_item_params_correspond<'a, 'tcx>( // check that the impl type can be made to match the trait type. - tcx.infer_ctxt(()).enter(|ref infcx| { + tcx.infer_ctxt().enter(|ref infcx| { let impl_param_env = tcx.param_env(self_type_did); let tcx = infcx.tcx; let mut fulfillment_cx = traits::FulfillmentContext::new(); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index f2fdc59762b1..844065cb3348 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -108,7 +108,7 @@ use lint; use util::common::{ErrorReported, indenter}; use util::nodemap::{DefIdMap, FxHashMap, NodeMap}; -use std::cell::{Cell, RefCell}; +use std::cell::{Cell, RefCell, Ref, RefMut}; use std::collections::hash_map::Entry; use std::cmp; use std::mem::replace; @@ -147,6 +147,33 @@ mod compare_method; mod intrinsic; mod op; +/// A wrapper for InferCtxt's `in_progress_tables` field. +#[derive(Copy, Clone)] +struct MaybeInProgressTables<'a, 'tcx: 'a> { + maybe_tables: Option<&'a RefCell>>, +} + +impl<'a, 'tcx> MaybeInProgressTables<'a, 'tcx> { + fn borrow(self) -> Ref<'a, ty::TypeckTables<'tcx>> { + match self.maybe_tables { + Some(tables) => tables.borrow(), + None => { + bug!("MaybeInProgressTables: inh/fcx.tables.borrow() with no tables") + } + } + } + + fn borrow_mut(self) -> RefMut<'a, ty::TypeckTables<'tcx>> { + match self.maybe_tables { + Some(tables) => tables.borrow_mut(), + None => { + bug!("MaybeInProgressTables: inh/fcx.tables.borrow_mut() with no tables") + } + } + } +} + + /// closures defined within the function. For example: /// /// fn foo() { @@ -159,6 +186,8 @@ mod op; pub struct Inherited<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { infcx: InferCtxt<'a, 'gcx, 'tcx>, + tables: MaybeInProgressTables<'a, 'tcx>, + locals: RefCell>>, fulfillment_cx: RefCell>, @@ -535,9 +564,8 @@ pub struct InheritedBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> { pub fn build(tcx: TyCtxt<'a, 'gcx, 'gcx>, def_id: DefId) -> InheritedBuilder<'a, 'gcx, 'tcx> { - let tables = ty::TypeckTables::empty(); InheritedBuilder { - infcx: tcx.infer_ctxt(tables), + infcx: tcx.infer_ctxt().with_fresh_in_progress_tables(), def_id, } } @@ -562,6 +590,9 @@ impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> { }); Inherited { + tables: MaybeInProgressTables { + maybe_tables: infcx.in_progress_tables, + }, infcx: infcx, fulfillment_cx: RefCell::new(traits::FulfillmentContext::new()), locals: RefCell::new(NodeMap()), @@ -3302,14 +3333,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.check_expr_has_type(base_expr, struct_ty); match struct_ty.sty { ty::TyAdt(adt, substs) if adt.is_struct() => { - self.tables.borrow_mut().fru_field_types.insert( - expr.id, - adt.struct_variant().fields.iter().map(|f| { - self.normalize_associated_types_in( - expr.span, &f.ty(self.tcx, substs) - ) - }).collect() - ); + let fru_field_types = adt.struct_variant().fields.iter().map(|f| { + self.normalize_associated_types_in(expr.span, &f.ty(self.tcx, substs)) + }).collect(); + self.tables.borrow_mut().fru_field_types.insert(expr.id, fru_field_types); } _ => { span_err!(self.tcx.sess, base_expr.span, E0436, diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs index 377b7b069d33..ccbc02990418 100644 --- a/src/librustc_typeck/coherence/builtin.rs +++ b/src/librustc_typeck/coherence/builtin.rs @@ -208,7 +208,7 @@ pub fn coerce_unsized_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, source, target); - tcx.infer_ctxt(()).enter(|infcx| { + tcx.infer_ctxt().enter(|infcx| { let cause = ObligationCause::misc(span, impl_node_id); let check_mutbl = |mt_a: ty::TypeAndMut<'tcx>, mt_b: ty::TypeAndMut<'tcx>, diff --git a/src/librustc_typeck/coherence/inherent_impls_overlap.rs b/src/librustc_typeck/coherence/inherent_impls_overlap.rs index afeb85a7a065..078ae34bc524 100644 --- a/src/librustc_typeck/coherence/inherent_impls_overlap.rs +++ b/src/librustc_typeck/coherence/inherent_impls_overlap.rs @@ -70,7 +70,7 @@ impl<'a, 'tcx> InherentOverlapChecker<'a, 'tcx> { for (i, &impl1_def_id) in impls.iter().enumerate() { for &impl2_def_id in &impls[(i + 1)..] { - self.tcx.infer_ctxt(()).enter(|infcx| { + self.tcx.infer_ctxt().enter(|infcx| { if traits::overlapping_impls(&infcx, impl1_def_id, impl2_def_id).is_some() { self.check_for_common_items_in_impls(impl1_def_id, impl2_def_id) } diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 06cb9f948c9b..26ea3ab3a335 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -155,7 +155,7 @@ fn require_same_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, expected: Ty<'tcx>, actual: Ty<'tcx>) -> bool { - tcx.infer_ctxt(()).enter(|ref infcx| { + tcx.infer_ctxt().enter(|ref infcx| { let param_env = ty::ParamEnv::empty(Reveal::UserFacing); let mut fulfill_cx = FulfillmentContext::new(); match infcx.at(&cause, param_env).eq(expected, actual) { From dd8f7cd126403955295c8b0cdbccc5ca5cbef763 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 10 Jun 2017 16:09:51 +0200 Subject: [PATCH 115/233] Moved FileMap construction to it's own constructor. The rationale is that BOM stripping is needed for lazy source loading for external crates, and duplication can be avoided by moving the corresponding functionality to libsyntax_pos. --- src/Cargo.lock | 1 + src/libsyntax/codemap.rs | 30 +++-------------------------- src/libsyntax_pos/Cargo.toml | 1 + src/libsyntax_pos/lib.rs | 37 ++++++++++++++++++++++++++++++++++++ 4 files changed, 42 insertions(+), 27 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 8bf4b6ad3e0c..3508e8c070bb 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -1682,6 +1682,7 @@ dependencies = [ name = "syntax_pos" version = "0.0.0" dependencies = [ + "rustc_data_structures 0.0.0", "serialize 0.0.0", ] diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index 0935ec1b01c9..442b92be1cb8 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -27,12 +27,9 @@ use std::rc::Rc; use std::env; use std::fs; -use std::hash::Hasher; use std::io::{self, Read}; use errors::CodeMapper; -use rustc_data_structures::stable_hasher::StableHasher; - /// Return the span itself if it doesn't come from a macro expansion, /// otherwise return the call site span up to the `enclosing_sp` by /// following the `expn_info` chain. @@ -161,34 +158,13 @@ impl CodeMap { /// Creates a new filemap without setting its line information. If you don't /// intend to set the line information yourself, you should use new_filemap_and_lines. - pub fn new_filemap(&self, filename: FileName, mut src: String) -> Rc { + pub fn new_filemap(&self, filename: FileName, src: String) -> Rc { let start_pos = self.next_start_pos(); let mut files = self.files.borrow_mut(); - // Remove utf-8 BOM if any. - if src.starts_with("\u{feff}") { - src.drain(..3); - } - - let end_pos = start_pos + src.len(); - let (filename, was_remapped) = self.path_mapping.map_prefix(filename); - - let mut hasher: StableHasher = StableHasher::new(); - hasher.write(src.as_bytes()); - let src_hash = hasher.finish(); - - let filemap = Rc::new(FileMap { - name: filename, - name_was_remapped: was_remapped, - crate_of_origin: 0, - src: Some(Rc::new(src)), - src_hash: src_hash, - start_pos: Pos::from_usize(start_pos), - end_pos: Pos::from_usize(end_pos), - lines: RefCell::new(Vec::new()), - multibyte_chars: RefCell::new(Vec::new()), - }); + let filemap = + Rc::new(FileMap::new(filename, was_remapped, src, Pos::from_usize(start_pos))); files.push(filemap.clone()); diff --git a/src/libsyntax_pos/Cargo.toml b/src/libsyntax_pos/Cargo.toml index 760aaa8a9578..dd8129bab510 100644 --- a/src/libsyntax_pos/Cargo.toml +++ b/src/libsyntax_pos/Cargo.toml @@ -10,3 +10,4 @@ crate-type = ["dylib"] [dependencies] serialize = { path = "../libserialize" } +rustc_data_structures = { path = "../librustc_data_structures" } diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index caea14971816..75ce8b675f3d 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -38,6 +38,11 @@ use std::ops::{Add, Sub}; use std::rc::Rc; use std::cmp; use std::fmt; +use std::hash::Hasher; + +use rustc_data_structures::stable_hasher::StableHasher; + +extern crate rustc_data_structures; use serialize::{Encodable, Decodable, Encoder, Decoder}; @@ -522,6 +527,31 @@ impl fmt::Debug for FileMap { } impl FileMap { + pub fn new(name: FileName, + name_was_remapped: bool, + mut src: String, + start_pos: BytePos) -> FileMap { + remove_bom(&mut src); + + let mut hasher: StableHasher = StableHasher::new(); + hasher.write(src.as_bytes()); + let src_hash = hasher.finish(); + + let end_pos = start_pos.to_usize() + src.len(); + + FileMap { + name: name, + name_was_remapped: name_was_remapped, + crate_of_origin: 0, + src: Some(Rc::new(src)), + src_hash: src_hash, + start_pos: start_pos, + end_pos: Pos::from_usize(end_pos), + lines: RefCell::new(Vec::new()), + multibyte_chars: RefCell::new(Vec::new()), + } + } + /// EFFECT: register a start-of-line offset in the /// table of line-beginnings. /// UNCHECKED INVARIANT: these offsets must be added in the right @@ -621,6 +651,13 @@ impl FileMap { } } +/// Remove utf-8 BOM if any. +fn remove_bom(src: &mut String) { + if src.starts_with("\u{feff}") { + src.drain(..3); + } +} + // _____________________________________________________________________________ // Pos, BytePos, CharPos // From c2c31b2db33e0d0b5356a0c9e032269034cdc70a Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 10 Jun 2017 21:08:32 +0200 Subject: [PATCH 116/233] Added external crates' sources to FileMap. They are now handled in their own member to prevent mutating access to the `src` member. This way, we can safely load external sources, while keeping the mutation of local source strings off-limits. --- src/librustc/ich/impls_syntax.rs | 1 + src/librustc_errors/lib.rs | 1 + src/libsyntax/codemap.rs | 20 ++++++++++++++++++++ src/libsyntax_pos/lib.rs | 13 +++++++++++++ 4 files changed, 35 insertions(+) diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs index cba5ca148d0e..b9cc3b5fb937 100644 --- a/src/librustc/ich/impls_syntax.rs +++ b/src/librustc/ich/impls_syntax.rs @@ -337,6 +337,7 @@ impl<'a, 'gcx, 'tcx> HashStable> for FileMa // Do not hash the source as it is not encoded src: _, src_hash, + external_src: _, start_pos, end_pos: _, ref lines, diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index 8d5e9e776ed2..545a485732e0 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -103,6 +103,7 @@ pub trait CodeMapper { fn span_to_filename(&self, sp: Span) -> FileName; fn merge_spans(&self, sp_lhs: Span, sp_rhs: Span) -> Option; fn call_span_if_macro(&self, sp: Span) -> Span; + fn load_source_for_filemap(&mut self, file: FileName) -> bool; } impl CodeSuggestion { diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index 442b92be1cb8..9779a6788453 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -219,6 +219,7 @@ impl CodeMap { crate_of_origin: crate_of_origin, src: None, src_hash: src_hash, + external_src: RefCell::new(ExternalSource::AbsentOk), start_pos: start_pos, end_pos: end_pos, lines: RefCell::new(file_local_lines), @@ -558,6 +559,25 @@ impl CodeMapper for CodeMap { } sp } + fn load_source_for_filemap(&mut self, filename: FileName) -> bool { + let file_map = if let Some(fm) = self.get_filemap(&filename) { + fm + } else { + return false; + }; + + if *file_map.external_src.borrow() == ExternalSource::AbsentOk { + let mut external_src = file_map.external_src.borrow_mut(); + if let Ok(src) = self.file_loader.read_file(Path::new(&filename)) { + *external_src = ExternalSource::Present(src); + return true; + } else { + *external_src = ExternalSource::AbsentErr; + } + } + + false + } } #[derive(Clone)] diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index 75ce8b675f3d..d6adf45e68a2 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -374,6 +374,14 @@ pub struct MultiByteChar { pub bytes: usize, } +#[derive(PartialEq, Eq, Clone)] +pub enum ExternalSource { + Present(String), + AbsentOk, + AbsentErr, + Unneeded, +} + /// A single source in the CodeMap. #[derive(Clone)] pub struct FileMap { @@ -389,6 +397,9 @@ pub struct FileMap { pub src: Option>, /// The source code's hash pub src_hash: u128, + /// The external source code (used for external crates, which will have a `None` + /// value as `self.src`. + pub external_src: RefCell, /// The start position of this source in the CodeMap pub start_pos: BytePos, /// The end position of this source in the CodeMap @@ -513,6 +524,7 @@ impl Decodable for FileMap { end_pos: end_pos, src: None, src_hash: src_hash, + external_src: RefCell::new(ExternalSource::AbsentOk), lines: RefCell::new(lines), multibyte_chars: RefCell::new(multibyte_chars) }) @@ -545,6 +557,7 @@ impl FileMap { crate_of_origin: 0, src: Some(Rc::new(src)), src_hash: src_hash, + external_src: RefCell::new(ExternalSource::Unneeded), start_pos: start_pos, end_pos: Pos::from_usize(end_pos), lines: RefCell::new(Vec::new()), From 11ee1b0b2e438f13153a1caff2d4ce6c2c9d0fa1 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 11 Jun 2017 06:17:12 +1000 Subject: [PATCH 117/233] Add missing term 'disjoint' from matches, rmatches This follows `match_indices` --- src/libcollections/str.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index eb32f4781948..fdb6ee42127b 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -1320,7 +1320,7 @@ impl str { core_str::StrExt::rsplitn(self, n, pat) } - /// An iterator over the matches of a pattern within the given string + /// An iterator over the disjoint matches of a pattern within the given string /// slice. /// /// The pattern can be a `&str`, [`char`], or a closure that @@ -1359,7 +1359,7 @@ impl str { core_str::StrExt::matches(self, pat) } - /// An iterator over the matches of a pattern within this string slice, + /// An iterator over the disjoint matches of a pattern within this string slice, /// yielded in reverse order. /// /// The pattern can be a `&str`, [`char`], or a closure that determines if From c04aa4ed0ce61d257ab10b4dbdaa64fa5cad37b1 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 11 Jun 2017 10:19:46 +0200 Subject: [PATCH 118/233] Improved lazy external source loading and inserted calls. --- src/librustc_errors/emitter.rs | 5 ++++- src/librustc_errors/lib.rs | 2 +- src/libsyntax/codemap.rs | 2 +- src/libsyntax_pos/lib.rs | 23 ++++++++++++++++++++++- 4 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index f820ea4c5e17..fc4d39ac482d 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -131,7 +131,7 @@ impl EmitterWriter { } } - fn preprocess_annotations(&self, msp: &MultiSpan) -> Vec { + fn preprocess_annotations(&mut self, msp: &MultiSpan) -> Vec { fn add_annotation_to_file(file_vec: &mut Vec, file: Rc, line_index: usize, @@ -175,6 +175,9 @@ impl EmitterWriter { if span_label.span == DUMMY_SP { continue; } + + cm.load_source_for_filemap(cm.span_to_filename(span_label.span)); + let lo = cm.lookup_char_pos(span_label.span.lo); let mut hi = cm.lookup_char_pos(span_label.span.hi); diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index 545a485732e0..a2a20424d6b4 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -103,7 +103,7 @@ pub trait CodeMapper { fn span_to_filename(&self, sp: Span) -> FileName; fn merge_spans(&self, sp_lhs: Span, sp_rhs: Span) -> Option; fn call_span_if_macro(&self, sp: Span) -> Span; - fn load_source_for_filemap(&mut self, file: FileName) -> bool; + fn load_source_for_filemap(&self, file: FileName) -> bool; } impl CodeSuggestion { diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index 9779a6788453..fb78b18b8981 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -559,7 +559,7 @@ impl CodeMapper for CodeMap { } sp } - fn load_source_for_filemap(&mut self, filename: FileName) -> bool { + fn load_source_for_filemap(&self, filename: FileName) -> bool { let file_map = if let Some(fm) = self.get_filemap(&filename) { fm } else { diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index d6adf45e68a2..9e545b813905 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -374,14 +374,35 @@ pub struct MultiByteChar { pub bytes: usize, } +/// The state of the lazy external source loading mechanism of a FileMap. #[derive(PartialEq, Eq, Clone)] pub enum ExternalSource { + /// The external source has been loaded already. Present(String), + /// No attempt has been made to load the external source. AbsentOk, + /// A failed attempt has been made to load the external source. AbsentErr, + /// No external source has to be loaded, since the FileMap represents a local crate. Unneeded, } +impl ExternalSource { + pub fn is_absent(&self) -> bool { + match *self { + ExternalSource::Present(_) => false, + _ => true, + } + } + + pub fn get_source(&self) -> Option<&str> { + match *self { + ExternalSource::Present(ref src) => Some(src), + _ => None, + } + } +} + /// A single source in the CodeMap. #[derive(Clone)] pub struct FileMap { @@ -620,7 +641,7 @@ impl FileMap { } pub fn is_imported(&self) -> bool { - self.src.is_none() + self.src.is_none() // TODO: change to something more sensible } pub fn byte_length(&self) -> u32 { From a5b8851e220d7a80222ea04d242603dd3392d17b Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 11 Jun 2017 13:31:40 +0200 Subject: [PATCH 119/233] Added consumption logic for external sources in FileMap We now fetch source lines from the `external_src` member as a secondary fallback if no regular source is present, that is, if the file map belongs to an external crate and the source has been fetched from disk. --- src/librustc_errors/emitter.rs | 6 +++-- src/librustc_errors/lib.rs | 11 ++++---- src/libsyntax/json.rs | 2 +- src/libsyntax_pos/lib.rs | 46 +++++++++++++++++++++------------- 4 files changed, 39 insertions(+), 26 deletions(-) diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index fc4d39ac482d..2099725c48aa 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -17,6 +17,7 @@ use RenderSpan::*; use snippet::{Annotation, AnnotationType, Line, MultilineAnnotation, StyledString, Style}; use styled_buffer::StyledBuffer; +use std::borrow::Cow; use std::io::prelude::*; use std::io; use std::rc::Rc; @@ -911,7 +912,8 @@ impl EmitterWriter { // Print out the annotate source lines that correspond with the error for annotated_file in annotated_files { // we can't annotate anything if the source is unavailable. - if annotated_file.file.src.is_none() { + if annotated_file.file.src.is_none() + && annotated_file.file.external_src.borrow().is_absent() { continue; } @@ -1012,7 +1014,7 @@ impl EmitterWriter { } else if line_idx_delta == 2 { let unannotated_line = annotated_file.file .get_line(annotated_file.lines[line_idx].line_index) - .unwrap_or(""); + .unwrap_or_else(|| Cow::from("")); let last_buffer_line_num = buffer.num_lines(); diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index a2a20424d6b4..26ecbe724f8d 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -37,6 +37,7 @@ use self::Level::*; use emitter::{Emitter, EmitterWriter}; +use std::borrow::Cow; use std::cell::{RefCell, Cell}; use std::{error, fmt}; use std::rc::Rc; @@ -122,7 +123,7 @@ impl CodeSuggestion { use syntax_pos::{CharPos, Loc, Pos}; fn push_trailing(buf: &mut String, - line_opt: Option<&str>, + line_opt: Option<&Cow>, lo: &Loc, hi_opt: Option<&Loc>) { let (lo, hi_opt) = (lo.col.to_usize(), hi_opt.map(|hi| hi.col.to_usize())); @@ -184,13 +185,13 @@ impl CodeSuggestion { let cur_lo = cm.lookup_char_pos(sp.lo); for (buf, substitute) in bufs.iter_mut().zip(substitutes) { if prev_hi.line == cur_lo.line { - push_trailing(buf, prev_line, &prev_hi, Some(&cur_lo)); + push_trailing(buf, prev_line.as_ref(), &prev_hi, Some(&cur_lo)); } else { - push_trailing(buf, prev_line, &prev_hi, None); + push_trailing(buf, prev_line.as_ref(), &prev_hi, None); // push lines between the previous and current span (if any) for idx in prev_hi.line..(cur_lo.line - 1) { if let Some(line) = fm.get_line(idx) { - buf.push_str(line); + buf.push_str(line.as_ref()); buf.push('\n'); } } @@ -206,7 +207,7 @@ impl CodeSuggestion { for buf in &mut bufs { // if the replacement already ends with a newline, don't print the next line if !buf.ends_with('\n') { - push_trailing(buf, prev_line, &prev_hi, None); + push_trailing(buf, prev_line.as_ref(), &prev_hi, None); } // remove trailing newline buf.pop(); diff --git a/src/libsyntax/json.rs b/src/libsyntax/json.rs index f37dcfdde898..e60edafe4ee4 100644 --- a/src/libsyntax/json.rs +++ b/src/libsyntax/json.rs @@ -314,7 +314,7 @@ impl DiagnosticSpanLine { h_end: usize) -> DiagnosticSpanLine { DiagnosticSpanLine { - text: fm.get_line(index).unwrap_or("").to_owned(), + text: fm.get_line(index).map_or(String::new(), |l| l.into_owned()), highlight_start: h_start, highlight_end: h_end, } diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index 9e545b813905..0bac896f6a2a 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -33,6 +33,7 @@ #![cfg_attr(stage0, feature(rustc_private))] #![cfg_attr(stage0, feature(staged_api))] +use std::borrow::Cow; use std::cell::{Cell, RefCell}; use std::ops::{Add, Sub}; use std::rc::Rc; @@ -605,24 +606,33 @@ impl FileMap { /// get a line from the list of pre-computed line-beginnings. /// line-number here is 0-based. - pub fn get_line(&self, line_number: usize) -> Option<&str> { - match self.src { - Some(ref src) => { - let lines = self.lines.borrow(); - lines.get(line_number).map(|&line| { - let begin: BytePos = line - self.start_pos; - let begin = begin.to_usize(); - // We can't use `lines.get(line_number+1)` because we might - // be parsing when we call this function and thus the current - // line is the last one we have line info for. - let slice = &src[begin..]; - match slice.find('\n') { - Some(e) => &slice[..e], - None => slice - } - }) + pub fn get_line(&self, line_number: usize) -> Option> { + fn get_until_newline(src: &str, begin: usize) -> &str { + // We can't use `lines.get(line_number+1)` because we might + // be parsing when we call this function and thus the current + // line is the last one we have line info for. + let slice = &src[begin..]; + match slice.find('\n') { + Some(e) => &slice[..e], + None => slice } - None => None + } + + let lines = self.lines.borrow(); + let line = if let Some(line) = lines.get(line_number) { + line + } else { + return None; + }; + let begin: BytePos = *line - self.start_pos; + let begin = begin.to_usize(); + + if let Some(ref src) = self.src { + Some(Cow::from(get_until_newline(src, begin))) + } else if let Some(src) = self.external_src.borrow().get_source() { + Some(Cow::Owned(String::from(get_until_newline(src, begin)))) + } else { + None } } @@ -641,7 +651,7 @@ impl FileMap { } pub fn is_imported(&self) -> bool { - self.src.is_none() // TODO: change to something more sensible + self.src.is_none() } pub fn byte_length(&self) -> u32 { From 9a8bbe9da9a9c5537379ee38e755cf35c7a4fc96 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 11 Jun 2017 13:48:54 +0200 Subject: [PATCH 120/233] Added hash verification to external source loading. --- src/libsyntax/codemap.rs | 9 ++------- src/libsyntax_pos/lib.rs | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index fb78b18b8981..8e04e47e25f9 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -567,13 +567,8 @@ impl CodeMapper for CodeMap { }; if *file_map.external_src.borrow() == ExternalSource::AbsentOk { - let mut external_src = file_map.external_src.borrow_mut(); - if let Ok(src) = self.file_loader.read_file(Path::new(&filename)) { - *external_src = ExternalSource::Present(src); - return true; - } else { - *external_src = ExternalSource::AbsentErr; - } + let src = self.file_loader.read_file(Path::new(&filename)).ok(); + return file_map.add_external_src(src); } false diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index 0bac896f6a2a..719c25e2410b 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -604,6 +604,26 @@ impl FileMap { lines.push(pos); } + /// add externally loaded source. + /// if the hash of the input doesn't match or no input is supplied via None, + /// it is interpreted as an error and the corresponding enum variant is set. + pub fn add_external_src(&self, src: Option) -> bool { + let mut external_src = self.external_src.borrow_mut(); + if let Some(src) = src { + let mut hasher: StableHasher = StableHasher::new(); + hasher.write(src.as_bytes()); + + if hasher.finish() == self.src_hash { + *external_src = ExternalSource::Present(src); + return true; + } + } else { + *external_src = ExternalSource::AbsentErr; + } + + false + } + /// get a line from the list of pre-computed line-beginnings. /// line-number here is 0-based. pub fn get_line(&self, line_number: usize) -> Option> { From 634cd2ce7398a82ee066e3111b9d20f837d39728 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 11 Jun 2017 15:09:49 +0200 Subject: [PATCH 121/233] Updated UI tests to include rendered external spans. --- src/test/ui/issue-41652/issue_41652.stderr | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/test/ui/issue-41652/issue_41652.stderr b/src/test/ui/issue-41652/issue_41652.stderr index 4625e9269c99..b7b1ddb7b88d 100644 --- a/src/test/ui/issue-41652/issue_41652.stderr +++ b/src/test/ui/issue-41652/issue_41652.stderr @@ -6,6 +6,11 @@ error[E0599]: no method named `f` found for type `{integer}` in the current scop | = note: found the following associated functions; to be used as methods, functions must have a `self` parameter note: candidate #1 is defined in the trait `issue_41652_b::Tr` + --> $DIR/auxiliary/issue_41652_b.rs:14:5 + | +14 | / fn f() +15 | | where Self: Sized; + | |__________________________^ = help: to disambiguate the method call, write `issue_41652_b::Tr::f(3)` instead error: aborting due to previous error(s) From afe841587df0d20b344b576641d0a32d32b87f54 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 11 Jun 2017 16:45:51 +0200 Subject: [PATCH 122/233] External spans: fixed unit tests and addressed review. --- src/librustc_data_structures/stable_hasher.rs | 2 +- src/libsyntax/codemap.rs | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/librustc_data_structures/stable_hasher.rs b/src/librustc_data_structures/stable_hasher.rs index f3572d3e25b3..5e291ea3c152 100644 --- a/src/librustc_data_structures/stable_hasher.rs +++ b/src/librustc_data_structures/stable_hasher.rs @@ -81,7 +81,7 @@ impl StableHasherResult for [u8; 20] { impl StableHasherResult for u128 { fn finish(mut hasher: StableHasher) -> Self { let hash_bytes: &[u8] = hasher.finalize(); - assert!(hash_bytes.len() >= mem::size_of::() * 2); + assert!(hash_bytes.len() >= mem::size_of::()); unsafe { ::std::ptr::read_unaligned(hash_bytes.as_ptr() as *const u128) diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index 8e04e47e25f9..7267f510a490 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -618,6 +618,7 @@ impl FilePathMapping { #[cfg(test)] mod tests { use super::*; + use std::borrow::Cow; use std::rc::Rc; #[test] @@ -627,12 +628,12 @@ mod tests { "first line.\nsecond line".to_string()); fm.next_line(BytePos(0)); // Test we can get lines with partial line info. - assert_eq!(fm.get_line(0), Some("first line.")); + assert_eq!(fm.get_line(0), Some(Cow::from("first line."))); // TESTING BROKEN BEHAVIOR: line break declared before actual line break. fm.next_line(BytePos(10)); - assert_eq!(fm.get_line(1), Some(".")); + assert_eq!(fm.get_line(1), Some(Cow::from("."))); fm.next_line(BytePos(12)); - assert_eq!(fm.get_line(2), Some("second line")); + assert_eq!(fm.get_line(2), Some(Cow::from("second line"))); } #[test] From 429dc51bfedd21f385dadc9bdf8d2e0163599814 Mon Sep 17 00:00:00 2001 From: Oliver Middleton Date: Sun, 11 Jun 2017 18:20:48 +0100 Subject: [PATCH 123/233] rustdoc: Link directly to associated types Rather than just linking to the trait. Also simplifies the logic used to decide whether to render the full QPath. --- src/librustdoc/html/format.rs | 42 +++++++++++++++------------------ src/test/rustdoc/assoc-types.rs | 7 ++++++ 2 files changed, 26 insertions(+), 23 deletions(-) diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 86660c28f80a..635691dd3458 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -459,22 +459,10 @@ pub fn href(did: DefId) -> Option<(String, ItemType, Vec)> { /// rendering function with the necessary arguments for linking to a local path. fn resolved_path(w: &mut fmt::Formatter, did: DefId, path: &clean::Path, print_all: bool, use_absolute: bool) -> fmt::Result { - let empty = clean::PathSegment { - name: String::new(), - params: clean::PathParameters::Parenthesized { - inputs: Vec::new(), - output: None, - } - }; - let last = path.segments.last() - .unwrap_or(&empty); - let rel_root = if path.segments.is_empty() { - None - } else { - match &*path.segments[0].name { - "self" => Some("./".to_string()), - _ => None, - } + let last = path.segments.last().unwrap(); + let rel_root = match &*path.segments[0].name { + "self" => Some("./".to_string()), + _ => None, }; if print_all { @@ -508,7 +496,7 @@ fn resolved_path(w: &mut fmt::Formatter, did: DefId, path: &clean::Path, Some((_, _, fqp)) => { format!("{}::{}", fqp[..fqp.len() - 1].join("::"), - HRef::new(did, fqp.last().unwrap_or(&String::new()))) + HRef::new(did, fqp.last().unwrap())) } None => format!("{}", HRef::new(did, &last.name)), } @@ -740,10 +728,8 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter, use_absolute: bool) -> fmt: } clean::QPath { ref name, ref self_type, ref trait_ } => { let should_show_cast = match *trait_ { - box clean::ResolvedPath { .. } => { - let path = clean::Path::singleton(name.clone()); - !path.segments.is_empty() && &format!("{:#}", trait_) != "()" && - &format!("{:#}", self_type) != "Self" + box clean::ResolvedPath { ref path, .. } => { + !path.segments.is_empty() && !self_type.is_self_type() } _ => true, }; @@ -772,8 +758,18 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter, use_absolute: bool) -> fmt: // everything comes in as a fully resolved QPath (hard to // look at). box clean::ResolvedPath { did, ref typarams, .. } => { - let path = clean::Path::singleton(name.clone()); - resolved_path(f, did, &path, true, use_absolute)?; + match href(did) { + Some((ref url, _, ref path)) if !f.alternate() => { + write!(f, + "{name}", + url = url, + shortty = ItemType::AssociatedType, + name = name, + path = path.join("::"))?; + } + _ => write!(f, "{}", name)?, + } // FIXME: `typarams` are not rendered, and this seems bad? drop(typarams); diff --git a/src/test/rustdoc/assoc-types.rs b/src/test/rustdoc/assoc-types.rs index e5485c356c29..d152be33f4c7 100644 --- a/src/test/rustdoc/assoc-types.rs +++ b/src/test/rustdoc/assoc-types.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-tidy-linelength + #![crate_type="lib"] // @has assoc_types/trait.Index.html @@ -18,11 +20,14 @@ pub trait Index { // @has - '//*[@id="index.v"]//code' 'fn index' // @has - '//*[@id="tymethod.index"]//code' \ // "fn index<'a>(&'a self, index: I) -> &'a Self::Output" + // @has - '//*[@id="tymethod.index"]//code//a[@href="../assoc_types/trait.Index.html#associatedtype.Output"]' \ + // "Output" fn index<'a>(&'a self, index: I) -> &'a Self::Output; } // @has assoc_types/fn.use_output.html // @has - '//*[@class="rust fn"]' '-> &T::Output' +// @has - '//*[@class="rust fn"]//a[@href="../assoc_types/trait.Index.html#associatedtype.Output"]' 'Output' pub fn use_output>(obj: &T, index: usize) -> &T::Output { obj.index(index) } @@ -33,10 +38,12 @@ pub trait Feed { // @has assoc_types/fn.use_input.html // @has - '//*[@class="rust fn"]' 'T::Input' +// @has - '//*[@class="rust fn"]//a[@href="../assoc_types/trait.Feed.html#associatedtype.Input"]' 'Input' pub fn use_input(_feed: &T, _element: T::Input) { } // @has assoc_types/fn.cmp_input.html // @has - '//*[@class="rust fn"]' 'where T::Input: PartialEq' +// @has - '//*[@class="rust fn"]//a[@href="../assoc_types/trait.Feed.html#associatedtype.Input"]' 'Input' pub fn cmp_input(a: &T::Input, b: &U::Input) -> bool where T::Input: PartialEq { From 7298dabdb3262c047748c4b26ce64c6c8769a7d9 Mon Sep 17 00:00:00 2001 From: Oliver Middleton Date: Sun, 11 Jun 2017 13:28:45 +0100 Subject: [PATCH 124/233] rustdoc: Stop stripping empty modules There is no good reason to strip empty modules with no documentation and doing so causes subtle problems. --- src/librustdoc/html/render.rs | 19 ++++--------------- src/librustdoc/passes/mod.rs | 18 +++++------------- src/test/rustdoc/empty-mod-private.rs | 27 +++++++++++++++++++++++++++ src/test/rustdoc/empty-mod-public.rs | 24 ++++++++++++++++++++++++ 4 files changed, 60 insertions(+), 28 deletions(-) create mode 100644 src/test/rustdoc/empty-mod-private.rs create mode 100644 src/test/rustdoc/empty-mod-public.rs diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index fea059e2757d..f9166774a6ea 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1349,7 +1349,7 @@ impl Context { // these modules are recursed into, but not rendered normally // (a flag on the context). if !self.render_redirect_pages { - self.render_redirect_pages = maybe_ignore_item(&item); + self.render_redirect_pages = item.is_stripped(); } if item.is_mod() { @@ -1432,7 +1432,7 @@ impl Context { // BTreeMap instead of HashMap to get a sorted output let mut map = BTreeMap::new(); for item in &m.items { - if maybe_ignore_item(item) { continue } + if item.is_stripped() { continue } let short = item.type_().css_class(); let myname = match item.name { @@ -1733,7 +1733,7 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context, if let clean::DefaultImplItem(..) = items[*i].inner { return false; } - !maybe_ignore_item(&items[*i]) + !items[*i].is_stripped() }).collect::>(); // the order of item types in the listing @@ -1902,17 +1902,6 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context, Ok(()) } -fn maybe_ignore_item(it: &clean::Item) -> bool { - match it.inner { - clean::StrippedItem(..) => true, - clean::ModuleItem(ref m) => { - it.doc_value().is_none() && m.items.is_empty() - && it.visibility != Some(clean::Public) - }, - _ => false, - } -} - fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Vec { let mut stability = vec![]; @@ -3332,7 +3321,7 @@ fn sidebar_module(fmt: &mut fmt::Formatter, _it: &clean::Item, if let clean::DefaultImplItem(..) = it.inner { false } else { - !maybe_ignore_item(it) && !it.is_stripped() && it.type_() == myty + !it.is_stripped() && it.type_() == myty } }) { let (short, name) = match myty { diff --git a/src/librustdoc/passes/mod.rs b/src/librustdoc/passes/mod.rs index 1cc4f9371cb6..8f6faabd157d 100644 --- a/src/librustdoc/passes/mod.rs +++ b/src/librustdoc/passes/mod.rs @@ -145,20 +145,12 @@ impl<'a> fold::DocFolder for Stripper<'a> { self.fold_item_recur(i) }; - i.and_then(|i| { - match i.inner { - // emptied modules have no need to exist - clean::ModuleItem(ref m) - if m.items.is_empty() && - i.doc_value().is_none() => None, - _ => { - if self.update_retained { - self.retained.insert(i.def_id); - } - Some(i) - } + if let Some(ref i) = i { + if self.update_retained { + self.retained.insert(i.def_id); } - }) + } + i } } diff --git a/src/test/rustdoc/empty-mod-private.rs b/src/test/rustdoc/empty-mod-private.rs new file mode 100644 index 000000000000..6b86af62a663 --- /dev/null +++ b/src/test/rustdoc/empty-mod-private.rs @@ -0,0 +1,27 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-tidy-linelength +// compile-flags: --no-defaults --passes collapse-docs --passes unindent-comments --passes strip-priv-imports + +// @has 'empty_mod_private/index.html' '//a[@href="foo/index.html"]' 'foo' +// @has 'empty_mod_private/sidebar-items.js' 'foo' +// @matches 'empty_mod_private/foo/index.html' '//h1' 'Module empty_mod_private::foo' +mod foo {} + +// @has 'empty_mod_private/index.html' '//a[@href="bar/index.html"]' 'bar' +// @has 'empty_mod_private/sidebar-items.js' 'bar' +// @matches 'empty_mod_private/bar/index.html' '//h1' 'Module empty_mod_private::bar' +mod bar { + // @has 'empty_mod_private/bar/index.html' '//a[@href="baz/index.html"]' 'baz' + // @has 'empty_mod_private/bar/sidebar-items.js' 'baz' + // @matches 'empty_mod_private/bar/baz/index.html' '//h1' 'Module empty_mod_private::bar::baz' + mod baz {} +} diff --git a/src/test/rustdoc/empty-mod-public.rs b/src/test/rustdoc/empty-mod-public.rs new file mode 100644 index 000000000000..413fe1614240 --- /dev/null +++ b/src/test/rustdoc/empty-mod-public.rs @@ -0,0 +1,24 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// @has 'empty_mod_public/index.html' '//a[@href="foo/index.html"]' 'foo' +// @has 'empty_mod_public/sidebar-items.js' 'foo' +// @matches 'empty_mod_public/foo/index.html' '//h1' 'Module empty_mod_public::foo' +pub mod foo {} + +// @has 'empty_mod_public/index.html' '//a[@href="bar/index.html"]' 'bar' +// @has 'empty_mod_public/sidebar-items.js' 'bar' +// @matches 'empty_mod_public/bar/index.html' '//h1' 'Module empty_mod_public::bar' +pub mod bar { + // @has 'empty_mod_public/bar/index.html' '//a[@href="baz/index.html"]' 'baz' + // @has 'empty_mod_public/bar/sidebar-items.js' 'baz' + // @matches 'empty_mod_public/bar/baz/index.html' '//h1' 'Module empty_mod_public::bar::baz' + pub mod baz {} +} From f4dd365bbb362a0aab0beaa31db73bf55d6a0481 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 10 Jun 2017 21:19:40 +0200 Subject: [PATCH 125/233] Add E0609 --- src/librustc_typeck/check/mod.rs | 7 +++-- src/librustc_typeck/diagnostics.rs | 27 +++++++++++++++++++ src/libsyntax/diagnostics/macros.rs | 11 ++++++++ src/test/compile-fail/E0609.rs | 18 +++++++++++++ src/test/ui/did_you_mean/issue-36798.stderr | 2 +- .../issue-36798_unknown_field.stderr | 2 +- .../macro-backtrace-invalid-internals.stderr | 4 +-- .../ui/mismatched_types/cast-rfc0401.stderr | 2 +- 8 files changed, 64 insertions(+), 9 deletions(-) create mode 100644 src/test/compile-fail/E0609.rs diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 04469dcaf2bd..9f0ee92930d3 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -2921,10 +2921,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { .emit(); self.tcx().types.err } else { - let mut err = self.type_error_struct(field.span, |actual| { - format!("no field `{}` on type `{}`", - field.node, actual) - }, expr_t); + let mut err = type_error_struct!(self.tcx().sess, field.span, expr_t, E0609, + "no field `{}` on type `{}`", + field.node, expr_t); match expr_t.sty { ty::TyAdt(def, _) if !def.is_enum() => { if let Some(suggested_field_name) = diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 910d5d740247..4f1eb929b8e8 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -4095,6 +4095,33 @@ assert_eq!(!Question::No, true); ``` "##, +E0609: r##" +An attempt to access a non-existent field in a struct was performed. + +Erroneous code example: + +```compile_fail,E0609 +struct StructWithFields { + x: u32, +} + +let s = StructWithFields { x: 0 }; +println!("{}", s.foo); // error: no field `foo` on type `StructWithFields` +``` + +To fix this error, check if you didn't misspell the field's name or that the +field actually exist. Example: + +``` +struct StructWithFields { + x: u32, +} + +let s = StructWithFields { x: 0 }; +println!("{}", s.x); // ok! +``` +"##, + } register_diagnostics! { diff --git a/src/libsyntax/diagnostics/macros.rs b/src/libsyntax/diagnostics/macros.rs index 13016d72127e..e8ecf58072a6 100644 --- a/src/libsyntax/diagnostics/macros.rs +++ b/src/libsyntax/diagnostics/macros.rs @@ -74,6 +74,17 @@ macro_rules! struct_span_err { }) } +#[macro_export] +macro_rules! type_error_struct { + ($session:expr, $span:expr, $typ:expr, $code:ident, $($message:tt)*) => ({ + if $typ.references_error() { + $session.diagnostic().struct_dummy() + } else { + struct_span_err!($session, $span, $code, $($message)*) + } + }) +} + #[macro_export] macro_rules! struct_span_warn { ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({ diff --git a/src/test/compile-fail/E0609.rs b/src/test/compile-fail/E0609.rs new file mode 100644 index 000000000000..f76c97274bde --- /dev/null +++ b/src/test/compile-fail/E0609.rs @@ -0,0 +1,18 @@ +// 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. + +struct Foo { + x: u32, +} + +fn main() { + let x = Foo { x: 0 }; + let _ = x.foo; //~ ERROR E0609 +} diff --git a/src/test/ui/did_you_mean/issue-36798.stderr b/src/test/ui/did_you_mean/issue-36798.stderr index ea628f10e0fd..a8d978d55140 100644 --- a/src/test/ui/did_you_mean/issue-36798.stderr +++ b/src/test/ui/did_you_mean/issue-36798.stderr @@ -1,4 +1,4 @@ -error: no field `baz` on type `Foo` +error[E0609]: no field `baz` on type `Foo` --> $DIR/issue-36798.rs:17:7 | 17 | f.baz; diff --git a/src/test/ui/did_you_mean/issue-36798_unknown_field.stderr b/src/test/ui/did_you_mean/issue-36798_unknown_field.stderr index a9090e3911b0..8228f9f3face 100644 --- a/src/test/ui/did_you_mean/issue-36798_unknown_field.stderr +++ b/src/test/ui/did_you_mean/issue-36798_unknown_field.stderr @@ -1,4 +1,4 @@ -error: no field `zz` on type `Foo` +error[E0609]: no field `zz` on type `Foo` --> $DIR/issue-36798_unknown_field.rs:17:7 | 17 | f.zz; diff --git a/src/test/ui/macros/macro-backtrace-invalid-internals.stderr b/src/test/ui/macros/macro-backtrace-invalid-internals.stderr index 2c83a84f0040..9694783b08b9 100644 --- a/src/test/ui/macros/macro-backtrace-invalid-internals.stderr +++ b/src/test/ui/macros/macro-backtrace-invalid-internals.stderr @@ -7,7 +7,7 @@ error[E0599]: no method named `fake` found for type `{integer}` in the current s 50 | fake_method_stmt!(); | -------------------- in this macro invocation -error: no field `fake` on type `{integer}` +error[E0609]: no field `fake` on type `{integer}` --> $DIR/macro-backtrace-invalid-internals.rs:21:13 | 21 | 1.fake @@ -34,7 +34,7 @@ error[E0599]: no method named `fake` found for type `{integer}` in the current s 54 | let _ = fake_method_expr!(); | ------------------- in this macro invocation -error: no field `fake` on type `{integer}` +error[E0609]: no field `fake` on type `{integer}` --> $DIR/macro-backtrace-invalid-internals.rs:39:13 | 39 | 1.fake diff --git a/src/test/ui/mismatched_types/cast-rfc0401.stderr b/src/test/ui/mismatched_types/cast-rfc0401.stderr index 8d31dd7500a3..58cd130dcc25 100644 --- a/src/test/ui/mismatched_types/cast-rfc0401.stderr +++ b/src/test/ui/mismatched_types/cast-rfc0401.stderr @@ -14,7 +14,7 @@ error: casting `*const U` as `*const str` is invalid | = note: vtable kinds may not match -error: no field `f` on type `fn() {main}` +error[E0609]: no field `f` on type `fn() {main}` --> $DIR/cast-rfc0401.rs:75:18 | 75 | let _ = main.f as *const u32; From a6d32153a6a70390e1c0c24907179d1e2a1f1ef9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 9 Jun 2017 20:30:33 -0700 Subject: [PATCH 126/233] Learn to parse `a as usize < b` Parsing `a as usize > b` always works, but `a as usize < b` was a parsing error because the parser would think the `<` started a generic type argument for `usize`. The parser now attempts to parse as before, and if a DiagnosticError is returned, try to parse again as a type with no generic arguments. If this fails, return the original `DiagnosticError`. --- src/libsyntax/parse/parser.rs | 98 +++++++++++++++++++++++++++++--- src/libsyntax/tokenstream.rs | 3 + src/test/run-pass/issue-22644.rs | 18 ++++++ 3 files changed, 111 insertions(+), 8 deletions(-) create mode 100644 src/test/run-pass/issue-22644.rs diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index d9cb2b4ab7db..a6ecd304dbd1 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -193,11 +193,13 @@ pub struct Parser<'a> { } +#[derive(Clone)] struct TokenCursor { frame: TokenCursorFrame, stack: Vec, } +#[derive(Clone)] struct TokenCursorFrame { delim: token::DelimToken, span: Span, @@ -397,6 +399,7 @@ impl Error { } } +#[derive(Debug)] pub enum LhsExpr { NotYetParsed, AttributesParsed(ThinVec), @@ -438,6 +441,8 @@ fn dummy_arg(span: Span) -> Arg { Arg { ty: P(ty), pat: pat, id: ast::DUMMY_NODE_ID } } +type RewindPoint = (token::Token, Span, Option, Span, TokenCursor, Vec); + impl<'a> Parser<'a> { pub fn new(sess: &'a ParseSess, tokens: TokenStream, @@ -786,6 +791,13 @@ impl<'a> Parser<'a> { } } + fn is_lt(&mut self) -> bool { + match self.token { + token::Lt | token::BinOp(token::Shl) => true, + _ => false, + } + } + /// Attempt to consume a `<`. If `<<` is seen, replace it with a single /// `<` and continue. If a `<` is not seen, return false. /// @@ -1724,7 +1736,7 @@ impl<'a> Parser<'a> { let segments = match mode { PathStyle::Type => { - self.parse_path_segments_without_colons()? + self.parse_path_segments_without_colons(false)? } PathStyle::Expr => { self.parse_path_segments_with_colons()? @@ -1745,6 +1757,16 @@ impl<'a> Parser<'a> { /// bounds are permitted and whether `::` must precede type parameter /// groups. pub fn parse_path(&mut self, mode: PathStyle) -> PResult<'a, ast::Path> { + self.parse_path_common(mode, false) + } + + pub fn parse_path_without_generics(&mut self, mode: PathStyle) -> PResult<'a, ast::Path> { + self.parse_path_common(mode, true) + } + + fn parse_path_common(&mut self, mode: PathStyle, dont_parse_generics: bool) + -> PResult<'a, ast::Path> + { maybe_whole!(self, NtPath, |x| x); let lo = self.meta_var_span.unwrap_or(self.span); @@ -1755,7 +1777,7 @@ impl<'a> Parser<'a> { // A bound set is a set of type parameter bounds. let mut segments = match mode { PathStyle::Type => { - self.parse_path_segments_without_colons()? + self.parse_path_segments_without_colons(dont_parse_generics)? } PathStyle::Expr => { self.parse_path_segments_with_colons()? @@ -1800,7 +1822,9 @@ impl<'a> Parser<'a> { /// - `a::b::c` /// - `a::b::c(V) -> W` /// - `a::b::c(V)` - pub fn parse_path_segments_without_colons(&mut self) -> PResult<'a, Vec> { + pub fn parse_path_segments_without_colons(&mut self, dont_parse_generics: bool) + -> PResult<'a, Vec> + { let mut segments = Vec::new(); loop { // First, parse an identifier. @@ -1819,7 +1843,8 @@ impl<'a> Parser<'a> { } // Parse types, optionally. - let parameters = if self.eat_lt() { + let parameters = if self.is_lt() && !dont_parse_generics { + let _ = self.eat_lt(); let (lifetimes, types, bindings) = self.parse_generic_args()?; self.expect_gt()?; ast::AngleBracketedParameterData { @@ -2798,8 +2823,40 @@ impl<'a> Parser<'a> { } // Special cases: if op == AssocOp::As { - let rhs = self.parse_ty_no_plus()?; - lhs = self.mk_expr(lhs_span.to(rhs.span), ExprKind::Cast(lhs, rhs), ThinVec::new()); + // Save the state of the parser before parsing type normally, in case there is a + // LessThan comparison after this cast. + let rp = self.get_rewind_point(); + match self.parse_ty_no_plus() { + Ok(rhs) => { + lhs = self.mk_expr(lhs_span.to(rhs.span), + ExprKind::Cast(lhs, rhs), ThinVec::new()); + } + Err(mut err) => { + // Rewind to before attempting to parse the type with generics, to get + // arround #22644. + let rp_err = self.get_rewind_point(); + self.rewind(rp); + let lo = self.span; + let path = match self.parse_path_without_generics(PathStyle::Type) { + Ok(path) => { + // Successfully parsed the type leaving a `<` yet to parse + err.cancel(); + path + } + Err(mut path_err) => { + // Still couldn't parse, return original error and parser state + path_err.cancel(); + self.rewind(rp_err); + return Err(err); + } + }; + let path = TyKind::Path(None, path); + let span = lo.to(self.prev_span); + let rhs = P(Ty { node: path, span: span, id: ast::DUMMY_NODE_ID }); + lhs = self.mk_expr(lhs_span.to(rhs.span), + ExprKind::Cast(lhs, rhs), ThinVec::new()); + } + }; continue } else if op == AssocOp::Colon { let rhs = self.parse_ty_no_plus()?; @@ -2901,7 +2958,9 @@ impl<'a> Parser<'a> { /// We only need to check lhs, not rhs, because all comparison ops /// have same precedence and are left-associative fn check_no_chained_comparison(&mut self, lhs: &Expr, outer_op: &AssocOp) { - debug_assert!(outer_op.is_comparison()); + debug_assert!(outer_op.is_comparison(), + "check_no_chained_comparison: {:?} is not comparison", + outer_op); match lhs.node { ExprKind::Binary(op, _, _) if op.node.is_comparison() => { // respan to include both operators @@ -2925,7 +2984,9 @@ impl<'a> Parser<'a> { fn parse_prefix_range_expr(&mut self, already_parsed_attrs: Option>) -> PResult<'a, P> { - debug_assert!(self.token == token::DotDot || self.token == token::DotDotDot); + debug_assert!(self.token == token::DotDot || self.token == token::DotDotDot, + "parse_prefix_range_expr: token {:?} is not DotDot or DotDotDot", + self.token); let tok = self.token.clone(); let attrs = self.parse_or_use_outer_attributes(already_parsed_attrs)?; let lo = self.span; @@ -6174,4 +6235,25 @@ impl<'a> Parser<'a> { _ => Err(self.fatal("expected string literal")) } } + + fn get_rewind_point(&mut self) -> RewindPoint { + ( + self.token.clone(), + self.span, + self.meta_var_span, + self.prev_span, + self.token_cursor.clone(), + self.expected_tokens.clone(), + ) + } + + fn rewind(&mut self, rp: RewindPoint) { + let (token, span, meta_var_span, prev_span, token_cursor, expected_tokens,) = rp; + self.token = token; + self.span = span; + self.meta_var_span = meta_var_span; + self.prev_span = prev_span; + self.token_cursor = token_cursor; + self.expected_tokens = expected_tokens; + } } diff --git a/src/libsyntax/tokenstream.rs b/src/libsyntax/tokenstream.rs index 339e7c0b628a..963482fc223f 100644 --- a/src/libsyntax/tokenstream.rs +++ b/src/libsyntax/tokenstream.rs @@ -227,14 +227,17 @@ impl TokenStream { } } +#[derive(Clone)] pub struct Cursor(CursorKind); +#[derive(Clone)] enum CursorKind { Empty, Tree(TokenTree, bool /* consumed? */), Stream(StreamCursor), } +#[derive(Clone)] struct StreamCursor { stream: RcSlice, index: usize, diff --git a/src/test/run-pass/issue-22644.rs b/src/test/run-pass/issue-22644.rs new file mode 100644 index 000000000000..9269180396c5 --- /dev/null +++ b/src/test/run-pass/issue-22644.rs @@ -0,0 +1,18 @@ +// 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. + +fn main() { + let a : u32 = 0; + let b : usize = 0; + + println!("{}", a as usize > b); + println!("{}", a as usize < b); + println!("{}", a as usize < 4); +} From 2f3789474042e16f0fb35d1a03d1acfce151774e Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 11 Jun 2017 19:48:46 +0200 Subject: [PATCH 127/233] Add E0610 --- src/librustc/ty/mod.rs | 18 +++++++ src/librustc_typeck/check/mod.rs | 49 ++++++++++--------- src/librustc_typeck/diagnostics.rs | 36 ++++++++++++-- src/test/compile-fail/E0610.rs | 14 ++++++ .../attempted-access-non-fatal.rs | 4 +- src/test/compile-fail/issue-24363.rs | 2 +- src/test/compile-fail/parse-error-correct.rs | 2 +- .../macro-backtrace-invalid-internals.stderr | 4 +- 8 files changed, 98 insertions(+), 31 deletions(-) create mode 100644 src/test/compile-fail/E0610.rs diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index afa2da3d561b..eea767cd868a 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -465,6 +465,24 @@ impl<'tcx> Hash for TyS<'tcx> { } } +impl<'tcx> TyS<'tcx> { + pub fn is_primitive_ty(&self) -> bool { + match self.sty { + TypeVariants::TyBool | + TypeVariants::TyChar | + TypeVariants::TyInt(_) | + TypeVariants::TyUint(_) | + TypeVariants::TyFloat(_) | + TypeVariants::TyInfer(InferTy::IntVar(_)) | + TypeVariants::TyInfer(InferTy::FloatVar(_)) | + TypeVariants::TyInfer(InferTy::FreshIntTy(_)) | + TypeVariants::TyInfer(InferTy::FreshFloatTy(_)) => true, + TypeVariants::TyRef(_, x) => x.ty.is_primitive_ty(), + _ => false, + } + } +} + impl<'a, 'gcx, 'tcx> HashStable> for ty::TyS<'tcx> { fn hash_stable(&self, hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 9f0ee92930d3..60bf321277cf 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -2921,29 +2921,34 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { .emit(); self.tcx().types.err } else { - let mut err = type_error_struct!(self.tcx().sess, field.span, expr_t, E0609, - "no field `{}` on type `{}`", - field.node, expr_t); - match expr_t.sty { - ty::TyAdt(def, _) if !def.is_enum() => { - if let Some(suggested_field_name) = - Self::suggest_field_name(def.struct_variant(), field, vec![]) { - err.span_label(field.span, - format!("did you mean `{}`?", suggested_field_name)); - } else { - err.span_label(field.span, - "unknown field"); - }; + if !expr_t.is_primitive_ty() { + let mut err = type_error_struct!(self.tcx().sess, field.span, expr_t, E0609, + "no field `{}` on type `{}`", + field.node, expr_t); + match expr_t.sty { + ty::TyAdt(def, _) if !def.is_enum() => { + if let Some(suggested_field_name) = + Self::suggest_field_name(def.struct_variant(), field, vec![]) { + err.span_label(field.span, + format!("did you mean `{}`?", suggested_field_name)); + } else { + err.span_label(field.span, "unknown field"); + }; + } + ty::TyRawPtr(..) => { + err.note(&format!("`{0}` is a native pointer; perhaps you need to deref \ + with `(*{0}).{1}`", + self.tcx.hir.node_to_pretty_string(base.id), + field.node)); + } + _ => {} } - ty::TyRawPtr(..) => { - err.note(&format!("`{0}` is a native pointer; perhaps you need to deref with \ - `(*{0}).{1}`", - self.tcx.hir.node_to_pretty_string(base.id), - field.node)); - } - _ => {} - } - err.emit(); + err + } else { + type_error_struct!(self.tcx().sess, field.span, expr_t, E0610, + "`{}` is a primitive type and therefore doesn't have fields", + expr_t) + }.emit(); self.tcx().types.err } } diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 4f1eb929b8e8..6ccfab0a324b 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -4096,7 +4096,7 @@ assert_eq!(!Question::No, true); "##, E0609: r##" -An attempt to access a non-existent field in a struct was performed. +Attempted to access a non-existent field in a struct. Erroneous code example: @@ -4109,8 +4109,8 @@ let s = StructWithFields { x: 0 }; println!("{}", s.foo); // error: no field `foo` on type `StructWithFields` ``` -To fix this error, check if you didn't misspell the field's name or that the -field actually exist. Example: +To fix this error, check that you didn't misspell the field's name or that the +field actually exists. Example: ``` struct StructWithFields { @@ -4122,6 +4122,36 @@ println!("{}", s.x); // ok! ``` "##, +E0610: r##" +Attempted to access a field on a primitive type. + +Erroneous code example: + +```compile_fail,E0610 +let x: u32 = 0; +println!("{}", x.foo); // error: `{integer}` is a primitive type, therefore + // doesn't have fields +``` + +Primitive types are the most basic types available in Rust and don't have +fields. To access data via named fields, struct types are used. Example: + +``` +// We declare struct called `Foo` containing two fields: +struct Foo { + x: u32, + y: i64, +} + +// We create an instance of this struct: +let variable = Foo { x: 0, y: -12 }; +// And we can now access its fields: +println!("x: {}, y: {}", variable.x, variable.y); +``` + +For more information see The Rust Book: https://doc.rust-lang.org/book/ +"##, + } register_diagnostics! { diff --git a/src/test/compile-fail/E0610.rs b/src/test/compile-fail/E0610.rs new file mode 100644 index 000000000000..522d8b0b9438 --- /dev/null +++ b/src/test/compile-fail/E0610.rs @@ -0,0 +1,14 @@ +// 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. + +fn main() { + let x = 0; + let _ = x.foo; //~ ERROR E0610 +} diff --git a/src/test/compile-fail/attempted-access-non-fatal.rs b/src/test/compile-fail/attempted-access-non-fatal.rs index fe8e793ed781..3d6c46f5ce3e 100644 --- a/src/test/compile-fail/attempted-access-non-fatal.rs +++ b/src/test/compile-fail/attempted-access-non-fatal.rs @@ -11,6 +11,6 @@ // Check that bogus field access is non-fatal fn main() { let x = 0; - let _ = x.foo; //~ no field `foo` on type `{integer}` - let _ = x.bar; //~ no field `bar` on type `{integer}` + let _ = x.foo; //~ `{integer}` is a primitive type and therefore doesn't have fields [E0610] + let _ = x.bar; //~ `{integer}` is a primitive type and therefore doesn't have fields [E0610] } diff --git a/src/test/compile-fail/issue-24363.rs b/src/test/compile-fail/issue-24363.rs index 03cae6e64ef5..619ad74ad00e 100644 --- a/src/test/compile-fail/issue-24363.rs +++ b/src/test/compile-fail/issue-24363.rs @@ -9,7 +9,7 @@ // except according to those terms. fn main() { - 1.create_a_type_error[ //~ no field `create_a_type_error` on type `{integer}` + 1.create_a_type_error[ //~ `{integer}` is a primitive type and therefore doesn't have fields ()+() //~ ERROR binary operation `+` cannot be applied // ^ ensure that we typeck the inner expression ^ ]; diff --git a/src/test/compile-fail/parse-error-correct.rs b/src/test/compile-fail/parse-error-correct.rs index 17b58a9f7c29..7dedfcf27275 100644 --- a/src/test/compile-fail/parse-error-correct.rs +++ b/src/test/compile-fail/parse-error-correct.rs @@ -17,5 +17,5 @@ fn main() { let y = 42; let x = y.; //~ ERROR unexpected token let x = y.(); //~ ERROR unexpected token - let x = y.foo; //~ ERROR no field + let x = y.foo; //~ ERROR `{integer}` is a primitive type and therefore doesn't have fields [E061 } diff --git a/src/test/ui/macros/macro-backtrace-invalid-internals.stderr b/src/test/ui/macros/macro-backtrace-invalid-internals.stderr index 9694783b08b9..95db694a0c61 100644 --- a/src/test/ui/macros/macro-backtrace-invalid-internals.stderr +++ b/src/test/ui/macros/macro-backtrace-invalid-internals.stderr @@ -7,7 +7,7 @@ error[E0599]: no method named `fake` found for type `{integer}` in the current s 50 | fake_method_stmt!(); | -------------------- in this macro invocation -error[E0609]: no field `fake` on type `{integer}` +error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields --> $DIR/macro-backtrace-invalid-internals.rs:21:13 | 21 | 1.fake @@ -34,7 +34,7 @@ error[E0599]: no method named `fake` found for type `{integer}` in the current s 54 | let _ = fake_method_expr!(); | ------------------- in this macro invocation -error[E0609]: no field `fake` on type `{integer}` +error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields --> $DIR/macro-backtrace-invalid-internals.rs:39:13 | 39 | 1.fake From 600237fa1962027e281383709691475d44e048aa Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 30 May 2017 10:37:11 +1200 Subject: [PATCH 128/233] Add a sig module to save-analysis Generates signatures for use in Rustdoc and similar tools. --- src/librustc_save_analysis/lib.rs | 1 + src/librustc_save_analysis/sig.rs | 560 ++++++++++++++++++++++++++++++ src/libsyntax/print/pprust.rs | 27 +- 3 files changed, 581 insertions(+), 7 deletions(-) create mode 100644 src/librustc_save_analysis/sig.rs diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index b74d3982d61c..655901aa8591 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -44,6 +44,7 @@ mod dump_visitor; pub mod external_data; #[macro_use] pub mod span_utils; +mod sig; use rustc::hir; use rustc::hir::def::Def; diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs new file mode 100644 index 000000000000..945f405659d5 --- /dev/null +++ b/src/librustc_save_analysis/sig.rs @@ -0,0 +1,560 @@ +// 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. + +// FIXME? None of these include visibility info. +// Large outstanding things - where clauses, defs/refs for generics +// paresable - each sig ends with `;` of ` {}` + +use SaveContext; + +use rls_data::{Signature, SigElement, Id}; + +use rustc::hir::def::Def; +use rustc::hir::def_id::DefId; +use syntax::ast::{self, NodeId}; +use syntax::print::pprust; + + +// TODO dup from json_dumper +fn id_from_def_id(id: DefId) -> Id { + Id { + krate: id.krate.as_u32(), + index: id.index.as_u32(), + } +} + +fn id_from_node_id(id: NodeId, scx: &SaveContext) -> Id { + let def_id = scx.tcx.hir.local_def_id(id); + id_from_def_id(def_id) +} + +type Result = ::std::result::Result; + +trait Sig { + fn make(&self, offset: usize, id: Option, scx: &SaveContext) -> Result; +} + +fn extend_sig(mut sig: Signature, + text: String, + defs: Vec, + refs: Vec) + -> Signature { + sig.text = text; + sig.defs.extend(defs.into_iter()); + sig.refs.extend(refs.into_iter()); + sig +} + +fn replace_text(mut sig: Signature, text: String) -> Signature { + sig.text = text; + sig +} + +fn merge_sigs(text: String, sigs: Vec) -> Signature { + let mut result = Signature { + text, + defs: vec![], + refs: vec![], + }; + + let (defs, refs): (Vec<_>, Vec<_>) = sigs.into_iter().map(|s| (s.defs, s.refs)).unzip(); + + result.defs.extend(defs.into_iter().flat_map(|ds| ds.into_iter())); + result.refs.extend(refs.into_iter().flat_map(|rs| rs.into_iter())); + + result +} + +fn text_sig(text: String) -> Signature { + Signature { + text: text, + defs: vec![], + refs: vec![], + } +} + +impl Sig for ast::Ty { + fn make(&self, offset: usize, _parent_id: Option, scx: &SaveContext) -> Result { + let id = Some(self.id); + match self.node { + ast::TyKind::Slice(ref ty) => { + let nested = ty.make(offset + 1, id, scx)?; + let text = format!("[{}]", nested.text); + Ok(replace_text(nested, text)) + } + ast::TyKind::Ptr(ref mt) => { + let prefix = match mt.mutbl { + ast::Mutability::Mutable => "*mut ", + ast::Mutability::Immutable => "*const ", + }; + let nested = mt.ty.make(offset + prefix.len(), id, scx)?; + let text = format!("{}{}", prefix, nested.text); + Ok(replace_text(nested, text)) + } + ast::TyKind::Rptr(ref lifetime, ref mt) => { + let mut prefix = "&".to_owned(); + if let &Some(ref l) = lifetime { + prefix.push_str(&l.ident.to_string()); + prefix.push(' '); + } + if let ast::Mutability::Mutable = mt.mutbl { + prefix.push_str("mut "); + }; + + let nested = mt.ty.make(offset + prefix.len(), id, scx)?; + let text = format!("{}{}", prefix, nested.text); + Ok(replace_text(nested, text)) + } + ast::TyKind::Never => { + Ok(text_sig("!".to_owned())) + }, + ast::TyKind::Tup(ref ts) => { + let mut text = "(".to_owned(); + let mut defs = vec![]; + let mut refs = vec![]; + for t in ts { + let nested = t.make(offset + text.len(), id, scx)?; + text.push_str(&nested.text); + text.push(','); + defs.extend(nested.defs.into_iter()); + refs.extend(nested.refs.into_iter()); + } + text.push(')'); + Ok(Signature { text, defs, refs }) + } + ast::TyKind::Paren(ref ty) => { + let nested = ty.make(offset + 1, id, scx)?; + let text = format!("({})", nested.text); + Ok(replace_text(nested, text)) + } + ast::TyKind::BareFn(ref f) => { + let mut text = String::new(); + if !f.lifetimes.is_empty() { + // FIXME defs, bounds on lifetimes + text.push_str("for<"); + text.push_str(&f.lifetimes.iter().map(|l| + l.lifetime.ident.to_string()).collect::>().join(", ")); + text.push('>'); + } + + if f.unsafety == ast::Unsafety::Unsafe { + text.push_str("unsafe "); + } + if f.abi != ::syntax::abi::Abi::Rust { + text.push_str("extern"); + text.push_str(&f.abi.to_string()); + text.push(' '); + } + text.push_str("fn("); + + let mut defs = vec![]; + let mut refs = vec![]; + for i in &f.decl.inputs { + let nested = i.ty.make(offset + text.len(), Some(i.id), scx)?; + text.push_str(&nested.text); + text.push(','); + defs.extend(nested.defs.into_iter()); + refs.extend(nested.refs.into_iter()); + } + text.push(')'); + if let ast::FunctionRetTy::Ty(ref t) = f.decl.output { + text.push_str(" -> "); + let nested = t.make(offset + text.len(), None, scx)?; + text.push_str(&nested.text); + text.push(','); + defs.extend(nested.defs.into_iter()); + refs.extend(nested.refs.into_iter()); + } + + Ok(Signature { text, defs, refs }) + } + ast::TyKind::Path(None, ref path) => { + path.make(offset, id, scx) + } + ast::TyKind::Path(Some(ref qself), ref path) => { + let nested_ty = qself.ty.make(offset + 1, id, scx)?; + let prefix = if qself.position == 0 { + format!("<{}>::", nested_ty.text) + } else if qself.position == 1 { + let first = pprust::path_segment_to_string(&path.segments[0]); + format!("<{} as {}>::", nested_ty.text, first) + } else { + // FIXME handle path instead of elipses. + format!("<{} as ...>::", nested_ty.text) + }; + + let name = pprust::path_segment_to_string(path.segments.last().ok_or("Bad path")?); + let def = scx.get_path_def(id.ok_or("Missing id for Path")?); + let id = id_from_def_id(def.def_id()); + if path.segments.len() - qself.position == 1 { + let start = offset + prefix.len(); + let end = start + name.len(); + + Ok(Signature { + text: prefix + &name, + defs: vec![], + refs: vec![SigElement { id, start, end }], + }) + } else { + let start = offset + prefix.len() + 5; + let end = start + name.len(); + // FIXME should put the proper path in there, not elipses. + Ok(Signature { + text: prefix + "...::" + &name, + defs: vec![], + refs: vec![SigElement { id, start, end }], + }) + } + } + ast::TyKind::TraitObject(ref bounds) => { + // FIXME recurse into bounds + let nested = pprust::bounds_to_string(bounds); + Ok(text_sig(nested)) + } + ast::TyKind::ImplTrait(ref bounds) => { + // FIXME recurse into bounds + let nested = pprust::bounds_to_string(bounds); + Ok(text_sig(format!("impl {}", nested))) + } + ast::TyKind::Array(ref ty, ref v) => { + let nested_ty = ty.make(offset + 1, id, scx)?; + let expr = pprust::expr_to_string(v).replace('\n', " "); + let text = format!("[{}; {}]", nested_ty.text, expr); + Ok(replace_text(nested_ty, text)) + } + ast::TyKind::Typeof(_) | + ast::TyKind::Infer | + ast::TyKind::Err | + ast::TyKind::ImplicitSelf | + ast::TyKind::Mac(_) => Err("Ty"), + } + } +} + +impl Sig for ast::Item { + fn make(&self, offset: usize, _parent_id: Option, scx: &SaveContext) -> Result { + let id = Some(self.id); + + let name_and_generics = |mut text: String, generics: &ast::Generics| -> Result { + let name = self.ident.to_string(); + let def = SigElement { + id: id_from_node_id(self.id, scx), + start: offset + 5, + end: offset + 5 + name.len(), + }; + text.push_str(&name); + let generics: Signature = generics.make(offset + text.len(), id, scx)?; + // FIXME where clause + let text = format!("{}{}", text, generics.text); + Ok(extend_sig(generics, text, vec![def], vec![])) + }; + + match self.node { + ast::ItemKind::Static(ref ty, m, ref expr) => { + let mut text = "static ".to_owned(); + if m == ast::Mutability::Mutable { + text.push_str("mut "); + } + let name = self.ident.to_string(); + let defs = vec![SigElement { + id: id_from_node_id(self.id, scx), + start: offset + text.len(), + end: offset + text.len() + name.len(), + }]; + text.push_str(&name); + text.push_str(": "); + + let ty = ty.make(offset + text.len(), id, scx)?; + text.push_str(&ty.text); + text.push_str(" = "); + + let expr = pprust::expr_to_string(expr).replace('\n', " "); + text.push_str(&expr); + text.push(';'); + + Ok(extend_sig(ty, text, defs, vec![])) + } + ast::ItemKind::Const(ref ty, ref expr) => { + let mut text = "const ".to_owned(); + let name = self.ident.to_string(); + let defs = vec![SigElement { + id: id_from_node_id(self.id, scx), + start: offset + text.len(), + end: offset + text.len() + name.len(), + }]; + text.push_str(&name); + text.push_str(": "); + + let ty = ty.make(offset + text.len(), id, scx)?; + text.push_str(&ty.text); + text.push_str(" = "); + + let expr = pprust::expr_to_string(expr).replace('\n', " "); + text.push_str(&expr); + text.push(';'); + + Ok(extend_sig(ty, text, defs, vec![])) + } + ast::ItemKind::Fn(ref decl, unsafety, constness, abi, ref generics, _) => { + let mut text = String::new(); + if constness.node == ast::Constness::Const { + text.push_str("const "); + } + if unsafety == ast::Unsafety::Unsafe { + text.push_str("unsafe "); + } + if abi != ::syntax::abi::Abi::Rust { + text.push_str("extern"); + text.push_str(&abi.to_string()); + text.push(' '); + } + text.push_str("fn "); + + let mut sig = name_and_generics(text, generics)?; + + sig.text.push('('); + for i in &decl.inputs { + // FIXME shoudl descend into patterns to add defs. + sig.text.push_str(&pprust::pat_to_string(&i.pat)); + sig.text.push_str(": "); + let nested = i.ty.make(offset + sig.text.len(), Some(i.id), scx)?; + sig.text.push_str(&nested.text); + sig.text.push(','); + sig.defs.extend(nested.defs.into_iter()); + sig.refs.extend(nested.refs.into_iter()); + } + sig.text.push(')'); + + if let ast::FunctionRetTy::Ty(ref t) = decl.output { + sig.text.push_str(" -> "); + let nested = t.make(offset + sig.text.len(), None, scx)?; + sig.text.push_str(&nested.text); + sig.text.push(','); + sig.defs.extend(nested.defs.into_iter()); + sig.refs.extend(nested.refs.into_iter()); + } + + Ok(sig) + } + ast::ItemKind::Mod(ref _mod) => { + let mut text = "mod ".to_owned(); + let name = self.ident.to_string(); + let defs = vec![SigElement { + id: id_from_node_id(self.id, scx), + start: offset + text.len(), + end: offset + text.len() + name.len(), + }]; + text.push_str(&name); + // Could be either `mod foo;` or `mod foo { ... }`, but we'll just puck one. + text.push(';'); + + Ok(Signature { + text, + defs, + refs: vec![], + }) + } + ast::ItemKind::Ty(ref ty, ref generics) => { + let text = "type ".to_owned(); + let mut sig = name_and_generics(text, generics)?; + + sig.text.push_str(" = "); + let ty = ty.make(offset + sig.text.len(), id, scx)?; + sig.text.push_str(&ty.text); + sig.text.push(';'); + + Ok(merge_sigs(sig.text.clone(), vec![sig, ty])) + } + ast::ItemKind::Enum(_, ref generics) => { + let text = "enum ".to_owned(); + let mut sig = name_and_generics(text, generics)?; + sig.text.push_str(" {}"); + Ok(sig) + } + ast::ItemKind::Struct(_, ref generics) => { + let text = "struct ".to_owned(); + let mut sig = name_and_generics(text, generics)?; + sig.text.push_str(" {}"); + Ok(sig) + } + ast::ItemKind::Union(_, ref generics) => { + let text = "union ".to_owned(); + let mut sig = name_and_generics(text, generics)?; + sig.text.push_str(" {}"); + Ok(sig) + } + ast::ItemKind::Trait(unsafety, ref generics, ref bounds, _) => { + let mut text = String::new(); + if unsafety == ast::Unsafety::Unsafe { + text.push_str("unsafe "); + } + text.push_str("trait "); + let mut sig = name_and_generics(text, generics)?; + + if !bounds.is_empty() { + sig.text.push_str(": "); + sig.text.push_str(&pprust::bounds_to_string(bounds)); + } + // FIXME where clause + sig.text.push_str(" {}"); + + Ok(sig) + } + ast::ItemKind::DefaultImpl(unsafety, ref trait_ref) => { + let mut text = String::new(); + if unsafety == ast::Unsafety::Unsafe { + text.push_str("unsafe "); + } + text.push_str("impl "); + let trait_sig = trait_ref.path.make(offset + text.len(), id, scx)?; + text.push_str(&trait_sig.text); + text.push_str(" for .. {}"); + Ok(replace_text(trait_sig, text)) + } + ast::ItemKind::Impl(unsafety, + polarity, + defaultness, + ref generics, + ref opt_trait, + ref ty, + _) => { + let mut text = String::new(); + if let ast::Defaultness::Default = defaultness { + text.push_str("default "); + } + if unsafety == ast::Unsafety::Unsafe { + text.push_str("unsafe "); + } + text.push_str("impl"); + + let generics_sig = generics.make(offset + text.len(), id, scx)?; + text.push_str(&generics_sig.text); + + text.push(' '); + + let trait_sig = if let Some(ref t) = *opt_trait { + if polarity == ast::ImplPolarity::Negative { + text.push('!'); + } + let trait_sig = t.path.make(offset + text.len(), id, scx)?; + text.push_str(&trait_sig.text); + text.push_str(" for "); + trait_sig + } else { + text_sig(String::new()) + }; + + let ty_sig = ty.make(offset + text.len(), id, scx)?; + text.push_str(&ty_sig.text); + + text.push_str(" {}"); + + Ok(merge_sigs(text, vec![generics_sig, trait_sig, ty_sig])) + + // FIXME where clause + } + ast::ItemKind::ForeignMod(_) => Err("extern mod"), + ast::ItemKind::GlobalAsm(_) => Err("glboal asm"), + ast::ItemKind::ExternCrate(_) => Err("extern crate"), + // FIXME should implement this (e.g., pub use). + ast::ItemKind::Use(_) => Err("import"), + ast::ItemKind::Mac(..) | + ast::ItemKind::MacroDef(_) => Err("Macro"), + } + } +} + +impl Sig for ast::Path { + fn make(&self, offset: usize, id: Option, scx: &SaveContext) -> Result { + let def = scx.get_path_def(id.ok_or("Missing id for Path")?); + let id = id_from_def_id(def.def_id()); + + let (name, start, end) = match def { + Def::AssociatedConst(..) | + Def::Variant(..) | + Def::VariantCtor(..) => { + let len = self.segments.len(); + if len < 2 { + return Err("Bad path"); + } + // FIXME: really we should descend into the generics here and add SigElements for + // them. + // FIXME: would be nice to have a def for the first path segment. + let seg1 = pprust::path_segment_to_string(&self.segments[len - 2]); + let seg2 = pprust::path_segment_to_string(&self.segments[len - 1]); + let start = offset + seg1.len() + 2; + (format!("{}::{}", seg1, seg2), start, start + seg2.len()) + } + _ => { + let name = pprust::path_segment_to_string(self.segments.last().ok_or("Bad path")?); + let end = offset + name.len(); + (name, offset, end) + } + }; + + Ok(Signature { + text: name, + defs: vec![], + refs: vec![SigElement { id, start, end }], + }) + } +} + +// This does not cover the where clause, which must be processed separately. +impl Sig for ast::Generics { + fn make(&self, offset: usize, _parent_id: Option, scx: &SaveContext) -> Result { + let total = self.lifetimes.len() + self.ty_params.len(); + if total == 0 { + return Ok(text_sig(String::new())); + } + + let mut text = "<".to_owned(); + + let mut defs = vec![]; + for l in &self.lifetimes { + let mut l_text = l.lifetime.ident.to_string(); + defs.push(SigElement { + id: id_from_node_id(l.lifetime.id, scx), + start: offset + text.len(), + end: offset + text.len() + l_text.len(), + }); + + if !l.bounds.is_empty() { + l_text.push_str(": "); + let bounds = l.bounds.iter().map(|l| l.ident.to_string()).collect::>().join(" + "); + l_text.push_str(&bounds); + // FIXME add lifetime bounds refs. + } + text.push_str(&l_text); + text.push(','); + } + for t in &self.ty_params { + let mut t_text = t.ident.to_string(); + defs.push(SigElement { + id: id_from_node_id(t.id, scx), + start: offset + text.len(), + end: offset + text.len() + t_text.len(), + }); + + if !t.bounds.is_empty() { + t_text.push_str(": "); + t_text.push_str(&pprust::bounds_to_string(&t.bounds)); + // FIXME descend properly into bounds. + } + text.push_str(&t_text); + text.push(','); + } + + text.push('>'); + Ok(Signature {text, defs, refs: vec![] }) + } +} + +// TODO impl items, trait items diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 073ededcb0ce..34cda433d525 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -370,6 +370,10 @@ pub fn path_to_string(p: &ast::Path) -> String { to_string(|s| s.print_path(p, false, 0, false)) } +pub fn path_segment_to_string(p: &ast::PathSegment) -> String { + to_string(|s| s.print_path_segment(p, false)) +} + pub fn ident_to_string(id: ast::Ident) -> String { to_string(|s| s.print_ident(id)) } @@ -2359,18 +2363,27 @@ impl<'a> State<'a> { if i > 0 { word(&mut self.s, "::")? } - if segment.identifier.name != keywords::CrateRoot.name() && - segment.identifier.name != "$crate" { - self.print_ident(segment.identifier)?; - if let Some(ref parameters) = segment.parameters { - self.print_path_parameters(parameters, colons_before_params)?; - } - } + self.print_path_segment(segment, colons_before_params)?; } Ok(()) } + fn print_path_segment(&mut self, + segment: &ast::PathSegment, + colons_before_params: bool) + -> io::Result<()> + { + if segment.identifier.name != keywords::CrateRoot.name() && + segment.identifier.name != "$crate" { + self.print_ident(segment.identifier)?; + if let Some(ref parameters) = segment.parameters { + self.print_path_parameters(parameters, colons_before_params)?; + } + } + Ok(()) + } + fn print_qpath(&mut self, path: &ast::Path, qself: &ast::QSelf, From 0058fdd110bd98a8e3e8b487247bef5f4e6cb618 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 30 May 2017 12:01:48 +1200 Subject: [PATCH 129/233] Update rls-data --- src/Cargo.lock | 6 +++--- src/librustc_save_analysis/Cargo.toml | 2 +- src/librustc_save_analysis/json_dumper.rs | 3 --- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 8bf4b6ad3e0c..7718dff3b837 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -1049,7 +1049,7 @@ dependencies = [ [[package]] name = "rls-data" -version = "0.4.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1372,7 +1372,7 @@ name = "rustc_save_analysis" version = "0.0.0" dependencies = [ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "rls-data 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rls-data 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2077,7 +2077,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum regex-syntax 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9191b1f57603095f105d317e375d19b1c9c5c3185ea9633a99a6dcbed04457" "checksum rls-analysis 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8d77d58e8933752142b5b92e3f8ba6d6f1630be6da5627c492268a43f79ffbda" "checksum rls-data 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fc4277ce3c57f456b11fe3145b181a844a25201bab5cbaa1978457e6e2f27d47" -"checksum rls-data 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "374a8fad31cc0681a7bfd8a04079dd4afd0e981d34e18a171b1a467445bdf51e" +"checksum rls-data 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9e2087477364c34faca86c2476765deb1185dbae3c598cfb1eb040f3a74d22b5" "checksum rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d7c7046dc6a92f2ae02ed302746db4382e75131b9ce20ce967259f6b5867a6a" "checksum rls-vfs 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ace07060dd154731b39254864245cbdd33c8f5f64fe1f630a089c72e2468f854" "checksum rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3058a43ada2c2d0b92b3ae38007a2d0fa5e9db971be260e0171408a4ff471c95" diff --git a/src/librustc_save_analysis/Cargo.toml b/src/librustc_save_analysis/Cargo.toml index 6d04bff82829..53a82cf73e95 100644 --- a/src/librustc_save_analysis/Cargo.toml +++ b/src/librustc_save_analysis/Cargo.toml @@ -14,7 +14,7 @@ rustc = { path = "../librustc" } rustc_typeck = { path = "../librustc_typeck" } syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } -rls-data = "0.3" +rls-data = "0.6" rls-span = "0.4" # FIXME(#40527) should move rustc serialize out of tree rustc-serialize = "0.3" diff --git a/src/librustc_save_analysis/json_dumper.rs b/src/librustc_save_analysis/json_dumper.rs index eaa0c0825f0e..a315cca9f4d8 100644 --- a/src/librustc_save_analysis/json_dumper.rs +++ b/src/librustc_save_analysis/json_dumper.rs @@ -484,10 +484,7 @@ impl Into for InheritanceData { impl Into for external_data::Signature { fn into(self) -> Signature { Signature { - span: self.span, text: self.text, - ident_start: self.ident_start, - ident_end: self.ident_end, defs: self.defs.into_iter().map(|s| s.into()).collect(), refs: self.refs.into_iter().map(|s| s.into()).collect(), } From a2a999f0356d037d09b7cd1d3b5b3011d6b810db Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 31 May 2017 15:59:48 +1200 Subject: [PATCH 130/233] Use the new signature stuff And fix a couple of bugs --- src/librustc_save_analysis/data.rs | 41 ++-------- src/librustc_save_analysis/dump_visitor.rs | 37 ++++----- src/librustc_save_analysis/external_data.rs | 65 +++++---------- src/librustc_save_analysis/json_api_dumper.rs | 14 ++-- src/librustc_save_analysis/json_dumper.rs | 43 +++------- src/librustc_save_analysis/lib.rs | 79 ++++--------------- src/librustc_save_analysis/sig.rs | 27 +++++-- 7 files changed, 95 insertions(+), 211 deletions(-) diff --git a/src/librustc_save_analysis/data.rs b/src/librustc_save_analysis/data.rs index cac1a2e3c5af..e15e3f6e79e2 100644 --- a/src/librustc_save_analysis/data.rs +++ b/src/librustc_save_analysis/data.rs @@ -18,7 +18,7 @@ use rustc::hir::def_id::{CrateNum, DefId}; use syntax::ast::{self, Attribute, NodeId}; use syntax_pos::Span; -use rls_data::ExternalCrateData; +use rls_data::{ExternalCrateData, Signature}; pub struct CrateData { pub name: String, @@ -129,7 +129,7 @@ pub struct EnumData { pub variants: Vec, pub visibility: Visibility, pub docs: String, - pub sig: Signature, + pub sig: Option, pub attributes: Vec, } @@ -165,7 +165,7 @@ pub struct FunctionData { pub visibility: Visibility, pub parent: Option, pub docs: String, - pub sig: Signature, + pub sig: Option, pub attributes: Vec, } @@ -251,7 +251,7 @@ pub struct MethodData { pub parent: Option, pub visibility: Visibility, pub docs: String, - pub sig: Signature, + pub sig: Option, pub attributes: Vec, } @@ -292,7 +292,7 @@ pub struct StructData { pub fields: Vec, pub visibility: Visibility, pub docs: String, - pub sig: Signature, + pub sig: Option, pub attributes: Vec, } @@ -307,7 +307,7 @@ pub struct StructVariantData { pub scope: NodeId, pub parent: Option, pub docs: String, - pub sig: Signature, + pub sig: Option, pub attributes: Vec, } @@ -322,7 +322,7 @@ pub struct TraitData { pub items: Vec, pub visibility: Visibility, pub docs: String, - pub sig: Signature, + pub sig: Option, pub attributes: Vec, } @@ -337,7 +337,7 @@ pub struct TupleVariantData { pub scope: NodeId, pub parent: Option, pub docs: String, - pub sig: Signature, + pub sig: Option, pub attributes: Vec, } @@ -419,28 +419,3 @@ pub struct VariableRefData { pub scope: NodeId, pub ref_id: DefId, } - - -/// Encodes information about the signature of a definition. This should have -/// enough information to create a nice display about a definition without -/// access to the source code. -#[derive(Clone, Debug)] -pub struct Signature { - pub span: Span, - pub text: String, - // These identify the main identifier for the defintion as byte offsets into - // `text`. E.g., of `foo` in `pub fn foo(...)` - pub ident_start: usize, - pub ident_end: usize, - pub defs: Vec, - pub refs: Vec, -} - -/// An element of a signature. `start` and `end` are byte offsets into the `text` -/// of the parent `Signature`. -#[derive(Clone, Debug)] -pub struct SigElement { - pub id: DefId, - pub start: usize, - pub end: usize, -} diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index a95236e2a507..568670cbdb61 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -48,12 +48,13 @@ use syntax::ptr::P; use syntax::codemap::Spanned; use syntax_pos::*; -use super::{escape, generated_code, SaveContext, PathCollector, docs_for_attrs}; -use super::data::*; -use super::dump::Dump; -use super::external_data::{Lower, make_def_id}; -use super::span_utils::SpanUtils; -use super::recorder; +use {escape, generated_code, SaveContext, PathCollector, docs_for_attrs}; +use data::*; +use dump::Dump; +use external_data::{Lower, make_def_id}; +use recorder; +use span_utils::SpanUtils; +use sig; use rls_data::ExternalCrateData; @@ -646,7 +647,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { fields: fields, visibility: From::from(&item.vis), docs: docs_for_attrs(&item.attrs), - sig: self.save_ctxt.sig_base(item), + sig: sig::item_signature(item, &self.save_ctxt), attributes: item.attrs.clone(), }.lower(self.tcx)); } @@ -679,18 +680,6 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { qualname.push_str("::"); qualname.push_str(&name); - let text = self.span.signature_string_for_span(variant.span); - let ident_start = text.find(&name).unwrap(); - let ident_end = ident_start + name.len(); - let sig = Signature { - span: variant.span, - text: text, - ident_start: ident_start, - ident_end: ident_end, - defs: vec![], - refs: vec![], - }; - match variant.node.data { ast::VariantData::Struct(ref fields, _) => { let sub_span = self.span.span_for_first_ident(variant.span); @@ -712,7 +701,8 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { scope: enum_data.scope, parent: Some(make_def_id(item.id, &self.tcx.hir)), docs: docs_for_attrs(&variant.node.attrs), - sig: sig, + // TODO + sig: None, attributes: variant.node.attrs.clone(), }.lower(self.tcx)); } @@ -739,7 +729,8 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { scope: enum_data.scope, parent: Some(make_def_id(item.id, &self.tcx.hir)), docs: docs_for_attrs(&variant.node.attrs), - sig: sig, + // TODO + sig: None, attributes: variant.node.attrs.clone(), }.lower(self.tcx)); } @@ -811,7 +802,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { items: methods.iter().map(|i| i.id).collect(), visibility: From::from(&item.vis), docs: docs_for_attrs(&item.attrs), - sig: self.save_ctxt.sig_base(item), + sig: sig::item_signature(item, &self.save_ctxt), attributes: item.attrs.clone(), }.lower(self.tcx)); } @@ -1369,7 +1360,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, visibility: From::from(&item.vis), parent: None, docs: docs_for_attrs(&item.attrs), - sig: Some(self.save_ctxt.sig_base(item)), + sig: sig::item_signature(item, &self.save_ctxt), attributes: item.attrs.clone(), }.lower(self.tcx)); } diff --git a/src/librustc_save_analysis/external_data.rs b/src/librustc_save_analysis/external_data.rs index 02441a0587eb..245a3bcc6179 100644 --- a/src/librustc_save_analysis/external_data.rs +++ b/src/librustc_save_analysis/external_data.rs @@ -16,9 +16,9 @@ use syntax::codemap::CodeMap; use syntax::print::pprust; use syntax_pos::Span; -use data::{self, Visibility, SigElement}; +use data::{self, Visibility}; -use rls_data::{SpanData, CratePreludeData, Attribute}; +use rls_data::{SpanData, CratePreludeData, Attribute, Signature}; use rls_span::{Column, Row}; // FIXME: this should be pub(crate), but the current snapshot doesn't allow it yet @@ -103,7 +103,7 @@ pub struct EnumData { pub variants: Vec, pub visibility: Visibility, pub docs: String, - pub sig: Signature, + pub sig: Option, pub attributes: Vec, } @@ -121,7 +121,7 @@ impl Lower for data::EnumData { variants: self.variants.into_iter().map(|id| make_def_id(id, &tcx.hir)).collect(), visibility: self.visibility, docs: self.docs, - sig: self.sig.lower(tcx), + sig: self.sig, attributes: self.attributes.lower(tcx), } } @@ -186,7 +186,7 @@ pub struct FunctionData { pub visibility: Visibility, pub parent: Option, pub docs: String, - pub sig: Signature, + pub sig: Option, pub attributes: Vec, } @@ -205,7 +205,7 @@ impl Lower for data::FunctionData { visibility: self.visibility, parent: self.parent, docs: self.docs, - sig: self.sig.lower(tcx), + sig: self.sig, attributes: self.attributes.lower(tcx), } } @@ -355,7 +355,7 @@ pub struct MethodData { pub visibility: Visibility, pub parent: Option, pub docs: String, - pub sig: Signature, + pub sig: Option, pub attributes: Vec, } @@ -374,7 +374,7 @@ impl Lower for data::MethodData { visibility: self.visibility, parent: self.parent, docs: self.docs, - sig: self.sig.lower(tcx), + sig: self.sig, attributes: self.attributes.lower(tcx), } } @@ -410,7 +410,7 @@ impl Lower for data::ModData { items: self.items.into_iter().map(|id| make_def_id(id, &tcx.hir)).collect(), visibility: self.visibility, docs: self.docs, - sig: self.sig.map(|s| s.lower(tcx)), + sig: self.sig, attributes: self.attributes.lower(tcx), } } @@ -450,7 +450,7 @@ pub struct StructData { pub fields: Vec, pub visibility: Visibility, pub docs: String, - pub sig: Signature, + pub sig: Option, pub attributes: Vec, } @@ -469,7 +469,7 @@ impl Lower for data::StructData { fields: self.fields.into_iter().map(|id| make_def_id(id, &tcx.hir)).collect(), visibility: self.visibility, docs: self.docs, - sig: self.sig.lower(tcx), + sig: self.sig, attributes: self.attributes.lower(tcx), } } @@ -486,7 +486,7 @@ pub struct StructVariantData { pub scope: DefId, pub parent: Option, pub docs: String, - pub sig: Signature, + pub sig: Option, pub attributes: Vec, } @@ -504,7 +504,7 @@ impl Lower for data::StructVariantData { scope: make_def_id(self.scope, &tcx.hir), parent: self.parent, docs: self.docs, - sig: self.sig.lower(tcx), + sig: self.sig, attributes: self.attributes.lower(tcx), } } @@ -521,7 +521,7 @@ pub struct TraitData { pub items: Vec, pub visibility: Visibility, pub docs: String, - pub sig: Signature, + pub sig: Option, pub attributes: Vec, } @@ -539,7 +539,7 @@ impl Lower for data::TraitData { items: self.items.into_iter().map(|id| make_def_id(id, &tcx.hir)).collect(), visibility: self.visibility, docs: self.docs, - sig: self.sig.lower(tcx), + sig: self.sig, attributes: self.attributes.lower(tcx), } } @@ -556,7 +556,7 @@ pub struct TupleVariantData { pub scope: DefId, pub parent: Option, pub docs: String, - pub sig: Signature, + pub sig: Option, pub attributes: Vec, } @@ -574,7 +574,7 @@ impl Lower for data::TupleVariantData { scope: make_def_id(self.scope, &tcx.hir), parent: self.parent, docs: self.docs, - sig: self.sig.lower(tcx), + sig: self.sig, attributes: self.attributes.lower(tcx), } } @@ -608,7 +608,7 @@ impl Lower for data::TypeDefData { visibility: self.visibility, parent: self.parent, docs: self.docs, - sig: self.sig.map(|s| s.lower(tcx)), + sig: self.sig, attributes: self.attributes.lower(tcx), } } @@ -718,7 +718,7 @@ impl Lower for data::VariableData { parent: self.parent, visibility: self.visibility, docs: self.docs, - sig: self.sig.map(|s| s.lower(tcx)), + sig: self.sig, attributes: self.attributes.lower(tcx), } } @@ -746,30 +746,3 @@ impl Lower for data::VariableRefData { } } } - -#[derive(Clone, Debug)] -pub struct Signature { - pub span: SpanData, - pub text: String, - // These identify the main identifier for the defintion as byte offsets into - // `text`. E.g., of `foo` in `pub fn foo(...)` - pub ident_start: usize, - pub ident_end: usize, - pub defs: Vec, - pub refs: Vec, -} - -impl Lower for data::Signature { - type Target = Signature; - - fn lower(self, tcx: TyCtxt) -> Signature { - Signature { - span: span_from_span(self.span, tcx.sess.codemap()), - text: self.text, - ident_start: self.ident_start, - ident_end: self.ident_end, - defs: self.defs, - refs: self.refs, - } - } -} diff --git a/src/librustc_save_analysis/json_api_dumper.rs b/src/librustc_save_analysis/json_api_dumper.rs index 49b14f5eca07..1f65efbf9dcd 100644 --- a/src/librustc_save_analysis/json_api_dumper.rs +++ b/src/librustc_save_analysis/json_api_dumper.rs @@ -133,7 +133,7 @@ impl Into> for EnumData { children: self.variants.into_iter().map(|id| id_from_def_id(id)).collect(), decl_id: None, docs: self.docs, - sig: Some(self.sig.into()), + sig: self.sig, attributes: vec![], }), _ => None, @@ -154,7 +154,7 @@ impl Into> for TupleVariantData { children: vec![], decl_id: None, docs: self.docs, - sig: Some(self.sig.into()), + sig: self.sig, attributes: vec![], }) } @@ -172,7 +172,7 @@ impl Into> for StructVariantData { children: vec![], decl_id: None, docs: self.docs, - sig: Some(self.sig.into()), + sig: self.sig, attributes: vec![], }) } @@ -191,7 +191,7 @@ impl Into> for StructData { children: self.fields.into_iter().map(|id| id_from_def_id(id)).collect(), decl_id: None, docs: self.docs, - sig: Some(self.sig.into()), + sig: self.sig, attributes: vec![], }), _ => None, @@ -212,7 +212,7 @@ impl Into> for TraitData { parent: None, decl_id: None, docs: self.docs, - sig: Some(self.sig.into()), + sig: self.sig, attributes: vec![], }), _ => None, @@ -233,7 +233,7 @@ impl Into> for FunctionData { parent: self.parent.map(|id| id_from_def_id(id)), decl_id: None, docs: self.docs, - sig: Some(self.sig.into()), + sig: self.sig, attributes: vec![], }), _ => None, @@ -254,7 +254,7 @@ impl Into> for MethodData { parent: self.parent.map(|id| id_from_def_id(id)), decl_id: self.decl_id.map(|id| id_from_def_id(id)), docs: self.docs, - sig: Some(self.sig.into()), + sig: self.sig, attributes: vec![], }), _ => None, diff --git a/src/librustc_save_analysis/json_dumper.rs b/src/librustc_save_analysis/json_dumper.rs index a315cca9f4d8..2832eb505eca 100644 --- a/src/librustc_save_analysis/json_dumper.rs +++ b/src/librustc_save_analysis/json_dumper.rs @@ -14,12 +14,11 @@ use rustc::hir::def_id::DefId; use rustc_serialize::json::as_json; use rls_data::{self, Id, Analysis, Import, ImportKind, Def, DefKind, Ref, RefKind, MacroRef, - Relation, RelationKind, Signature, SigElement, CratePreludeData}; + Relation, RelationKind, CratePreludeData}; use rls_span::{Column, Row}; -use external_data; use external_data::*; -use data::{self, VariableKind}; +use data::VariableKind; use dump::Dump; pub struct JsonDumper { @@ -121,7 +120,7 @@ impl<'b, O: DumpOutput + 'b> Dump for JsonDumper { children: data.items.into_iter().map(|id| id_from_def_id(id)).collect(), decl_id: None, docs: data.docs, - sig: data.sig.map(|s| s.into()), + sig: data.sig, attributes: data.attributes.into_iter().map(|a| a.into()).collect(), }; if def.span.file_name.to_str().unwrap() != def.value { @@ -220,7 +219,7 @@ impl Into for EnumData { children: self.variants.into_iter().map(|id| id_from_def_id(id)).collect(), decl_id: None, docs: self.docs, - sig: Some(self.sig.into()), + sig: self.sig, attributes: self.attributes, } } @@ -239,7 +238,7 @@ impl Into for TupleVariantData { children: vec![], decl_id: None, docs: self.docs, - sig: Some(self.sig.into()), + sig: self.sig, attributes: self.attributes, } } @@ -257,7 +256,7 @@ impl Into for StructVariantData { children: vec![], decl_id: None, docs: self.docs, - sig: Some(self.sig.into()), + sig: self.sig, attributes: self.attributes, } } @@ -275,7 +274,7 @@ impl Into for StructData { children: self.fields.into_iter().map(|id| id_from_def_id(id)).collect(), decl_id: None, docs: self.docs, - sig: Some(self.sig.into()), + sig: self.sig, attributes: self.attributes, } } @@ -293,7 +292,7 @@ impl Into for TraitData { children: self.items.into_iter().map(|id| id_from_def_id(id)).collect(), decl_id: None, docs: self.docs, - sig: Some(self.sig.into()), + sig: self.sig, attributes: self.attributes, } } @@ -311,7 +310,7 @@ impl Into for FunctionData { children: vec![], decl_id: None, docs: self.docs, - sig: Some(self.sig.into()), + sig: self.sig, attributes: self.attributes, } } @@ -329,7 +328,7 @@ impl Into for MethodData { children: vec![], decl_id: self.decl_id.map(|id| id_from_def_id(id)), docs: self.docs, - sig: Some(self.sig.into()), + sig: self.sig, attributes: self.attributes, } } @@ -365,7 +364,7 @@ impl Into for TypeDefData { children: vec![], decl_id: None, docs: String::new(), - sig: self.sig.map(|s| s.into()), + sig: self.sig, attributes: self.attributes, } } @@ -480,23 +479,3 @@ impl Into for InheritanceData { } } } - -impl Into for external_data::Signature { - fn into(self) -> Signature { - Signature { - text: self.text, - defs: self.defs.into_iter().map(|s| s.into()).collect(), - refs: self.refs.into_iter().map(|s| s.into()).collect(), - } - } -} - -impl Into for data::SigElement { - fn into(self) -> SigElement { - SigElement { - id: id_from_def_id(self.id), - start: self.start, - end: self.end, - } - } -} diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 655901aa8591..06309a4f79e7 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -141,7 +141,8 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { visibility: From::from(&item.vis), parent: None, docs: docs_for_attrs(&item.attrs), - sig: self.sig_base_extern(item), + // TODO + sig: None, attributes: item.attrs.clone(), })) } @@ -161,7 +162,8 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { type_value: ty_to_string(ty), visibility: From::from(&item.vis), docs: docs_for_attrs(&item.attrs), - sig: Some(self.sig_base_extern(item)), + // TODO + sig: None, attributes: item.attrs.clone(), })) } @@ -187,7 +189,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { visibility: From::from(&item.vis), parent: None, docs: docs_for_attrs(&item.attrs), - sig: self.sig_base(item), + sig: sig::item_signature(item, self), attributes: item.attrs.clone(), })) } @@ -216,7 +218,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { type_value: ty_to_string(&typ), visibility: From::from(&item.vis), docs: docs_for_attrs(&item.attrs), - sig: Some(self.sig_base(item)), + sig: sig::item_signature(item, self), attributes: item.attrs.clone(), })) } @@ -236,7 +238,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { type_value: ty_to_string(&typ), visibility: From::from(&item.vis), docs: docs_for_attrs(&item.attrs), - sig: Some(self.sig_base(item)), + sig: sig::item_signature(item, self), attributes: item.attrs.clone(), })) } @@ -259,7 +261,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { items: m.items.iter().map(|i| i.id).collect(), visibility: From::from(&item.vis), docs: docs_for_attrs(&item.attrs), - sig: Some(self.sig_base(item)), + sig: sig::item_signature(item, self), attributes: item.attrs.clone(), })) } @@ -283,7 +285,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { variants: def.variants.iter().map(|v| v.node.data.id()).collect(), visibility: From::from(&item.vis), docs: docs_for_attrs(&item.attrs), - sig: self.sig_base(item), + sig: sig::item_signature(item, self), attributes: item.attrs.clone(), })) } @@ -347,18 +349,6 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { let def_id = self.tcx.hir.local_def_id(field.id); let typ = self.tcx.type_of(def_id).to_string(); - let span = field.span; - let text = self.span_utils.snippet(field.span); - let ident_start = text.find(&name).unwrap(); - let ident_end = ident_start + name.len(); - let sig = Signature { - span: span, - text: text, - ident_start: ident_start, - ident_end: ident_end, - defs: vec![], - refs: vec![], - }; Some(VariableData { id: field.id, kind: VariableKind::Field, @@ -371,7 +361,8 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { type_value: typ, visibility: From::from(&field.vis), docs: docs_for_attrs(&field.attrs), - sig: Some(sig), + // TODO + sig: None, attributes: field.attrs.clone(), }) } else { @@ -460,22 +451,9 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { let sub_span = self.span_utils.sub_span_after_keyword(span, keywords::Fn); filter!(self.span_utils, sub_span, span, None); - let name = name.to_string(); - let text = self.span_utils.signature_string_for_span(span); - let ident_start = text.find(&name).unwrap(); - let ident_end = ident_start + name.len(); - let sig = Signature { - span: span, - text: text, - ident_start: ident_start, - ident_end: ident_end, - defs: vec![], - refs: vec![], - }; - Some(FunctionData { id: id, - name: name, + name: name.to_string(), qualname: qualname, declaration: decl_id, span: sub_span.unwrap(), @@ -485,7 +463,8 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { visibility: vis, parent: parent_scope, docs: docs, - sig: sig, + // TODO + sig: None, attributes: attributes, }) } @@ -787,36 +766,6 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { } } - fn sig_base(&self, item: &ast::Item) -> Signature { - let text = self.span_utils.signature_string_for_span(item.span); - let name = item.ident.to_string(); - let ident_start = text.find(&name).expect("Name not in signature?"); - let ident_end = ident_start + name.len(); - Signature { - span: Span { hi: item.span.lo + BytePos(text.len() as u32), ..item.span }, - text: text, - ident_start: ident_start, - ident_end: ident_end, - defs: vec![], - refs: vec![], - } - } - - fn sig_base_extern(&self, item: &ast::ForeignItem) -> Signature { - let text = self.span_utils.signature_string_for_span(item.span); - let name = item.ident.to_string(); - let ident_start = text.find(&name).expect("Name not in signature?"); - let ident_end = ident_start + name.len(); - Signature { - span: Span { hi: item.span.lo + BytePos(text.len() as u32), ..item.span }, - text: text, - ident_start: ident_start, - ident_end: ident_end, - defs: vec![], - refs: vec![], - } - } - #[inline] pub fn enclosing_scope(&self, id: NodeId) -> NodeId { self.tcx.hir.get_enclosing_scope(id).unwrap_or(CRATE_NODE_ID) diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs index 945f405659d5..0dd0112a1b69 100644 --- a/src/librustc_save_analysis/sig.rs +++ b/src/librustc_save_analysis/sig.rs @@ -22,6 +22,10 @@ use syntax::ast::{self, NodeId}; use syntax::print::pprust; +pub fn item_signature(item: &ast::Item, scx: &SaveContext) -> Option { + item.make(0, None, scx).ok() +} + // TODO dup from json_dumper fn id_from_def_id(id: DefId) -> Id { Id { @@ -246,8 +250,8 @@ impl Sig for ast::Item { let name = self.ident.to_string(); let def = SigElement { id: id_from_node_id(self.id, scx), - start: offset + 5, - end: offset + 5 + name.len(), + start: offset + text.len(), + end: offset + text.len() + name.len(), }; text.push_str(&name); let generics: Signature = generics.make(offset + text.len(), id, scx)?; @@ -336,7 +340,6 @@ impl Sig for ast::Item { sig.text.push_str(" -> "); let nested = t.make(offset + sig.text.len(), None, scx)?; sig.text.push_str(&nested.text); - sig.text.push(','); sig.defs.extend(nested.defs.into_iter()); sig.refs.extend(nested.refs.into_iter()); } @@ -473,10 +476,23 @@ impl Sig for ast::Item { impl Sig for ast::Path { fn make(&self, offset: usize, id: Option, scx: &SaveContext) -> Result { + // if generated_code(span) { + // return Err("Generated code"); + // } + let def = scx.get_path_def(id.ok_or("Missing id for Path")?); - let id = id_from_def_id(def.def_id()); let (name, start, end) = match def { + Def::Label(..) | + Def::PrimTy(..) | + Def::SelfTy(..) | + Def::Err => { + return Ok(Signature { + text: pprust::path_to_string(self), + defs: vec![], + refs: vec![], + }) + } Def::AssociatedConst(..) | Def::Variant(..) | Def::VariantCtor(..) => { @@ -499,6 +515,7 @@ impl Sig for ast::Path { } }; + let id = id_from_def_id(def.def_id()); Ok(Signature { text: name, defs: vec![], @@ -557,4 +574,4 @@ impl Sig for ast::Generics { } } -// TODO impl items, trait items +// TODO impl items, trait items, fields, extern items, enum variant From 35abf139a2e43b8695d907ab62bc2bb46bc8bcc3 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 31 May 2017 16:13:27 +1200 Subject: [PATCH 131/233] Small refactoring + docs --- src/librustc_save_analysis/json_api_dumper.rs | 2 +- src/librustc_save_analysis/json_dumper.rs | 11 +---- src/librustc_save_analysis/lib.rs | 16 ++++++- src/librustc_save_analysis/sig.rs | 47 +++++++++++-------- 4 files changed, 45 insertions(+), 31 deletions(-) diff --git a/src/librustc_save_analysis/json_api_dumper.rs b/src/librustc_save_analysis/json_api_dumper.rs index 1f65efbf9dcd..5c6876461346 100644 --- a/src/librustc_save_analysis/json_api_dumper.rs +++ b/src/librustc_save_analysis/json_api_dumper.rs @@ -15,7 +15,7 @@ use rustc_serialize::json::as_json; use external_data::*; use data::{VariableKind, Visibility}; use dump::Dump; -use json_dumper::id_from_def_id; +use id_from_def_id; use rls_data::{Analysis, Import, ImportKind, Def, DefKind, CratePreludeData}; diff --git a/src/librustc_save_analysis/json_dumper.rs b/src/librustc_save_analysis/json_dumper.rs index 2832eb505eca..58df612c687c 100644 --- a/src/librustc_save_analysis/json_dumper.rs +++ b/src/librustc_save_analysis/json_dumper.rs @@ -10,7 +10,6 @@ use std::io::Write; -use rustc::hir::def_id::DefId; use rustc_serialize::json::as_json; use rls_data::{self, Id, Analysis, Import, ImportKind, Def, DefKind, Ref, RefKind, MacroRef, @@ -20,6 +19,7 @@ use rls_span::{Column, Row}; use external_data::*; use data::VariableKind; use dump::Dump; +use id_from_def_id; pub struct JsonDumper { result: Analysis, @@ -163,15 +163,6 @@ impl<'b, O: DumpOutput + 'b> Dump for JsonDumper { // method, but not the supplied method). In both cases, we are currently // ignoring it. -// DefId::index is a newtype and so the JSON serialisation is ugly. Therefore -// we use our own Id which is the same, but without the newtype. -pub fn id_from_def_id(id: DefId) -> Id { - Id { - krate: id.krate.as_u32(), - index: id.index.as_u32(), - } -} - impl Into for ExternCrateData { fn into(self) -> Import { Import { diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 06309a4f79e7..b6fafe3ee52b 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -1026,6 +1026,20 @@ fn escape(s: String) -> String { // Helper function to determine if a span came from a // macro expansion or syntax extension. -pub fn generated_code(span: Span) -> bool { +fn generated_code(span: Span) -> bool { span.ctxt != NO_EXPANSION || span == DUMMY_SP } + +// DefId::index is a newtype and so the JSON serialisation is ugly. Therefore +// we use our own Id which is the same, but without the newtype. +fn id_from_def_id(id: DefId) -> rls_data::Id { + rls_data::Id { + krate: id.krate.as_u32(), + index: id.index.as_u32(), + } +} + +fn id_from_node_id(id: NodeId, scx: &SaveContext) -> rls_data::Id { + let def_id = scx.tcx.hir.local_def_id(id); + id_from_def_id(def_id) +} diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs index 0dd0112a1b69..6b734eb52480 100644 --- a/src/librustc_save_analysis/sig.rs +++ b/src/librustc_save_analysis/sig.rs @@ -8,16 +8,38 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// FIXME? None of these include visibility info. -// Large outstanding things - where clauses, defs/refs for generics -// paresable - each sig ends with `;` of ` {}` +// A signature is a string representation of an item's type signature, excluding +// any body. It also includes ids for any defs or refs in the signature. For +// example: +// +// ``` +// fn foo(x: String) { +// println!("{}", x); +// } +// ``` +// The signature string is something like "fn foo(x: String) {}" and the signature +// will have defs for `foo` and `x` and a ref for `String`. +// +// All signature text should parse in the correct context (i.e., in a module or +// impl, etc.). Clients may want to trim trailing `{}` or `;`. The text of a +// signature is not guaranteed to be stable (it may improve or change as the +// syntax changes, or whitespace or punctuation may change). It is also likely +// not to be pretty - no attempt is made to prettify the text. It is recommended +// that clients run the text through Rustfmt. +// +// This module generates Signatures for items by walking the AST and looking up +// references. +// +// Signatures do not include visibility info. I'm not sure if this is a feature +// or an ommission (FIXME). +// +// FIXME where clauses need implementing, defs/refs in generics are mostly missing. -use SaveContext; +use {SaveContext, id_from_def_id, id_from_node_id}; -use rls_data::{Signature, SigElement, Id}; +use rls_data::{Signature, SigElement}; use rustc::hir::def::Def; -use rustc::hir::def_id::DefId; use syntax::ast::{self, NodeId}; use syntax::print::pprust; @@ -26,19 +48,6 @@ pub fn item_signature(item: &ast::Item, scx: &SaveContext) -> Option item.make(0, None, scx).ok() } -// TODO dup from json_dumper -fn id_from_def_id(id: DefId) -> Id { - Id { - krate: id.krate.as_u32(), - index: id.index.as_u32(), - } -} - -fn id_from_node_id(id: NodeId, scx: &SaveContext) -> Id { - let def_id = scx.tcx.hir.local_def_id(id); - id_from_def_id(def_id) -} - type Result = ::std::result::Result; trait Sig { From 5ebb0e2498edc84093003d8053a7d11e51536120 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 5 Jun 2017 16:42:39 +1200 Subject: [PATCH 132/233] Implement a bunch more signature functions --- src/librustc_save_analysis/dump_visitor.rs | 6 +- src/librustc_save_analysis/lib.rs | 9 +- src/librustc_save_analysis/sig.rs | 251 +++++++++++++++++++-- 3 files changed, 231 insertions(+), 35 deletions(-) diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 568670cbdb61..61fc9a9adfb0 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -701,8 +701,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { scope: enum_data.scope, parent: Some(make_def_id(item.id, &self.tcx.hir)), docs: docs_for_attrs(&variant.node.attrs), - // TODO - sig: None, + sig: sig::variant_signature(variant, &self.save_ctxt), attributes: variant.node.attrs.clone(), }.lower(self.tcx)); } @@ -729,8 +728,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { scope: enum_data.scope, parent: Some(make_def_id(item.id, &self.tcx.hir)), docs: docs_for_attrs(&variant.node.attrs), - // TODO - sig: None, + sig: sig::variant_signature(variant, &self.save_ctxt), attributes: variant.node.attrs.clone(), }.lower(self.tcx)); } diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index b6fafe3ee52b..8e280377ce2d 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -141,8 +141,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { visibility: From::from(&item.vis), parent: None, docs: docs_for_attrs(&item.attrs), - // TODO - sig: None, + sig: sig::foreign_item_signature(item, self), attributes: item.attrs.clone(), })) } @@ -162,8 +161,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { type_value: ty_to_string(ty), visibility: From::from(&item.vis), docs: docs_for_attrs(&item.attrs), - // TODO - sig: None, + sig: sig::foreign_item_signature(item, self), attributes: item.attrs.clone(), })) } @@ -361,8 +359,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { type_value: typ, visibility: From::from(&field.vis), docs: docs_for_attrs(&field.attrs), - // TODO - sig: None, + sig: sig::field_signature(field, self), attributes: field.attrs.clone(), }) } else { diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs index 6b734eb52480..b2a62038dfc1 100644 --- a/src/librustc_save_analysis/sig.rs +++ b/src/librustc_save_analysis/sig.rs @@ -48,6 +48,21 @@ pub fn item_signature(item: &ast::Item, scx: &SaveContext) -> Option item.make(0, None, scx).ok() } +pub fn foreign_item_signature(item: &ast::ForeignItem, scx: &SaveContext) -> Option { + item.make(0, None, scx).ok() +} + +/// Signature for a struct or tuple field declaration. +/// Does not include a trailing comma. +pub fn field_signature(field: &ast::StructField, scx: &SaveContext) -> Option { + field.make(0, None, scx).ok() +} + +/// Does not include a trailing comma. +pub fn variant_signature(variant: &ast::Variant, scx: &SaveContext) -> Option { + variant.node.make(0, None, scx).ok() +} + type Result = ::std::result::Result; trait Sig { @@ -255,20 +270,6 @@ impl Sig for ast::Item { fn make(&self, offset: usize, _parent_id: Option, scx: &SaveContext) -> Result { let id = Some(self.id); - let name_and_generics = |mut text: String, generics: &ast::Generics| -> Result { - let name = self.ident.to_string(); - let def = SigElement { - id: id_from_node_id(self.id, scx), - start: offset + text.len(), - end: offset + text.len() + name.len(), - }; - text.push_str(&name); - let generics: Signature = generics.make(offset + text.len(), id, scx)?; - // FIXME where clause - let text = format!("{}{}", text, generics.text); - Ok(extend_sig(generics, text, vec![def], vec![])) - }; - match self.node { ast::ItemKind::Static(ref ty, m, ref expr) => { let mut text = "static ".to_owned(); @@ -330,7 +331,12 @@ impl Sig for ast::Item { } text.push_str("fn "); - let mut sig = name_and_generics(text, generics)?; + let mut sig = name_and_generics(text, + offset, + generics, + self.id, + self.ident, + scx)?; sig.text.push('('); for i in &decl.inputs { @@ -352,6 +358,7 @@ impl Sig for ast::Item { sig.defs.extend(nested.defs.into_iter()); sig.refs.extend(nested.refs.into_iter()); } + sig.text.push_str(" {}"); Ok(sig) } @@ -375,7 +382,12 @@ impl Sig for ast::Item { } ast::ItemKind::Ty(ref ty, ref generics) => { let text = "type ".to_owned(); - let mut sig = name_and_generics(text, generics)?; + let mut sig = name_and_generics(text, + offset, + generics, + self.id, + self.ident, + scx)?; sig.text.push_str(" = "); let ty = ty.make(offset + sig.text.len(), id, scx)?; @@ -386,19 +398,34 @@ impl Sig for ast::Item { } ast::ItemKind::Enum(_, ref generics) => { let text = "enum ".to_owned(); - let mut sig = name_and_generics(text, generics)?; + let mut sig = name_and_generics(text, + offset, + generics, + self.id, + self.ident, + scx)?; sig.text.push_str(" {}"); Ok(sig) } ast::ItemKind::Struct(_, ref generics) => { let text = "struct ".to_owned(); - let mut sig = name_and_generics(text, generics)?; + let mut sig = name_and_generics(text, + offset, + generics, + self.id, + self.ident, + scx)?; sig.text.push_str(" {}"); Ok(sig) } ast::ItemKind::Union(_, ref generics) => { let text = "union ".to_owned(); - let mut sig = name_and_generics(text, generics)?; + let mut sig = name_and_generics(text, + offset, + generics, + self.id, + self.ident, + scx)?; sig.text.push_str(" {}"); Ok(sig) } @@ -408,7 +435,12 @@ impl Sig for ast::Item { text.push_str("unsafe "); } text.push_str("trait "); - let mut sig = name_and_generics(text, generics)?; + let mut sig = name_and_generics(text, + offset, + generics, + self.id, + self.ident, + scx)?; if !bounds.is_empty() { sig.text.push_str(": "); @@ -485,10 +517,6 @@ impl Sig for ast::Item { impl Sig for ast::Path { fn make(&self, offset: usize, id: Option, scx: &SaveContext) -> Result { - // if generated_code(span) { - // return Err("Generated code"); - // } - let def = scx.get_path_def(id.ok_or("Missing id for Path")?); let (name, start, end) = match def { @@ -583,4 +611,177 @@ impl Sig for ast::Generics { } } -// TODO impl items, trait items, fields, extern items, enum variant +impl Sig for ast::StructField { + fn make(&self, offset: usize, _parent_id: Option, scx: &SaveContext) -> Result { + let mut text = String::new(); + let mut defs = None; + if let Some(ref ident) = self.ident { + text.push_str(&ident.to_string()); + defs = Some(SigElement { + id: id_from_node_id(self.id, scx), + start: offset, + end: offset + text.len(), + }); + text.push_str(": "); + } + + let mut ty_sig = self.ty.make(offset + text.len(), Some(self.id), scx)?; + text.push_str(&ty_sig.text); + ty_sig.text = text; + ty_sig.defs.extend(defs.into_iter()); + Ok(ty_sig) + } +} + + +impl Sig for ast::Variant_ { + fn make(&self, offset: usize, _parent_id: Option, scx: &SaveContext) -> Result { + let mut text = self.name.to_string(); + match self.data { + ast::VariantData::Struct(ref fields, id) => { + let name_def = SigElement { + id: id_from_node_id(id, scx), + start: offset, + end: offset + text.len(), + }; + text.push_str(" { "); + let mut defs = vec![name_def]; + let mut refs = vec![]; + for f in fields { + let field_sig = f.make(offset + text.len(), Some(id), scx)?; + text.push_str(&field_sig.text); + text.push_str(", "); + defs.extend(field_sig.defs.into_iter()); + refs.extend(field_sig.refs.into_iter()); + } + text.push('}'); + Ok(Signature { + text, + defs: defs, + refs: refs, + }) + } + ast::VariantData::Tuple(ref fields, id) => { + let name_def = SigElement { + id: id_from_node_id(id, scx), + start: offset, + end: offset + text.len(), + }; + text.push('('); + let mut defs = vec![name_def]; + let mut refs = vec![]; + for f in fields { + let field_sig = f.make(offset + text.len(), Some(id), scx)?; + text.push_str(&field_sig.text); + text.push_str(", "); + defs.extend(field_sig.defs.into_iter()); + refs.extend(field_sig.refs.into_iter()); + } + text.push(')'); + Ok(Signature { + text, + defs: defs, + refs: refs, + }) + } + ast::VariantData::Unit(id) => { + let name_def = SigElement { + id: id_from_node_id(id, scx), + start: offset, + end: offset + text.len(), + }; + Ok(Signature { + text, + defs: vec![name_def], + refs: vec![], + }) + } + } + } +} + +impl Sig for ast::ForeignItem { + fn make(&self, offset: usize, _parent_id: Option, scx: &SaveContext) -> Result { + let id = Some(self.id); + match self.node { + ast::ForeignItemKind::Fn(ref decl, ref generics) => { + let mut text = String::new(); + text.push_str("fn "); + + let mut sig = name_and_generics(text, + offset, + generics, + self.id, + self.ident, + scx)?; + + sig.text.push('('); + for i in &decl.inputs { + // FIXME should descend into patterns to add defs. + sig.text.push_str(&pprust::pat_to_string(&i.pat)); + sig.text.push_str(": "); + let nested = i.ty.make(offset + sig.text.len(), Some(i.id), scx)?; + sig.text.push_str(&nested.text); + sig.text.push(','); + sig.defs.extend(nested.defs.into_iter()); + sig.refs.extend(nested.refs.into_iter()); + } + sig.text.push(')'); + + if let ast::FunctionRetTy::Ty(ref t) = decl.output { + sig.text.push_str(" -> "); + let nested = t.make(offset + sig.text.len(), None, scx)?; + sig.text.push_str(&nested.text); + sig.defs.extend(nested.defs.into_iter()); + sig.refs.extend(nested.refs.into_iter()); + } + sig.text.push(';'); + + Ok(sig) + } + ast::ForeignItemKind::Static(ref ty, m) => { + let mut text = "static ".to_owned(); + if m { + text.push_str("mut "); + } + let name = self.ident.to_string(); + let defs = vec![SigElement { + id: id_from_node_id(self.id, scx), + start: offset + text.len(), + end: offset + text.len() + name.len(), + }]; + text.push_str(&name); + text.push_str(": "); + + let ty_sig = ty.make(offset + text.len(), id, scx)?; + text.push(';'); + + Ok(extend_sig(ty_sig, text, defs, vec![])) + } + } + } +} + +fn name_and_generics(mut text: String, + offset: usize, + generics: &ast::Generics, + id: NodeId, + name: ast::Ident, + scx: &SaveContext) + -> Result { + let name = name.to_string(); + let def = SigElement { + id: id_from_node_id(id, scx), + start: offset + text.len(), + end: offset + text.len() + name.len(), + }; + text.push_str(&name); + let generics: Signature = generics.make(offset + text.len(), Some(id), scx)?; + // FIXME where clause + let text = format!("{}{}", text, generics.text); + Ok(extend_sig(generics, text, vec![def], vec![])) +} + + +// TODO impl items, trait items +// for impl/trait sigs - function for each kind, rather than use trait. From cb7fcdd520d8297bbb2bea6e0a017d1b5df0b819 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 6 Jun 2017 12:19:54 +1200 Subject: [PATCH 133/233] Impl and trait item sigs --- src/librustc_save_analysis/dump_visitor.rs | 45 +++--- src/librustc_save_analysis/lib.rs | 8 +- src/librustc_save_analysis/sig.rs | 152 ++++++++++++++++++++- 3 files changed, 178 insertions(+), 27 deletions(-) diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 61fc9a9adfb0..ea346d99e31b 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -392,13 +392,13 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { sig: &'l ast::MethodSig, body: Option<&'l ast::Block>, id: ast::NodeId, - name: ast::Name, + name: ast::Ident, vis: Visibility, attrs: &'l [Attribute], span: Span) { debug!("process_method: {}:{}", id, name); - if let Some(method_data) = self.save_ctxt.get_method_data(id, name, span) { + if let Some(method_data) = self.save_ctxt.get_method_data(id, name.name, span) { let sig_str = ::make_signature(&sig.decl, &sig.generics); if body.is_some() { @@ -424,7 +424,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { Some(id) => { for item in self.tcx.associated_items(id) { if item.kind == ty::AssociatedKind::Method { - if item.name == name { + if item.name == name.name { decl_id = Some(item.def_id); break; } @@ -456,7 +456,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { parent: trait_id, visibility: vis, docs: docs_for_attrs(attrs), - sig: method_data.sig, + sig: sig::method_signature(id, name, sig, &self.save_ctxt), attributes: attrs.to_vec(), }.lower(self.tcx)); } @@ -581,13 +581,14 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { name: ast::Name, span: Span, typ: &'l ast::Ty, - expr: &'l ast::Expr, + expr: Option<&'l ast::Expr>, parent_id: DefId, vis: Visibility, attrs: &'l [Attribute]) { let qualname = format!("::{}", self.tcx.node_path_str(id)); let sub_span = self.span.sub_span_after_keyword(span, keywords::Const); + let value = expr.map(|e| self.span.snippet(e.span)).unwrap_or(String::new()); if !self.span.filter_generated(sub_span, span) { self.dumper.variable(VariableData { @@ -596,20 +597,22 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { id: id, name: name.to_string(), qualname: qualname, - value: self.span.snippet(expr.span), + value: value, type_value: ty_to_string(&typ), scope: self.cur_scope, parent: Some(parent_id), visibility: vis, docs: docs_for_attrs(attrs), - sig: None, + sig: sig::assoc_const_signature(id, name, typ, expr, &self.save_ctxt), attributes: attrs.to_vec(), }.lower(self.tcx)); } // walk type and init value self.visit_ty(typ); - self.visit_expr(expr); + if let Some(expr) = expr { + self.visit_expr(expr); + } } // FIXME tuple structs should generate tuple-specific data. @@ -1122,12 +1125,12 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { fn process_trait_item(&mut self, trait_item: &'l ast::TraitItem, trait_id: DefId) { self.process_macro_use(trait_item.span, trait_item.id); match trait_item.node { - ast::TraitItemKind::Const(ref ty, Some(ref expr)) => { + ast::TraitItemKind::Const(ref ty, ref expr) => { self.process_assoc_const(trait_item.id, trait_item.ident.name, trait_item.span, &ty, - &expr, + expr.as_ref().map(|e| &**e), trait_id, Visibility::Public, &trait_item.attrs); @@ -1136,12 +1139,12 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { self.process_method(sig, body.as_ref().map(|x| &**x), trait_item.id, - trait_item.ident.name, + trait_item.ident, Visibility::Public, &trait_item.attrs, trait_item.span); } - ast::TraitItemKind::Type(ref _bounds, ref default_ty) => { + ast::TraitItemKind::Type(ref bounds, ref default_ty) => { // FIXME do something with _bounds (for type refs) let name = trait_item.ident.name.to_string(); let qualname = format!("::{}", self.tcx.node_path_str(trait_item.id)); @@ -1157,7 +1160,11 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { visibility: Visibility::Public, parent: Some(trait_id), docs: docs_for_attrs(&trait_item.attrs), - sig: None, + sig: sig::assoc_type_signature(trait_item.id, + trait_item.ident, + Some(bounds), + default_ty.as_ref().map(|ty| &**ty), + &self.save_ctxt), attributes: trait_item.attrs.clone(), }.lower(self.tcx)); } @@ -1166,7 +1173,6 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { self.visit_ty(default_ty) } } - ast::TraitItemKind::Const(ref ty, None) => self.visit_ty(ty), ast::TraitItemKind::Macro(_) => {} } } @@ -1179,7 +1185,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { impl_item.ident.name, impl_item.span, &ty, - &expr, + Some(expr), impl_id, From::from(&impl_item.vis), &impl_item.attrs); @@ -1188,12 +1194,17 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { self.process_method(sig, Some(body), impl_item.id, - impl_item.ident.name, + impl_item.ident, From::from(&impl_item.vis), &impl_item.attrs, impl_item.span); } - ast::ImplItemKind::Type(ref ty) => self.visit_ty(ty), + ast::ImplItemKind::Type(ref ty) => { + // FIXME uses of the assoc type should ideally point to this + // 'def' and the name here should be a ref to the def in the + // trait. + self.visit_ty(ty) + } ast::ImplItemKind::Macro(_) => {} } } diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 8e280377ce2d..4802494f08ea 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -369,8 +369,11 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { // FIXME would be nice to take a MethodItem here, but the ast provides both // trait and impl flavours, so the caller must do the disassembly. - pub fn get_method_data(&self, id: ast::NodeId, - name: ast::Name, span: Span) -> Option { + pub fn get_method_data(&self, + id: ast::NodeId, + name: ast::Name, + span: Span) + -> Option { // The qualname for a method is the trait name or name of the struct in an impl in // which the method is declared in, followed by the method's name. let (qualname, parent_scope, decl_id, vis, docs, attributes) = @@ -460,7 +463,6 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { visibility: vis, parent: parent_scope, docs: docs, - // TODO sig: None, attributes: attributes, }) diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs index b2a62038dfc1..1d03ab1383af 100644 --- a/src/librustc_save_analysis/sig.rs +++ b/src/librustc_save_analysis/sig.rs @@ -14,7 +14,7 @@ // // ``` // fn foo(x: String) { -// println!("{}", x); +// println!("{}", x); // } // ``` // The signature string is something like "fn foo(x: String) {}" and the signature @@ -63,6 +63,32 @@ pub fn variant_signature(variant: &ast::Variant, scx: &SaveContext) -> Option Option { + make_method_signature(id, ident, m, scx).ok() +} + +pub fn assoc_const_signature(id: NodeId, + ident: ast::Name, + ty: &ast::Ty, + default: Option<&ast::Expr>, + scx: &SaveContext) + -> Option { + make_assoc_const_signature(id, ident, ty, default, scx).ok() +} + +pub fn assoc_type_signature(id: NodeId, + ident: ast::Ident, + bounds: Option<&ast::TyParamBounds>, + default: Option<&ast::Ty>, + scx: &SaveContext) + -> Option { + make_assoc_type_signature(id, ident, bounds, default, scx).ok() +} + type Result = ::std::result::Result; trait Sig { @@ -215,7 +241,7 @@ impl Sig for ast::Ty { format!("<{} as {}>::", nested_ty.text, first) } else { // FIXME handle path instead of elipses. - format!("<{} as ...>::", nested_ty.text) + format!("<{} as ...>::", nested_ty.text) }; let name = pprust::path_segment_to_string(path.segments.last().ok_or("Bad path")?); @@ -263,7 +289,7 @@ impl Sig for ast::Ty { ast::TyKind::ImplicitSelf | ast::TyKind::Mac(_) => Err("Ty"), } - } + } } impl Sig for ast::Item { @@ -497,7 +523,7 @@ impl Sig for ast::Item { let ty_sig = ty.make(offset + text.len(), id, scx)?; text.push_str(&ty_sig.text); - + text.push_str(" {}"); Ok(merge_sigs(text, vec![generics_sig, trait_sig, ty_sig])) @@ -582,7 +608,9 @@ impl Sig for ast::Generics { if !l.bounds.is_empty() { l_text.push_str(": "); - let bounds = l.bounds.iter().map(|l| l.ident.to_string()).collect::>().join(" + "); + let bounds = l.bounds.iter().map(|l| { + l.ident.to_string() + }).collect::>().join(" + "); l_text.push_str(&bounds); // FIXME add lifetime bounds refs. } @@ -783,5 +811,115 @@ fn name_and_generics(mut text: String, } -// TODO impl items, trait items -// for impl/trait sigs - function for each kind, rather than use trait. +fn make_assoc_type_signature(id: NodeId, + ident: ast::Ident, + bounds: Option<&ast::TyParamBounds>, + default: Option<&ast::Ty>, + scx: &SaveContext) + -> Result { + let mut text = "type ".to_owned(); + let name = ident.to_string(); + let mut defs = vec![SigElement { + id: id_from_node_id(id, scx), + start: text.len(), + end: text.len() + name.len(), + }]; + let mut refs = vec![]; + text.push_str(&name); + if let Some(bounds) = bounds { + text.push_str(": "); + // FIXME should descend into bounds + text.push_str(&pprust::bounds_to_string(bounds)); + } + if let Some(default) = default { + text.push_str(" = "); + let ty_sig = default.make(text.len(), Some(id), scx)?; + text.push_str(&ty_sig.text); + defs.extend(ty_sig.defs.into_iter()); + refs.extend(ty_sig.refs.into_iter()); + } + text.push(';'); + Ok(Signature { text, defs, refs }) +} + +fn make_assoc_const_signature(id: NodeId, + ident: ast::Name, + ty: &ast::Ty, + default: Option<&ast::Expr>, + scx: &SaveContext) + -> Result { + let mut text = "const ".to_owned(); + let name = ident.to_string(); + let mut defs = vec![SigElement { + id: id_from_node_id(id, scx), + start: text.len(), + end: text.len() + name.len(), + }]; + let mut refs = vec![]; + text.push_str(&name); + text.push_str(": "); + + let ty_sig = ty.make(text.len(), Some(id), scx)?; + text.push_str(&ty_sig.text); + defs.extend(ty_sig.defs.into_iter()); + refs.extend(ty_sig.refs.into_iter()); + + if let Some(default) = default { + text.push_str(" = "); + text.push_str(&pprust::expr_to_string(default)); + } + text.push(';'); + Ok(Signature { text, defs, refs }) +} + +fn make_method_signature(id: NodeId, + ident: ast::Ident, + m: &ast::MethodSig, + scx: &SaveContext) + -> Result { + // FIXME code dup with function signature + let mut text = String::new(); + if m.constness.node == ast::Constness::Const { + text.push_str("const "); + } + if m.unsafety == ast::Unsafety::Unsafe { + text.push_str("unsafe "); + } + if m.abi != ::syntax::abi::Abi::Rust { + text.push_str("extern"); + text.push_str(&m.abi.to_string()); + text.push(' '); + } + text.push_str("fn "); + + let mut sig = name_and_generics(text, + 0, + &m.generics, + id, + ident, + scx)?; + + sig.text.push('('); + for i in &m.decl.inputs { + // FIXME shoudl descend into patterns to add defs. + sig.text.push_str(&pprust::pat_to_string(&i.pat)); + sig.text.push_str(": "); + let nested = i.ty.make(sig.text.len(), Some(i.id), scx)?; + sig.text.push_str(&nested.text); + sig.text.push(','); + sig.defs.extend(nested.defs.into_iter()); + sig.refs.extend(nested.refs.into_iter()); + } + sig.text.push(')'); + + if let ast::FunctionRetTy::Ty(ref t) = m.decl.output { + sig.text.push_str(" -> "); + let nested = t.make(sig.text.len(), None, scx)?; + sig.text.push_str(&nested.text); + sig.defs.extend(nested.defs.into_iter()); + sig.refs.extend(nested.refs.into_iter()); + } + sig.text.push_str(" {}"); + + Ok(sig) +} From d438b8180c52b2cb85c2f4f29ee09c88e5eba0da Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 6 Jun 2017 16:12:11 +1200 Subject: [PATCH 134/233] Fix a bug where Json API save-analysis was not labelled as such --- src/librustc_save_analysis/json_api_dumper.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/librustc_save_analysis/json_api_dumper.rs b/src/librustc_save_analysis/json_api_dumper.rs index 5c6876461346..bddee6460ff9 100644 --- a/src/librustc_save_analysis/json_api_dumper.rs +++ b/src/librustc_save_analysis/json_api_dumper.rs @@ -17,7 +17,7 @@ use data::{VariableKind, Visibility}; use dump::Dump; use id_from_def_id; -use rls_data::{Analysis, Import, ImportKind, Def, DefKind, CratePreludeData}; +use rls_data::{Analysis, Import, ImportKind, Def, DefKind, CratePreludeData, Format}; // A dumper to dump a restricted set of JSON information, designed for use with @@ -33,7 +33,9 @@ pub struct JsonApiDumper<'b, W: Write + 'b> { impl<'b, W: Write> JsonApiDumper<'b, W> { pub fn new(writer: &'b mut W) -> JsonApiDumper<'b, W> { - JsonApiDumper { output: writer, result: Analysis::new() } + let mut result = Analysis::new(); + result.kind = Format::JsonApi; + JsonApiDumper { output: writer, result } } } From 34bd80a782ffc75a61a31794fa1fb8b7c48eb765 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 12 Jun 2017 14:29:59 +1200 Subject: [PATCH 135/233] Fix rebasing error --- src/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 7718dff3b837..efbbe36c981a 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -1040,7 +1040,7 @@ dependencies = [ [[package]] name = "rls-data" -version = "0.3.1" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2076,7 +2076,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957" "checksum regex-syntax 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9191b1f57603095f105d317e375d19b1c9c5c3185ea9633a99a6dcbed04457" "checksum rls-analysis 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8d77d58e8933752142b5b92e3f8ba6d6f1630be6da5627c492268a43f79ffbda" -"checksum rls-data 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fc4277ce3c57f456b11fe3145b181a844a25201bab5cbaa1978457e6e2f27d47" +"checksum rls-data 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "374a8fad31cc0681a7bfd8a04079dd4afd0e981d34e18a171b1a467445bdf51e" "checksum rls-data 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9e2087477364c34faca86c2476765deb1185dbae3c598cfb1eb040f3a74d22b5" "checksum rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d7c7046dc6a92f2ae02ed302746db4382e75131b9ce20ce967259f6b5867a6a" "checksum rls-vfs 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ace07060dd154731b39254864245cbdd33c8f5f64fe1f630a089c72e2468f854" From 0389d40ce0a891bc7d37ca15c12e23df79d71524 Mon Sep 17 00:00:00 2001 From: Mark Buer Date: Mon, 12 Jun 2017 13:33:25 +0930 Subject: [PATCH 136/233] Capture elapsed duration in Thread::park_timeout example --- src/libstd/thread/mod.rs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 64c31c2a681c..dda11e50380f 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -787,12 +787,16 @@ pub fn park_timeout_ms(ms: u32) { /// /// let timeout = Duration::from_secs(2); /// let beginning_park = Instant::now(); -/// park_timeout(timeout); /// -/// while beginning_park.elapsed() < timeout { -/// println!("restarting park_timeout after {:?}", beginning_park.elapsed()); -/// let timeout = timeout - beginning_park.elapsed(); -/// park_timeout(timeout); +/// let mut timeout_remaining = timeout; +/// loop { +/// park_timeout(timeout_remaining); +/// let elapsed = beginning_park.elapsed(); +/// if elapsed >= timeout { +/// break; +/// } +/// println!("restarting park_timeout after {:?}", elapsed); +/// timeout_remaining = timeout - elapsed; /// } /// ``` /// From 3a7dbf48feb325bbe8517bc0fd7546e80931c8ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 11 Jun 2017 23:47:26 -0700 Subject: [PATCH 137/233] Suggest non-ambiguous comparison after cast ``` warning: `<` is interpreted as a start of generic arguments for `usize`, not comparison --> $DIR/issue-22644.rs:16:33 | 16 | println!("{}", a as usize < b); | ^ expected one of `!`, `(`, `+`, `,`, `::`, or `>` here | help: if you want to compare the casted value then write | println!("{}", (a as usize) < b); ``` --- src/librustc_errors/diagnostic.rs | 4 ++++ src/libsyntax/parse/parser.rs | 21 +++++++++++++++++++-- src/test/{run-pass => ui}/issue-22644.rs | 0 src/test/ui/issue-22644.stderr | 20 ++++++++++++++++++++ 4 files changed, 43 insertions(+), 2 deletions(-) rename src/test/{run-pass => ui}/issue-22644.rs (100%) create mode 100644 src/test/ui/issue-22644.stderr diff --git a/src/librustc_errors/diagnostic.rs b/src/librustc_errors/diagnostic.rs index 7a64cdeee65c..d7c21127474a 100644 --- a/src/librustc_errors/diagnostic.rs +++ b/src/librustc_errors/diagnostic.rs @@ -248,6 +248,10 @@ impl Diagnostic { self.message.iter().map(|i| i.0.to_owned()).collect::() } + pub fn set_message(&mut self, message: &str) { + self.message = vec![(message.to_owned(), Style::NoStyle)]; + } + pub fn styled_message(&self) -> &Vec<(String, Style)> { &self.message } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index a6ecd304dbd1..76b14071ec32 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -42,7 +42,7 @@ use ast::RangeEnd; use {ast, attr}; use codemap::{self, CodeMap, Spanned, respan}; use syntax_pos::{self, Span, BytePos}; -use errors::{self, DiagnosticBuilder}; +use errors::{self, DiagnosticBuilder, Level}; use parse::{self, classify, token}; use parse::common::SeqSep; use parse::lexer::TokenAndSpan; @@ -2840,7 +2840,24 @@ impl<'a> Parser<'a> { let path = match self.parse_path_without_generics(PathStyle::Type) { Ok(path) => { // Successfully parsed the type leaving a `<` yet to parse - err.cancel(); + let codemap = self.sess.codemap(); + let suggestion_span = lhs_span.to(self.prev_span); + let suggestion = match codemap.span_to_snippet(suggestion_span) { + Ok(lstring) => format!("({})", lstring), + _ => format!("()") + }; + let warn_message = match codemap.span_to_snippet(self.prev_span) { + Ok(lstring) => format!("`{}`", lstring), + _ => "a type".to_string(), + }; + err.span_suggestion(suggestion_span, + "if you want to compare the casted value then write", + suggestion); + err.level = Level::Warning; + err.set_message(&format!("`<` is interpreted as a start of generic \ + arguments for {}, not a comparison", + warn_message)); + err.emit(); path } Err(mut path_err) => { diff --git a/src/test/run-pass/issue-22644.rs b/src/test/ui/issue-22644.rs similarity index 100% rename from src/test/run-pass/issue-22644.rs rename to src/test/ui/issue-22644.rs diff --git a/src/test/ui/issue-22644.stderr b/src/test/ui/issue-22644.stderr new file mode 100644 index 000000000000..1e85daa57780 --- /dev/null +++ b/src/test/ui/issue-22644.stderr @@ -0,0 +1,20 @@ +warning: `<` is interpreted as a start of generic arguments for `usize`, not comparison + --> $DIR/issue-22644.rs:16:33 + | +16 | println!("{}", a as usize < b); + | ^ expected one of `!`, `(`, `+`, `,`, `::`, or `>` here + | +help: if you want to compare the casted value then write + | println!("{}", (a as usize) < b); + +warning: `<` is interpreted as a start of generic arguments for `usize`, not comparison + --> $DIR/issue-22644.rs:17:33 + | +17 | println!("{}", a as usize < 4); + | -^ unexpected token + | | + | expected one of `>`, identifier, lifetime, or type here + | +help: if you want to compare the casted value then write + | println!("{}", (a as usize) < 4); + From fdff2d3588451c49adca5d92f551af94e920f0e8 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Fri, 9 Jun 2017 17:58:49 +0200 Subject: [PATCH 138/233] Add some documentation to the dep_node module. --- src/librustc/dep_graph/dep_node.rs | 52 ++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 5f3dd9052034..3b6a7f87c13a 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -8,6 +8,58 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. + +//! This module defines the `DepNode` type which the compiler uses to represent +//! nodes in the dependency graph. A `DepNode` consists of a `DepKind` (which +//! specifies the kind of thing it represents, like a piece of HIR, MIR, etc) +//! and a `Fingerprint`, a 128 bit hash value the exact meaning of which +//! depends on the node's `DepKind`. Together, the kind and the fingerprint +//! fully identify a dependency node, even across multiple compilation sessions. +//! In other words, the value of the fingerprint does not depend on anything +//! that is specific to a given compilation session, like an unpredictable +//! interning key (e.g. NodeId, DefId, Symbol) or the numeric value of a +//! pointer. The concept behind this could be compared to how git commit hashes +//! uniquely identify a given commit and has a few advantages: +//! +//! * A `DepNode` can simply be serialized to disk and loaded in another session +//! without the need to do any "rebasing (like we have to do for Spans and +//! NodeIds) or "retracing" like we had to do for `DefId` in earlier +//! implementations of the dependency graph. +//! * A `Fingerprint` is just a bunch of bits, which allows `DepNode` to +//! implement `Copy`, `Sync`, `Send`, `Freeze`, etc. +//! * Since we just have a bit pattern, `DepNode` can be mapped from disk into +//! memory without any post-processing (e.g. "abomination-style" pointer +//! reconstruction). +//! * Because a `DepNode` is self-contained, we can instantiate `DepNodes` that +//! refer to things that do not exist anymore. In previous implementations +//! `DepNode` contained a `DefId`. A `DepNode` referring to something that +//! had been removed between the previous and the current compilation session +//! could not be instantiated because the current compilation session +//! contained no `DefId` for thing that had been removed. +//! +//! `DepNode` definition happens in the `define_dep_nodes!()` macro. This macro +//! defines the `DepKind` enum and a corresponding `DepConstructor` enum. The +//! `DepConstructor` enum links a `DepKind` to the parameters that are needed at +//! runtime in order to construct a valid `DepNode` fingerprint. +//! +//! Because the macro sees what parameters a given `DepKind` requires, it can +//! "infer" some properties for each kind of `DepNode`: +//! +//! * Whether a `DepNode` of a given kind has any parameters at all. Some +//! `DepNode`s, like `Krate`, represent global concepts with only one value. +//! * Whether it is possible, in principle, to reconstruct a query key from a +//! given `DepNode`. Many `DepKind`s only require a single `DefId` parameter, +//! in which case it is possible to map the node's fingerprint back to the +//! `DefId` it was computed from. In other cases, too much information gets +//! lost during fingerprint computation. +//! +//! The `DepConstructor` enum, together with `DepNode::new()` ensures that only +//! valid `DepNode` instances can be constructed. For example, the API does not +//! allow for constructing parameterless `DepNode`s with anything other +//! than a zeroed out fingerprint. More generally speaking, it relieves the +//! user of the `DepNode` API of having to know how to compute the expected +//! fingerprint for a given set of node parameters. + use hir::def_id::{CrateNum, DefId}; use hir::map::DefPathHash; From 2366c464a7aac7e35d9a6f0c43832d31ffd8b4b8 Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Fri, 9 Jun 2017 22:34:18 +0200 Subject: [PATCH 139/233] Add dedicated docstrings to Sum/Product impl of Result (and fix a minor grammar typo below) --- src/libcore/iter/traits.rs | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/libcore/iter/traits.rs b/src/libcore/iter/traits.rs index 015cc150dc27..679cf3a9b23e 100644 --- a/src/libcore/iter/traits.rs +++ b/src/libcore/iter/traits.rs @@ -798,6 +798,23 @@ impl Iterator for ResultShunt impl Sum> for Result where T: Sum, { + /// Takes each element in the `Iterator`: if it is an `Err`, no further + /// elements are taken, and the `Err` is returned. Should no `Err` occur, + /// the sum of all elements is returned. + /// + /// # Examples + /// + /// This sums up every integer in a vector, rejecting the sum if a negative + /// element is encountered: + /// + /// ``` + /// let v = vec![1, 2]; + /// let res: Result = v.iter().map(|&x: &i32| + /// if x < 0 { Err("Negative element found") } + /// else { Ok(x) } + /// ).sum(); + /// assert_eq!(res, Ok(3)); + /// ``` fn sum(iter: I) -> Result where I: Iterator>, { @@ -809,6 +826,9 @@ impl Sum> for Result impl Product> for Result where T: Product, { + /// Takes each element in the `Iterator`: if it is an `Err`, no further + /// elements are taken, and the `Err` is returned. Should no `Err` occur, + /// the product of all elements is returned. fn product(iter: I) -> Result where I: Iterator>, { @@ -819,7 +839,7 @@ impl Product> for Result /// An iterator that always continues to yield `None` when exhausted. /// /// Calling next on a fused iterator that has returned `None` once is guaranteed -/// to return [`None`] again. This trait is should be implemented by all iterators +/// to return [`None`] again. This trait should be implemented by all iterators /// that behave this way because it allows for some significant optimizations. /// /// Note: In general, you should not use `FusedIterator` in generic bounds if From 20df0e949133fc7bb45b5a630b78f24720e55fe5 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Thu, 16 Mar 2017 14:41:48 +0100 Subject: [PATCH 140/233] Add `-Z span_free_rvalues`. This is solely a hack to make comparing test output plausible; it makes closures print as [closure@node_id] instead of [closure@span-with-host-path] in debug printouts. --- src/librustc/mir/mod.rs | 6 +++++- src/librustc/session/config.rs | 2 ++ src/librustc/util/ppaux.rs | 6 +++++- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 80c42917196d..2b2d96351f6c 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -1224,7 +1224,11 @@ impl<'tcx> Debug for Rvalue<'tcx> { AggregateKind::Closure(def_id, _) => ty::tls::with(|tcx| { if let Some(node_id) = tcx.hir.as_local_node_id(def_id) { - let name = format!("[closure@{:?}]", tcx.hir.span(node_id)); + let name = if tcx.sess.opts.debugging_opts.span_free_formats { + format!("[closure@{:?}]", node_id) + } else { + format!("[closure@{:?}]", tcx.hir.span(node_id)) + }; let mut struct_fmt = fmt.debug_struct(&name); tcx.with_freevars(node_id, |freevars| { diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 589489b49b4f..99435ccf929c 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -893,6 +893,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, DB_OPTIONS, db_type_desc, dbsetters, verbose: bool = (false, parse_bool, [UNTRACKED], "in general, enable more debug printouts"), + span_free_formats: bool = (false, parse_bool, [UNTRACKED], + "when debug-printing compiler state, do not include spans"), // o/w tests have closure@path time_passes: bool = (false, parse_bool, [UNTRACKED], "measure time of each rustc pass"), count_llvm_insns: bool = (false, parse_bool, diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 15fbeb5108fd..39f8a1d81b88 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -789,7 +789,11 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> { write!(f, "[closure")?; if let Some(node_id) = tcx.hir.as_local_node_id(did) { - write!(f, "@{:?}", tcx.hir.span(node_id))?; + if tcx.sess.opts.debugging_opts.span_free_formats { + write!(f, "@{:?}", node_id)?; + } else { + write!(f, "@{:?}", tcx.hir.span(node_id))?; + } let mut sep = " "; tcx.with_freevars(node_id, |freevars| { for (freevar, upvar_ty) in freevars.iter().zip(upvar_tys) { From 609813bbc292e32d257a2c205f783babe07a5c60 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Thu, 23 Mar 2017 11:08:08 +0100 Subject: [PATCH 141/233] `-Z identify_regions` toggles rendering of (previously hidden) unnamed regions. Unlike `-Z verbose`, it is succinct. It uniquely identifies regions when displaying them, and distinguishes code extents from user-specified lifetimes in the output by leveraging a syntactic restriction: you cannot write a lifetime that starts with a numeric character. For example, it prints 'ce for the more verbose `ReScope(CodeExtent())`. --- src/librustc/mir/mod.rs | 14 ++++++++++++-- src/librustc/session/config.rs | 2 ++ src/librustc/util/ppaux.rs | 23 +++++++++++++++++++++++ 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 2b2d96351f6c..e212f1c10069 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -1176,12 +1176,22 @@ impl<'tcx> Debug for Rvalue<'tcx> { UnaryOp(ref op, ref a) => write!(fmt, "{:?}({:?})", op, a), Discriminant(ref lval) => write!(fmt, "discriminant({:?})", lval), NullaryOp(ref op, ref t) => write!(fmt, "{:?}({:?})", op, t), - Ref(_, borrow_kind, ref lv) => { + Ref(region, borrow_kind, ref lv) => { let kind_str = match borrow_kind { BorrowKind::Shared => "", BorrowKind::Mut | BorrowKind::Unique => "mut ", }; - write!(fmt, "&{}{:?}", kind_str, lv) + + // When identifying regions, add trailing space if + // necessary. + let region = if ppaux::identify_regions() { + let mut region = format!("{}", region); + if region.len() > 0 { region.push(' '); } + region + } else { + "".to_owned() + }; + write!(fmt, "&{}{}{:?}", region, kind_str, lv) } Aggregate(ref kind, ref lvs) => { diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 99435ccf929c..283b18f967ff 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -895,6 +895,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "in general, enable more debug printouts"), span_free_formats: bool = (false, parse_bool, [UNTRACKED], "when debug-printing compiler state, do not include spans"), // o/w tests have closure@path + identify_regions: bool = (false, parse_bool, [UNTRACKED], + "make unnamed regions display as '# (where # is some non-ident unique id)"), time_passes: bool = (false, parse_bool, [UNTRACKED], "measure time of each rustc pass"), count_llvm_insns: bool = (false, parse_bool, diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 39f8a1d81b88..1fa635771966 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use hir::BodyId; use hir::def_id::DefId; use hir::map::definitions::DefPathData; +use middle::region::{CodeExtent, BlockRemainder}; use ty::subst::{self, Subst}; use ty::{BrAnon, BrEnv, BrFresh, BrNamed}; use ty::{TyBool, TyChar, TyAdt}; @@ -32,6 +34,10 @@ pub fn verbose() -> bool { ty::tls::with(|tcx| tcx.sess.verbose()) } +pub fn identify_regions() -> bool { + ty::tls::with(|tcx| tcx.sess.opts.debugging_opts.identify_regions) +} + fn fn_sig(f: &mut fmt::Formatter, inputs: &[Ty], variadic: bool, @@ -519,6 +525,23 @@ impl fmt::Display for ty::RegionKind { ty::ReSkolemized(_, br) => { write!(f, "{}", br) } + ty::ReScope(code_extent) if identify_regions() => { + match code_extent { + CodeExtent::Misc(node_id) => + write!(f, "'{}mce", node_id.as_u32()), + CodeExtent::CallSiteScope(BodyId { node_id }) => + write!(f, "'{}cce", node_id.as_u32()), + CodeExtent::ParameterScope(BodyId { node_id }) => + write!(f, "'{}pce", node_id.as_u32()), + CodeExtent::DestructionScope(node_id) => + write!(f, "'{}dce", node_id.as_u32()), + CodeExtent::Remainder(BlockRemainder { block, first_statement_index }) => + write!(f, "'{}_{}rce", block, first_statement_index), + } + } + ty::ReVar(region_vid) if identify_regions() => { + write!(f, "'{}rv", region_vid.index) + } ty::ReScope(_) | ty::ReVar(_) | ty::ReErased => Ok(()), From cbed41a174aad44e069bec09bf1e502591c132ae Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Tue, 23 May 2017 13:18:20 +0200 Subject: [PATCH 142/233] Add destruction extents around blocks and statements in HAIR. --- src/librustc_mir/build/block.rs | 52 ++++++++++++++++++------------- src/librustc_mir/build/scope.rs | 17 ++++++++++ src/librustc_mir/hair/cx/block.rs | 11 +++++++ src/librustc_mir/hair/mod.rs | 2 ++ 4 files changed, 60 insertions(+), 22 deletions(-) diff --git a/src/librustc_mir/build/block.rs b/src/librustc_mir/build/block.rs index d81de954dbf1..1933ef29b539 100644 --- a/src/librustc_mir/build/block.rs +++ b/src/librustc_mir/build/block.rs @@ -21,21 +21,24 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { ast_block: &'tcx hir::Block, source_info: SourceInfo) -> BlockAnd<()> { - let Block { extent, span, stmts, expr, targeted_by_break } = self.hir.mirror(ast_block); - self.in_scope(extent, block, move |this| { - if targeted_by_break { - // This is a `break`-able block (currently only `catch { ... }`) - let exit_block = this.cfg.start_new_block(); - let block_exit = this.in_breakable_scope(None, exit_block, - destination.clone(), |this| { + let Block { extent, opt_destruction_extent, span, stmts, expr, targeted_by_break } = + self.hir.mirror(ast_block); + self.in_opt_scope(opt_destruction_extent, block, move |this| { + this.in_scope(extent, block, move |this| { + if targeted_by_break { + // This is a `break`-able block (currently only `catch { ... }`) + let exit_block = this.cfg.start_new_block(); + let block_exit = this.in_breakable_scope( + None, exit_block, destination.clone(), |this| { + this.ast_block_stmts(destination, block, span, stmts, expr) + }); + this.cfg.terminate(unpack!(block_exit), source_info, + TerminatorKind::Goto { target: exit_block }); + exit_block.unit() + } else { this.ast_block_stmts(destination, block, span, stmts, expr) - }); - this.cfg.terminate(unpack!(block_exit), source_info, - TerminatorKind::Goto { target: exit_block }); - exit_block.unit() - } else { - this.ast_block_stmts(destination, block, span, stmts, expr) - } + } + }) }) } @@ -67,12 +70,14 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let mut let_extent_stack = Vec::with_capacity(8); let outer_visibility_scope = this.visibility_scope; for stmt in stmts { - let Stmt { span: _, kind } = this.hir.mirror(stmt); + let Stmt { span: _, kind, opt_destruction_extent } = this.hir.mirror(stmt); match kind { StmtKind::Expr { scope, expr } => { - unpack!(block = this.in_scope(scope, block, |this| { - let expr = this.hir.mirror(expr); - this.stmt_expr(block, expr) + unpack!(block = this.in_opt_scope(opt_destruction_extent, block, |this| { + this.in_scope(scope, block, |this| { + let expr = this.hir.mirror(expr); + this.stmt_expr(block, expr) + }) })); } StmtKind::Let { remainder_scope, init_scope, pattern, initializer } => { @@ -89,10 +94,13 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // Evaluate the initializer, if present. if let Some(init) = initializer { - unpack!(block = this.in_scope(init_scope, block, move |this| { - // FIXME #30046 ^~~~ - this.expr_into_pattern(block, pattern, init) - })); + unpack!(block = this.in_opt_scope( + opt_destruction_extent, block, move |this| { + this.in_scope(init_scope, block, move |this| { + // FIXME #30046 ^~~~ + this.expr_into_pattern(block, pattern, init) + }) + })); } else { this.visit_bindings(&pattern, &mut |this, _, _, node, span, _| { this.storage_live_binding(block, node, span); diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index a99e7b4be576..d9c303369ccd 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -269,6 +269,23 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { res } + pub fn in_opt_scope(&mut self, + opt_extent: Option, + mut block: BasicBlock, + f: F) + -> BlockAnd + where F: FnOnce(&mut Builder<'a, 'gcx, 'tcx>) -> BlockAnd + { + debug!("in_opt_scope(opt_extent={:?}, block={:?})", opt_extent, block); + if let Some(extent) = opt_extent { self.push_scope(extent); } + let rv = unpack!(block = f(self)); + if let Some(extent) = opt_extent { + unpack!(block = self.pop_scope(extent, block)); + } + debug!("in_scope: exiting opt_extent={:?} block={:?}", opt_extent, block); + block.and(rv) + } + /// Convenience wrapper that pushes a scope and then executes `f` /// to build its contents, popping the scope afterwards. pub fn in_scope(&mut self, diff --git a/src/librustc_mir/hair/cx/block.rs b/src/librustc_mir/hair/cx/block.rs index 47c50b78f3ac..fad070ca8d8f 100644 --- a/src/librustc_mir/hair/cx/block.rs +++ b/src/librustc_mir/hair/cx/block.rs @@ -22,9 +22,14 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Block { // We have to eagerly translate the "spine" of the statements // in order to get the lexical scoping correctly. let stmts = mirror_stmts(cx, self.id, &*self.stmts); + let opt_def_id = cx.tcx.hir.opt_local_def_id(self.id); + let opt_destruction_extent = opt_def_id.and_then(|def_id| { + cx.tcx.region_maps(def_id).opt_destruction_extent(self.id) + }); Block { targeted_by_break: self.targeted_by_break, extent: CodeExtent::Misc(self.id), + opt_destruction_extent: opt_destruction_extent, span: self.span, stmts: stmts, expr: self.expr.to_ref(), @@ -37,7 +42,11 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, stmts: &'tcx [hir::Stmt]) -> Vec> { let mut result = vec![]; + let opt_def_id = cx.tcx.hir.opt_local_def_id(block_id); for (index, stmt) in stmts.iter().enumerate() { + let opt_dxn_ext = opt_def_id.and_then(|def_id| { + cx.tcx.region_maps(def_id).opt_destruction_extent(stmt.node.id()) + }); match stmt.node { hir::StmtExpr(ref expr, id) | hir::StmtSemi(ref expr, id) => { @@ -47,6 +56,7 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, scope: CodeExtent::Misc(id), expr: expr.to_ref(), }, + opt_destruction_extent: opt_dxn_ext, }))) } hir::StmtDecl(ref decl, id) => { @@ -69,6 +79,7 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, pattern: pattern, initializer: local.init.to_ref(), }, + opt_destruction_extent: opt_dxn_ext, }))); } } diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs index 044096699b1a..bb11cce74875 100644 --- a/src/librustc_mir/hair/mod.rs +++ b/src/librustc_mir/hair/mod.rs @@ -33,6 +33,7 @@ pub use rustc_const_eval::pattern::{BindingMode, Pattern, PatternKind, FieldPatt pub struct Block<'tcx> { pub targeted_by_break: bool, pub extent: CodeExtent, + pub opt_destruction_extent: Option, pub span: Span, pub stmts: Vec>, pub expr: Option>, @@ -47,6 +48,7 @@ pub enum StmtRef<'tcx> { pub struct Stmt<'tcx> { pub span: Span, pub kind: StmtKind<'tcx>, + pub opt_destruction_extent: Option, } #[derive(Clone, Debug)] From a658bb21e4b8742f227b07bfc3c26a0a34381285 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Fri, 26 May 2017 18:21:03 +0200 Subject: [PATCH 143/233] Paired source_info with extent; thread both through to pts where EndRegion will need construction. --- src/librustc_mir/build/block.rs | 26 ++++++++++++----------- src/librustc_mir/build/expr/as_lvalue.rs | 2 +- src/librustc_mir/build/expr/as_operand.rs | 2 ++ src/librustc_mir/build/expr/as_rvalue.rs | 3 ++- src/librustc_mir/build/expr/as_temp.rs | 5 +++-- src/librustc_mir/build/expr/into.rs | 1 + src/librustc_mir/build/expr/stmt.rs | 8 +++---- src/librustc_mir/build/mod.rs | 5 +++-- src/librustc_mir/build/scope.rs | 20 ++++++++--------- 9 files changed, 40 insertions(+), 32 deletions(-) diff --git a/src/librustc_mir/build/block.rs b/src/librustc_mir/build/block.rs index 1933ef29b539..f3f366bb7923 100644 --- a/src/librustc_mir/build/block.rs +++ b/src/librustc_mir/build/block.rs @@ -23,8 +23,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { -> BlockAnd<()> { let Block { extent, opt_destruction_extent, span, stmts, expr, targeted_by_break } = self.hir.mirror(ast_block); - self.in_opt_scope(opt_destruction_extent, block, move |this| { - this.in_scope(extent, block, move |this| { + self.in_opt_scope(opt_destruction_extent.map(|de|(de, source_info)), block, move |this| { + this.in_scope((extent, source_info), block, move |this| { if targeted_by_break { // This is a `break`-able block (currently only `catch { ... }`) let exit_block = this.cfg.start_new_block(); @@ -69,16 +69,18 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // First we build all the statements in the block. let mut let_extent_stack = Vec::with_capacity(8); let outer_visibility_scope = this.visibility_scope; + let source_info = this.source_info(span); for stmt in stmts { let Stmt { span: _, kind, opt_destruction_extent } = this.hir.mirror(stmt); match kind { StmtKind::Expr { scope, expr } => { - unpack!(block = this.in_opt_scope(opt_destruction_extent, block, |this| { - this.in_scope(scope, block, |this| { - let expr = this.hir.mirror(expr); - this.stmt_expr(block, expr) - }) - })); + unpack!(block = this.in_opt_scope( + opt_destruction_extent.map(|de|(de, source_info)), block, |this| { + this.in_scope((scope, source_info), block, |this| { + let expr = this.hir.mirror(expr); + this.stmt_expr(block, expr) + }) + })); } StmtKind::Let { remainder_scope, init_scope, pattern, initializer } => { let tcx = this.hir.tcx(); @@ -95,9 +97,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // Evaluate the initializer, if present. if let Some(init) = initializer { unpack!(block = this.in_opt_scope( - opt_destruction_extent, block, move |this| { - this.in_scope(init_scope, block, move |this| { - // FIXME #30046 ^~~~ + opt_destruction_extent.map(|de|(de, source_info)), block, move |this| { + this.in_scope((init_scope, source_info), block, move |this| { + // FIXME #30046 ^~~~ this.expr_into_pattern(block, pattern, init) }) })); @@ -126,7 +128,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // Finally, we pop all the let scopes before exiting out from the scope of block // itself. for extent in let_extent_stack.into_iter().rev() { - unpack!(block = this.pop_scope(extent, block)); + unpack!(block = this.pop_scope((extent, source_info), block)); } // Restore the original visibility scope. this.visibility_scope = outer_visibility_scope; diff --git a/src/librustc_mir/build/expr/as_lvalue.rs b/src/librustc_mir/build/expr/as_lvalue.rs index df2841a66826..04c23215463d 100644 --- a/src/librustc_mir/build/expr/as_lvalue.rs +++ b/src/librustc_mir/build/expr/as_lvalue.rs @@ -40,7 +40,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let source_info = this.source_info(expr_span); match expr.kind { ExprKind::Scope { extent, value } => { - this.in_scope(extent, block, |this| this.as_lvalue(block, value)) + this.in_scope((extent, source_info), block, |this| this.as_lvalue(block, value)) } ExprKind::Field { lhs, name } => { let lvalue = unpack!(block = this.as_lvalue(block, lhs)); diff --git a/src/librustc_mir/build/expr/as_operand.rs b/src/librustc_mir/build/expr/as_operand.rs index 5178963179d6..4679e0bb0a5c 100644 --- a/src/librustc_mir/build/expr/as_operand.rs +++ b/src/librustc_mir/build/expr/as_operand.rs @@ -56,6 +56,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let this = self; if let ExprKind::Scope { extent, value } = expr.kind { + let source_info = this.source_info(expr.span); + let extent = (extent, source_info); return this.in_scope(extent, block, |this| { this.as_operand(block, scope, value) }); diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index 2884b60fdd8a..2512291f1a44 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -59,6 +59,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { match expr.kind { ExprKind::Scope { extent, value } => { + let extent = (extent, source_info); this.in_scope(extent, block, |this| this.as_rvalue(block, scope, value)) } ExprKind::Repeat { value, count } => { @@ -99,7 +100,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // to start, malloc some memory of suitable type (thus far, uninitialized): let box_ = Rvalue::NullaryOp(NullOp::Box, value.ty); this.cfg.push_assign(block, source_info, &result, box_); - this.in_scope(value_extents, block, |this| { + this.in_scope((value_extents, source_info), block, |this| { // schedule a shallow free of that memory, lest we unwind: this.schedule_box_free(expr_span, value_extents, &result, value.ty); // initialize the box contents: diff --git a/src/librustc_mir/build/expr/as_temp.rs b/src/librustc_mir/build/expr/as_temp.rs index 17d74571ce48..faaa46a4a8fd 100644 --- a/src/librustc_mir/build/expr/as_temp.rs +++ b/src/librustc_mir/build/expr/as_temp.rs @@ -39,14 +39,15 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { block, temp_lifetime, expr); let this = self; + let expr_span = expr.span; + let source_info = this.source_info(expr_span); if let ExprKind::Scope { extent, value } = expr.kind { - return this.in_scope(extent, block, |this| { + return this.in_scope((extent, source_info), block, |this| { this.as_temp(block, temp_lifetime, value) }); } let expr_ty = expr.ty.clone(); - let expr_span = expr.span; let temp = this.temp(expr_ty.clone(), expr_span); let source_info = this.source_info(expr_span); diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index d456bc3ded39..97d63ac6d190 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -39,6 +39,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { match expr.kind { ExprKind::Scope { extent, value } => { + let extent = (extent, source_info); this.in_scope(extent, block, |this| this.into(destination, block, value)) } ExprKind::Block { body: ast_block } => { diff --git a/src/librustc_mir/build/expr/stmt.rs b/src/librustc_mir/build/expr/stmt.rs index 3c7ab373651d..3120ac219082 100644 --- a/src/librustc_mir/build/expr/stmt.rs +++ b/src/librustc_mir/build/expr/stmt.rs @@ -24,7 +24,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { match expr.kind { ExprKind::Scope { extent, value } => { let value = this.hir.mirror(value); - this.in_scope(extent, block, |this| this.stmt_expr(block, value)) + this.in_scope((extent, source_info), block, |this| this.stmt_expr(block, value)) } ExprKind::Assign { lhs, rhs } => { let lhs = this.hir.mirror(lhs); @@ -81,7 +81,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { *this.find_breakable_scope(expr_span, label); let continue_block = continue_block.expect( "Attempted to continue in non-continuable breakable block"); - this.exit_scope(expr_span, extent, block, continue_block); + this.exit_scope(expr_span, (extent, source_info), block, continue_block); this.cfg.start_new_block().unit() } ExprKind::Break { label, value } => { @@ -99,7 +99,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } else { this.cfg.push_assign_unit(block, source_info, &destination) } - this.exit_scope(expr_span, extent, block, break_block); + this.exit_scope(expr_span, (extent, source_info), block, break_block); this.cfg.start_new_block().unit() } ExprKind::Return { value } => { @@ -116,7 +116,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { }; let extent = this.extent_of_return_scope(); let return_block = this.return_block(); - this.exit_scope(expr_span, extent, block, return_block); + this.exit_scope(expr_span, (extent, source_info), block, return_block); this.cfg.start_new_block().unit() } ExprKind::InlineAsm { asm, outputs, inputs } => { diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 56c0e18d6f91..eb1414d42e17 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -339,8 +339,9 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, let call_site_extent = CodeExtent::CallSiteScope(body.id()); let arg_extent = CodeExtent::ParameterScope(body.id()); let mut block = START_BLOCK; - unpack!(block = builder.in_scope(call_site_extent, block, |builder| { - unpack!(block = builder.in_scope(arg_extent, block, |builder| { + let source_info = builder.source_info(span); + unpack!(block = builder.in_scope((call_site_extent, source_info), block, |builder| { + unpack!(block = builder.in_scope((arg_extent, source_info), block, |builder| { builder.args_and_body(block, &arguments, arg_extent, &body.value) })); // Attribute epilogue to function's closing brace diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index d9c303369ccd..84b69bbf610f 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -270,14 +270,14 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } pub fn in_opt_scope(&mut self, - opt_extent: Option, + opt_extent: Option<(CodeExtent, SourceInfo)>, mut block: BasicBlock, f: F) -> BlockAnd where F: FnOnce(&mut Builder<'a, 'gcx, 'tcx>) -> BlockAnd { debug!("in_opt_scope(opt_extent={:?}, block={:?})", opt_extent, block); - if let Some(extent) = opt_extent { self.push_scope(extent); } + if let Some(extent) = opt_extent { self.push_scope(extent.0); } let rv = unpack!(block = f(self)); if let Some(extent) = opt_extent { unpack!(block = self.pop_scope(extent, block)); @@ -289,14 +289,14 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { /// Convenience wrapper that pushes a scope and then executes `f` /// to build its contents, popping the scope afterwards. pub fn in_scope(&mut self, - extent: CodeExtent, + extent: (CodeExtent, SourceInfo), mut block: BasicBlock, f: F) -> BlockAnd where F: FnOnce(&mut Builder<'a, 'gcx, 'tcx>) -> BlockAnd { debug!("in_scope(extent={:?}, block={:?})", extent, block); - self.push_scope(extent); + self.push_scope(extent.0); let rv = unpack!(block = f(self)); unpack!(block = self.pop_scope(extent, block)); debug!("in_scope: exiting extent={:?} block={:?}", extent, block); @@ -324,7 +324,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { /// drops onto the end of `block` that are needed. This must /// match 1-to-1 with `push_scope`. pub fn pop_scope(&mut self, - extent: CodeExtent, + extent: (CodeExtent, SourceInfo), mut block: BasicBlock) -> BlockAnd<()> { debug!("pop_scope({:?}, {:?})", extent, block); @@ -332,7 +332,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // to make sure all the `cached_block`s are filled in. self.diverge_cleanup(); let scope = self.scopes.pop().unwrap(); - assert_eq!(scope.extent, extent); + assert_eq!(scope.extent, extent.0); unpack!(block = build_scope_drops(&mut self.cfg, &scope, &self.scopes, @@ -348,11 +348,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { /// module comment for details. pub fn exit_scope(&mut self, span: Span, - extent: CodeExtent, + extent: (CodeExtent, SourceInfo), mut block: BasicBlock, target: BasicBlock) { debug!("exit_scope(extent={:?}, block={:?}, target={:?})", extent, block, target); - let scope_count = 1 + self.scopes.iter().rev().position(|scope| scope.extent == extent) + let scope_count = 1 + self.scopes.iter().rev().position(|scope| scope.extent == extent.0) .unwrap_or_else(||{ span_bug!(span, "extent {:?} does not enclose", extent) }); @@ -363,7 +363,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let mut rest = &mut self.scopes[(len - scope_count)..]; while let Some((scope, rest_)) = {rest}.split_last_mut() { rest = rest_; - block = if let Some(&e) = scope.cached_exits.get(&(target, extent)) { + block = if let Some(&e) = scope.cached_exits.get(&(target, extent.0)) { self.cfg.terminate(block, scope.source_info(span), TerminatorKind::Goto { target: e }); return; @@ -371,7 +371,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let b = self.cfg.start_new_block(); self.cfg.terminate(block, scope.source_info(span), TerminatorKind::Goto { target: b }); - scope.cached_exits.insert((target, extent), b); + scope.cached_exits.insert((target, extent.0), b); b }; unpack!(block = build_scope_drops(&mut self.cfg, From 7c0c4cde80ef871858d5e9dcef506157fcdcc21c Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Fri, 26 May 2017 18:54:23 +0200 Subject: [PATCH 144/233] Pass span through diverge_cleanup down to build_diverge_scope where it can be used for building the diverge path's terminator. --- src/librustc_mir/build/expr/into.rs | 2 +- src/librustc_mir/build/matches/test.rs | 2 +- src/librustc_mir/build/scope.rs | 13 +++++++------ 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index 97d63ac6d190..b7abc707a380 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -234,7 +234,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { .collect(); let success = this.cfg.start_new_block(); - let cleanup = this.diverge_cleanup(); + let cleanup = this.diverge_cleanup(expr_span); this.cfg.terminate(block, source_info, TerminatorKind::Call { func: fun, args: args, diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs index 28386fa598ce..f4d43e041ae8 100644 --- a/src/librustc_mir/build/matches/test.rs +++ b/src/librustc_mir/build/matches/test.rs @@ -306,7 +306,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let bool_ty = self.hir.bool_ty(); let eq_result = self.temp(bool_ty, test.span); let eq_block = self.cfg.start_new_block(); - let cleanup = self.diverge_cleanup(); + let cleanup = self.diverge_cleanup(test.span); self.cfg.terminate(block, source_info, TerminatorKind::Call { func: Operand::Constant(box Constant { span: test.span, diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index 84b69bbf610f..28828d45b2e9 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -330,7 +330,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { debug!("pop_scope({:?}, {:?})", extent, block); // We need to have `cached_block`s available for all the drops, so we call diverge_cleanup // to make sure all the `cached_block`s are filled in. - self.diverge_cleanup(); + self.diverge_cleanup(extent.1.span); let scope = self.scopes.pop().unwrap(); assert_eq!(scope.extent, extent.0); unpack!(block = build_scope_drops(&mut self.cfg, @@ -607,7 +607,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { /// This path terminates in Resume. Returns the start of the path. /// See module comment for more details. None indicates there’s no /// cleanup to do at this point. - pub fn diverge_cleanup(&mut self) -> Option { + pub fn diverge_cleanup(&mut self, span: Span) -> Option { if !self.scopes.iter().any(|scope| scope.needs_cleanup) { return None; } @@ -641,7 +641,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { }; for scope in scopes.iter_mut().filter(|s| s.needs_cleanup) { - target = build_diverge_scope(hir.tcx(), cfg, &unit_temp, scope, target); + target = build_diverge_scope(hir.tcx(), cfg, &unit_temp, span, scope, target); } Some(target) } @@ -657,7 +657,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } let source_info = self.source_info(span); let next_target = self.cfg.start_new_block(); - let diverge_target = self.diverge_cleanup(); + let diverge_target = self.diverge_cleanup(span); self.cfg.terminate(block, source_info, TerminatorKind::Drop { location: location, @@ -675,7 +675,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { value: Operand<'tcx>) -> BlockAnd<()> { let source_info = self.source_info(span); let next_target = self.cfg.start_new_block(); - let diverge_target = self.diverge_cleanup(); + let diverge_target = self.diverge_cleanup(span); self.cfg.terminate(block, source_info, TerminatorKind::DropAndReplace { location: location, @@ -698,7 +698,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let source_info = self.source_info(span); let success_block = self.cfg.start_new_block(); - let cleanup = self.diverge_cleanup(); + let cleanup = self.diverge_cleanup(span); self.cfg.terminate(block, source_info, TerminatorKind::Assert { @@ -767,6 +767,7 @@ fn build_scope_drops<'tcx>(cfg: &mut CFG<'tcx>, fn build_diverge_scope<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, cfg: &mut CFG<'tcx>, unit_temp: &Lvalue<'tcx>, + span: Span, scope: &mut Scope<'tcx>, mut target: BasicBlock) -> BasicBlock From 1d315cf7da85911dfa239331fab30607ce2d1dce Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Fri, 17 Feb 2017 13:38:42 +0100 Subject: [PATCH 145/233] Add `EndRegion` statement kind to MIR. * Emit `EndRegion` for every code-extent for which we observe a borrow. To do this, we needed to thread source info back through to `fn in_scope`, which makes this commit a bit more painful than one might have expected. * There is `end_region` emission in `Builder::pop_scope` and in `Builder::exit_scope`; the first handles falling out of a scope normally, the second handles e.g. `break`. * Remove `EndRegion` statements during the erase_regions mir transformation. * Preallocate the terminator block, and throw an `Unreachable` marker on it from the outset. Then overwrite that Terminator as necessary on demand. * Instead of marking the scope as needs_cleanup after seeing a borrow, just treat every scope in the chain as being part of the diverge_block (after any *one* of them has separately signalled that it needs cleanup, e.g. due to having a destructor to run). * Allow for resume terminators to be patched when looking up drop flags. (In particular, `MirPatch::new` has an explicit code path, presumably previously unreachable, that patches up such resume terminators.) * Make `Scope` implement `Debug` trait. * Expanded a stray comment: we do not emit StorageDead on diverging paths, but that end behavior might not be desirable. --- src/librustc/ich/impls_mir.rs | 3 ++ src/librustc/mir/mod.rs | 21 ++++++++++ src/librustc/mir/visit.rs | 1 + .../borrowck/mir/dataflow/impls.rs | 1 + .../borrowck/mir/dataflow/sanity_check.rs | 1 + .../borrowck/mir/elaborate_drops.rs | 5 +++ .../borrowck/mir/gather_moves.rs | 1 + src/librustc_borrowck/borrowck/mir/mod.rs | 1 + src/librustc_mir/build/block.rs | 3 +- src/librustc_mir/build/cfg.rs | 11 +++++ src/librustc_mir/build/expr/as_temp.rs | 1 - src/librustc_mir/build/scope.rs | 40 +++++++++++++++---- src/librustc_mir/transform/erase_regions.rs | 9 +++++ src/librustc_mir/transform/qualify_consts.rs | 1 + src/librustc_mir/transform/type_check.rs | 1 + src/librustc_mir/util/patch.rs | 1 + src/librustc_passes/mir_stats.rs | 1 + src/librustc_trans/mir/constant.rs | 1 + src/librustc_trans/mir/statement.rs | 1 + 19 files changed, 94 insertions(+), 10 deletions(-) diff --git a/src/librustc/ich/impls_mir.rs b/src/librustc/ich/impls_mir.rs index ae2bea3027d4..cb017b7f8864 100644 --- a/src/librustc/ich/impls_mir.rs +++ b/src/librustc/ich/impls_mir.rs @@ -226,6 +226,9 @@ for mir::StatementKind<'tcx> { mir::StatementKind::StorageDead(ref lvalue) => { lvalue.hash_stable(hcx, hasher); } + mir::StatementKind::EndRegion(ref extents) => { + extents.hash_stable(hcx, hasher); + } mir::StatementKind::Nop => {} mir::StatementKind::InlineAsm { ref asm, ref outputs, ref inputs } => { asm.hash_stable(hcx, hasher); diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index e212f1c10069..c8d03e7b3058 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -12,6 +12,7 @@ use graphviz::IntoCow; use middle::const_val::ConstVal; +use middle::region::CodeExtent; use rustc_const_math::{ConstUsize, ConstInt, ConstMathErr}; use rustc_data_structures::indexed_vec::{IndexVec, Idx}; use rustc_data_structures::control_flow_graph::dominators::{Dominators, dominators}; @@ -804,6 +805,10 @@ pub enum StatementKind<'tcx> { inputs: Vec> }, + /// Mark one terminating point of an extent (i.e. static region). + /// (The starting point(s) arise implicitly from borrows.) + EndRegion(CodeExtent), + /// No-op. Useful for deleting instructions without affecting statement indices. Nop, } @@ -813,6 +818,8 @@ impl<'tcx> Debug for Statement<'tcx> { use self::StatementKind::*; match self.kind { Assign(ref lv, ref rv) => write!(fmt, "{:?} = {:?}", lv, rv), + // (reuse lifetime rendering policy from ppaux.) + EndRegion(ref ce) => write!(fmt, "EndRegion({})", ty::ReScope(*ce)), StorageLive(ref lv) => write!(fmt, "StorageLive({:?})", lv), StorageDead(ref lv) => write!(fmt, "StorageDead({:?})", lv), SetDiscriminant{lvalue: ref lv, variant_index: index} => { @@ -1472,6 +1479,13 @@ impl<'tcx> TypeFoldable<'tcx> for Statement<'tcx> { outputs: outputs.fold_with(folder), inputs: inputs.fold_with(folder) }, + + // Note for future: If we want to expose the extents + // during the fold, we need to either generalize EndRegion + // to carry `[ty::Region]`, or extend the `TypeFolder` + // trait with a `fn fold_extent`. + EndRegion(ref extent) => EndRegion(extent.clone()), + Nop => Nop, }; Statement { @@ -1490,6 +1504,13 @@ impl<'tcx> TypeFoldable<'tcx> for Statement<'tcx> { StorageDead(ref lvalue) => lvalue.visit_with(visitor), InlineAsm { ref outputs, ref inputs, .. } => outputs.visit_with(visitor) || inputs.visit_with(visitor), + + // Note for future: If we want to expose the extents + // during the visit, we need to either generalize EndRegion + // to carry `[ty::Region]`, or extend the `TypeVisitor` + // trait with a `fn visit_extent`. + EndRegion(ref _extent) => false, + Nop => false, } } diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index 780ce736bfd3..ac1c0306f701 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -325,6 +325,7 @@ macro_rules! make_mir_visitor { ref $($mutability)* rvalue) => { self.visit_assign(block, lvalue, rvalue, location); } + StatementKind::EndRegion(_) => {} StatementKind::SetDiscriminant{ ref $($mutability)* lvalue, .. } => { self.visit_lvalue(lvalue, LvalueContext::Store, location); } diff --git a/src/librustc_borrowck/borrowck/mir/dataflow/impls.rs b/src/librustc_borrowck/borrowck/mir/dataflow/impls.rs index da8aa231ccf1..1a1ac7f9c74d 100644 --- a/src/librustc_borrowck/borrowck/mir/dataflow/impls.rs +++ b/src/librustc_borrowck/borrowck/mir/dataflow/impls.rs @@ -474,6 +474,7 @@ impl<'a, 'tcx> BitDenotation for MovingOutStatements<'a, 'tcx> { mir::StatementKind::StorageLive(_) | mir::StatementKind::StorageDead(_) | mir::StatementKind::InlineAsm { .. } | + mir::StatementKind::EndRegion(_) | mir::StatementKind::Nop => {} } } diff --git a/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs b/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs index 44e3b38ea385..2c55460fb301 100644 --- a/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs +++ b/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs @@ -105,6 +105,7 @@ fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir::StatementKind::StorageLive(_) | mir::StatementKind::StorageDead(_) | mir::StatementKind::InlineAsm { .. } | + mir::StatementKind::EndRegion(_) | mir::StatementKind::Nop => continue, mir::StatementKind::SetDiscriminant{ .. } => span_bug!(stmt.source_info.span, diff --git a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs index b03d34819f63..7acfc2c3bbaf 100644 --- a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs +++ b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs @@ -585,6 +585,11 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { // drop elaboration should handle that by itself continue } + TerminatorKind::Resume => { + // We can replace resumes with gotos + // jumping to a canonical resume. + continue + } TerminatorKind::DropAndReplace { .. } => { // this contains the move of the source and // the initialization of the destination. We diff --git a/src/librustc_borrowck/borrowck/mir/gather_moves.rs b/src/librustc_borrowck/borrowck/mir/gather_moves.rs index b03d2a775df7..a0ecdcc8e2ff 100644 --- a/src/librustc_borrowck/borrowck/mir/gather_moves.rs +++ b/src/librustc_borrowck/borrowck/mir/gather_moves.rs @@ -413,6 +413,7 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> { "SetDiscriminant should not exist during borrowck"); } StatementKind::InlineAsm { .. } | + StatementKind::EndRegion(_) | StatementKind::Nop => {} } } diff --git a/src/librustc_borrowck/borrowck/mir/mod.rs b/src/librustc_borrowck/borrowck/mir/mod.rs index 2b39d2a256e1..e3b99b9d4bd4 100644 --- a/src/librustc_borrowck/borrowck/mir/mod.rs +++ b/src/librustc_borrowck/borrowck/mir/mod.rs @@ -394,6 +394,7 @@ fn drop_flag_effects_for_location<'a, 'tcx, F>( mir::StatementKind::StorageLive(_) | mir::StatementKind::StorageDead(_) | mir::StatementKind::InlineAsm { .. } | + mir::StatementKind::EndRegion(_) | mir::StatementKind::Nop => {} }, None => { diff --git a/src/librustc_mir/build/block.rs b/src/librustc_mir/build/block.rs index f3f366bb7923..865174aa272e 100644 --- a/src/librustc_mir/build/block.rs +++ b/src/librustc_mir/build/block.rs @@ -71,7 +71,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let outer_visibility_scope = this.visibility_scope; let source_info = this.source_info(span); for stmt in stmts { - let Stmt { span: _, kind, opt_destruction_extent } = this.hir.mirror(stmt); + let Stmt { span, kind, opt_destruction_extent } = this.hir.mirror(stmt); match kind { StmtKind::Expr { scope, expr } => { unpack!(block = this.in_opt_scope( @@ -122,7 +122,6 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { if let Some(expr) = expr { unpack!(block = this.into(destination, block, expr)); } else { - let source_info = this.source_info(span); this.cfg.push_assign_unit(block, source_info, destination); } // Finally, we pop all the let scopes before exiting out from the scope of block diff --git a/src/librustc_mir/build/cfg.rs b/src/librustc_mir/build/cfg.rs index 40a78933aad2..c20f8bde7838 100644 --- a/src/librustc_mir/build/cfg.rs +++ b/src/librustc_mir/build/cfg.rs @@ -14,6 +14,7 @@ //! Routines for manipulating the control-flow graph. use build::CFG; +use rustc::middle::region::CodeExtent; use rustc::mir::*; impl<'tcx> CFG<'tcx> { @@ -43,6 +44,16 @@ impl<'tcx> CFG<'tcx> { self.block_data_mut(block).statements.push(statement); } + pub fn push_end_region(&mut self, + block: BasicBlock, + source_info: SourceInfo, + extent: CodeExtent) { + self.push(block, Statement { + source_info: source_info, + kind: StatementKind::EndRegion(extent), + }); + } + pub fn push_assign(&mut self, block: BasicBlock, source_info: SourceInfo, diff --git a/src/librustc_mir/build/expr/as_temp.rs b/src/librustc_mir/build/expr/as_temp.rs index faaa46a4a8fd..9be306d2848b 100644 --- a/src/librustc_mir/build/expr/as_temp.rs +++ b/src/librustc_mir/build/expr/as_temp.rs @@ -49,7 +49,6 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let expr_ty = expr.ty.clone(); let temp = this.temp(expr_ty.clone(), expr_span); - let source_info = this.source_info(expr_span); if !expr_ty.is_never() && temp_lifetime.is_some() { this.cfg.push(block, Statement { diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index 28828d45b2e9..469fd5750a2f 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -94,10 +94,11 @@ use rustc::ty::subst::{Kind, Subst}; use rustc::ty::{Ty, TyCtxt}; use rustc::mir::*; use rustc::mir::transform::MirSource; -use syntax_pos::Span; +use syntax_pos::{Span}; use rustc_data_structures::indexed_vec::Idx; use rustc_data_structures::fx::FxHashMap; +#[derive(Debug)] pub struct Scope<'tcx> { /// The visibility scope this scope was created in. visibility_scope: VisibilityScope, @@ -114,7 +115,7 @@ pub struct Scope<'tcx> { /// * pollutting the cleanup MIR with StorageDead creates /// landing pads even though there's no actual destructors /// * freeing up stack space has no effect during unwinding - needs_cleanup: bool, + pub(super) needs_cleanup: bool, /// set of lvalues to drop when exiting this scope. This starts /// out empty but grows as variables are declared during the @@ -141,6 +142,7 @@ pub struct Scope<'tcx> { cached_exits: FxHashMap<(BasicBlock, CodeExtent), BasicBlock>, } +#[derive(Debug)] struct DropData<'tcx> { /// span where drop obligation was incurred (typically where lvalue was declared) span: Span, @@ -152,6 +154,7 @@ struct DropData<'tcx> { kind: DropKind } +#[derive(Debug)] enum DropKind { Value { /// The cached block for the cleanups-on-diverge path. This block @@ -163,6 +166,7 @@ enum DropKind { Storage } +#[derive(Debug)] struct FreeData<'tcx> { /// span where free obligation was incurred span: Span, @@ -338,6 +342,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { &self.scopes, block, self.arg_count)); + + self.cfg.push_end_region(block, extent.1, scope.extent); block.unit() } @@ -379,6 +385,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { rest, block, self.arg_count)); + + // End all regions for scopes out of which we are breaking. + self.cfg.push_end_region(block, extent.1, scope.extent); + if let Some(ref free_data) = scope.free { let next = self.cfg.start_new_block(); let free = build_free(self.hir.tcx(), &tmp, free_data, next); @@ -640,7 +650,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { resumeblk }; - for scope in scopes.iter_mut().filter(|s| s.needs_cleanup) { + for scope in scopes.iter_mut() { target = build_diverge_scope(hir.tcx(), cfg, &unit_temp, span, scope, target); } Some(target) @@ -775,9 +785,9 @@ fn build_diverge_scope<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, // Build up the drops in **reverse** order. The end result will // look like: // - // [drops[n]] -...-> [drops[0]] -> [Free] -> [target] - // | | - // +------------------------------------+ + // [EndRegion Block] -> [drops[n]] -...-> [drops[0]] -> [Free] -> [target] + // | | + // +---------------------------------------------------------+ // code for scope // // The code in this function reads from right to left. At each @@ -807,9 +817,16 @@ fn build_diverge_scope<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, // Next, build up the drops. Here we iterate the vector in // *forward* order, so that we generate drops[0] first (right to // left in diagram above). - for drop_data in &mut scope.drops { + for (j, drop_data) in scope.drops.iter_mut().enumerate() { + debug!("build_diverge_scope drop_data[{}]: {:?}", j, drop_data); // Only full value drops are emitted in the diverging path, // not StorageDead. + // + // Note: This may not actually be what we desire (are we + // "freeing" stack storage as we unwind, or merely observing a + // frozen stack)? In particular, the intent may have been to + // match the behavior of clang, but on inspection eddyb says + // this is not what clang does. let cached_block = match drop_data.kind { DropKind::Value { ref mut cached_block } => cached_block, DropKind::Storage => continue @@ -829,6 +846,15 @@ fn build_diverge_scope<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, }; } + // Finally, push the EndRegion block, used by mir-borrowck. (Block + // becomes trivial goto after pass that removes all EndRegions.) + { + let block = cfg.start_new_cleanup_block(); + cfg.push_end_region(block, source_info(span), scope.extent); + cfg.terminate(block, source_info(span), TerminatorKind::Goto { target: target }); + target = block + } + target } diff --git a/src/librustc_mir/transform/erase_regions.rs b/src/librustc_mir/transform/erase_regions.rs index fa88eca6ec3f..e809695c1804 100644 --- a/src/librustc_mir/transform/erase_regions.rs +++ b/src/librustc_mir/transform/erase_regions.rs @@ -65,6 +65,15 @@ impl<'a, 'tcx> MutVisitor<'tcx> for EraseRegionsVisitor<'a, 'tcx> { substs: &mut ClosureSubsts<'tcx>) { *substs = self.tcx.erase_regions(substs); } + + fn visit_statement(&mut self, + _block: BasicBlock, + statement: &mut Statement<'tcx>, + _location: Location) { + if let StatementKind::EndRegion(_) = statement.kind { + statement.kind = StatementKind::Nop; + } + } } pub struct EraseRegions; diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index d60e761bc0b9..041d78d3c24b 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -907,6 +907,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { StatementKind::StorageLive(_) | StatementKind::StorageDead(_) | StatementKind::InlineAsm {..} | + StatementKind::EndRegion(_) | StatementKind::Nop => {} } }); diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs index e23f0705b6a0..efde39ad6a4c 100644 --- a/src/librustc_mir/transform/type_check.rs +++ b/src/librustc_mir/transform/type_check.rs @@ -413,6 +413,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { } } StatementKind::InlineAsm { .. } | + StatementKind::EndRegion(_) | StatementKind::Nop => {} } } diff --git a/src/librustc_mir/util/patch.rs b/src/librustc_mir/util/patch.rs index 7898d93c22e3..ac121131eb99 100644 --- a/src/librustc_mir/util/patch.rs +++ b/src/librustc_mir/util/patch.rs @@ -46,6 +46,7 @@ impl<'tcx> MirPatch<'tcx> { for (bb, block) in mir.basic_blocks().iter_enumerated() { if let TerminatorKind::Resume = block.terminator().kind { if block.statements.len() > 0 { + assert!(resume_stmt_block.is_none()); resume_stmt_block = Some(bb); } else { resume_block = Some(bb); diff --git a/src/librustc_passes/mir_stats.rs b/src/librustc_passes/mir_stats.rs index e29da3a64965..4dd38cc515c7 100644 --- a/src/librustc_passes/mir_stats.rs +++ b/src/librustc_passes/mir_stats.rs @@ -125,6 +125,7 @@ impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> { self.record("Statement", statement); self.record(match statement.kind { StatementKind::Assign(..) => "StatementKind::Assign", + StatementKind::EndRegion(..) => "StatementKind::EndRegion", StatementKind::SetDiscriminant { .. } => "StatementKind::SetDiscriminant", StatementKind::StorageLive(..) => "StatementKind::StorageLive", StatementKind::StorageDead(..) => "StatementKind::StorageDead", diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs index 4967ef2f7908..16ef32ccf577 100644 --- a/src/librustc_trans/mir/constant.rs +++ b/src/librustc_trans/mir/constant.rs @@ -284,6 +284,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { } mir::StatementKind::StorageLive(_) | mir::StatementKind::StorageDead(_) | + mir::StatementKind::EndRegion(_) | mir::StatementKind::Nop => {} mir::StatementKind::InlineAsm { .. } | mir::StatementKind::SetDiscriminant{ .. } => { diff --git a/src/librustc_trans/mir/statement.rs b/src/librustc_trans/mir/statement.rs index 52c2afca4748..170a76a49497 100644 --- a/src/librustc_trans/mir/statement.rs +++ b/src/librustc_trans/mir/statement.rs @@ -86,6 +86,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { asm::trans_inline_asm(&bcx, asm, outputs, input_vals); bcx } + mir::StatementKind::EndRegion(_) | mir::StatementKind::Nop => bcx, } } From 0a5211e80951eeb89e6f8e9e10b31398904d8d76 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Mon, 22 May 2017 13:06:51 +0200 Subject: [PATCH 146/233] Add post-pass to remove EndRegions of unborrowed extents. --- src/librustc_driver/driver.rs | 3 + .../transform/clean_end_regions.rs | 84 +++++++++++++++++++ src/librustc_mir/transform/mod.rs | 1 + 3 files changed, 88 insertions(+) create mode 100644 src/librustc_mir/transform/clean_end_regions.rs diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index bca82ff9a46d..b1620ed53c71 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -912,6 +912,9 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, let mut passes = Passes::new(); passes.push_hook(mir::transform::dump_mir::DumpMir); + // Remove all `EndRegion` statements that are not involved in borrows. + passes.push_pass(MIR_CONST, mir::transform::clean_end_regions::CleanEndRegions); + // What we need to do constant evaluation. passes.push_pass(MIR_CONST, mir::transform::simplify::SimplifyCfg::new("initial")); passes.push_pass(MIR_CONST, mir::transform::type_check::TypeckMir); diff --git a/src/librustc_mir/transform/clean_end_regions.rs b/src/librustc_mir/transform/clean_end_regions.rs new file mode 100644 index 000000000000..36125f945436 --- /dev/null +++ b/src/librustc_mir/transform/clean_end_regions.rs @@ -0,0 +1,84 @@ +// 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. + +//! This module provides one pass, `CleanEndRegions`, that reduces the +//! set of `EndRegion` statements in the MIR. +//! +//! The "pass" is actually implemented as two traversals (aka visits) +//! of the input MIR. The first traversal, `GatherBorrowedRegions`, +//! finds all of the regions in the MIR that are involved in a borrow. +//! +//! The second traversal, `DeleteTrivialEndRegions`, walks over the +//! MIR and removes any `EndRegion` that is applied to a region that +//! was not seen in the previous pass. + +use rustc_data_structures::fx::FxHashSet; + +use rustc::middle::region::CodeExtent; +use rustc::mir::transform::{MirPass, MirSource}; +use rustc::mir::{BasicBlock, Location, Mir, Rvalue, Statement, StatementKind}; +use rustc::mir::visit::{MutVisitor, Visitor}; +use rustc::ty::{RegionKind, TyCtxt}; + +pub struct CleanEndRegions; + +struct GatherBorrowedRegions { + seen_regions: FxHashSet, +} + +struct DeleteTrivialEndRegions<'a> { + seen_regions: &'a FxHashSet, +} + +impl MirPass for CleanEndRegions { + fn run_pass<'a, 'tcx>(&self, + _tcx: TyCtxt<'a, 'tcx, 'tcx>, + _source: MirSource, + mir: &mut Mir<'tcx>) { + let mut gather = GatherBorrowedRegions { seen_regions: FxHashSet() }; + gather.visit_mir(mir); + + let mut delete = DeleteTrivialEndRegions { seen_regions: &mut gather.seen_regions }; + delete.visit_mir(mir); + } +} + +impl<'tcx> Visitor<'tcx> for GatherBorrowedRegions { + fn visit_rvalue(&mut self, + rvalue: &Rvalue<'tcx>, + location: Location) { + if let Rvalue::Ref(r, _, _) = *rvalue { + if let RegionKind::ReScope(ce) = *r { + self.seen_regions.insert(ce); + } + } + self.super_rvalue(rvalue, location); + } +} + +impl<'a, 'tcx> MutVisitor<'tcx> for DeleteTrivialEndRegions<'a> { + fn visit_statement(&mut self, + block: BasicBlock, + statement: &mut Statement<'tcx>, + location: Location) { + let mut delete_it = false; + + if let StatementKind::EndRegion(ref extent) = statement.kind { + if !self.seen_regions.contains(extent) { + delete_it = true; + } + } + + if delete_it { + statement.kind = StatementKind::Nop; + } + self.super_statement(block, statement, location); + } +} diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index fcea5d4c8604..4594c611d596 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -24,6 +24,7 @@ use syntax::ast; use syntax_pos::{DUMMY_SP, Span}; use transform; +pub mod clean_end_regions; pub mod simplify_branches; pub mod simplify; pub mod erase_regions; From 9dd55276a6249110ce6aa52e450612f716f27149 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Thu, 23 Mar 2017 11:03:17 +0100 Subject: [PATCH 147/233] Leverage mir-opt to encode tests for `EndRegion`. The tests use `-Z identify_regions` so one can eyeball output for sanity. The tests with closures use `-Z span_free_formats` so that host-specific paths do not get embedded into the dumped MIR. The tests check against MIR dump output immediately prior to borrowck (determined by hand to be the dump from after the "qualify-consts" pass) since that is when `EndRegion` will be most relevant in the near term. --- src/test/mir-opt/README.md | 27 ++++++++- src/test/mir-opt/end_region_1.rs | 38 +++++++++++++ src/test/mir-opt/end_region_2.rs | 66 ++++++++++++++++++++++ src/test/mir-opt/end_region_3.rs | 69 +++++++++++++++++++++++ src/test/mir-opt/end_region_4.rs | 75 ++++++++++++++++++++++++ src/test/mir-opt/end_region_5.rs | 80 ++++++++++++++++++++++++++ src/test/mir-opt/end_region_6.rs | 83 +++++++++++++++++++++++++++ src/test/mir-opt/end_region_7.rs | 97 ++++++++++++++++++++++++++++++++ src/test/mir-opt/end_region_8.rs | 86 ++++++++++++++++++++++++++++ src/test/mir-opt/end_region_9.rs | 85 ++++++++++++++++++++++++++++ 10 files changed, 705 insertions(+), 1 deletion(-) create mode 100644 src/test/mir-opt/end_region_1.rs create mode 100644 src/test/mir-opt/end_region_2.rs create mode 100644 src/test/mir-opt/end_region_3.rs create mode 100644 src/test/mir-opt/end_region_4.rs create mode 100644 src/test/mir-opt/end_region_5.rs create mode 100644 src/test/mir-opt/end_region_6.rs create mode 100644 src/test/mir-opt/end_region_7.rs create mode 100644 src/test/mir-opt/end_region_8.rs create mode 100644 src/test/mir-opt/end_region_9.rs diff --git a/src/test/mir-opt/README.md b/src/test/mir-opt/README.md index 9144e9757f6a..28a124e3c61c 100644 --- a/src/test/mir-opt/README.md +++ b/src/test/mir-opt/README.md @@ -22,7 +22,32 @@ All the test information is in comments so the test is runnable. For each $file_name, compiletest expects [$expected_line_0, ..., $expected_line_N] to appear in the dumped MIR in order. Currently it allows -other non-matched lines before, after and in-between. +other non-matched lines before, after and in-between. Note that this includes +lines that end basic blocks or begin new ones; it is good practice +in your tests to include the terminator for each of your basic blocks as an +internal sanity check guarding against a test like: + +``` +bb0: { + StorageLive(_1); + _1 = const true; + StorageDead(_1); +} +``` + +that will inadvertantly pattern-matching against: + +``` +bb0: { + StorageLive(_1); + _1 = const true; + goto -> bb1 +} +bb1: { + StorageDead(_1); + return; +} +``` Lines match ignoring whitespace, and the prefix "//" is removed. diff --git a/src/test/mir-opt/end_region_1.rs b/src/test/mir-opt/end_region_1.rs new file mode 100644 index 000000000000..55dac4440275 --- /dev/null +++ b/src/test/mir-opt/end_region_1.rs @@ -0,0 +1,38 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: -Z identify_regions +// ignore-tidy-linelength + +// This is just about the simplest program that exhibits an EndRegion. + +fn main() { + let a = 3; + let b = &a; +} + +// END RUST SOURCE +// START rustc.node4.SimplifyCfg-qualify-consts.after.mir +// let mut _0: (); +// let _1: i32; +// let _2: &'6_1rce i32; +// +// bb0: { +// StorageLive(_1); +// _1 = const 3i32; +// StorageLive(_2); +// _2 = &'6_1rce _1; +// _0 = (); +// StorageDead(_2); +// EndRegion('6_1rce); +// StorageDead(_1); +// return; +// } +// END rustc.node4.SimplifyCfg-qualify-consts.after.mir diff --git a/src/test/mir-opt/end_region_2.rs b/src/test/mir-opt/end_region_2.rs new file mode 100644 index 000000000000..a1386ec47a13 --- /dev/null +++ b/src/test/mir-opt/end_region_2.rs @@ -0,0 +1,66 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: -Z identify_regions +// ignore-tidy-linelength + +// We will EndRegion for borrows in a loop that occur before break but +// not those after break. + +fn main() { + loop { + let a = true; + let b = &a; + if a { break; } + let c = &a; + } +} + +// END RUST SOURCE +// START rustc.node4.SimplifyCfg-qualify-consts.after.mir +// let mut _0: (); +// let _2: bool; +// let _3: &'7_1rce bool; +// let _7: &'7_3rce bool; +// let mut _4: (); +// let mut _5: bool; +// bb0: { +// goto -> bb1; +// } +// bb1: { +// StorageLive(_2); +// _2 = const true; +// StorageLive(_3); +// _3 = &'7_1rce _2; +// StorageLive(_5); +// _5 = _2; +// switchInt(_5) -> [0u8: bb3, otherwise: bb2]; +// } +// bb2: { +// _0 = (); +// StorageDead(_5); +// StorageDead(_3); +// EndRegion('7_1rce); +// StorageDead(_2); +// return; +// } +// bb3: { +// StorageDead(_5); +// StorageLive(_7); +// _7 = &'7_3rce _2; +// _1 = (); +// StorageDead(_7); +// EndRegion('7_3rce); +// StorageDead(_3); +// EndRegion('7_1rce); +// StorageDead(_2); +// goto -> bb1; +// } +// END rustc.node4.SimplifyCfg-qualify-consts.after.mir diff --git a/src/test/mir-opt/end_region_3.rs b/src/test/mir-opt/end_region_3.rs new file mode 100644 index 000000000000..b3d2809e76ce --- /dev/null +++ b/src/test/mir-opt/end_region_3.rs @@ -0,0 +1,69 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: -Z identify_regions +// ignore-tidy-linelength + +// Binding the borrow's subject outside the loop does not increase the +// scope of the borrow. + +fn main() { + let mut a; + loop { + a = true; + let b = &a; + if a { break; } + let c = &a; + } +} + +// END RUST SOURCE +// START rustc.node4.SimplifyCfg-qualify-consts.after.mir +// let mut _0: (); +// let mut _1: bool; +// let _3: &'9_1rce bool; +// let _7: &'9_3rce bool; +// let mut _2: (); +// let mut _4: (); +// let mut _5: bool; +// +// bb0: { +// StorageLive(_1); +// goto -> bb1; +// } +// bb1: { +// _1 = const true; +// StorageLive(_3); +// _3 = &'9_1rce _1; +// StorageLive(_5); +// _5 = _1; +// switchInt(_5) -> [0u8: bb3, otherwise: bb2]; +// } +// bb2: { +// _0 = (); +// StorageDead(_5); +// StorageDead(_3); +// EndRegion('9_1rce); +// StorageDead(_1); +// return; +// } +// bb3: { +// _4 = (); +// StorageDead(_5); +// StorageLive(_7); +// _7 = &'9_3rce _1; +// _2 = (); +// StorageDead(_7); +// EndRegion('9_3rce); +// StorageDead(_3); +// EndRegion('9_1rce); +// goto -> bb1; +// } +// END rustc.node4.SimplifyCfg-qualify-consts.after.mir diff --git a/src/test/mir-opt/end_region_4.rs b/src/test/mir-opt/end_region_4.rs new file mode 100644 index 000000000000..16ade9f96fd1 --- /dev/null +++ b/src/test/mir-opt/end_region_4.rs @@ -0,0 +1,75 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: -Z identify_regions +// ignore-tidy-linelength + +// Unwinding should EndRegion for in-scope borrows: Direct borrows. + +fn main() { + let d = D(0); + let a = 0; + let b = &a; + foo(*b); + let c = &a; +} + +struct D(i32); +impl Drop for D { fn drop(&mut self) { println!("dropping D({})", self.0); } } + +fn foo(i: i32) { + if i > 0 { panic!("im positive"); } +} + +// END RUST SOURCE +// START rustc.node4.SimplifyCfg-qualify-consts.after.mir +// let mut _0: (); +// let _1: D; +// let _3: i32; +// let _4: &'6_2rce i32; +// let _7: &'6_4rce i32; +// let mut _5: (); +// let mut _6: i32; +// +// bb0: { +// StorageLive(_1); +// _1 = D::{{constructor}}(const 0i32,); +// StorageLive(_3); +// _3 = const 0i32; +// StorageLive(_4); +// _4 = &'6_2rce _3; +// StorageLive(_6); +// _6 = (*_4); +// _5 = const foo(_6) -> [return: bb2, unwind: bb3]; +// } +// bb1: { +// resume; +// } +// bb2: { +// StorageDead(_6); +// StorageLive(_7); +// _7 = &'6_4rce _3; +// _0 = (); +// StorageDead(_7); +// EndRegion('6_4rce); +// StorageDead(_4); +// EndRegion('6_2rce); +// StorageDead(_3); +// drop(_1) -> bb4; +// } +// bb3: { +// EndRegion('6_2rce); +// drop(_1) -> bb1; +// } +// bb4: { +// StorageDead(_1); +// return; +// } +// END rustc.node4.SimplifyCfg-qualify-consts.after.mir diff --git a/src/test/mir-opt/end_region_5.rs b/src/test/mir-opt/end_region_5.rs new file mode 100644 index 000000000000..513632a4cdf3 --- /dev/null +++ b/src/test/mir-opt/end_region_5.rs @@ -0,0 +1,80 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: -Z identify_regions -Z span_free_formats +// ignore-tidy-linelength + +// Unwinding should EndRegion for in-scope borrows: Borrowing via by-ref closure. + +fn main() { + let d = D(0); + foo(|| -> i32 { d.0 }); +} + +struct D(i32); +impl Drop for D { fn drop(&mut self) { println!("dropping D({})", self.0); } } + +fn foo(f: F) where F: FnOnce() -> i32 { + if f() > 0 { panic!("im positive"); } +} + +// END RUST SOURCE +// START rustc.node4.SimplifyCfg-qualify-consts.after.mir +// fn main() -> () { +// let mut _0: (); +// let _1: D; +// let mut _2: (); +// let mut _3: (); +// let mut _4: [closure@NodeId(18) d: &'19mce D]; +// let mut _5: &'19mce D; +// +// bb0: { +// StorageLive(_1); +// _1 = D::{{constructor}}(const 0i32,); +// StorageLive(_4); +// StorageLive(_5); +// _5 = &'19mce _1; +// _4 = [closure@NodeId(18)] { d: _5 }; +// StorageDead(_5); +// _3 = const foo(_4) -> [return: bb2, unwind: bb3]; +// } +// bb1: { +// resume; +// } +// bb2: { +// StorageDead(_4); +// EndRegion('19mce); +// _0 = (); +// drop(_1) -> bb4; +// } +// bb3: { +// EndRegion('19mce); +// drop(_1) -> bb1; +// } +// bb4: { +// StorageDead(_1); +// return; +// } +// } +// END rustc.node4.SimplifyCfg-qualify-consts.after.mir + +// START rustc.node18.SimplifyCfg-qualify-consts.after.mir +// fn main::{{closure}}(_1: [closure@NodeId(18) d:&'19mce D]) -> i32 { +// let mut _0: i32; +// let mut _2: i32; +// +// bb0: { +// StorageLive(_2); +// _2 = ((*(_1.0: &'19mce D)).0: i32); +// _0 = _2; +// StorageDead(_2); +// return; +// } +// END rustc.node18.SimplifyCfg-qualify-consts.after.mir diff --git a/src/test/mir-opt/end_region_6.rs b/src/test/mir-opt/end_region_6.rs new file mode 100644 index 000000000000..e82556f3ce4b --- /dev/null +++ b/src/test/mir-opt/end_region_6.rs @@ -0,0 +1,83 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: -Z identify_regions -Z span_free_formats +// ignore-tidy-linelength + +// Unwinding should EndRegion for in-scope borrows: 2nd borrow within by-ref closure. + +fn main() { + let d = D(0); + foo(|| -> i32 { let r = &d; r.0 }); +} + +struct D(i32); +impl Drop for D { fn drop(&mut self) { println!("dropping D({})", self.0); } } + +fn foo(f: F) where F: FnOnce() -> i32 { + if f() > 0 { panic!("im positive"); } +} + +// END RUST SOURCE +// START rustc.node4.SimplifyCfg-qualify-consts.after.mir +// let mut _0: (); +// let _1: D; +// let mut _2: (); +// let mut _3: (); +// let mut _4: [closure@NodeId(22) d:&'23mce D]; +// let mut _5: &'23mce D; +// +// bb0: { +// StorageLive(_1); +// _1 = D::{{constructor}}(const 0i32,); +// StorageLive(_4); +// StorageLive(_5); +// _5 = &'23mce _1; +// _4 = [closure@NodeId(22)] { d: _5 }; +// StorageDead(_5); +// _3 = const foo(_4) -> [return: bb2, unwind: bb3]; +// } +// bb1: { +// resume; +// } +// bb2: { +// StorageDead(_4); +// EndRegion('23mce); +// _0 = (); +// drop(_1) -> bb4; +// } +// bb3: { +// EndRegion('23mce); +// drop(_1) -> bb1; +// } +// bb4: { +// StorageDead(_1); +// return; +// } +// END rustc.node4.SimplifyCfg-qualify-consts.after.mir + +// START rustc.node22.SimplifyCfg-qualify-consts.after.mir +// fn main::{{closure}}(_1: [closure@NodeId(22) d:&'23mce D]) -> i32 { +// let mut _0: i32; +// let _2: &'14_0rce D; +// let mut _3: i32; +// +// bb0: { +// StorageLive(_2); +// _2 = &'14_0rce (*(_1.0: &'23mce D)); +// StorageLive(_3); +// _3 = ((*_2).0: i32); +// _0 = _3; +// StorageDead(_3); +// StorageDead(_2); +// EndRegion('14_0rce); +// return; +// } +// END rustc.node22.SimplifyCfg-qualify-consts.after.mir diff --git a/src/test/mir-opt/end_region_7.rs b/src/test/mir-opt/end_region_7.rs new file mode 100644 index 000000000000..3fbd3f368659 --- /dev/null +++ b/src/test/mir-opt/end_region_7.rs @@ -0,0 +1,97 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: -Z identify_regions -Z span_free_formats +// ignore-tidy-linelength + +// Unwinding should EndRegion for in-scope borrows: Borrow of moved data. + +fn main() { + let d = D(0); + foo(move || -> i32 { let r = &d; r.0 }); +} + +struct D(i32); +impl Drop for D { fn drop(&mut self) { println!("dropping D({})", self.0); } } + +fn foo(f: F) where F: FnOnce() -> i32 { + if f() > 0 { panic!("im positive"); } +} + +// END RUST SOURCE +// START rustc.node4.SimplifyCfg-qualify-consts.after.mir +// fn main() -> () { +// let mut _0: (); +// let _1: D; +// let mut _2: (); +// let mut _3: (); +// let mut _4: [closure@NodeId(22) d:D]; +// let mut _5: D; +// +// bb0: { +// StorageLive(_1); +// _1 = D::{{constructor}}(const 0i32,); +// StorageLive(_4); +// StorageLive(_5); +// _5 = _1; +// _4 = [closure@NodeId(22)] { d: _5 }; +// drop(_5) -> [return: bb4, unwind: bb3]; +// } +// bb1: { +// resume; +// } +// bb2: { +// drop(_1) -> bb1; +// } +// bb3: { +// drop(_4) -> bb2; +// } +// bb4: { +// StorageDead(_5); +// _3 = const foo(_4) -> [return: bb5, unwind: bb3]; +// } +// bb5: { +// drop(_4) -> [return: bb6, unwind: bb2]; +// } +// bb6: { +// StorageDead(_4); +// _0 = (); +// drop(_1) -> bb7; +// } +// bb7: { +// StorageDead(_1); +// return; +// } +// } +// END rustc.node4.SimplifyCfg-qualify-consts.after.mir + +// START rustc.node22.SimplifyCfg-qualify-consts.after.mir +// fn main::{{closure}}(_1: [closure@NodeId(22) d:D]) -> i32 { +// let mut _0: i32; +// let _2: &'14_0rce D; +// let mut _3: (); +// let mut _4: i32; +// +// bb0: { +// StorageLive(_2); +// _2 = &'14_0rce (_1.0: D); +// StorageLive(_4); +// _4 = ((*_2).0: i32); +// _0 = _4; +// StorageDead(_4); +// StorageDead(_2); +// EndRegion('14_0rce); +// drop(_1) -> bb1; +// } +// bb1: { +// return; +// } +// } +// END rustc.node22.SimplifyCfg-qualify-consts.after.mir diff --git a/src/test/mir-opt/end_region_8.rs b/src/test/mir-opt/end_region_8.rs new file mode 100644 index 000000000000..7fb3f0b91181 --- /dev/null +++ b/src/test/mir-opt/end_region_8.rs @@ -0,0 +1,86 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: -Z identify_regions -Z span_free_formats +// ignore-tidy-linelength + +// Unwinding should EndRegion for in-scope borrows: Move of borrow into closure. + +fn main() { + let d = D(0); + let r = &d; + foo(move || -> i32 { r.0 }); +} + +struct D(i32); +impl Drop for D { fn drop(&mut self) { println!("dropping D({})", self.0); } } + +fn foo(f: F) where F: FnOnce() -> i32 { + if f() > 0 { panic!("im positive"); } +} + +// END RUST SOURCE +// START rustc.node4.SimplifyCfg-qualify-consts.after.mir +// fn main() -> () { +// let mut _0: (); +// let _1: D; +// let _3: &'6_1rce D; +// let mut _2: (); +// let mut _4: (); +// let mut _5: [closure@NodeId(22) r:&'6_1rce D]; +// let mut _6: &'6_1rce D; +// +// bb0: { +// StorageLive(_1); +// _1 = D::{{constructor}}(const 0i32,); +// StorageLive(_3); +// _3 = &'6_1rce _1; +// StorageLive(_5); +// StorageLive(_6); +// _6 = _3; +// _5 = [closure@NodeId(22)] { r: _6 }; +// StorageDead(_6); +// _4 = const foo(_5) -> [return: bb2, unwind: bb3]; +// } +// bb1: { +// resume; +// } +// bb2: { +// StorageDead(_5); +// _0 = (); +// StorageDead(_3); +// EndRegion('6_1rce); +// drop(_1) -> bb4; +// } +// bb3: { +// EndRegion('6_1rce); +// drop(_1) -> bb1; +// } +// bb4: { +// StorageDead(_1); +// return; +// } +// } +// END rustc.node4.SimplifyCfg-qualify-consts.after.mir + +// START rustc.node22.SimplifyCfg-qualify-consts.after.mir +// fn main::{{closure}}(_1: [closure@NodeId(22) r:&'6_1rce D]) -> i32 { +// let mut _0: i32; +// let mut _2: i32; +// +// bb0: { +// StorageLive(_2); +// _2 = ((*(_1.0: &'6_1rce D)).0: i32); +// _0 = _2; +// StorageDead(_2); +// return; +// } +// } +// END rustc.node22.SimplifyCfg-qualify-consts.after.mir diff --git a/src/test/mir-opt/end_region_9.rs b/src/test/mir-opt/end_region_9.rs new file mode 100644 index 000000000000..deff984e4d0d --- /dev/null +++ b/src/test/mir-opt/end_region_9.rs @@ -0,0 +1,85 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: -Z identify_regions -Z span_free_formats +// ignore-tidy-linelength + +// This test models a scenario that arielb1 found during review. +// Namely, any filtering of EndRegions must ensure to continue to emit +// any necessary EndRegions that occur earlier in the source than the +// first borrow involving that region. +// +// It is tricky to actually construct examples of this, which is the +// main reason that I am keeping this test even though I have now +// removed the pre-filter that motivated the test in the first place. + +fn main() { + let mut second_iter = false; + let x = 3; + 'a: loop { + let mut y; + loop { + if second_iter { + break 'a; // want to generate `EndRegion('a)` here + } else { + y = &/*'a*/ x; + } + second_iter = true; + } + } +} + +// END RUST SOURCE +// START rustc.node4.SimplifyCfg-qualify-consts.after.mir +// fn main() -> () { +// let mut _0: (); +// let mut _1: bool; +// let _2: i32; +// let mut _4: &'13_0rce i32; +// let mut _3: (); +// let mut _5: !; +// let mut _6: (); +// let mut _7: bool; +// let mut _8: !; +// +// bb0: { +// StorageLive(_1); +// _1 = const false; +// StorageLive(_2); +// _2 = const 3i32; +// StorageLive(_4); +// goto -> bb1; +// } +// +// bb1: { +// StorageLive(_7); +// _7 = _1; +// switchInt(_7) -> [0u8: bb3, otherwise: bb2]; +// } +// +// bb2: { +// _0 = (); +// StorageDead(_7); +// StorageDead(_4); +// EndRegion('13_0rce); +// StorageDead(_2); +// StorageDead(_1); +// return; +// } +// +// bb3: { +// _4 = &'13_0rce _2; +// _6 = (); +// StorageDead(_7); +// _1 = const true; +// _3 = (); +// goto -> bb1; +// } +// } From 5eff019779c5875c53c7fc39a72603cf8825e38d Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Mon, 29 May 2017 11:46:02 +0200 Subject: [PATCH 148/233] Update basic_assignment test to reflect small changes to codegen. --- src/test/mir-opt/basic_assignment.rs | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/test/mir-opt/basic_assignment.rs b/src/test/mir-opt/basic_assignment.rs index e4eb1aeaf9be..ef5158a403a9 100644 --- a/src/test/mir-opt/basic_assignment.rs +++ b/src/test/mir-opt/basic_assignment.rs @@ -50,7 +50,7 @@ fn main() { // StorageLive(_6); // StorageLive(_7); // _7 = _4; -// replace(_6 <- _7) -> [return: bb5, unwind: bb4]; +// replace(_6 <- _7) -> [return: bb6, unwind: bb7]; // } // bb1: { // resume; @@ -59,24 +59,30 @@ fn main() { // drop(_4) -> bb1; // } // bb3: { -// drop(_6) -> bb2; +// goto -> bb2; // } // bb4: { -// drop(_7) -> bb3; +// drop(_6) -> bb3; // } // bb5: { -// drop(_7) -> [return: bb6, unwind: bb3]; +// goto -> bb4; // } // bb6: { -// StorageDead(_7); -// _0 = (); -// drop(_6) -> [return: bb7, unwind: bb2]; +// drop(_7) -> [return: bb8, unwind: bb4]; // } // bb7: { -// StorageDead(_6); -// drop(_4) -> bb8; +// drop(_7) -> bb5; // } // bb8: { +// StorageDead(_7); +// _0 = (); +// drop(_6) -> [return: bb9, unwind: bb2]; +// } +// bb9: { +// StorageDead(_6); +// drop(_4) -> bb10; +// } +// bb10: { // StorageDead(_4); // StorageDead(_2); // StorageDead(_1); From 163d40d1d86d06b6c937ec5a062a134025984b4f Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Wed, 31 May 2017 16:07:24 +0200 Subject: [PATCH 149/233] Update test/codegen/drop.rs to reflect inconsequential change in basic block ordering. --- src/test/codegen/drop.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/codegen/drop.rs b/src/test/codegen/drop.rs index d7e2cb6d9a50..1961060c2c26 100644 --- a/src/test/codegen/drop.rs +++ b/src/test/codegen/drop.rs @@ -32,9 +32,9 @@ pub fn droppy() { // CHECK-NOT: invoke{{.*}}drop{{.*}}SomeUniqueName // CHECK: call{{.*}}drop{{.*}}SomeUniqueName // CHECK: call{{.*}}drop{{.*}}SomeUniqueName -// CHECK: call{{.*}}drop{{.*}}SomeUniqueName // CHECK-NOT: call{{.*}}drop{{.*}}SomeUniqueName // CHECK: invoke{{.*}}drop{{.*}}SomeUniqueName +// CHECK: call{{.*}}drop{{.*}}SomeUniqueName // CHECK: invoke{{.*}}drop{{.*}}SomeUniqueName // CHECK: call{{.*}}drop{{.*}}SomeUniqueName // CHECK-NOT: {{(call|invoke).*}}drop{{.*}}SomeUniqueName From 11f4968bd7372ed3986ff7d83fb14218ef0f2f20 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Fri, 2 Jun 2017 12:52:09 +0200 Subject: [PATCH 150/233] Revised comment explaining my addition of case for `TerminatorKind::Resume`. Also, I removed the `continue;` statement. I don't think it makes a difference whether its there or not, but having it there confuses things when the actual goal was to side-step the assertion in the default case. --- src/librustc_borrowck/borrowck/mir/elaborate_drops.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs index 7acfc2c3bbaf..833697726089 100644 --- a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs +++ b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs @@ -585,11 +585,6 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { // drop elaboration should handle that by itself continue } - TerminatorKind::Resume => { - // We can replace resumes with gotos - // jumping to a canonical resume. - continue - } TerminatorKind::DropAndReplace { .. } => { // this contains the move of the source and // the initialization of the destination. We @@ -599,6 +594,11 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { assert!(self.patch.is_patched(bb)); allow_initializations = false; } + TerminatorKind::Resume => { + // It is possible for `Resume` to be patched + // (in particular it can be patched to be replaced with + // a Goto; see `MirPatch::new`). + } _ => { assert!(!self.patch.is_patched(bb)); } From 271133b03ee5da57334670f50cd8a6ebbc35d140 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 12 Jun 2017 15:37:26 +0200 Subject: [PATCH 151/233] External spans: address review. * The lazy loading mechanism has been moved to a more appropriate place. * Return values from the functions invoked there are properly used. * Documentation has gotten some minor improvements. * Possibly some larger restructuring will need to take place still. --- src/librustc_errors/emitter.rs | 9 +++------ src/librustc_errors/lib.rs | 4 ++-- src/libsyntax/codemap.rs | 16 +++------------- src/libsyntax_pos/lib.rs | 35 +++++++++++++++++++--------------- 4 files changed, 28 insertions(+), 36 deletions(-) diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index 2099725c48aa..b4b14328b3db 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -177,8 +177,6 @@ impl EmitterWriter { continue; } - cm.load_source_for_filemap(cm.span_to_filename(span_label.span)); - let lo = cm.lookup_char_pos(span_label.span.lo); let mut hi = cm.lookup_char_pos(span_label.span.hi); @@ -891,10 +889,10 @@ impl EmitterWriter { let mut annotated_files = self.preprocess_annotations(msp); // Make sure our primary file comes first - let primary_lo = if let (Some(ref cm), Some(ref primary_span)) = + let (primary_lo, cm) = if let (Some(cm), Some(ref primary_span)) = (self.cm.as_ref(), msp.primary_span().as_ref()) { if primary_span != &&DUMMY_SP { - cm.lookup_char_pos(primary_span.lo) + (cm.lookup_char_pos(primary_span.lo), cm) } else { emit_to_destination(&buffer.render(), level, &mut self.dst)?; return Ok(()); @@ -912,8 +910,7 @@ impl EmitterWriter { // Print out the annotate source lines that correspond with the error for annotated_file in annotated_files { // we can't annotate anything if the source is unavailable. - if annotated_file.file.src.is_none() - && annotated_file.file.external_src.borrow().is_absent() { + if !cm.ensure_filemap_source_present(annotated_file.file.clone()) { continue; } diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index 26ecbe724f8d..975b720276e8 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -50,7 +50,7 @@ pub mod registry; pub mod styled_buffer; mod lock; -use syntax_pos::{BytePos, Loc, FileLinesResult, FileName, MultiSpan, Span, NO_EXPANSION}; +use syntax_pos::{BytePos, Loc, FileLinesResult, FileMap, FileName, MultiSpan, Span, NO_EXPANSION}; #[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)] pub enum RenderSpan { @@ -104,7 +104,7 @@ pub trait CodeMapper { fn span_to_filename(&self, sp: Span) -> FileName; fn merge_spans(&self, sp_lhs: Span, sp_rhs: Span) -> Option; fn call_span_if_macro(&self, sp: Span) -> Span; - fn load_source_for_filemap(&self, file: FileName) -> bool; + fn ensure_filemap_source_present(&self, file_map: Rc) -> bool; } impl CodeSuggestion { diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index 7267f510a490..5b10139cd196 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -559,19 +559,9 @@ impl CodeMapper for CodeMap { } sp } - fn load_source_for_filemap(&self, filename: FileName) -> bool { - let file_map = if let Some(fm) = self.get_filemap(&filename) { - fm - } else { - return false; - }; - - if *file_map.external_src.borrow() == ExternalSource::AbsentOk { - let src = self.file_loader.read_file(Path::new(&filename)).ok(); - return file_map.add_external_src(src); - } - - false + fn ensure_filemap_source_present(&self, file_map: Rc) -> bool { + let src = self.file_loader.read_file(Path::new(&file_map.name)).ok(); + return file_map.add_external_src(src) } } diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index 719c25e2410b..94656b3aea79 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -604,28 +604,33 @@ impl FileMap { lines.push(pos); } - /// add externally loaded source. - /// if the hash of the input doesn't match or no input is supplied via None, + /// Add externally loaded source. + /// If the hash of the input doesn't match or no input is supplied via None, /// it is interpreted as an error and the corresponding enum variant is set. + /// The return value signifies whether some kind of source is present. pub fn add_external_src(&self, src: Option) -> bool { - let mut external_src = self.external_src.borrow_mut(); - if let Some(src) = src { - let mut hasher: StableHasher = StableHasher::new(); - hasher.write(src.as_bytes()); + if *self.external_src.borrow() == ExternalSource::AbsentOk { + let mut external_src = self.external_src.borrow_mut(); + if let Some(src) = src { + let mut hasher: StableHasher = StableHasher::new(); + hasher.write(src.as_bytes()); - if hasher.finish() == self.src_hash { - *external_src = ExternalSource::Present(src); - return true; + if hasher.finish() == self.src_hash { + *external_src = ExternalSource::Present(src); + return true; + } + } else { + *external_src = ExternalSource::AbsentErr; } - } else { - *external_src = ExternalSource::AbsentErr; - } - false + false + } else { + self.src.is_some() || self.external_src.borrow().get_source().is_some() + } } - /// get a line from the list of pre-computed line-beginnings. - /// line-number here is 0-based. + /// Get a line from the list of pre-computed line-beginnings. + /// The line number here is 0-based. pub fn get_line(&self, line_number: usize) -> Option> { fn get_until_newline(src: &str, begin: usize) -> &str { // We can't use `lines.get(line_number+1)` because we might From 5fcfa08e9899044e5cad2ac238206d83568a863f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 11 Jun 2017 23:49:28 -0700 Subject: [PATCH 152/233] Fix affected tests --- src/libsyntax/parse/parser.rs | 3 ++- src/test/parse-fail/better-expected.rs | 2 +- src/test/parse-fail/bounds-type-where.rs | 2 +- src/test/parse-fail/closure-return-syntax.rs | 2 +- src/test/parse-fail/empty-impl-semicolon.rs | 2 +- src/test/parse-fail/multitrait.rs | 2 +- src/test/parse-fail/removed-syntax-closure-lifetime.rs | 2 +- src/test/parse-fail/removed-syntax-fixed-vec.rs | 2 +- src/test/parse-fail/removed-syntax-ptr-lifetime.rs | 2 +- src/test/ui/issue-22644.stderr | 8 ++++---- 10 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 76b14071ec32..ee74d9ec2e65 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2851,7 +2851,8 @@ impl<'a> Parser<'a> { _ => "a type".to_string(), }; err.span_suggestion(suggestion_span, - "if you want to compare the casted value then write", + "if you want to compare the casted value \ + then write:", suggestion); err.level = Level::Warning; err.set_message(&format!("`<` is interpreted as a start of generic \ diff --git a/src/test/parse-fail/better-expected.rs b/src/test/parse-fail/better-expected.rs index b60201c251dc..d78ac3cb5ce9 100644 --- a/src/test/parse-fail/better-expected.rs +++ b/src/test/parse-fail/better-expected.rs @@ -11,5 +11,5 @@ // compile-flags: -Z parse-only fn main() { - let x: [isize 3]; //~ ERROR expected one of `!`, `(`, `+`, `::`, `;`, `<`, or `]`, found `3` + let x: [isize 3]; //~ ERROR expected one of `!`, `(`, `+`, `::`, `;`, or `]`, found `3` } diff --git a/src/test/parse-fail/bounds-type-where.rs b/src/test/parse-fail/bounds-type-where.rs index 9dc5d8277446..103785495933 100644 --- a/src/test/parse-fail/bounds-type-where.rs +++ b/src/test/parse-fail/bounds-type-where.rs @@ -18,6 +18,6 @@ type A where T: Trait + Trait = u8; // OK type A where = u8; // OK type A where T: Trait + = u8; // OK type A where T, = u8; -//~^ ERROR expected one of `!`, `(`, `+`, `::`, `:`, `<`, `==`, or `=`, found `,` +//~^ ERROR expected one of `!`, `(`, `+`, `::`, `:`, `==`, or `=`, found `,` fn main() {} diff --git a/src/test/parse-fail/closure-return-syntax.rs b/src/test/parse-fail/closure-return-syntax.rs index 1da673591801..f3be750e2546 100644 --- a/src/test/parse-fail/closure-return-syntax.rs +++ b/src/test/parse-fail/closure-return-syntax.rs @@ -13,5 +13,5 @@ fn main() { let x = || -> i32 22; - //~^ ERROR expected one of `!`, `(`, `::`, `<`, or `{`, found `22` + //~^ ERROR expected one of `!`, `(`, `::`, or `{`, found `22` } diff --git a/src/test/parse-fail/empty-impl-semicolon.rs b/src/test/parse-fail/empty-impl-semicolon.rs index 9939f1e36ea9..ef25e5d0fc2e 100644 --- a/src/test/parse-fail/empty-impl-semicolon.rs +++ b/src/test/parse-fail/empty-impl-semicolon.rs @@ -10,4 +10,4 @@ // compile-flags: -Z parse-only -impl Foo; //~ ERROR expected one of `!`, `(`, `+`, `::`, `<`, `for`, `where`, or `{`, found `;` +impl Foo; //~ ERROR expected one of `!`, `(`, `+`, `::`, `for`, `where`, or `{`, found `;` diff --git a/src/test/parse-fail/multitrait.rs b/src/test/parse-fail/multitrait.rs index b7c9b1658846..d2be89d19ece 100644 --- a/src/test/parse-fail/multitrait.rs +++ b/src/test/parse-fail/multitrait.rs @@ -15,7 +15,7 @@ struct S { } impl Cmp, ToString for S { -//~^ ERROR: expected one of `!`, `(`, `+`, `::`, `<`, `for`, `where`, or `{`, found `,` +//~^ ERROR: expected one of `!`, `(`, `+`, `::`, `for`, `where`, or `{`, found `,` fn eq(&&other: S) { false } fn to_string(&self) -> String { "hi".to_string() } } diff --git a/src/test/parse-fail/removed-syntax-closure-lifetime.rs b/src/test/parse-fail/removed-syntax-closure-lifetime.rs index b305b1894a81..2dd2bd22d1a3 100644 --- a/src/test/parse-fail/removed-syntax-closure-lifetime.rs +++ b/src/test/parse-fail/removed-syntax-closure-lifetime.rs @@ -11,4 +11,4 @@ // compile-flags: -Z parse-only type closure = Box; -//~^ ERROR expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `/` +//~^ ERROR expected one of `!`, `(`, `+`, `,`, `::`, or `>`, found `/` diff --git a/src/test/parse-fail/removed-syntax-fixed-vec.rs b/src/test/parse-fail/removed-syntax-fixed-vec.rs index 0f34db088520..f943d5d50cac 100644 --- a/src/test/parse-fail/removed-syntax-fixed-vec.rs +++ b/src/test/parse-fail/removed-syntax-fixed-vec.rs @@ -10,4 +10,4 @@ // compile-flags: -Z parse-only -type v = [isize * 3]; //~ ERROR expected one of `!`, `(`, `+`, `::`, `;`, `<`, or `]`, found `*` +type v = [isize * 3]; //~ ERROR expected one of `!`, `(`, `+`, `::`, `;`, or `]`, found `*` diff --git a/src/test/parse-fail/removed-syntax-ptr-lifetime.rs b/src/test/parse-fail/removed-syntax-ptr-lifetime.rs index b91ab8730b3d..40f368e71054 100644 --- a/src/test/parse-fail/removed-syntax-ptr-lifetime.rs +++ b/src/test/parse-fail/removed-syntax-ptr-lifetime.rs @@ -10,4 +10,4 @@ // compile-flags: -Z parse-only -type bptr = &lifetime/isize; //~ ERROR expected one of `!`, `(`, `::`, `;`, or `<`, found `/` +type bptr = &lifetime/isize; //~ ERROR expected one of `!`, `(`, `::`, or `;`, found `/` diff --git a/src/test/ui/issue-22644.stderr b/src/test/ui/issue-22644.stderr index 1e85daa57780..2cbb42653565 100644 --- a/src/test/ui/issue-22644.stderr +++ b/src/test/ui/issue-22644.stderr @@ -1,13 +1,13 @@ -warning: `<` is interpreted as a start of generic arguments for `usize`, not comparison +warning: `<` is interpreted as a start of generic arguments for `usize`, not a comparison --> $DIR/issue-22644.rs:16:33 | 16 | println!("{}", a as usize < b); | ^ expected one of `!`, `(`, `+`, `,`, `::`, or `>` here | -help: if you want to compare the casted value then write +help: if you want to compare the casted value then write: | println!("{}", (a as usize) < b); -warning: `<` is interpreted as a start of generic arguments for `usize`, not comparison +warning: `<` is interpreted as a start of generic arguments for `usize`, not a comparison --> $DIR/issue-22644.rs:17:33 | 17 | println!("{}", a as usize < 4); @@ -15,6 +15,6 @@ warning: `<` is interpreted as a start of generic arguments for `usize`, not com | | | expected one of `>`, identifier, lifetime, or type here | -help: if you want to compare the casted value then write +help: if you want to compare the casted value then write: | println!("{}", (a as usize) < 4); From f8d36581479e929f4bd12e506d70b1552948925e Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 9 Jun 2017 19:05:14 +0200 Subject: [PATCH 153/233] Add E0608 --- src/librustc_typeck/check/mod.rs | 10 +++------- src/librustc_typeck/diagnostics.rs | 21 ++++++++++++++++++++ src/test/compile-fail/E0608.rs | 13 ++++++++++++ src/test/compile-fail/index-bot.rs | 2 +- src/test/compile-fail/index_message.rs | 2 +- src/test/compile-fail/issue-27842.rs | 4 ++-- src/test/compile-fail/issue-40861.rs | 2 +- src/test/compile-fail/slice-2.rs | 8 ++++---- src/test/ui/span/suggestion-non-ascii.stderr | 2 +- 9 files changed, 47 insertions(+), 17 deletions(-) create mode 100644 src/test/compile-fail/E0608.rs diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 880137f7c71b..d428852d39e8 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3889,13 +3889,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { element_ty } None => { - let mut err = self.type_error_struct( - expr.span, - |actual| { - format!("cannot index a value of type `{}`", - actual) - }, - base_t); + let mut err = struct_span_err!(tcx.sess, expr.span, E0608, + "cannot index into a value of type `{}`", + base_t); // Try to give some advice about indexing tuples. if let ty::TyTuple(..) = base_t.sty { let mut needs_note = true; diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 6ccfab0a324b..5342fb6cc878 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -4095,6 +4095,27 @@ assert_eq!(!Question::No, true); ``` "##, +E0608: r##" +An attempt to index into a type which doesn't implement the `std::ops::Index` +trait was performed. + +Erroneous code example: + +```compile_fail,E0608 +0u8[2]; // error: cannot index into a value of type `u8` +``` + +To be able to index a value from a type, it needs to implement the +`std::ops::Index` trait. Example: + +``` +let v: Vec = vec![0, 1, 2, 3]; + +// The `Vec` type implements the `Index` trait so you can do: +println!("{}", v[2]); +``` +"##, + E0609: r##" Attempted to access a non-existent field in a struct. diff --git a/src/test/compile-fail/E0608.rs b/src/test/compile-fail/E0608.rs new file mode 100644 index 000000000000..d47356a97eed --- /dev/null +++ b/src/test/compile-fail/E0608.rs @@ -0,0 +1,13 @@ +// 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. + +fn main() { + 0u8[2]; //~ ERROR E0608 +} diff --git a/src/test/compile-fail/index-bot.rs b/src/test/compile-fail/index-bot.rs index 05b047233004..fc88ff6f47b8 100644 --- a/src/test/compile-fail/index-bot.rs +++ b/src/test/compile-fail/index-bot.rs @@ -9,5 +9,5 @@ // except according to those terms. fn main() { - (return)[0]; //~ ERROR cannot index a value of type `!` + (return)[0]; //~ ERROR cannot index into a value of type `!` } diff --git a/src/test/compile-fail/index_message.rs b/src/test/compile-fail/index_message.rs index 26dd98757a8c..b9daad936c33 100644 --- a/src/test/compile-fail/index_message.rs +++ b/src/test/compile-fail/index_message.rs @@ -10,5 +10,5 @@ fn main() { let z = (); - let _ = z[0]; //~ ERROR cannot index a value of type `()` + let _ = z[0]; //~ ERROR cannot index into a value of type `()` } diff --git a/src/test/compile-fail/issue-27842.rs b/src/test/compile-fail/issue-27842.rs index f7cd4e03c3b1..8c71761df2fb 100644 --- a/src/test/compile-fail/issue-27842.rs +++ b/src/test/compile-fail/issue-27842.rs @@ -12,13 +12,13 @@ fn main() { let tup = (0, 1, 2); // the case where we show a suggestion let _ = tup[0]; - //~^ ERROR cannot index a value of type + //~^ ERROR cannot index into a value of type //~| HELP to access tuple elements, use //~| SUGGESTION let _ = tup.0 // the case where we show just a general hint let i = 0_usize; let _ = tup[i]; - //~^ ERROR cannot index a value of type + //~^ ERROR cannot index into a value of type //~| HELP to access tuple elements, use tuple indexing syntax (e.g. `tuple.0`) } diff --git a/src/test/compile-fail/issue-40861.rs b/src/test/compile-fail/issue-40861.rs index e525b3954f5e..75d58c58538d 100644 --- a/src/test/compile-fail/issue-40861.rs +++ b/src/test/compile-fail/issue-40861.rs @@ -12,5 +12,5 @@ fn f(_: &[f32]) {} fn main() { ()[f(&[1.0])]; - //~^ ERROR cannot index a value of type `()` + //~^ ERROR cannot index into a value of type `()` } diff --git a/src/test/compile-fail/slice-2.rs b/src/test/compile-fail/slice-2.rs index 99dc3e68c8f7..44b9d94c5665 100644 --- a/src/test/compile-fail/slice-2.rs +++ b/src/test/compile-fail/slice-2.rs @@ -14,8 +14,8 @@ struct Foo; fn main() { let x = Foo; - &x[..]; //~ ERROR cannot index a value of type `Foo` - &x[Foo..]; //~ ERROR cannot index a value of type `Foo` - &x[..Foo]; //~ ERROR cannot index a value of type `Foo` - &x[Foo..Foo]; //~ ERROR cannot index a value of type `Foo` + &x[..]; //~ ERROR cannot index into a value of type `Foo` + &x[Foo..]; //~ ERROR cannot index into a value of type `Foo` + &x[..Foo]; //~ ERROR cannot index into a value of type `Foo` + &x[Foo..Foo]; //~ ERROR cannot index into a value of type `Foo` } diff --git a/src/test/ui/span/suggestion-non-ascii.stderr b/src/test/ui/span/suggestion-non-ascii.stderr index b6353c0f6a20..68d43d3f5cd8 100644 --- a/src/test/ui/span/suggestion-non-ascii.stderr +++ b/src/test/ui/span/suggestion-non-ascii.stderr @@ -1,4 +1,4 @@ -error: cannot index a value of type `({integer},)` +error[E0608]: cannot index into a value of type `({integer},)` --> $DIR/suggestion-non-ascii.rs:14:21 | 14 | println!("☃{}", tup[0]); From 46a6af12aa8d688aa52279647b01be6035adf22c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 12 Jun 2017 10:22:08 -0700 Subject: [PATCH 154/233] Change `<` interpreted as generic arg start warning ``` warning: `<` is interpreted as a start of generic arguments for `usize`, not a comparison --> $DIR/issue-22644.rs:16:33 | 16 | println!("{}", a as usize < b); | - ^ interpreted as generic argument | | | not interpreted as comparison | help: if you want to compare the casted value then write: | println!("{}", (a as usize) < b); ``` --- src/libsyntax/parse/parser.rs | 56 ++++++++++++++++++++-------------- src/test/ui/issue-22644.stderr | 10 +++--- 2 files changed, 39 insertions(+), 27 deletions(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index ee74d9ec2e65..b3623fbe3ac1 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -42,7 +42,7 @@ use ast::RangeEnd; use {ast, attr}; use codemap::{self, CodeMap, Spanned, respan}; use syntax_pos::{self, Span, BytePos}; -use errors::{self, DiagnosticBuilder, Level}; +use errors::{self, DiagnosticBuilder}; use parse::{self, classify, token}; use parse::common::SeqSep; use parse::lexer::TokenAndSpan; @@ -441,7 +441,14 @@ fn dummy_arg(span: Span) -> Arg { Arg { ty: P(ty), pat: pat, id: ast::DUMMY_NODE_ID } } -type RewindPoint = (token::Token, Span, Option, Span, TokenCursor, Vec); +struct RewindPoint { + token: token::Token, + span: Span, + meta_var_span: Option, + prev_span: Span, + token_cursor: TokenCursor, + expected_tokens: Vec, +} impl<'a> Parser<'a> { pub fn new(sess: &'a ParseSess, @@ -2835,11 +2842,13 @@ impl<'a> Parser<'a> { // Rewind to before attempting to parse the type with generics, to get // arround #22644. let rp_err = self.get_rewind_point(); + let sp = rp_err.span.clone(); self.rewind(rp); let lo = self.span; let path = match self.parse_path_without_generics(PathStyle::Type) { Ok(path) => { // Successfully parsed the type leaving a `<` yet to parse + err.cancel(); let codemap = self.sess.codemap(); let suggestion_span = lhs_span.to(self.prev_span); let suggestion = match codemap.span_to_snippet(suggestion_span) { @@ -2850,15 +2859,17 @@ impl<'a> Parser<'a> { Ok(lstring) => format!("`{}`", lstring), _ => "a type".to_string(), }; - err.span_suggestion(suggestion_span, + let msg = format!("`<` is interpreted as a start of generic \ + arguments for {}, not a comparison", + warn_message); + let mut warn = self.sess.span_diagnostic.struct_span_warn(sp, &msg); + warn.span_label(sp, "interpreted as generic argument"); + warn.span_label(self.span, "not interpreted as comparison"); + warn.span_suggestion(suggestion_span, "if you want to compare the casted value \ then write:", suggestion); - err.level = Level::Warning; - err.set_message(&format!("`<` is interpreted as a start of generic \ - arguments for {}, not a comparison", - warn_message)); - err.emit(); + warn.emit(); path } Err(mut path_err) => { @@ -6255,23 +6266,22 @@ impl<'a> Parser<'a> { } fn get_rewind_point(&mut self) -> RewindPoint { - ( - self.token.clone(), - self.span, - self.meta_var_span, - self.prev_span, - self.token_cursor.clone(), - self.expected_tokens.clone(), - ) + RewindPoint { + token: self.token.clone(), + span: self.span, + meta_var_span: self.meta_var_span, + prev_span: self.prev_span, + token_cursor: self.token_cursor.clone(), + expected_tokens: self.expected_tokens.clone(), + } } fn rewind(&mut self, rp: RewindPoint) { - let (token, span, meta_var_span, prev_span, token_cursor, expected_tokens,) = rp; - self.token = token; - self.span = span; - self.meta_var_span = meta_var_span; - self.prev_span = prev_span; - self.token_cursor = token_cursor; - self.expected_tokens = expected_tokens; + self.token = rp.token; + self.span = rp.span; + self.meta_var_span = rp.meta_var_span; + self.prev_span = rp.prev_span; + self.token_cursor = rp.token_cursor; + self.expected_tokens = rp.expected_tokens; } } diff --git a/src/test/ui/issue-22644.stderr b/src/test/ui/issue-22644.stderr index 2cbb42653565..1e7861755877 100644 --- a/src/test/ui/issue-22644.stderr +++ b/src/test/ui/issue-22644.stderr @@ -2,7 +2,9 @@ warning: `<` is interpreted as a start of generic arguments for `usize`, not a c --> $DIR/issue-22644.rs:16:33 | 16 | println!("{}", a as usize < b); - | ^ expected one of `!`, `(`, `+`, `,`, `::`, or `>` here + | - ^ interpreted as generic argument + | | + | not interpreted as comparison | help: if you want to compare the casted value then write: | println!("{}", (a as usize) < b); @@ -11,9 +13,9 @@ warning: `<` is interpreted as a start of generic arguments for `usize`, not a c --> $DIR/issue-22644.rs:17:33 | 17 | println!("{}", a as usize < 4); - | -^ unexpected token - | | - | expected one of `>`, identifier, lifetime, or type here + | - ^ interpreted as generic argument + | | + | not interpreted as comparison | help: if you want to compare the casted value then write: | println!("{}", (a as usize) < 4); From d11973ae2a41bb84cd933e6646f3d8e6f28201e8 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 12 Jun 2017 21:47:39 +0200 Subject: [PATCH 155/233] External spans: added lazy source loading elsewhere * In other places where the `src` member of a file map is accessed, we now load and possibly work with external source as well. --- src/libsyntax/codemap.rs | 45 ++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index 5b10139cd196..b3d9cf9da36c 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -415,30 +415,31 @@ impl CodeMap { local_end.fm.start_pos) })); } else { - match local_begin.fm.src { - Some(ref src) => { - let start_index = local_begin.pos.to_usize(); - let end_index = local_end.pos.to_usize(); - let source_len = (local_begin.fm.end_pos - - local_begin.fm.start_pos).to_usize(); + self.ensure_filemap_source_present(local_begin.fm.clone()); - if start_index > end_index || end_index > source_len { - return Err(SpanSnippetError::MalformedForCodemap( - MalformedCodemapPositions { - name: local_begin.fm.name.clone(), - source_len: source_len, - begin_pos: local_begin.pos, - end_pos: local_end.pos, - })); - } + let start_index = local_begin.pos.to_usize(); + let end_index = local_end.pos.to_usize(); + let source_len = (local_begin.fm.end_pos - + local_begin.fm.start_pos).to_usize(); - return Ok((&src[start_index..end_index]).to_string()) - } - None => { - return Err(SpanSnippetError::SourceNotAvailable { - filename: local_begin.fm.name.clone() - }); - } + if start_index > end_index || end_index > source_len { + return Err(SpanSnippetError::MalformedForCodemap( + MalformedCodemapPositions { + name: local_begin.fm.name.clone(), + source_len: source_len, + begin_pos: local_begin.pos, + end_pos: local_end.pos, + })); + } + + if let Some(ref src) = local_begin.fm.src { + return Ok((&src[start_index..end_index]).to_string()); + } else if let Some(src) = local_begin.fm.external_src.borrow().get_source() { + return Ok((&src[start_index..end_index]).to_string()); + } else { + return Err(SpanSnippetError::SourceNotAvailable { + filename: local_begin.fm.name.clone() + }); } } } From 3f99118871371fae708f23aaf7632d26ad9251a5 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 8 Jun 2017 13:22:57 -0400 Subject: [PATCH 156/233] kill various tasks we no longer need and remove outdated README text In the case of `TransCrateItem`, I had to tweak the tests a bit, but it's a concept that doesn't work well under new system. --- src/librustc/dep_graph/README.md | 137 +----------------- src/librustc/dep_graph/dep_node.rs | 5 - src/librustc/lint/context.rs | 3 - src/librustc_incremental/persist/preds/mod.rs | 3 +- src/librustc_trans/trans_item.rs | 18 --- src/librustc_typeck/coherence/overlap.rs | 5 - .../dep-graph-assoc-type-trans.rs | 1 - .../compile-fail/dep-graph-caller-callee.rs | 2 - src/test/compile-fail/dep-graph-trait-impl.rs | 5 - src/test/incremental/dirty_clean.rs | 4 - src/test/incremental/krate-inlined.rs | 14 +- .../incremental/remapped_paths_cc/main.rs | 4 - src/test/incremental/string_constant.rs | 3 - 13 files changed, 13 insertions(+), 191 deletions(-) diff --git a/src/librustc/dep_graph/README.md b/src/librustc/dep_graph/README.md index 72715cf6bc74..c747c443b3a4 100644 --- a/src/librustc/dep_graph/README.md +++ b/src/librustc/dep_graph/README.md @@ -18,7 +18,7 @@ one of three things: 1. HIR nodes (like `Hir(DefId)`) represent the HIR input itself. 2. Data nodes (like `ItemSignature(DefId)`) represent some computed information about a particular item. -3. Procedure notes (like `CoherenceCheckImpl(DefId)`) represent some +3. Procedure nodes (like `CoherenceCheckTrait(DefId)`) represent some procedure that is executing. Usually this procedure is performing some kind of check for errors. You can think of them as computed values where the value being computed is `()` (and the @@ -57,139 +57,10 @@ recompile that item for sure. But we need the dep tracking map to tell us what *else* we have to recompile. Shared state is anything that is used to communicate results from one item to another. -### Identifying the current task +### Identifying the current task, tracking reads/writes, etc -The dep graph always tracks a current task: this is basically the -`DepNode` that the compiler is computing right now. Typically it would -be a procedure node, but it can also be a data node (as noted above, -the two are kind of equivalent). - -You set the current task by calling `dep_graph.in_task(node)`. For example: - -```rust -let _task = tcx.dep_graph.in_task(DepNode::Privacy); -``` - -Now all the code until `_task` goes out of scope will be considered -part of the "privacy task". - -The tasks are maintained in a stack, so it is perfectly fine to nest -one task within another. Because pushing a task is considered to be -computing a value, when you nest a task `N2` inside of a task `N1`, we -automatically add an edge `N2 -> N1` (since `N1` presumably needed the -result of `N2` to complete): - -```rust -let _n1 = tcx.dep_graph.in_task(DepNode::N1); -let _n2 = tcx.dep_graph.in_task(DepNode::N2); -// this will result in an edge N1 -> n2 -``` - -### Ignore tasks - -Although it is rarely needed, you can also push a special "ignore" -task: - -```rust -let _ignore = tc.dep_graph.in_ignore(); -``` - -This will cause all read/write edges to be ignored until it goes out -of scope or until something else is pushed. For example, we could -suppress the edge between nested tasks like so: - -```rust -let _n1 = tcx.dep_graph.in_task(DepNode::N1); -let _ignore = tcx.dep_graph.in_ignore(); -let _n2 = tcx.dep_graph.in_task(DepNode::N2); -// now no edge is added -``` - -### Tracking reads and writes - -We need to identify what shared state is read/written by the current -task as it executes. The most fundamental way of doing that is to invoke -the `read` and `write` methods on `DepGraph`: - -```rust -// Adds an edge from DepNode::Hir(some_def_id) to the current task -tcx.dep_graph.read(DepNode::Hir(some_def_id)) - -// Adds an edge from the current task to DepNode::ItemSignature(some_def_id) -tcx.dep_graph.write(DepNode::ItemSignature(some_def_id)) -``` - -However, you should rarely need to invoke those methods directly. -Instead, the idea is to *encapsulate* shared state into some API that -will invoke `read` and `write` automatically. The most common way to -do this is to use a `DepTrackingMap`, described in the next section, -but any sort of abstraction barrier will do. In general, the strategy -is that getting access to information implicitly adds an appropriate -`read`. So, for example, when you use the -`dep_graph::visit_all_items_in_krate` helper method, it will visit -each item `X`, start a task `Foo(X)` for that item, and automatically -add an edge `Hir(X) -> Foo(X)`. This edge is added because the code is -being given access to the HIR node for `X`, and hence it is expected -to read from it. Similarly, reading from the `tcache` map for item `X` -(which is a `DepTrackingMap`, described below) automatically invokes -`dep_graph.read(ItemSignature(X))`. - -**Note:** adding `Hir` nodes requires a bit of caution due to the -"inlining" that old trans and constant evaluation still use. See the -section on inlining below. - -To make this strategy work, a certain amount of indirection is -required. For example, modules in the HIR do not have direct pointers -to the items that they contain. Rather, they contain node-ids -- one -can then ask the HIR map for the item with a given node-id. This gives -us an opportunity to add an appropriate read edge. - -#### Explicit calls to read and write when starting a new subtask - -One time when you *may* need to call `read` and `write` directly is -when you push a new task onto the stack, either by calling `in_task` -as shown above or indirectly, such as with the `memoize` pattern -described below. In that case, any data that the task has access to -from the surrounding environment must be explicitly "read". For -example, in `librustc_typeck`, the collection code visits all items -and, among other things, starts a subtask producing its signature -(what follows is simplified pseudocode, of course): - -```rust -fn visit_item(item: &hir::Item) { - // Here, current subtask is "Collect(X)", and an edge Hir(X) -> Collect(X) - // has automatically been added by `visit_all_items_in_krate`. - let sig = signature_of_item(item); -} - -fn signature_of_item(item: &hir::Item) { - let def_id = tcx.map.local_def_id(item.id); - let task = tcx.dep_graph.in_task(DepNode::ItemSignature(def_id)); - tcx.dep_graph.read(DepNode::Hir(def_id)); // <-- the interesting line - ... -} -``` - -Here you can see that, in `signature_of_item`, we started a subtask -corresponding to producing the `ItemSignature`. This subtask will read from -`item` -- but it gained access to `item` implicitly. This means that if it just -reads from `item`, there would be missing edges in the graph: - - Hir(X) --+ // added by the explicit call to `read` - | | - | +---> ItemSignature(X) -> Collect(X) - | ^ - | | - +---------------------------------+ // added by `visit_all_items_in_krate` - -In particular, the edge from `Hir(X)` to `ItemSignature(X)` is only -present because we called `read` ourselves when entering the `ItemSignature(X)` -task. - -So, the rule of thumb: when entering a new task yourself, register -reads on any shared state that you inherit. (This actually comes up -fairly infrequently though: the main place you need caution is around -memoization.) +FIXME(#42293). This text needs to be rewritten for the new red-green +system, which doesn't fully exist yet. #### Dependency tracking map diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 3b6a7f87c13a..d5b57874766c 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -315,9 +315,6 @@ define_dep_nodes!( Coherence, Resolve, CoherenceCheckTrait(DefId), - CoherenceCheckImpl(DefId), - CoherenceOverlapCheck(DefId), - CoherenceOverlapCheckSpecial(DefId), Variance, PrivacyAccessLevels(CrateNum), @@ -332,8 +329,6 @@ define_dep_nodes!( RvalueCheck(DefId), Reachability, MirKeys, - LateLintCheck, - TransCrateItem(DefId), TransWriteMetadata, CrateVariances, diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index aa7428e59103..a9e0ef511024 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -25,7 +25,6 @@ //! for all lint attributes. use self::TargetLint::*; -use dep_graph::{DepNode, DepKind}; use middle::privacy::AccessLevels; use traits::Reveal; use ty::{self, TyCtxt}; @@ -1341,8 +1340,6 @@ fn check_lint_name_cmdline(sess: &Session, lint_cx: &LintStore, /// /// Consumes the `lint_store` field of the `Session`. pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { - let _task = tcx.dep_graph.in_task(DepNode::new_no_params(DepKind::LateLintCheck)); - let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE); let krate = tcx.hir.krate(); diff --git a/src/librustc_incremental/persist/preds/mod.rs b/src/librustc_incremental/persist/preds/mod.rs index 0a259ad26858..f7b6b7376d1f 100644 --- a/src/librustc_incremental/persist/preds/mod.rs +++ b/src/librustc_incremental/persist/preds/mod.rs @@ -57,8 +57,7 @@ impl<'q> Predecessors<'q> { } // if -Z query-dep-graph is passed, save more extended data // to enable better unit testing - DepKind::TypeckTables | - DepKind::TransCrateItem => tcx.sess.opts.debugging_opts.query_dep_graph, + DepKind::TypeckTables => tcx.sess.opts.debugging_opts.query_dep_graph, _ => false, } diff --git a/src/librustc_trans/trans_item.rs b/src/librustc_trans/trans_item.rs index 2a36ef9358e4..0dc2bc85e30e 100644 --- a/src/librustc_trans/trans_item.rs +++ b/src/librustc_trans/trans_item.rs @@ -23,7 +23,6 @@ use common; use declare; use llvm; use monomorphize::Instance; -use rustc::dep_graph::DepKind; use rustc::hir; use rustc::hir::def_id::DefId; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; @@ -63,22 +62,9 @@ impl<'a, 'tcx> TransItem<'tcx> { self.to_raw_string(), ccx.codegen_unit().name()); - // (*) This code executes in the context of a dep-node for the - // entire CGU. In some cases, we introduce dep-nodes for - // particular items that we are translating (these nodes will - // have read edges coming into the CGU node). These smaller - // nodes are not needed for correctness -- we always - // invalidate an entire CGU at a time -- but they enable - // finer-grained testing, since you can write tests that check - // that the incoming edges to a particular fn are from a - // particular set. - match *self { TransItem::Static(node_id) => { let tcx = ccx.tcx(); - let def_id = tcx.hir.local_def_id(node_id); - let dep_node = def_id.to_dep_node(tcx, DepKind::TransCrateItem); - let _task = ccx.tcx().dep_graph.in_task(dep_node); // (*) let item = tcx.hir.expect_item(node_id); if let hir::ItemStatic(_, m, _) = item.node { match consts::trans_static(&ccx, m, item.id, &item.attrs) { @@ -100,10 +86,6 @@ impl<'a, 'tcx> TransItem<'tcx> { } } TransItem::Fn(instance) => { - let _task = ccx.tcx().dep_graph.in_task( - instance.def_id() - .to_dep_node(ccx.tcx(), DepKind::TransCrateItem)); // (*) - base::trans_instance(&ccx, instance); } } diff --git a/src/librustc_typeck/coherence/overlap.rs b/src/librustc_typeck/coherence/overlap.rs index 781e323dea39..59ebae16d08c 100644 --- a/src/librustc_typeck/coherence/overlap.rs +++ b/src/librustc_typeck/coherence/overlap.rs @@ -15,7 +15,6 @@ use rustc::traits; use rustc::ty::{self, TyCtxt, TypeFoldable}; use syntax::ast; -use rustc::dep_graph::DepKind; use rustc::hir; use rustc::hir::itemlikevisit::ItemLikeVisitor; @@ -38,10 +37,6 @@ pub fn check_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, node_id: ast::NodeId) { return } - let _task = - tcx.dep_graph.in_task(trait_def_id.to_dep_node(tcx, - DepKind::CoherenceOverlapCheck)); - // Trigger building the specialization graph for the trait of this impl. // This will detect any overlap errors. tcx.specialization_graph_of(trait_def_id); diff --git a/src/test/compile-fail/dep-graph-assoc-type-trans.rs b/src/test/compile-fail/dep-graph-assoc-type-trans.rs index fe76a4d439f3..007a80008a84 100644 --- a/src/test/compile-fail/dep-graph-assoc-type-trans.rs +++ b/src/test/compile-fail/dep-graph-assoc-type-trans.rs @@ -36,7 +36,6 @@ mod y { use Foo; #[rustc_then_this_would_need(TypeckTables)] //~ ERROR OK - #[rustc_then_this_would_need(TransCrateItem)] //~ ERROR OK pub fn use_char_assoc() { // Careful here: in the representation, ::T gets // normalized away, so at a certain point we had no edge to diff --git a/src/test/compile-fail/dep-graph-caller-callee.rs b/src/test/compile-fail/dep-graph-caller-callee.rs index 9cb87886809a..222c19720055 100644 --- a/src/test/compile-fail/dep-graph-caller-callee.rs +++ b/src/test/compile-fail/dep-graph-caller-callee.rs @@ -28,7 +28,6 @@ mod y { // These dependencies SHOULD exist: #[rustc_then_this_would_need(TypeckTables)] //~ ERROR OK - #[rustc_then_this_would_need(TransCrateItem)] //~ ERROR OK pub fn y() { x::x(); } @@ -40,7 +39,6 @@ mod z { // These are expected to yield errors, because changes to `x` // affect the BODY of `y`, but not its signature. #[rustc_then_this_would_need(TypeckTables)] //~ ERROR no path - #[rustc_then_this_would_need(TransCrateItem)] //~ ERROR no path pub fn z() { y::y(); } diff --git a/src/test/compile-fail/dep-graph-trait-impl.rs b/src/test/compile-fail/dep-graph-trait-impl.rs index c0f9f0546260..85b3e69065d9 100644 --- a/src/test/compile-fail/dep-graph-trait-impl.rs +++ b/src/test/compile-fail/dep-graph-trait-impl.rs @@ -35,25 +35,21 @@ mod y { use Foo; #[rustc_then_this_would_need(TypeckTables)] //~ ERROR OK - #[rustc_then_this_would_need(TransCrateItem)] //~ ERROR OK pub fn with_char() { char::method('a'); } #[rustc_then_this_would_need(TypeckTables)] //~ ERROR OK - #[rustc_then_this_would_need(TransCrateItem)] //~ ERROR OK pub fn take_foo_with_char() { take_foo::('a'); } #[rustc_then_this_would_need(TypeckTables)] //~ ERROR OK - #[rustc_then_this_would_need(TransCrateItem)] //~ ERROR OK pub fn with_u32() { u32::method(22); } #[rustc_then_this_would_need(TypeckTables)] //~ ERROR OK - #[rustc_then_this_would_need(TransCrateItem)] //~ ERROR OK pub fn take_foo_with_u32() { take_foo::(22); } @@ -67,7 +63,6 @@ mod z { // These are expected to yield errors, because changes to `x` // affect the BODY of `y`, but not its signature. #[rustc_then_this_would_need(TypeckTables)] //~ ERROR no path - #[rustc_then_this_would_need(TransCrateItem)] //~ ERROR no path pub fn z() { y::with_char(); y::with_u32(); diff --git a/src/test/incremental/dirty_clean.rs b/src/test/incremental/dirty_clean.rs index ce9865103dcc..b828cc9c70ae 100644 --- a/src/test/incremental/dirty_clean.rs +++ b/src/test/incremental/dirty_clean.rs @@ -36,19 +36,15 @@ mod y { use x; #[rustc_clean(label="TypeckTables", cfg="cfail2")] - #[rustc_clean(label="TransCrateItem", cfg="cfail2")] pub fn y() { //[cfail2]~^ ERROR `TypeckTables(y::y)` not found in dep graph, but should be clean - //[cfail2]~| ERROR `TransCrateItem(y::y)` not found in dep graph, but should be clean x::x(); } } mod z { #[rustc_dirty(label="TypeckTables", cfg="cfail2")] - #[rustc_dirty(label="TransCrateItem", cfg="cfail2")] pub fn z() { //[cfail2]~^ ERROR `TypeckTables(z::z)` found in dep graph, but should be dirty - //[cfail2]~| ERROR `TransCrateItem(z::z)` found in dep graph, but should be dirty } } diff --git a/src/test/incremental/krate-inlined.rs b/src/test/incremental/krate-inlined.rs index ba32b41983fc..043cb761da09 100644 --- a/src/test/incremental/krate-inlined.rs +++ b/src/test/incremental/krate-inlined.rs @@ -9,20 +9,22 @@ // except according to those terms. // Regr. test that using HIR inlined from another krate does *not* add -// a dependency from the local Krate node. +// a dependency from the local Krate node. We can't easily test that +// directly anymore, so now we test that we get reuse. -// revisions: cfail1 +// revisions: rpass1 rpass2 // compile-flags: -Z query-dep-graph #![allow(warnings)] #![feature(rustc_attrs)] +#![rustc_partition_reused(module="krate_inlined-x", cfg="rpass2")] -#![rustc_if_this_changed(Krate)] - -fn main() { } +fn main() { + #[cfg(rpass2)] + () +} mod x { - #[rustc_then_this_would_need(TransCrateItem)] //[cfail1]~ ERROR no path fn method() { // use some methods that require inlining HIR from another crate: let mut v = vec![]; diff --git a/src/test/incremental/remapped_paths_cc/main.rs b/src/test/incremental/remapped_paths_cc/main.rs index be4764c7d994..701c5fec49b5 100644 --- a/src/test/incremental/remapped_paths_cc/main.rs +++ b/src/test/incremental/remapped_paths_cc/main.rs @@ -25,8 +25,6 @@ extern crate extern_crate; -#[rustc_clean(label="TransCrateItem", cfg="rpass2")] -#[rustc_clean(label="TransCrateItem", cfg="rpass3")] fn main() { some_mod::some_fn(); } @@ -34,8 +32,6 @@ fn main() { mod some_mod { use extern_crate; - #[rustc_clean(label="TransCrateItem", cfg="rpass2")] - #[rustc_dirty(label="TransCrateItem", cfg="rpass3")] pub fn some_fn() { extern_crate::inline_fn(); } diff --git a/src/test/incremental/string_constant.rs b/src/test/incremental/string_constant.rs index 669d001cc63d..36a26cf1755a 100644 --- a/src/test/incremental/string_constant.rs +++ b/src/test/incremental/string_constant.rs @@ -28,7 +28,6 @@ mod x { #[cfg(rpass2)] #[rustc_dirty(label="TypeckTables", cfg="rpass2")] - #[rustc_dirty(label="TransCrateItem", cfg="rpass2")] pub fn x() { println!("{}", "2"); } @@ -38,7 +37,6 @@ mod y { use x; #[rustc_clean(label="TypeckTables", cfg="rpass2")] - #[rustc_clean(label="TransCrateItem", cfg="rpass2")] pub fn y() { x::x(); } @@ -48,7 +46,6 @@ mod z { use y; #[rustc_clean(label="TypeckTables", cfg="rpass2")] - #[rustc_clean(label="TransCrateItem", cfg="rpass2")] pub fn z() { y::y(); } From 03ff38e0182592d0d131580abc534a1f29f9d8fd Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 9 Jun 2017 21:20:47 -0400 Subject: [PATCH 157/233] kill various DepNode variants --- src/librustc/dep_graph/dep_node.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index d5b57874766c..fda29ca73662 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -315,12 +315,10 @@ define_dep_nodes!( Coherence, Resolve, CoherenceCheckTrait(DefId), - Variance, PrivacyAccessLevels(CrateNum), // Represents the MIR for a fn; also used as the task node for // things read/modify that MIR. - MirKrate, Mir(DefId), MirShim(DefIdList), @@ -350,7 +348,6 @@ define_dep_nodes!( InherentImpls(DefId), TypeckBodiesKrate, TypeckTables(DefId), - UsedTraitImports(DefId), ConstEval(DefId), SymbolName(DefId), SpecializationGraph(DefId), From f61bee340c5fc6b7aeb64f6cf63ba760432b2945 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 12 Jun 2017 15:31:24 -0400 Subject: [PATCH 158/233] kill dep-graph-unrelated test Doesnt' seem to add much value, and since we don't track `TransCrateItem` anymore, it's not clear what to translate it to. --- src/test/compile-fail/dep-graph-unrelated.rs | 22 -------------------- 1 file changed, 22 deletions(-) delete mode 100644 src/test/compile-fail/dep-graph-unrelated.rs diff --git a/src/test/compile-fail/dep-graph-unrelated.rs b/src/test/compile-fail/dep-graph-unrelated.rs deleted file mode 100644 index 079f2b52fd46..000000000000 --- a/src/test/compile-fail/dep-graph-unrelated.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Test that two unrelated functions have no trans dependency. - -// compile-flags: -Z query-dep-graph - -#![feature(rustc_attrs)] -#![allow(dead_code)] - -#[rustc_if_this_changed] -fn main() { } - -#[rustc_then_this_would_need(TransCrateItem)] //~ ERROR no path from `main` -fn bar() { } From 36973f743fa5155382ff92e482a9ebdaf6a710a3 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 12 Jun 2017 15:56:01 -0400 Subject: [PATCH 159/233] consider closures/ty-fn-defs when making trait selection keys Fixes #42602. --- src/librustc/ty/mod.rs | 4 ++- src/test/incremental/issue-42602.rs | 45 +++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 src/test/incremental/issue-42602.rs diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index d6b144ba59a1..13e46a265c69 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -944,7 +944,9 @@ impl<'tcx> TraitPredicate<'tcx> { self.input_types() .flat_map(|t| t.walk()) .filter_map(|t| match t.sty { - ty::TyAdt(adt_def, _) => Some(adt_def.did), + ty::TyAdt(adt_def, ..) => Some(adt_def.did), + ty::TyClosure(def_id, ..) => Some(def_id), + ty::TyFnDef(def_id, ..) => Some(def_id), _ => None }) .next() diff --git a/src/test/incremental/issue-42602.rs b/src/test/incremental/issue-42602.rs new file mode 100644 index 000000000000..cb2236d37503 --- /dev/null +++ b/src/test/incremental/issue-42602.rs @@ -0,0 +1,45 @@ +// 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. + +// Regression test for #42602. It used to be that we had +// a dep-graph like +// +// typeck(foo) -> FnOnce -> typeck(bar) +// +// This was fixed by improving the resolution of the `FnOnce` trait +// selection node. + +// revisions:cfail1 +// compile-flags:-Zquery-dep-graph + +#![feature(rustc_attrs)] + +fn main() { + a::foo(); + b::bar(); +} + +mod a { + #[rustc_if_this_changed(HirBody)] + pub fn foo() { + let x = vec![1, 2, 3]; + let v = || ::std::mem::drop(x); + v(); + } +} + +mod b { + #[rustc_then_this_would_need(TypeckTables)] //[cfail1]~ ERROR no path + pub fn bar() { + let x = vec![1, 2, 3]; + let v = || ::std::mem::drop(x); + v(); + } +} From 68ccba81aea7f4ae86c97d88a6d7a3ea3f758f7e Mon Sep 17 00:00:00 2001 From: Oliver Middleton Date: Mon, 12 Jun 2017 19:00:09 +0100 Subject: [PATCH 160/233] rustdoc: Fix missing enum variant reexports --- src/librustdoc/clean/inline.rs | 8 ++++---- src/librustdoc/visit_ast.rs | 24 ++++++++++-------------- src/test/rustdoc/issue-35488.rs | 23 +++++++++++++++++++++++ 3 files changed, 37 insertions(+), 18 deletions(-) create mode 100644 src/test/rustdoc/issue-35488.rs diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 8f7add14d0a0..e617402d8db3 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -77,10 +77,10 @@ pub fn try_inline(cx: &DocContext, def: Def, name: ast::Name) ret.extend(build_impls(cx, did)); clean::EnumItem(build_enum(cx, did)) } - // Assume that the enum type is reexported next to the variant, and - // variants don't show up in documentation specially. - // Similarly, consider that struct type is reexported next to its constructor. - Def::Variant(..) | + // Never inline enum variants but leave them shown as reexports. + Def::Variant(..) => return None, + // Assume that enum variants and struct types are reexported next to + // their constructors. Def::VariantCtor(..) | Def::StructCtor(..) => return Some(Vec::new()), Def::Mod(did) => { diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 39ebe490d0eb..657aab958bb9 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -329,25 +329,21 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { if !self.view_item_stack.insert(def_node_id) { return false } let ret = match tcx.hir.get(def_node_id) { - hir_map::NodeItem(it) => { + hir_map::NodeItem(&hir::Item { node: hir::ItemMod(ref m), .. }) if glob => { let prev = mem::replace(&mut self.inlining, true); - if glob { - match it.node { - hir::ItemMod(ref m) => { - for i in &m.item_ids { - let i = self.cx.tcx.hir.expect_item(i.id); - self.visit_item(i, None, om); - } - } - hir::ItemEnum(..) => {} - _ => { panic!("glob not mapped to a module or enum"); } - } - } else { - self.visit_item(it, renamed, om); + for i in &m.item_ids { + let i = self.cx.tcx.hir.expect_item(i.id); + self.visit_item(i, None, om); } self.inlining = prev; true } + hir_map::NodeItem(it) if !glob => { + let prev = mem::replace(&mut self.inlining, true); + self.visit_item(it, renamed, om); + self.inlining = prev; + true + } _ => false, }; self.view_item_stack.remove(&def_node_id); diff --git a/src/test/rustdoc/issue-35488.rs b/src/test/rustdoc/issue-35488.rs new file mode 100644 index 000000000000..f24166a65f05 --- /dev/null +++ b/src/test/rustdoc/issue-35488.rs @@ -0,0 +1,23 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +mod foo { + pub enum Foo { + Bar, + } + pub use self::Foo::*; +} + +// @has 'issue_35488/index.html' '//code' 'pub use self::Foo::*;' +// @has 'issue_35488/enum.Foo.html' +pub use self::foo::*; + +// @has 'issue_35488/index.html' '//code' 'pub use std::option::Option::None;' +pub use std::option::Option::None; From 900ba559b637b6d99bc95e6f0d270543713096fd Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Mon, 12 Jun 2017 23:08:08 +0100 Subject: [PATCH 161/233] Compile WindowsMMap too on MSVC --- src/libprofiler_builtins/build.rs | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/libprofiler_builtins/build.rs b/src/libprofiler_builtins/build.rs index a9685ca7e1aa..4397d2ebb21e 100644 --- a/src/libprofiler_builtins/build.rs +++ b/src/libprofiler_builtins/build.rs @@ -21,9 +21,24 @@ fn main() { let target = env::var("TARGET").expect("TARGET was not set"); let cfg = &mut gcc::Config::new(); + let mut profile_sources = vec!["GCDAProfiling.c", + "InstrProfiling.c", + "InstrProfilingBuffer.c", + "InstrProfilingFile.c", + "InstrProfilingMerge.c", + "InstrProfilingMergeFile.c", + "InstrProfilingPlatformDarwin.c", + "InstrProfilingPlatformLinux.c", + "InstrProfilingPlatformOther.c", + "InstrProfilingRuntime.cc", + "InstrProfilingUtil.c", + "InstrProfilingValue.c", + "InstrProfilingWriter.c"]; + if target.contains("msvc") { // Don't pull in extra libraries on MSVC cfg.flag("/Zl"); + profile_sources.push("WindowsMMap.c"); } else { // Turn off various features of gcc and such, mostly copying // compiler-rt's build system already @@ -34,20 +49,6 @@ fn main() { cfg.define("VISIBILITY_HIDDEN", None); } - let profile_sources = &["GCDAProfiling.c", - "InstrProfiling.c", - "InstrProfilingBuffer.c", - "InstrProfilingFile.c", - "InstrProfilingMerge.c", - "InstrProfilingMergeFile.c", - "InstrProfilingPlatformDarwin.c", - "InstrProfilingPlatformLinux.c", - "InstrProfilingPlatformOther.c", - "InstrProfilingRuntime.cc", - "InstrProfilingUtil.c", - "InstrProfilingValue.c", - "InstrProfilingWriter.c"]; - for src in profile_sources { cfg.file(Path::new("../compiler-rt/lib/profile").join(src)); } From 8748bdd353e7d8744fdbb3c1c1b2e6c7f424b065 Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Mon, 12 Jun 2017 23:08:57 +0100 Subject: [PATCH 162/233] Redefine strdup, open, fdopen as _strdup, _open, _fdopen to avoid linking errors on MSVC --- src/libprofiler_builtins/build.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/libprofiler_builtins/build.rs b/src/libprofiler_builtins/build.rs index 4397d2ebb21e..1ee284ff4dab 100644 --- a/src/libprofiler_builtins/build.rs +++ b/src/libprofiler_builtins/build.rs @@ -39,6 +39,9 @@ fn main() { // Don't pull in extra libraries on MSVC cfg.flag("/Zl"); profile_sources.push("WindowsMMap.c"); + cfg.define("strdup", Some("_strdup")); + cfg.define("open", Some("_open")); + cfg.define("fdopen", Some("_fdopen")); } else { // Turn off various features of gcc and such, mostly copying // compiler-rt's build system already From d7039fb2b95d5b1976bb18818347e460832f42bf Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Mon, 12 Jun 2017 23:10:28 +0100 Subject: [PATCH 163/233] Fill in tracking issue for the profile feature --- src/doc/unstable-book/src/compiler-flags/profile.md | 2 +- src/doc/unstable-book/src/language-features/profiler-runtime.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/unstable-book/src/compiler-flags/profile.md b/src/doc/unstable-book/src/compiler-flags/profile.md index 3b4f34e67c53..66d14fd09978 100644 --- a/src/doc/unstable-book/src/compiler-flags/profile.md +++ b/src/doc/unstable-book/src/compiler-flags/profile.md @@ -1,6 +1,6 @@ # `profile` -The tracking issue for this feature is: None +The tracking issue for this feature is: [#42524](https://github.com/rust-lang/rust/issues/42524). ------------------------ diff --git a/src/doc/unstable-book/src/language-features/profiler-runtime.md b/src/doc/unstable-book/src/language-features/profiler-runtime.md index a9879c8d5a65..aee86f63952a 100644 --- a/src/doc/unstable-book/src/language-features/profiler-runtime.md +++ b/src/doc/unstable-book/src/language-features/profiler-runtime.md @@ -1,5 +1,5 @@ # `profiler_runtime` -The tracking issue for this feature is: None. +The tracking issue for this feature is: [#42524](https://github.com/rust-lang/rust/issues/42524). ------------------------ From ffd83fdf7deacc8f985dab0d44bfe1e2becf6543 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 13 Jun 2017 11:35:04 +1200 Subject: [PATCH 164/233] Update RLS again --- src/tools/rls | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rls b/src/tools/rls index bfe80cfa8db7..0d0f3baad02d 160000 --- a/src/tools/rls +++ b/src/tools/rls @@ -1 +1 @@ -Subproject commit bfe80cfa8db75500e67ca8762465d27662674637 +Subproject commit 0d0f3baad02d65d96befbb90e77bf8a326dd14f5 From 5b5499d5e60777b277d97efce5e62ab98c9cf823 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Mon, 12 Jun 2017 17:00:55 +0200 Subject: [PATCH 165/233] incr.comp.: Make DepNode's std::fmt::Debug implementation useful again. --- src/librustc/dep_graph/dep_node.rs | 124 ++++++++++++++++++++++++++++- src/librustc/dep_graph/graph.rs | 19 +++++ src/librustc/ich/fingerprint.rs | 11 +++ 3 files changed, 150 insertions(+), 4 deletions(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 3b6a7f87c13a..787a9fb38aa5 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -67,6 +67,7 @@ use ich::Fingerprint; use ty::TyCtxt; use rustc_data_structures::stable_hasher::{StableHasher, HashStable}; use ich::StableHashingContext; +use std::fmt; use std::hash::Hash; // erase!() just makes tokens go away. It's used to specify which macro argument @@ -145,7 +146,7 @@ macro_rules! define_dep_nodes { ),* } - #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, + #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] pub struct DepNode { pub kind: DepKind, @@ -166,10 +167,22 @@ macro_rules! define_dep_nodes { let tupled_args = ( $($tuple_arg,)* ); let hash = DepNodeParams::to_fingerprint(&tupled_args, tcx); - return DepNode { + let dep_node = DepNode { kind: DepKind::$variant, hash }; + + if cfg!(debug_assertions) && + !dep_node.kind.can_reconstruct_query_key() && + (tcx.sess.opts.debugging_opts.incremental_info || + tcx.sess.opts.debugging_opts.query_dep_graph) + { + tcx.dep_graph.register_dep_node_debug_str(dep_node, || { + tupled_args.to_debug_str(tcx) + }); + } + + return dep_node; })* // struct args @@ -177,10 +190,22 @@ macro_rules! define_dep_nodes { let tupled_args = ( $($struct_arg_name,)* ); let hash = DepNodeParams::to_fingerprint(&tupled_args, tcx); - return DepNode { + let dep_node = DepNode { kind: DepKind::$variant, hash }; + + if cfg!(debug_assertions) && + !dep_node.kind.can_reconstruct_query_key() && + (tcx.sess.opts.debugging_opts.incremental_info || + tcx.sess.opts.debugging_opts.query_dep_graph) + { + tcx.dep_graph.register_dep_node_debug_str(dep_node, || { + tupled_args.to_debug_str(tcx) + }); + } + + return dep_node; })* DepNode { @@ -267,6 +292,36 @@ macro_rules! define_dep_nodes { ); } +impl fmt::Debug for DepNode { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{:?}", self.kind)?; + + if !self.kind.has_params() { + return Ok(()); + } + + write!(f, "(")?; + + ::ty::tls::with_opt(|opt_tcx| { + if let Some(tcx) = opt_tcx { + if let Some(def_id) = self.extract_def_id(tcx) { + write!(f, "{}", tcx.item_path_str(def_id))?; + } else if let Some(ref s) = tcx.dep_graph.dep_node_debug_str(*self) { + write!(f, "{}", s)?; + } else { + write!(f, "{:?}", self.hash)?; + } + } else { + write!(f, "{:?}", self.hash)?; + } + Ok(()) + })?; + + write!(f, ")") + } +} + + impl DefPathHash { #[inline] pub fn to_dep_node(self, kind: DepKind) -> DepNode { @@ -434,10 +489,11 @@ define_dep_nodes!( trait DepNodeParams<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> { const CAN_RECONSTRUCT_QUERY_KEY: bool; fn to_fingerprint(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Fingerprint; + fn to_debug_str(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> String; } impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a, T> DepNodeParams<'a, 'gcx, 'tcx> for T - where T: HashStable> + where T: HashStable> + fmt::Debug { default const CAN_RECONSTRUCT_QUERY_KEY: bool = false; @@ -449,6 +505,10 @@ impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a, T> DepNodeParams<'a, 'gcx, 'tcx> for T hasher.finish() } + + default fn to_debug_str(&self, _: TyCtxt<'a, 'gcx, 'tcx>) -> String { + format!("{:?}", *self) + } } impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for (DefId,) { @@ -457,6 +517,62 @@ impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for (DefId,) { fn to_fingerprint(&self, tcx: TyCtxt) -> Fingerprint { tcx.def_path_hash(self.0).0 } + + fn to_debug_str(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> String { + tcx.item_path_str(self.0) + } +} + +impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for (DefId, DefId) { + const CAN_RECONSTRUCT_QUERY_KEY: bool = false; + + fn to_fingerprint(&self, tcx: TyCtxt) -> Fingerprint { + let (def_id_0, def_id_1) = *self; + + let def_path_hash_0 = tcx.def_path_hash(def_id_0); + let def_path_hash_1 = tcx.def_path_hash(def_id_1); + + def_path_hash_0.0.combine(def_path_hash_1.0) + } + + fn to_debug_str(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> String { + let (def_id_0, def_id_1) = *self; + + format!("({}, {})", + tcx.def_path(def_id_0).to_string(tcx), + tcx.def_path(def_id_1).to_string(tcx)) + } +} + + +impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for (DefIdList,) { + const CAN_RECONSTRUCT_QUERY_KEY: bool = false; + + fn to_fingerprint(&self, tcx: TyCtxt) -> Fingerprint { + let mut fingerprint = Fingerprint::zero(); + + for &def_id in self.0.iter() { + let def_path_hash = tcx.def_path_hash(def_id); + fingerprint = fingerprint.combine(def_path_hash.0); + } + + fingerprint + } + + fn to_debug_str(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> String { + use std::fmt::Write; + + let mut s = String::new(); + write!(&mut s, "[").unwrap(); + + for &def_id in self.0.iter() { + write!(&mut s, "{}", tcx.def_path(def_id).to_string(tcx)).unwrap(); + } + + write!(&mut s, "]").unwrap(); + + s + } } /// A "work product" corresponds to a `.o` (or other) file that we diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index 6afd31bfe92d..e48e61d80351 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -37,6 +37,8 @@ struct DepGraphData { /// Work-products that we generate in this run. work_products: RefCell>, + + dep_node_debug: RefCell>, } impl DepGraph { @@ -46,6 +48,7 @@ impl DepGraph { thread: DepGraphThreadData::new(enabled), previous_work_products: RefCell::new(FxHashMap()), work_products: RefCell::new(FxHashMap()), + dep_node_debug: RefCell::new(FxHashMap()), }) } } @@ -152,6 +155,22 @@ impl DepGraph { pub fn previous_work_products(&self) -> Ref> { self.data.previous_work_products.borrow() } + + #[inline(always)] + pub(super) fn register_dep_node_debug_str(&self, + dep_node: DepNode, + debug_str_gen: F) + where F: FnOnce() -> String + { + let mut dep_node_debug = self.data.dep_node_debug.borrow_mut(); + + dep_node_debug.entry(dep_node) + .or_insert_with(debug_str_gen); + } + + pub(super) fn dep_node_debug_str(&self, dep_node: DepNode) -> Option { + self.data.dep_node_debug.borrow().get(&dep_node).cloned() + } } /// A "work product" is an intermediate result that we save into the diff --git a/src/librustc/ich/fingerprint.rs b/src/librustc/ich/fingerprint.rs index 8308c756c053..2391b61253aa 100644 --- a/src/librustc/ich/fingerprint.rs +++ b/src/librustc/ich/fingerprint.rs @@ -31,9 +31,20 @@ impl Fingerprint { self.0 } + #[inline] + pub fn combine(self, other: Fingerprint) -> Fingerprint { + // See https://stackoverflow.com/a/27952689 on why this function is + // implemented this way. + Fingerprint( + self.0.wrapping_mul(3).wrapping_add(other.0), + self.1.wrapping_mul(3).wrapping_add(other.1) + ) + } + pub fn to_hex(&self) -> String { format!("{:x}{:x}", self.0, self.1) } + } impl ::std::fmt::Display for Fingerprint { From d714b9790b59673ea66d837063e044be136e4f09 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Tue, 13 Jun 2017 13:47:13 +0200 Subject: [PATCH 166/233] incr.comp.: Don't use Ident in DefPath because that's unstable across compilation sessions. --- src/librustc/hir/lowering.rs | 2 +- src/librustc/hir/map/def_collector.rs | 39 ++++---- src/librustc/hir/map/definitions.rs | 139 +++++++++++++------------- 3 files changed, 93 insertions(+), 87 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index a6ab67e04693..3d77381e2e93 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -2686,7 +2686,7 @@ impl<'a> LoweringContext<'a> { let parent_def = self.parent_def.unwrap(); let def_id = { let defs = self.resolver.definitions(); - let def_path_data = DefPathData::Binding(Ident::with_empty_ctxt(name)); + let def_path_data = DefPathData::Binding(name); let def_index = defs .create_def_with_parent(parent_def, id, def_path_data, REGULAR_SPACE, Mark::root()); DefId::local(def_index) diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs index cb25b462b6e2..7fbefa5788b2 100644 --- a/src/librustc/hir/map/def_collector.rs +++ b/src/librustc/hir/map/def_collector.rs @@ -15,6 +15,7 @@ use syntax::ast::*; use syntax::ext::hygiene::Mark; use syntax::visit; use syntax::symbol::keywords; +use syntax::symbol::Symbol; use hir::map::{ITEM_LIKE_SPACE, REGULAR_SPACE}; @@ -103,14 +104,14 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { DefPathData::Impl, ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) | ItemKind::Trait(..) | ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) | ItemKind::Ty(..) => - DefPathData::TypeNs(i.ident.modern()), + DefPathData::TypeNs(i.ident.name), ItemKind::Mod(..) if i.ident == keywords::Invalid.ident() => { return visit::walk_item(self, i); } - ItemKind::Mod(..) => DefPathData::Module(i.ident.modern()), + ItemKind::Mod(..) => DefPathData::Module(i.ident.name), ItemKind::Static(..) | ItemKind::Const(..) | ItemKind::Fn(..) => - DefPathData::ValueNs(i.ident.modern()), - ItemKind::MacroDef(..) => DefPathData::MacroDef(i.ident.modern()), + DefPathData::ValueNs(i.ident.name), + ItemKind::MacroDef(..) => DefPathData::MacroDef(i.ident.name), ItemKind::Mac(..) => return self.visit_macro_invoc(i.id, false), ItemKind::GlobalAsm(..) => DefPathData::Misc, ItemKind::Use(ref view_path) => { @@ -138,13 +139,13 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { for v in &enum_definition.variants { let variant_def_index = this.create_def(v.node.data.id(), - DefPathData::EnumVariant(v.node.name.modern()), + DefPathData::EnumVariant(v.node.name.name), REGULAR_SPACE); this.with_parent(variant_def_index, |this| { for (index, field) in v.node.data.fields().iter().enumerate() { - let ident = field.ident.map(Ident::modern) - .unwrap_or_else(|| Ident::from_str(&index.to_string())); - this.create_def(field.id, DefPathData::Field(ident), REGULAR_SPACE); + let name = field.ident.map(|ident| ident.name) + .unwrap_or_else(|| Symbol::intern(&index.to_string())); + this.create_def(field.id, DefPathData::Field(name), REGULAR_SPACE); } if let Some(ref expr) = v.node.disr_expr { @@ -162,9 +163,9 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { } for (index, field) in struct_def.fields().iter().enumerate() { - let ident = field.ident.map(Ident::modern) - .unwrap_or_else(|| Ident::from_str(&index.to_string())); - this.create_def(field.id, DefPathData::Field(ident), REGULAR_SPACE); + let name = field.ident.map(|ident| ident.name) + .unwrap_or_else(|| Symbol::intern(&index.to_string())); + this.create_def(field.id, DefPathData::Field(name), REGULAR_SPACE); } } _ => {} @@ -175,7 +176,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { fn visit_foreign_item(&mut self, foreign_item: &'a ForeignItem) { let def = self.create_def(foreign_item.id, - DefPathData::ValueNs(foreign_item.ident.modern()), + DefPathData::ValueNs(foreign_item.ident.name), REGULAR_SPACE); self.with_parent(def, |this| { @@ -186,7 +187,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { fn visit_generics(&mut self, generics: &'a Generics) { for ty_param in generics.ty_params.iter() { self.create_def(ty_param.id, - DefPathData::TypeParam(ty_param.ident.modern()), + DefPathData::TypeParam(ty_param.ident.name), REGULAR_SPACE); } @@ -196,8 +197,8 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { fn visit_trait_item(&mut self, ti: &'a TraitItem) { let def_data = match ti.node { TraitItemKind::Method(..) | TraitItemKind::Const(..) => - DefPathData::ValueNs(ti.ident.modern()), - TraitItemKind::Type(..) => DefPathData::TypeNs(ti.ident.modern()), + DefPathData::ValueNs(ti.ident.name), + TraitItemKind::Type(..) => DefPathData::TypeNs(ti.ident.name), TraitItemKind::Macro(..) => return self.visit_macro_invoc(ti.id, false), }; @@ -214,8 +215,8 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { fn visit_impl_item(&mut self, ii: &'a ImplItem) { let def_data = match ii.node { ImplItemKind::Method(..) | ImplItemKind::Const(..) => - DefPathData::ValueNs(ii.ident.modern()), - ImplItemKind::Type(..) => DefPathData::TypeNs(ii.ident.modern()), + DefPathData::ValueNs(ii.ident.name), + ImplItemKind::Type(..) => DefPathData::TypeNs(ii.ident.name), ImplItemKind::Macro(..) => return self.visit_macro_invoc(ii.id, false), }; @@ -236,7 +237,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { PatKind::Mac(..) => return self.visit_macro_invoc(pat.id, false), PatKind::Ident(_, id, _) => { let def = self.create_def(pat.id, - DefPathData::Binding(id.node.modern()), + DefPathData::Binding(id.node.name), REGULAR_SPACE); self.parent_def = Some(def); } @@ -281,7 +282,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { fn visit_lifetime_def(&mut self, def: &'a LifetimeDef) { self.create_def(def.lifetime.id, - DefPathData::LifetimeDef(def.lifetime.ident.modern()), + DefPathData::LifetimeDef(def.lifetime.ident.name), REGULAR_SPACE); } diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index ae43035f3b2e..c969aef675ff 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -24,8 +24,8 @@ use rustc_data_structures::stable_hasher::StableHasher; use serialize::{Encodable, Decodable, Encoder, Decoder}; use std::fmt::Write; use std::hash::Hash; -use syntax::ast::{self, Ident}; -use syntax::ext::hygiene::{Mark, SyntaxContext}; +use syntax::ast; +use syntax::ext::hygiene::Mark; use syntax::symbol::{Symbol, InternedString}; use ty::TyCtxt; use util::nodemap::NodeMap; @@ -248,7 +248,39 @@ impl DefKey { // and the special "root_parent" below. 0u8.hash(&mut hasher); parent_hash.hash(&mut hasher); - self.disambiguated_data.hash(&mut hasher); + + let DisambiguatedDefPathData { + ref data, + disambiguator, + } = self.disambiguated_data; + + ::std::mem::discriminant(data).hash(&mut hasher); + match *data { + DefPathData::TypeNs(name) | + DefPathData::ValueNs(name) | + DefPathData::Module(name) | + DefPathData::MacroDef(name) | + DefPathData::TypeParam(name) | + DefPathData::LifetimeDef(name) | + DefPathData::EnumVariant(name) | + DefPathData::Binding(name) | + DefPathData::Field(name) | + DefPathData::GlobalMetaData(name) => { + (*name.as_str()).hash(&mut hasher); + } + + DefPathData::Impl | + DefPathData::CrateRoot | + DefPathData::Misc | + DefPathData::ClosureExpr | + DefPathData::StructCtor | + DefPathData::Initializer | + DefPathData::ImplTrait | + DefPathData::Typeof => {} + }; + + disambiguator.hash(&mut hasher); + DefPathHash(hasher.finish()) } @@ -354,7 +386,7 @@ impl DefPath { } } -#[derive(Clone, Debug, RustcEncodable, RustcDecodable)] +#[derive(Clone, Debug, Eq, PartialEq, Hash, RustcEncodable, RustcDecodable)] pub enum DefPathData { // Root: these should only be used for the root nodes, because // they are treated specially by the `def_path` function. @@ -368,31 +400,31 @@ pub enum DefPathData { /// An impl Impl, /// Something in the type NS - TypeNs(Ident), + TypeNs(Symbol), /// Something in the value NS - ValueNs(Ident), + ValueNs(Symbol), /// A module declaration - Module(Ident), + Module(Symbol), /// A macro rule - MacroDef(Ident), + MacroDef(Symbol), /// A closure expression ClosureExpr, // Subportions of items /// A type parameter (generic parameter) - TypeParam(Ident), + TypeParam(Symbol), /// A lifetime definition - LifetimeDef(Ident), + LifetimeDef(Symbol), /// A variant of a enum - EnumVariant(Ident), + EnumVariant(Symbol), /// A struct field - Field(Ident), + Field(Symbol), /// Implicit ctor for a tuple-like struct StructCtor, /// Initializer for a const Initializer, /// Pattern binding - Binding(Ident), + Binding(Symbol), /// An `impl Trait` type node. ImplTrait, /// A `typeof` type node. @@ -401,7 +433,7 @@ pub enum DefPathData { /// GlobalMetaData identifies a piece of crate metadata that is global to /// a whole crate (as opposed to just one item). GlobalMetaData components /// are only supposed to show up right below the crate root. - GlobalMetaData(Ident) + GlobalMetaData(Symbol) } #[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug, @@ -604,19 +636,19 @@ impl Definitions { } impl DefPathData { - pub fn get_opt_ident(&self) -> Option { + pub fn get_opt_name(&self) -> Option { use self::DefPathData::*; match *self { - TypeNs(ident) | - ValueNs(ident) | - Module(ident) | - MacroDef(ident) | - TypeParam(ident) | - LifetimeDef(ident) | - EnumVariant(ident) | - Binding(ident) | - Field(ident) | - GlobalMetaData(ident) => Some(ident), + TypeNs(name) | + ValueNs(name) | + Module(name) | + MacroDef(name) | + TypeParam(name) | + LifetimeDef(name) | + EnumVariant(name) | + Binding(name) | + Field(name) | + GlobalMetaData(name) => Some(name), Impl | CrateRoot | @@ -629,24 +661,20 @@ impl DefPathData { } } - pub fn get_opt_name(&self) -> Option { - self.get_opt_ident().map(|ident| ident.name) - } - pub fn as_interned_str(&self) -> InternedString { use self::DefPathData::*; let s = match *self { - TypeNs(ident) | - ValueNs(ident) | - Module(ident) | - MacroDef(ident) | - TypeParam(ident) | - LifetimeDef(ident) | - EnumVariant(ident) | - Binding(ident) | - Field(ident) | - GlobalMetaData(ident) => { - return ident.name.as_str(); + TypeNs(name) | + ValueNs(name) | + Module(name) | + MacroDef(name) | + TypeParam(name) | + LifetimeDef(name) | + EnumVariant(name) | + Binding(name) | + Field(name) | + GlobalMetaData(name) => { + return name.as_str(); } // note that this does not show up in user printouts @@ -669,29 +697,6 @@ impl DefPathData { } } -impl Eq for DefPathData {} -impl PartialEq for DefPathData { - fn eq(&self, other: &DefPathData) -> bool { - ::std::mem::discriminant(self) == ::std::mem::discriminant(other) && - self.get_opt_ident() == other.get_opt_ident() - } -} - -impl ::std::hash::Hash for DefPathData { - fn hash(&self, hasher: &mut H) { - ::std::mem::discriminant(self).hash(hasher); - if let Some(ident) = self.get_opt_ident() { - if ident.ctxt == SyntaxContext::empty() && ident.name == ident.name.interned() { - ident.name.as_str().hash(hasher) - } else { - // FIXME(jseyfried) implement stable hashing for idents with macros 2.0 hygiene info - ident.hash(hasher) - } - } - } -} - - // We define the GlobalMetaDataKind enum with this macro because we want to // make sure that we exhaustively iterate over all variants when registering // the corresponding DefIndices in the DefTable. @@ -712,7 +717,7 @@ macro_rules! define_global_metadata_kind { definitions.create_def_with_parent( CRATE_DEF_INDEX, ast::DUMMY_NODE_ID, - DefPathData::GlobalMetaData(instance.ident()), + DefPathData::GlobalMetaData(instance.name()), DefIndexAddressSpace::High, Mark::root() ); @@ -726,7 +731,7 @@ macro_rules! define_global_metadata_kind { let def_key = DefKey { parent: Some(CRATE_DEF_INDEX), disambiguated_data: DisambiguatedDefPathData { - data: DefPathData::GlobalMetaData(self.ident()), + data: DefPathData::GlobalMetaData(self.name()), disambiguator: 0, } }; @@ -734,7 +739,7 @@ macro_rules! define_global_metadata_kind { def_path_table.key_to_index[&def_key] } - fn ident(&self) -> Ident { + fn name(&self) -> Symbol { let string = match *self { $( @@ -744,7 +749,7 @@ macro_rules! define_global_metadata_kind { )* }; - Ident::from_str(string) + Symbol::intern(string) } } ) From 9b88a1b30b5f18a47f5868a954a8d19fb2588d61 Mon Sep 17 00:00:00 2001 From: Marco A L Barbosa Date: Mon, 12 Jun 2017 20:07:24 -0300 Subject: [PATCH 167/233] Add docker image for wasm32-unknown-emscripten - rename emscripten docker image to asmjs - create wasm32 docker image --- .travis.yml | 2 +- src/ci/docker/asmjs/Dockerfile | 44 ++++++++++++++++ src/ci/docker/emscripten/Dockerfile | 41 --------------- src/ci/docker/emscripten/build-emscripten.sh | 53 -------------------- src/ci/docker/wasm32/Dockerfile | 44 ++++++++++++++++ src/ci/docker/wasm32/node | 18 +++++++ 6 files changed, 107 insertions(+), 95 deletions(-) create mode 100644 src/ci/docker/asmjs/Dockerfile delete mode 100644 src/ci/docker/emscripten/Dockerfile delete mode 100755 src/ci/docker/emscripten/build-emscripten.sh create mode 100644 src/ci/docker/wasm32/Dockerfile create mode 100755 src/ci/docker/wasm32/node diff --git a/.travis.yml b/.travis.yml index 40fecb3ee5ea..b4096bd1687d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -36,7 +36,7 @@ matrix: - env: IMAGE=dist-x86_64-linux DEPLOY=1 ALLOW_TRY=1 - env: IMAGE=dist-x86_64-musl DEPLOY=1 - env: IMAGE=dist-x86_64-netbsd DEPLOY=1 - - env: IMAGE=emscripten + - env: IMAGE=asmjs - env: IMAGE=i686-gnu - env: IMAGE=i686-gnu-nopt - env: IMAGE=x86_64-gnu diff --git a/src/ci/docker/asmjs/Dockerfile b/src/ci/docker/asmjs/Dockerfile new file mode 100644 index 000000000000..899ce1e4569d --- /dev/null +++ b/src/ci/docker/asmjs/Dockerfile @@ -0,0 +1,44 @@ +FROM ubuntu:16.04 + +RUN apt-get update && apt-get install -y --no-install-recommends \ + g++ \ + make \ + file \ + curl \ + ca-certificates \ + python \ + git \ + cmake \ + sudo \ + gdb \ + xz-utils + +# dumb-init +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.sh + +# emscripten +COPY scripts/emscripten.sh /scripts/ +RUN bash /scripts/emscripten.sh + +# env +ENV PATH=$PATH:/emsdk-portable +ENV PATH=$PATH:/emsdk-portable/clang/e1.37.13_64bit/ +ENV PATH=$PATH:/emsdk-portable/emscripten/1.37.13/ +ENV PATH=$PATH:/emsdk-portable/node/4.1.1_64bit/bin/ +ENV EMSCRIPTEN=/emsdk-portable/emscripten/1.37.13/ +ENV BINARYEN_ROOT=/emsdk-portable/clang/e1.37.13_64bit/binaryen/ +ENV EM_CONFIG=/emsdk-portable/.emscripten + +ENV TARGETS=asmjs-unknown-emscripten + +ENV RUST_CONFIGURE_ARGS --target=$TARGETS + +ENV SCRIPT python2.7 ../x.py test --target $TARGETS + +# cache +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh + +# init +ENTRYPOINT ["/usr/bin/dumb-init", "--"] diff --git a/src/ci/docker/emscripten/Dockerfile b/src/ci/docker/emscripten/Dockerfile deleted file mode 100644 index 0f0e5b69c32c..000000000000 --- a/src/ci/docker/emscripten/Dockerfile +++ /dev/null @@ -1,41 +0,0 @@ -FROM ubuntu:16.04 - -RUN apt-get update && apt-get install -y --no-install-recommends \ - g++ \ - make \ - file \ - curl \ - ca-certificates \ - python \ - git \ - cmake \ - sudo \ - gdb \ - xz-utils \ - lib32stdc++6 - -RUN curl -o /usr/local/bin/sccache \ - https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-05-12-sccache-x86_64-unknown-linux-musl && \ - chmod +x /usr/local/bin/sccache - -RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \ - dpkg -i dumb-init_*.deb && \ - rm dumb-init_*.deb -ENTRYPOINT ["/usr/bin/dumb-init", "--"] - -WORKDIR /tmp -COPY emscripten/build-emscripten.sh /tmp/ -RUN ./build-emscripten.sh -ENV PATH=$PATH:/tmp/emsdk_portable -ENV PATH=$PATH:/tmp/emsdk_portable/clang/tag-e1.37.10/build_tag-e1.37.10_32/bin -ENV PATH=$PATH:/tmp/emsdk_portable/node/4.1.1_32bit/bin -ENV PATH=$PATH:/tmp/emsdk_portable/emscripten/tag-1.37.10 -ENV EMSCRIPTEN=/tmp/emsdk_portable/emscripten/tag-1.37.10 - -ENV RUST_CONFIGURE_ARGS --target=asmjs-unknown-emscripten - -# Run `emcc` first as it's got a prompt and doesn't actually do anything, after -# that's done with do the real build. -ENV SCRIPT emcc && \ - python2.7 ../x.py test --target asmjs-unknown-emscripten - diff --git a/src/ci/docker/emscripten/build-emscripten.sh b/src/ci/docker/emscripten/build-emscripten.sh deleted file mode 100755 index 8d6a28f418bf..000000000000 --- a/src/ci/docker/emscripten/build-emscripten.sh +++ /dev/null @@ -1,53 +0,0 @@ -#!/bin/bash -# 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. - -set -ex - -hide_output() { - set +x - on_err=" -echo ERROR: An error was encountered with the build. -cat /tmp/build.log -exit 1 -" - trap "$on_err" ERR - bash -c "while true; do sleep 30; echo \$(date) - building ...; done" & - PING_LOOP_PID=$! - $@ &> /tmp/build.log - trap - ERR - kill $PING_LOOP_PID - rm /tmp/build.log - set -x -} - -curl https://s3.amazonaws.com/mozilla-games/emscripten/releases/emsdk-portable.tar.gz | \ - tar xzf - - -# Some versions of the EMSDK archive have their contents in .emsdk-portable -# and others in emsdk_portable. Make sure the EMSDK ends up in a fixed path. -if [ -d emsdk-portable ]; then - mv emsdk-portable emsdk_portable -fi - -if [ ! -d emsdk_portable ]; then - echo "ERROR: Invalid emsdk archive. Dumping working directory." >&2 - ls -l - exit 1 -fi - -# Some versions of the EMSDK set the permissions of the root directory to -# 0700. Ensure the directory is readable by all users. -chmod 755 emsdk_portable - -source emsdk_portable/emsdk_env.sh -hide_output emsdk update -hide_output emsdk install --build=Release sdk-tag-1.37.10-32bit -hide_output emsdk activate --build=Release sdk-tag-1.37.10-32bit diff --git a/src/ci/docker/wasm32/Dockerfile b/src/ci/docker/wasm32/Dockerfile new file mode 100644 index 000000000000..07fa9fbde2d4 --- /dev/null +++ b/src/ci/docker/wasm32/Dockerfile @@ -0,0 +1,44 @@ +FROM ubuntu:16.04 + +RUN apt-get update && apt-get install -y --no-install-recommends \ + g++ \ + make \ + file \ + curl \ + ca-certificates \ + python \ + git \ + cmake \ + sudo \ + gdb \ + xz-utils + +# dumb-init +COPY scripts/dumb-init.sh /scripts/ +RUN sh /scripts/dumb-init.sh + +# emscripten +COPY scripts/emscripten.sh /scripts/ +RUN bash /scripts/emscripten.sh +COPY wasm32/node /usr/local/bin/node + +# env +ENV PATH=$PATH:/emsdk-portable +ENV PATH=$PATH:/emsdk-portable/clang/e1.37.13_64bit/ +ENV PATH=$PATH:/emsdk-portable/emscripten/1.37.13/ +ENV EMSCRIPTEN=/emsdk-portable/emscripten/1.37.13/ +ENV BINARYEN_ROOT=/emsdk-portable/clang/e1.37.13_64bit/binaryen/ +ENV EM_CONFIG=/emsdk-portable/.emscripten + +ENV TARGETS=wasm32-unknown-emscripten + +ENV RUST_CONFIGURE_ARGS --target=$TARGETS + +ENV SCRIPT python2.7 ../x.py test --target $TARGETS + +# cache +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh + +# init +ENTRYPOINT ["/usr/bin/dumb-init", "--"] diff --git a/src/ci/docker/wasm32/node b/src/ci/docker/wasm32/node new file mode 100755 index 000000000000..dfa7f221ffa2 --- /dev/null +++ b/src/ci/docker/wasm32/node @@ -0,0 +1,18 @@ +#!/bin/bash +# 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. + +path="$(dirname $1)" +file="$(basename $1)" + +shift + +cd "$path" +exec /node-v8.0.0-linux-x64/bin/node "$file" "$@" From 554f21bc02d07050cd182c06b01175267533becc Mon Sep 17 00:00:00 2001 From: Marco A L Barbosa Date: Tue, 13 Jun 2017 09:32:49 -0300 Subject: [PATCH 168/233] Do not execute .asm.js files on wasm32 tests Files with extensions .asm.js are used to generate .wasm files, they are not intented to be execute. --- src/bootstrap/check.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 385376333c1d..0bba68545c55 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -563,7 +563,9 @@ fn find_tests(dir: &Path, let filename = e.file_name().into_string().unwrap(); if (target.contains("windows") && filename.ends_with(".exe")) || (!target.contains("windows") && !filename.contains(".")) || - (target.contains("emscripten") && filename.ends_with(".js")) { + (target.contains("emscripten") && + filename.ends_with(".js") && + !filename.ends_with(".asm.js")) { dst.push(e.path()); } } From bd4fe454050fa6ac8c74bc1ee70e0b4b909d245e Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Tue, 13 Jun 2017 14:46:35 +0200 Subject: [PATCH 169/233] External spans: Added a test for #38875. A bug has been discovered and fixed in the process. --- src/librustc_metadata/decoder.rs | 2 +- .../ui/issue-38875/auxiliary/issue_38875_b.rs | 11 +++++++++++ src/test/ui/issue-38875/issue_38875.rs | 17 +++++++++++++++++ src/test/ui/issue-38875/issue_38875.stderr | 14 ++++++++++++++ 4 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/issue-38875/auxiliary/issue_38875_b.rs create mode 100644 src/test/ui/issue-38875/issue_38875.rs create mode 100644 src/test/ui/issue-38875/issue_38875.stderr diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index cd50fc4d5276..7d8d2939a1b4 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -765,7 +765,7 @@ impl<'a, 'tcx> CrateMetadata { assert!(!self.is_proc_macro(id)); let ast = self.entry(id).ast.unwrap(); let def_id = self.local_def_id(id); - let body = ast.decode(self).body.decode(self); + let body = ast.decode((self, tcx)).body.decode((self, tcx)); tcx.hir.intern_inlined_body(def_id, body) } diff --git a/src/test/ui/issue-38875/auxiliary/issue_38875_b.rs b/src/test/ui/issue-38875/auxiliary/issue_38875_b.rs new file mode 100644 index 000000000000..dd58735209b8 --- /dev/null +++ b/src/test/ui/issue-38875/auxiliary/issue_38875_b.rs @@ -0,0 +1,11 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub const FOO: usize = *&0; diff --git a/src/test/ui/issue-38875/issue_38875.rs b/src/test/ui/issue-38875/issue_38875.rs new file mode 100644 index 000000000000..42e3c05a38c7 --- /dev/null +++ b/src/test/ui/issue-38875/issue_38875.rs @@ -0,0 +1,17 @@ +// 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. + +// aux-build:issue_38875_b.rs + +extern crate issue_38875_b; + +fn main() { + let test_x = [0; issue_38875_b::FOO]; +} diff --git a/src/test/ui/issue-38875/issue_38875.stderr b/src/test/ui/issue-38875/issue_38875.stderr new file mode 100644 index 000000000000..ceed83d9313c --- /dev/null +++ b/src/test/ui/issue-38875/issue_38875.stderr @@ -0,0 +1,14 @@ +error[E0080]: constant evaluation error + --> $DIR/auxiliary/issue_38875_b.rs:11:24 + | +11 | pub const FOO: usize = *&0; + | ^^^ unimplemented constant expression: deref operation + | +note: for repeat count here + --> $DIR/issue_38875.rs:16:22 + | +16 | let test_x = [0; issue_38875_b::FOO]; + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error(s) + From 405adb6d0c44d018cf4ce39d3bc486ebd8584cfb Mon Sep 17 00:00:00 2001 From: Marco A L Barbosa Date: Tue, 13 Jun 2017 10:46:54 -0300 Subject: [PATCH 170/233] Ignore some failing test on wasm32-unknown-emscripten See #42629 and #42630. --- src/libcore/tests/num/dec2flt/mod.rs | 2 ++ src/libcore/tests/num/dec2flt/rawfp.rs | 3 +++ src/libcore/tests/num/flt2dec/strategy/dragon.rs | 1 + src/libcore/tests/num/flt2dec/strategy/grisu.rs | 1 + src/libcore/tests/num/mod.rs | 1 + src/libstd/f64.rs | 3 +++ src/test/run-pass/asm-concat-src.rs | 2 +- src/test/run-pass/conditional-compile-arch.rs | 3 +++ src/test/run-pass/issue-27859.rs | 2 ++ src/test/run-pass/out-of-stack.rs | 2 +- 10 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/libcore/tests/num/dec2flt/mod.rs b/src/libcore/tests/num/dec2flt/mod.rs index 5d546c643e7e..9934e1dab966 100644 --- a/src/libcore/tests/num/dec2flt/mod.rs +++ b/src/libcore/tests/num/dec2flt/mod.rs @@ -33,6 +33,7 @@ macro_rules! test_literal { }) } +#[cfg_attr(all(target_arch = "wasm32", target_os = "emscripten"), ignore)] // issue 42630 #[test] fn ordinary() { test_literal!(1.0); @@ -43,6 +44,7 @@ fn ordinary() { test_literal!(2.2250738585072014e-308); } +#[cfg_attr(all(target_arch = "wasm32", target_os = "emscripten"), ignore)] // issue 42630 #[test] fn special_code_paths() { test_literal!(36893488147419103229.0); // 2^65 - 3, triggers half-to-even with even significand diff --git a/src/libcore/tests/num/dec2flt/rawfp.rs b/src/libcore/tests/num/dec2flt/rawfp.rs index 2b0afc402027..c9cd2bf5a9ae 100644 --- a/src/libcore/tests/num/dec2flt/rawfp.rs +++ b/src/libcore/tests/num/dec2flt/rawfp.rs @@ -86,6 +86,7 @@ fn rounding_overflow() { assert_eq!(rounded.k, adjusted_k + 1); } +#[cfg_attr(all(target_arch = "wasm32", target_os = "emscripten"), ignore)] // issue 42630 #[test] fn prev_float_monotonic() { let mut x = 1.0; @@ -121,6 +122,7 @@ fn next_float_inf() { assert_eq!(next_float(f64::INFINITY), f64::INFINITY); } +#[cfg_attr(all(target_arch = "wasm32", target_os = "emscripten"), ignore)] // issue 42630 #[test] fn next_prev_identity() { for &x in &SOME_FLOATS { @@ -131,6 +133,7 @@ fn next_prev_identity() { } } +#[cfg_attr(all(target_arch = "wasm32", target_os = "emscripten"), ignore)] // issue 42630 #[test] fn next_float_monotonic() { let mut x = 0.49999999999999; diff --git a/src/libcore/tests/num/flt2dec/strategy/dragon.rs b/src/libcore/tests/num/flt2dec/strategy/dragon.rs index 4edb0f3df60c..03772a765cc6 100644 --- a/src/libcore/tests/num/flt2dec/strategy/dragon.rs +++ b/src/libcore/tests/num/flt2dec/strategy/dragon.rs @@ -24,6 +24,7 @@ fn test_mul_pow10() { } } +#[cfg_attr(all(target_arch = "wasm32", target_os = "emscripten"), ignore)] // issue 42630 #[test] fn shortest_sanity_test() { f64_shortest_sanity_test(format_shortest); diff --git a/src/libcore/tests/num/flt2dec/strategy/grisu.rs b/src/libcore/tests/num/flt2dec/strategy/grisu.rs index 79e66ee669e1..17fb99bcc922 100644 --- a/src/libcore/tests/num/flt2dec/strategy/grisu.rs +++ b/src/libcore/tests/num/flt2dec/strategy/grisu.rs @@ -38,6 +38,7 @@ fn test_max_pow10_no_more_than() { } +#[cfg_attr(all(target_arch = "wasm32", target_os = "emscripten"), ignore)] // issue 42630 #[test] fn shortest_sanity_test() { f64_shortest_sanity_test(format_shortest); diff --git a/src/libcore/tests/num/mod.rs b/src/libcore/tests/num/mod.rs index 51737c9c3b48..8fdcc36a268e 100644 --- a/src/libcore/tests/num/mod.rs +++ b/src/libcore/tests/num/mod.rs @@ -169,6 +169,7 @@ test_impl_from! { test_u16f64, u16, f64 } test_impl_from! { test_u32f64, u32, f64 } // Float -> Float +#[cfg_attr(all(target_arch = "wasm32", target_os = "emscripten"), ignore)] // issue 42630 #[test] fn test_f32f64() { use core::f32; diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs index 82e3903eec7b..813998b75028 100644 --- a/src/libstd/f64.rs +++ b/src/libstd/f64.rs @@ -1158,6 +1158,7 @@ mod tests { assert_eq!(Fp::Zero, neg_zero.classify()); } + #[cfg_attr(all(target_arch = "wasm32", target_os = "emscripten"), ignore)] // issue 42630 #[test] fn test_one() { let one: f64 = 1.0f64; @@ -1210,6 +1211,7 @@ mod tests { assert!((-109.2f64).is_finite()); } + #[cfg_attr(all(target_arch = "wasm32", target_os = "emscripten"), ignore)] // issue 42630 #[test] fn test_is_normal() { let nan: f64 = NAN; @@ -1227,6 +1229,7 @@ mod tests { assert!(!1e-308f64.is_normal()); } + #[cfg_attr(all(target_arch = "wasm32", target_os = "emscripten"), ignore)] // issue 42630 #[test] fn test_classify() { let nan: f64 = NAN; diff --git a/src/test/run-pass/asm-concat-src.rs b/src/test/run-pass/asm-concat-src.rs index ea3d0c3aa0ee..fb257bf7b500 100644 --- a/src/test/run-pass/asm-concat-src.rs +++ b/src/test/run-pass/asm-concat-src.rs @@ -9,7 +9,7 @@ // except according to those terms. // pretty-expanded FIXME #23616 -// ignore-asmjs +// ignore-emscripten #![feature(asm)] diff --git a/src/test/run-pass/conditional-compile-arch.rs b/src/test/run-pass/conditional-compile-arch.rs index 24c461d5f511..6e3e4be0d8e8 100644 --- a/src/test/run-pass/conditional-compile-arch.rs +++ b/src/test/run-pass/conditional-compile-arch.rs @@ -36,3 +36,6 @@ pub fn main() { } #[cfg(target_arch = "asmjs")] pub fn main() { } + +#[cfg(target_arch = "wasm32")] +pub fn main() { } diff --git a/src/test/run-pass/issue-27859.rs b/src/test/run-pass/issue-27859.rs index 900614be612f..56036caca15b 100644 --- a/src/test/run-pass/issue-27859.rs +++ b/src/test/run-pass/issue-27859.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-wasm32 issue 42629 + #[inline(never)] fn foo(a: f32, b: f32) -> f32 { a % b diff --git a/src/test/run-pass/out-of-stack.rs b/src/test/run-pass/out-of-stack.rs index a7748b6d6a2a..7e70c4a7ab38 100644 --- a/src/test/run-pass/out-of-stack.rs +++ b/src/test/run-pass/out-of-stack.rs @@ -10,7 +10,7 @@ // ignore-android: FIXME (#20004) // ignore-musl -// ignore-asmjs +// ignore-emscripten #![feature(asm)] #![feature(libc)] From f0c400b04e37071acfbf70ca007c67e302f377e0 Mon Sep 17 00:00:00 2001 From: Marco A L Barbosa Date: Tue, 13 Jun 2017 10:49:03 -0300 Subject: [PATCH 171/233] travis: Enable wasm32-unknown-emscripten tests --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index b4096bd1687d..33705cc1f02e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -39,6 +39,7 @@ matrix: - env: IMAGE=asmjs - env: IMAGE=i686-gnu - env: IMAGE=i686-gnu-nopt + - env: IMAGE=wasm32 - env: IMAGE=x86_64-gnu - env: IMAGE=x86_64-gnu-full-bootstrap - env: IMAGE=x86_64-gnu-aux From dd0727fee46a843a80c44b24dfd1b0704683072e Mon Sep 17 00:00:00 2001 From: Marco A L Barbosa Date: Tue, 13 Jun 2017 11:02:00 -0300 Subject: [PATCH 172/233] Add missing emscripten.sh file --- src/ci/docker/scripts/emscripten.sh | 53 +++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 src/ci/docker/scripts/emscripten.sh diff --git a/src/ci/docker/scripts/emscripten.sh b/src/ci/docker/scripts/emscripten.sh new file mode 100644 index 000000000000..8aa5a98d7fc5 --- /dev/null +++ b/src/ci/docker/scripts/emscripten.sh @@ -0,0 +1,53 @@ +# 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. + +set -ex + +hide_output() { + set +x + on_err=" +echo ERROR: An error was encountered with the build. +cat /tmp/build.log +exit 1 +" + trap "$on_err" ERR + bash -c "while true; do sleep 30; echo \$(date) - building ...; done" & + PING_LOOP_PID=$! + $@ &> /tmp/build.log + trap - ERR + kill $PING_LOOP_PID + rm -f /tmp/build.log + set -x +} + +cd / +curl -L https://s3.amazonaws.com/mozilla-games/emscripten/releases/emsdk-portable.tar.gz | \ + tar -xz + +cd /emsdk-portable +./emsdk update +hide_output ./emsdk install sdk-1.37.13-64bit +./emsdk activate sdk-1.37.13-64bit + +# Compile and cache libc +source ./emsdk_env.sh +echo "main(){}" > a.c +HOME=/emsdk-portable/ emcc a.c +HOME=/emsdk-portable/ emcc -s BINARYEN=1 a.c +rm -f a.* + +# Make emsdk usable by any user +cp /root/.emscripten /emsdk-portable +chmod a+rxw -R /emsdk-portable + +# node 8 is required to run wasm +cd / +curl -L https://nodejs.org/dist/v8.0.0/node-v8.0.0-linux-x64.tar.xz | \ + tar -xJ From e32365272872d9bd69dd3f89113f2a47158960c5 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Tue, 13 Jun 2017 17:11:53 +0200 Subject: [PATCH 173/233] dep_node: Add comment about method specialization being just a performance optimization --- src/librustc/dep_graph/dep_node.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 787a9fb38aa5..032338e4d1e9 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -526,6 +526,9 @@ impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for (DefId,) { impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for (DefId, DefId) { const CAN_RECONSTRUCT_QUERY_KEY: bool = false; + // We actually would not need to specialize the implementation of this + // method but it's faster to combine the hashes than to instantiate a full + // hashing context and stable-hashing state. fn to_fingerprint(&self, tcx: TyCtxt) -> Fingerprint { let (def_id_0, def_id_1) = *self; @@ -548,6 +551,9 @@ impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for (DefId, De impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for (DefIdList,) { const CAN_RECONSTRUCT_QUERY_KEY: bool = false; + // We actually would not need to specialize the implementation of this + // method but it's faster to combine the hashes than to instantiate a full + // hashing context and stable-hashing state. fn to_fingerprint(&self, tcx: TyCtxt) -> Fingerprint { let mut fingerprint = Fingerprint::zero(); From 35d6eb38d255f82f21a745d4c2037ee0ee71740b Mon Sep 17 00:00:00 2001 From: Marco A L Barbosa Date: Tue, 13 Jun 2017 12:39:00 -0300 Subject: [PATCH 174/233] Make tidy happy --- src/ci/docker/wasm32/Dockerfile | 2 +- src/ci/docker/wasm32/{node => node.sh} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename src/ci/docker/wasm32/{node => node.sh} (100%) diff --git a/src/ci/docker/wasm32/Dockerfile b/src/ci/docker/wasm32/Dockerfile index 07fa9fbde2d4..daf398ac0962 100644 --- a/src/ci/docker/wasm32/Dockerfile +++ b/src/ci/docker/wasm32/Dockerfile @@ -20,7 +20,7 @@ RUN sh /scripts/dumb-init.sh # emscripten COPY scripts/emscripten.sh /scripts/ RUN bash /scripts/emscripten.sh -COPY wasm32/node /usr/local/bin/node +COPY wasm32/node.sh /usr/local/bin/node # env ENV PATH=$PATH:/emsdk-portable diff --git a/src/ci/docker/wasm32/node b/src/ci/docker/wasm32/node.sh similarity index 100% rename from src/ci/docker/wasm32/node rename to src/ci/docker/wasm32/node.sh From e75937022e9df6ade583b11ee44038ef32d1299a Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sat, 3 Jun 2017 18:14:29 +0200 Subject: [PATCH 175/233] Add docs to librustc/hir/check_attr.rs --- src/librustc/hir/check_attr.rs | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs index f553c03d09bd..3034242b5940 100644 --- a/src/librustc/hir/check_attr.rs +++ b/src/librustc/hir/check_attr.rs @@ -8,6 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +//! This module implements some validity checks for attributes. +//! In particular it verifies that `#[inline]` and `#[repr]` attributes are +//! attached to items that actually support them and if there are +//! conflicts between multiple such attributes attached to the same +//! item. + use session::Session; use syntax::ast; @@ -40,6 +46,18 @@ struct CheckAttrVisitor<'a> { } impl<'a> CheckAttrVisitor<'a> { + /// Check any attribute. + fn check_attribute(&self, attr: &ast::Attribute, target: Target) { + if let Some(name) = attr.name() { + match &*name.as_str() { + "inline" => self.check_inline(attr, target), + "repr" => self.check_repr(attr, target), + _ => (), + } + } + } + + /// Check if an `#[inline]` is applied to a function. fn check_inline(&self, attr: &ast::Attribute, target: Target) { if target != Target::Fn { struct_span_err!(self.sess, attr.span, E0518, "attribute should be applied to function") @@ -48,6 +66,7 @@ impl<'a> CheckAttrVisitor<'a> { } } + /// Check if an `#[repr]` attr is valid. fn check_repr(&self, attr: &ast::Attribute, target: Target) { let words = match attr.meta_item_list() { Some(words) => words, @@ -135,16 +154,6 @@ impl<'a> CheckAttrVisitor<'a> { "conflicting packed and align representation hints").emit(); } } - - fn check_attribute(&self, attr: &ast::Attribute, target: Target) { - if let Some(name) = attr.name() { - match &*name.as_str() { - "inline" => self.check_inline(attr, target), - "repr" => self.check_repr(attr, target), - _ => (), - } - } - } } impl<'a> Visitor<'a> for CheckAttrVisitor<'a> { From dba9f84dc464e6e9ff89cc0882660dc192244b17 Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Tue, 13 Jun 2017 20:21:58 +0100 Subject: [PATCH 176/233] Fix gcc version required by libprofiler_builtins --- src/libprofiler_builtins/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libprofiler_builtins/Cargo.toml b/src/libprofiler_builtins/Cargo.toml index dbbc168e7ea3..a60db3136797 100644 --- a/src/libprofiler_builtins/Cargo.toml +++ b/src/libprofiler_builtins/Cargo.toml @@ -15,4 +15,4 @@ doc = false core = { path = "../libcore" } [build-dependencies] -gcc = "0.3.27" +gcc = "0.3.50" From 5c084fd8edd986d8a4bd9ff37b303f8777623a56 Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Tue, 13 Jun 2017 20:22:43 +0100 Subject: [PATCH 177/233] Add libprofiler_builtins to the list of paths for the rust-src component --- src/bootstrap/dist.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 26d44ae7693a..ebf602373c96 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -570,6 +570,7 @@ pub fn rust_src(build: &Build) { "src/libgetopts", "src/compiler-rt", "src/jemalloc", + "src/libprofiler_builtins", ]; let std_src_dirs_exclude = [ "src/compiler-rt/test", From 124ad70a9c492dd5399fe6b9334477a6c8fcedde Mon Sep 17 00:00:00 2001 From: Marco A L Barbosa Date: Tue, 13 Jun 2017 17:01:39 -0300 Subject: [PATCH 178/233] Let's try --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 33705cc1f02e..dca0c16be891 100644 --- a/.travis.yml +++ b/.travis.yml @@ -39,7 +39,7 @@ matrix: - env: IMAGE=asmjs - env: IMAGE=i686-gnu - env: IMAGE=i686-gnu-nopt - - env: IMAGE=wasm32 + - env: IMAGE=wasm32 ALLOW_PR=1 - env: IMAGE=x86_64-gnu - env: IMAGE=x86_64-gnu-full-bootstrap - env: IMAGE=x86_64-gnu-aux From c291e87dae377c3632c6731d618ef1433d79b041 Mon Sep 17 00:00:00 2001 From: Arthur Arnold Date: Tue, 13 Jun 2017 17:08:12 -0300 Subject: [PATCH 179/233] changed upper bound digit in octal rule to 7 --- src/grammar/lexer.l | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/grammar/lexer.l b/src/grammar/lexer.l index 77737c99496f..91652bfdf246 100644 --- a/src/grammar/lexer.l +++ b/src/grammar/lexer.l @@ -126,7 +126,7 @@ while { return WHILE; } {ident} { return IDENT; } 0x[0-9a-fA-F_]+ { BEGIN(suffix); return LIT_INTEGER; } -0o[0-8_]+ { BEGIN(suffix); return LIT_INTEGER; } +0o[0-7_]+ { BEGIN(suffix); return LIT_INTEGER; } 0b[01_]+ { BEGIN(suffix); return LIT_INTEGER; } [0-9][0-9_]* { BEGIN(suffix); return LIT_INTEGER; } [0-9][0-9_]*\.(\.|[a-zA-Z]) { yyless(yyleng - 2); BEGIN(suffix); return LIT_INTEGER; } From a5dc96397498cf2c0a05407320ff33d939b652e3 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 13 Jun 2017 21:37:13 +0200 Subject: [PATCH 180/233] Add E0617 --- src/librustc_typeck/check/mod.rs | 32 +++++++++---------------- src/librustc_typeck/diagnostics.rs | 21 ++++++++++++++++ src/test/compile-fail/E0617.rs | 32 +++++++++++++++++++++++++ src/test/compile-fail/variadic-ffi-3.rs | 12 +++++----- 4 files changed, 70 insertions(+), 27 deletions(-) create mode 100644 src/test/compile-fail/E0617.rs diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 880137f7c71b..c12df083c30e 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -2553,42 +2553,32 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // We also need to make sure we at least write the ty of the other // arguments which we skipped above. if variadic { + fn variadic_error<'tcx>(s: &Session, span: Span, t: Ty<'tcx>, cast_ty: &str) { + type_error_struct!(s, span, t, E0617, + "can't pass `{}` to variadic function, cast to `{}`", + t, cast_ty).emit(); + } + for arg in args.iter().skip(expected_arg_count) { let arg_ty = self.check_expr(&arg); // There are a few types which get autopromoted when passed via varargs // in C but we just error out instead and require explicit casts. - let arg_ty = self.structurally_resolved_type(arg.span, - arg_ty); + let arg_ty = self.structurally_resolved_type(arg.span, arg_ty); match arg_ty.sty { ty::TyFloat(ast::FloatTy::F32) => { - self.type_error_message(arg.span, |t| { - format!("can't pass an `{}` to variadic \ - function, cast to `c_double`", t) - }, arg_ty); + variadic_error(tcx.sess, arg.span, arg_ty, "c_double"); } ty::TyInt(ast::IntTy::I8) | ty::TyInt(ast::IntTy::I16) | ty::TyBool => { - self.type_error_message(arg.span, |t| { - format!("can't pass `{}` to variadic \ - function, cast to `c_int`", - t) - }, arg_ty); + variadic_error(tcx.sess, arg.span, arg_ty, "c_int"); } ty::TyUint(ast::UintTy::U8) | ty::TyUint(ast::UintTy::U16) => { - self.type_error_message(arg.span, |t| { - format!("can't pass `{}` to variadic \ - function, cast to `c_uint`", - t) - }, arg_ty); + variadic_error(tcx.sess, arg.span, arg_ty, "c_uint"); } ty::TyFnDef(.., f) => { let ptr_ty = self.tcx.mk_fn_ptr(f); let ptr_ty = self.resolve_type_vars_if_possible(&ptr_ty); - self.type_error_message(arg.span, - |t| { - format!("can't pass `{}` to variadic \ - function, cast to `{}`", t, ptr_ty) - }, arg_ty); + variadic_error(tcx.sess, arg.span, arg_ty, &format!("{}", ptr_ty)); } _ => {} } diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 6ccfab0a324b..76c664d7997a 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -4152,6 +4152,27 @@ println!("x: {}, y: {}", variable.x, variable.y); For more information see The Rust Book: https://doc.rust-lang.org/book/ "##, +E0617: r##" +Attempted to pass an invalid type of variable into a variadic function. + +Erroneous code example: + +```compile_fail,E0617 +extern { + fn printf(c: *const i8, ...); +} + +unsafe { + printf(::std::ptr::null(), 0f32); + // error: can't pass an `f32` to variadic function, cast to `c_double` +} +``` + +To fix this error, you need to pass variables corresponding to C types as much +as possible. For better explanations, see The Rust Book: +https://doc.rust-lang.org/book/ +"##, + } register_diagnostics! { diff --git a/src/test/compile-fail/E0617.rs b/src/test/compile-fail/E0617.rs new file mode 100644 index 000000000000..7b769ff4ae2e --- /dev/null +++ b/src/test/compile-fail/E0617.rs @@ -0,0 +1,32 @@ +// 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. + +// ignore-tidy-linelength + +extern { + fn printf(c: *const i8, ...); +} + +fn main() { + unsafe { + printf(::std::ptr::null(), 0f32); + //~^ ERROR can't pass `f32` to variadic function, cast to `c_double` [E0617] + printf(::std::ptr::null(), 0i8); + //~^ ERROR can't pass `i8` to variadic function, cast to `c_int` [E0617] + printf(::std::ptr::null(), 0i16); + //~^ ERROR can't pass `i16` to variadic function, cast to `c_int` [E0617] + printf(::std::ptr::null(), 0u8); + //~^ ERROR can't pass `u8` to variadic function, cast to `c_uint` [E0617] + printf(::std::ptr::null(), 0u16); + //~^ ERROR can't pass `u16` to variadic function, cast to `c_uint` [E0617] + printf(::std::ptr::null(), printf); + //~^ ERROR can't pass `unsafe extern "C" fn(*const i8, ...) {printf}` to variadic function, cast to `unsafe extern "C" fn(*const i8, ...)` [E0617] + } +} diff --git a/src/test/compile-fail/variadic-ffi-3.rs b/src/test/compile-fail/variadic-ffi-3.rs index 565d8549b372..fb102027180f 100644 --- a/src/test/compile-fail/variadic-ffi-3.rs +++ b/src/test/compile-fail/variadic-ffi-3.rs @@ -35,11 +35,11 @@ fn main() { //~| found type `extern "C" fn(isize, u8) {bar}` //~| NOTE: expected variadic fn, found non-variadic function - foo(1, 2, 3f32); //~ ERROR: can't pass an `f32` to variadic function, cast to `c_double` - foo(1, 2, true); //~ ERROR: can't pass `bool` to variadic function, cast to `c_int` - foo(1, 2, 1i8); //~ ERROR: can't pass `i8` to variadic function, cast to `c_int` - foo(1, 2, 1u8); //~ ERROR: can't pass `u8` to variadic function, cast to `c_uint` - foo(1, 2, 1i16); //~ ERROR: can't pass `i16` to variadic function, cast to `c_int` - foo(1, 2, 1u16); //~ ERROR: can't pass `u16` to variadic function, cast to `c_uint` + foo(1, 2, 3f32); //~ ERROR can't pass `f32` to variadic function, cast to `c_double` + foo(1, 2, true); //~ ERROR can't pass `bool` to variadic function, cast to `c_int` + foo(1, 2, 1i8); //~ ERROR can't pass `i8` to variadic function, cast to `c_int` + foo(1, 2, 1u8); //~ ERROR can't pass `u8` to variadic function, cast to `c_uint` + foo(1, 2, 1i16); //~ ERROR can't pass `i16` to variadic function, cast to `c_int` + foo(1, 2, 1u16); //~ ERROR can't pass `u16` to variadic function, cast to `c_uint` } } From 9da77b3ec5dd99c50629005480323e6684957409 Mon Sep 17 00:00:00 2001 From: Marco A L Barbosa Date: Tue, 13 Jun 2017 19:14:15 -0300 Subject: [PATCH 181/233] Disable wasm32 image --- .travis.yml | 2 +- src/ci/docker/{ => disabled}/wasm32/Dockerfile | 0 src/ci/docker/{ => disabled}/wasm32/node.sh | 0 3 files changed, 1 insertion(+), 1 deletion(-) rename src/ci/docker/{ => disabled}/wasm32/Dockerfile (100%) rename src/ci/docker/{ => disabled}/wasm32/node.sh (100%) diff --git a/.travis.yml b/.travis.yml index dca0c16be891..60aac42fb687 100644 --- a/.travis.yml +++ b/.travis.yml @@ -39,7 +39,7 @@ matrix: - env: IMAGE=asmjs - env: IMAGE=i686-gnu - env: IMAGE=i686-gnu-nopt - - env: IMAGE=wasm32 ALLOW_PR=1 + # - env: IMAGE=wasm32 issue 42646 - env: IMAGE=x86_64-gnu - env: IMAGE=x86_64-gnu-full-bootstrap - env: IMAGE=x86_64-gnu-aux diff --git a/src/ci/docker/wasm32/Dockerfile b/src/ci/docker/disabled/wasm32/Dockerfile similarity index 100% rename from src/ci/docker/wasm32/Dockerfile rename to src/ci/docker/disabled/wasm32/Dockerfile diff --git a/src/ci/docker/wasm32/node.sh b/src/ci/docker/disabled/wasm32/node.sh similarity index 100% rename from src/ci/docker/wasm32/node.sh rename to src/ci/docker/disabled/wasm32/node.sh From 9a471606c05621db6ab85f6bb645e52e0f9ad5eb Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 8 Jun 2017 14:10:26 +1200 Subject: [PATCH 182/233] Remove CSV format of save-analysis data --- src/librustc/session/config.rs | 4 - src/librustc_driver/lib.rs | 3 - src/librustc_save_analysis/csv_dumper.rs | 436 ----------------------- src/librustc_save_analysis/lib.rs | 9 +- src/test/run-make/save-analysis/Makefile | 1 - 5 files changed, 1 insertion(+), 452 deletions(-) delete mode 100644 src/librustc_save_analysis/csv_dumper.rs diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 589489b49b4f..9f950414219b 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -935,8 +935,6 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, save_analysis: bool = (false, parse_bool, [UNTRACKED], "write syntax and type analysis (in JSON format) information, in \ addition to normal output"), - save_analysis_csv: bool = (false, parse_bool, [UNTRACKED], - "write syntax and type analysis (in CSV format) information, in addition to normal output"), save_analysis_api: bool = (false, parse_bool, [UNTRACKED], "write syntax and type analysis information for opaque libraries (in JSON format), \ in addition to normal output"), @@ -2469,8 +2467,6 @@ mod tests { assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); opts.debugging_opts.save_analysis = true; assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); - opts.debugging_opts.save_analysis_csv = true; - assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); opts.debugging_opts.save_analysis_api = true; assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); opts.debugging_opts.print_move_fragments = true; diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index c5f89e861fa1..995007eb16fe 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -534,15 +534,12 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls { fn save_analysis(sess: &Session) -> bool { sess.opts.debugging_opts.save_analysis || - sess.opts.debugging_opts.save_analysis_csv || sess.opts.debugging_opts.save_analysis_api } fn save_analysis_format(sess: &Session) -> save::Format { if sess.opts.debugging_opts.save_analysis { save::Format::Json - } else if sess.opts.debugging_opts.save_analysis_csv { - save::Format::Csv } else if sess.opts.debugging_opts.save_analysis_api { save::Format::JsonApi } else { diff --git a/src/librustc_save_analysis/csv_dumper.rs b/src/librustc_save_analysis/csv_dumper.rs deleted file mode 100644 index 4bab135ff12f..000000000000 --- a/src/librustc_save_analysis/csv_dumper.rs +++ /dev/null @@ -1,436 +0,0 @@ -// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::io::Write; - -use super::external_data::*; -use super::dump::Dump; - -use rls_data::{SpanData, CratePreludeData}; - -pub struct CsvDumper<'b, W: 'b> { - output: &'b mut W -} - -impl<'b, W: Write> CsvDumper<'b, W> { - pub fn new(writer: &'b mut W) -> CsvDumper<'b, W> { - CsvDumper { output: writer } - } - - fn record(&mut self, kind: &str, span: SpanData, values: String) { - let span_str = span_extent_str(span); - if let Err(_) = write!(self.output, "{},{}{}\n", kind, span_str, values) { - error!("Error writing output"); - } - } - - fn record_raw(&mut self, info: &str) { - if let Err(_) = write!(self.output, "{}", info) { - error!("Error writing output '{}'", info); - } - } -} - -impl<'b, W: Write + 'b> Dump for CsvDumper<'b, W> { - fn crate_prelude(&mut self, data: CratePreludeData) { - let values = make_values_str(&[ - ("name", &data.crate_name), - ("crate_root", &data.crate_root) - ]); - - self.record("crate", data.span, values); - - for c in data.external_crates { - let num = c.num.to_string(); - let values = make_values_str(&[ - ("name", &c.name), - ("crate", &num), - ("file_name", &c.file_name) - ]); - - self.record_raw(&format!("external_crate{}\n", values)); - } - - self.record_raw("end_external_crates\n"); - } - - fn enum_data(&mut self, data: EnumData) { - let id = data.id.index.as_u32().to_string(); - let scope = data.scope.index.as_u32().to_string(); - let values = make_values_str(&[ - ("id", &id), - ("qualname", &data.qualname), - ("scopeid", &scope), - ("value", &data.value) - ]); - - self.record("enum", data.span, values); - } - - fn extern_crate(&mut self, data: ExternCrateData) { - let id = data.id.index.as_u32().to_string(); - let crate_num = data.crate_num.to_string(); - let scope = data.scope.index.as_u32().to_string(); - let values = make_values_str(&[ - ("id", &id), - ("name", &data.name), - ("location", &data.location), - ("crate", &crate_num), - ("scopeid", &scope) - ]); - - self.record("extern_crate", data.span, values); - } - - fn impl_data(&mut self, data: ImplData) { - let self_ref = data.self_ref.unwrap_or(null_def_id()); - let trait_ref = data.trait_ref.unwrap_or(null_def_id()); - - let id = data.id.index.as_u32().to_string(); - let ref_id = self_ref.index.as_usize().to_string(); - let ref_id_crate = self_ref.krate.to_string(); - let trait_id = trait_ref.index.as_usize().to_string(); - let trait_id_crate = trait_ref.krate.to_string(); - let scope = data.scope.index.as_u32().to_string(); - let values = make_values_str(&[ - ("id", &id), - ("refid", &ref_id), - ("refidcrate", &ref_id_crate), - ("traitid", &trait_id), - ("traitidcrate", &trait_id_crate), - ("scopeid", &scope) - ]); - - self.record("impl", data.span, values); - } - - fn inheritance(&mut self, data: InheritanceData) { - let base_id = data.base_id.index.as_usize().to_string(); - let base_crate = data.base_id.krate.to_string(); - let deriv_id = data.deriv_id.index.as_u32().to_string(); - let deriv_crate = data.deriv_id.krate.to_string(); - let values = make_values_str(&[ - ("base", &base_id), - ("basecrate", &base_crate), - ("derived", &deriv_id), - ("derivedcrate", &deriv_crate) - ]); - - self.record("inheritance", data.span, values); - } - - fn function(&mut self, data: FunctionData) { - let (decl_id, decl_crate) = match data.declaration { - Some(id) => (id.index.as_usize().to_string(), id.krate.to_string()), - None => (String::new(), String::new()) - }; - - let id = data.id.index.as_u32().to_string(); - let scope = data.scope.index.as_u32().to_string(); - let values = make_values_str(&[ - ("id", &id), - ("qualname", &data.qualname), - ("declid", &decl_id), - ("declidcrate", &decl_crate), - ("scopeid", &scope) - ]); - - self.record("function", data.span, values); - } - - fn function_ref(&mut self, data: FunctionRefData) { - let ref_id = data.ref_id.index.as_usize().to_string(); - let ref_crate = data.ref_id.krate.to_string(); - let scope = data.scope.index.as_u32().to_string(); - let values = make_values_str(&[ - ("refid", &ref_id), - ("refidcrate", &ref_crate), - ("qualname", ""), - ("scopeid", &scope) - ]); - - self.record("fn_ref", data.span, values); - } - - fn function_call(&mut self, data: FunctionCallData) { - let ref_id = data.ref_id.index.as_usize().to_string(); - let ref_crate = data.ref_id.krate.to_string(); - let qualname = String::new(); - let scope = data.scope.index.as_u32().to_string(); - let values = make_values_str(&[ - ("refid", &ref_id), - ("refidcrate", &ref_crate), - ("qualname", &qualname), - ("scopeid", &scope) - ]); - - self.record("fn_call", data.span, values); - } - - fn method(&mut self, data: MethodData) { - let id = data.id.index.as_u32().to_string(); - let scope = data.scope.index.as_u32().to_string(); - let values = make_values_str(&[ - ("id", &id), - ("qualname", &data.qualname), - ("scopeid", &scope) - ]); - - self.record("method_decl", data.span, values); - } - - fn method_call(&mut self, data: MethodCallData) { - let (dcn, dck) = match data.decl_id { - Some(declid) => (declid.index.as_usize().to_string(), declid.krate.to_string()), - None => (String::new(), String::new()), - }; - - let ref_id = data.ref_id.unwrap_or(null_def_id()); - - let def_id = ref_id.index.as_usize().to_string(); - let def_crate = ref_id.krate.to_string(); - let scope = data.scope.index.as_u32().to_string(); - let values = make_values_str(&[ - ("refid", &def_id), - ("refidcrate", &def_crate), - ("declid", &dcn), - ("declidcrate", &dck), - ("scopeid", &scope) - ]); - - self.record("method_call", data.span, values); - } - - fn macro_data(&mut self, data: MacroData) { - let values = make_values_str(&[ - ("name", &data.name), - ("qualname", &data.qualname) - ]); - - self.record("macro", data.span, values); - } - - fn macro_use(&mut self, data: MacroUseData) { - let scope = data.scope.index.as_u32().to_string(); - let values = make_values_str(&[ - ("callee_name", &data.name), - ("qualname", &data.qualname), - ("scopeid", &scope) - ]); - - self.record("macro_use", data.span, values); - } - - fn mod_data(&mut self, data: ModData) { - let id = data.id.index.as_u32().to_string(); - let scope = data.scope.index.as_u32().to_string(); - let values = make_values_str(&[ - ("id", &id), - ("qualname", &data.qualname), - ("scopeid", &scope), - ("def_file", &data.filename) - ]); - - self.record("module", data.span, values); - } - - fn mod_ref(&mut self, data: ModRefData) { - let (ref_id, ref_crate) = match data.ref_id { - Some(rid) => (rid.index.as_usize().to_string(), rid.krate.to_string()), - None => (0.to_string(), 0.to_string()) - }; - - let scope = data.scope.index.as_u32().to_string(); - let values = make_values_str(&[ - ("refid", &ref_id), - ("refidcrate", &ref_crate), - ("qualname", &data.qualname), - ("scopeid", &scope) - ]); - - self.record("mod_ref", data.span, values); - } - - fn struct_data(&mut self, data: StructData) { - let id = data.id.index.as_u32().to_string(); - let ctor_id = data.ctor_id.index.as_u32().to_string(); - let scope = data.scope.index.as_u32().to_string(); - let values = make_values_str(&[ - ("id", &id), - ("ctor_id", &ctor_id), - ("qualname", &data.qualname), - ("scopeid", &scope), - ("value", &data.value) - ]); - - self.record("struct", data.span, values); - } - - fn struct_variant(&mut self, data: StructVariantData) { - let id = data.id.index.as_u32().to_string(); - let scope = data.scope.index.as_u32().to_string(); - let values = make_values_str(&[ - ("id", &id), - ("ctor_id", &id), - ("qualname", &data.qualname), - ("type", &data.type_value), - ("value", &data.value), - ("scopeid", &scope) - ]); - - self.record("variant_struct", data.span, values); - } - - fn trait_data(&mut self, data: TraitData) { - let id = data.id.index.as_u32().to_string(); - let scope = data.scope.index.as_u32().to_string(); - let values = make_values_str(&[ - ("id", &id), - ("qualname", &data.qualname), - ("scopeid", &scope), - ("value", &data.value) - ]); - - self.record("trait", data.span, values); - } - - fn tuple_variant(&mut self, data: TupleVariantData) { - let id = data.id.index.as_u32().to_string(); - let scope = data.scope.index.as_u32().to_string(); - let values = make_values_str(&[ - ("id", &id), - ("name", &data.name), - ("qualname", &data.qualname), - ("type", &data.type_value), - ("value", &data.value), - ("scopeid", &scope) - ]); - - self.record("variant", data.span, values); - } - - fn type_ref(&mut self, data: TypeRefData) { - let (ref_id, ref_crate) = match data.ref_id { - Some(id) => (id.index.as_usize().to_string(), id.krate.to_string()), - None => (0.to_string(), 0.to_string()) - }; - - let scope = data.scope.index.as_u32().to_string(); - let values = make_values_str(&[ - ("refid", &ref_id), - ("refidcrate", &ref_crate), - ("qualname", &data.qualname), - ("scopeid", &scope) - ]); - - self.record("type_ref", data.span, values); - } - - fn typedef(&mut self, data: TypeDefData) { - let id = data.id.index.as_u32().to_string(); - let values = make_values_str(&[ - ("id", &id), - ("qualname", &data.qualname), - ("value", &data.value) - ]); - - self.record("typedef", data.span, values); - } - - fn use_data(&mut self, data: UseData) { - let mod_id = data.mod_id.unwrap_or(null_def_id()); - - let id = data.id.index.as_u32().to_string(); - let ref_id = mod_id.index.as_usize().to_string(); - let ref_crate = mod_id.krate.to_string(); - let scope = data.scope.index.as_u32().to_string(); - let values = make_values_str(&[ - ("id", &id), - ("refid", &ref_id), - ("refidcrate", &ref_crate), - ("name", &data.name), - ("scopeid", &scope) - ]); - - self.record("use_alias", data.span, values); - } - - fn use_glob(&mut self, data: UseGlobData) { - let names = data.names.join(", "); - - let id = data.id.index.as_u32().to_string(); - let scope = data.scope.index.as_u32().to_string(); - let values = make_values_str(&[ - ("id", &id), - ("value", &names), - ("scopeid", &scope) - ]); - - self.record("use_glob", data.span, values); - } - - fn variable(&mut self, data: VariableData) { - let id = data.id.index.as_u32().to_string(); - let scope = data.scope.index.as_u32().to_string(); - let values = make_values_str(&[ - ("id", &id), - ("name", &data.name), - ("qualname", &data.qualname), - ("value", &data.value), - ("type", &data.type_value), - ("scopeid", &scope) - ]); - - self.record("variable", data.span, values); - } - - fn variable_ref(&mut self, data: VariableRefData) { - let ref_id = data.ref_id.index.as_usize().to_string(); - let ref_crate = data.ref_id.krate.to_string(); - let scope = data.scope.index.as_u32().to_string(); - let values = make_values_str(&[ - ("refid", &ref_id), - ("refidcrate", &ref_crate), - ("qualname", ""), - ("scopeid", &scope) - ]); - - self.record("var_ref", data.span, values) - } -} - -// Helper function to escape quotes in a string -fn escape(s: String) -> String { - s.replace("\"", "\"\"") -} - -fn make_values_str(pairs: &[(&'static str, &str)]) -> String { - let pairs = pairs.into_iter().map(|&(f, v)| { - // Never take more than 1020 chars - if v.len() > 1020 { - (f, &v[..1020]) - } else { - (f, v) - } - }); - - let strs = pairs.map(|(f, v)| format!(",{},\"{}\"", f, escape(String::from(v)))); - strs.fold(String::new(), |mut s, ss| { - s.push_str(&ss); - s - }) -} - -fn span_extent_str(span: SpanData) -> String { - format!("file_name,\"{}\",file_line,{},file_col,{},byte_start,{},\ - file_line_end,{},file_col_end,{},byte_end,{}", - span.file_name.to_str().unwrap(), span.line_start.0, span.column_start.0, - span.byte_start, span.line_end.0, span.column_end.0, span.byte_end) -} diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 4802494f08ea..be879a01fb8f 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -35,7 +35,6 @@ extern crate rls_data; extern crate rls_span; -mod csv_dumper; mod json_api_dumper; mod json_dumper; mod data; @@ -68,7 +67,6 @@ use syntax::print::pprust::{ty_to_string, arg_to_string}; use syntax::codemap::MacroAttribute; use syntax_pos::*; -pub use self::csv_dumper::CsvDumper; pub use self::json_api_dumper::JsonApiDumper; pub use self::json_dumper::JsonDumper; pub use self::data::*; @@ -866,17 +864,13 @@ fn docs_for_attrs(attrs: &[Attribute]) -> String { #[derive(Clone, Copy, Debug, RustcEncodable)] pub enum Format { - Csv, Json, JsonApi, } impl Format { fn extension(&self) -> &'static str { - match *self { - Format::Csv => ".csv", - Format::Json | Format::JsonApi => ".json", - } + ".json" } } @@ -959,7 +953,6 @@ impl<'a> SaveHandler for DumpHandler<'a> { let output = &mut self.output_file(&save_ctxt.tcx.sess); match self.format { - Format::Csv => dump!(CsvDumper::new(output)), Format::Json => dump!(JsonDumper::new(output)), Format::JsonApi => dump!(JsonApiDumper::new(output)), } diff --git a/src/test/run-make/save-analysis/Makefile b/src/test/run-make/save-analysis/Makefile index 3711b6ea8959..9ebc40d4013c 100644 --- a/src/test/run-make/save-analysis/Makefile +++ b/src/test/run-make/save-analysis/Makefile @@ -3,6 +3,5 @@ all: code krate2: krate2.rs $(RUSTC) $< code: foo.rs krate2 - $(RUSTC) foo.rs -Zsave-analysis-csv $(RUSTC) foo.rs -Zsave-analysis $(RUSTC) foo.rs -Zsave-analysis-api From edd3cd84feab2672f448017e0e41f04e114dfaf3 Mon Sep 17 00:00:00 2001 From: Havvy Date: Tue, 13 Jun 2017 18:49:30 -0700 Subject: [PATCH 183/233] Remove sometimes in std::io::Read doc We use it immediately in the next sentence, and the word is filler. --- src/libstd/io/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index c872a8e52611..23836adced82 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -389,7 +389,7 @@ fn read_to_end(r: &mut R, buf: &mut Vec) -> Result /// The `Read` trait allows for reading bytes from a source. /// -/// Implementors of the `Read` trait are sometimes called 'readers'. +/// Implementors of the `Read` trait are called 'readers'. /// /// Readers are defined by one required method, `read()`. Each call to `read` /// will attempt to pull bytes from this source into a provided buffer. A From d81089875153046f80057f08eaf3ea5f40676010 Mon Sep 17 00:00:00 2001 From: est31 Date: Mon, 12 Jun 2017 15:06:12 +0200 Subject: [PATCH 184/233] Librarify tidy Convert tidy into a library so that the data it creates can be used by external tools. --- src/tools/tidy/src/lib.rs | 88 ++++++++++++++++++++++++++++++++++++++ src/tools/tidy/src/main.rs | 82 ++++------------------------------- 2 files changed, 97 insertions(+), 73 deletions(-) create mode 100644 src/tools/tidy/src/lib.rs diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs new file mode 100644 index 000000000000..bcf86e4489be --- /dev/null +++ b/src/tools/tidy/src/lib.rs @@ -0,0 +1,88 @@ +// 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. + +//! Library used by tidy and other tools +//! +//! This library contains the tidy lints and exposes it +//! to be used by tools. + +#![deny(warnings)] + +use std::fs; + +use std::path::Path; + +macro_rules! t { + ($e:expr, $p:expr) => (match $e { + Ok(e) => e, + Err(e) => panic!("{} failed on {} with {}", stringify!($e), ($p).display(), e), + }); + + ($e:expr) => (match $e { + Ok(e) => e, + Err(e) => panic!("{} failed with {}", stringify!($e), e), + }) +} + +macro_rules! tidy_error { + ($bad:expr, $fmt:expr, $($arg:tt)*) => ({ + use std::io::Write; + *$bad = true; + write!(::std::io::stderr(), "tidy error: ").expect("could not write to stderr"); + writeln!(::std::io::stderr(), $fmt, $($arg)*).expect("could not write to stderr"); + }); +} + +pub mod bins; +pub mod style; +pub mod errors; +pub mod features; +pub mod cargo; +pub mod pal; +pub mod deps; +pub mod unstable_book; + +fn filter_dirs(path: &Path) -> bool { + let skip = [ + "src/jemalloc", + "src/llvm", + "src/libbacktrace", + "src/compiler-rt", + "src/rustllvm", + "src/liblibc", + "src/vendor", + "src/rt/hoedown", + "src/tools/cargo", + "src/tools/rls", + "src/tools/rust-installer", + ]; + skip.iter().any(|p| path.ends_with(p)) +} + +fn walk_many(paths: &[&Path], skip: &mut FnMut(&Path) -> bool, f: &mut FnMut(&Path)) { + for path in paths { + walk(path, skip, f); + } +} + +fn walk(path: &Path, skip: &mut FnMut(&Path) -> bool, f: &mut FnMut(&Path)) { + for entry in t!(fs::read_dir(path), path) { + let entry = t!(entry); + let kind = t!(entry.file_type()); + let path = entry.path(); + if kind.is_dir() { + if !skip(&path) { + walk(&path, skip, f); + } + } else { + f(&path); + } + } +} diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs index 23a31131f7a6..433192a21ec9 100644 --- a/src/tools/tidy/src/main.rs +++ b/src/tools/tidy/src/main.rs @@ -8,47 +8,21 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Tidy checks for source code in this repository +//! Tidy checks source code in this repository //! //! This program runs all of the various tidy checks for style, cleanliness, //! etc. This is run by default on `make check` and as part of the auto //! builders. -use std::env; -use std::fs; -use std::io::{self, Write}; -use std::path::{PathBuf, Path}; +#![deny(warnings)] + +extern crate tidy; +use tidy::*; + use std::process; - -macro_rules! t { - ($e:expr, $p:expr) => (match $e { - Ok(e) => e, - Err(e) => panic!("{} failed on {} with {}", stringify!($e), ($p).display(), e), - }); - - ($e:expr) => (match $e { - Ok(e) => e, - Err(e) => panic!("{} failed with {}", stringify!($e), e), - }) -} - -macro_rules! tidy_error { - ($bad:expr, $fmt:expr, $($arg:tt)*) => ({ - use std::io::Write; - *$bad = true; - write!(::std::io::stderr(), "tidy error: ").expect("could not write to stderr"); - writeln!(::std::io::stderr(), $fmt, $($arg)*).expect("could not write to stderr"); - }); -} - -mod bins; -mod style; -mod errors; -mod features; -mod cargo; -mod pal; -mod deps; -mod unstable_book; +use std::path::PathBuf; +use std::env; +use std::io::{self, Write}; fn main() { let path = env::args_os().skip(1).next().expect("need an argument"); @@ -74,41 +48,3 @@ fn main() { process::exit(1); } } - -fn filter_dirs(path: &Path) -> bool { - let skip = [ - "src/jemalloc", - "src/llvm", - "src/libbacktrace", - "src/compiler-rt", - "src/rustllvm", - "src/liblibc", - "src/vendor", - "src/rt/hoedown", - "src/tools/cargo", - "src/tools/rls", - "src/tools/rust-installer", - ]; - skip.iter().any(|p| path.ends_with(p)) -} - -fn walk_many(paths: &[&Path], skip: &mut FnMut(&Path) -> bool, f: &mut FnMut(&Path)) { - for path in paths { - walk(path, skip, f); - } -} - -fn walk(path: &Path, skip: &mut FnMut(&Path) -> bool, f: &mut FnMut(&Path)) { - for entry in t!(fs::read_dir(path), path) { - let entry = t!(entry); - let kind = t!(entry.file_type()); - let path = entry.path(); - if kind.is_dir() { - if !skip(&path) { - walk(&path, skip, f); - } - } else { - f(&path); - } - } -} From c2d59067fb9f365e302710005b5c3ccc3ea85f9a Mon Sep 17 00:00:00 2001 From: est31 Date: Mon, 12 Jun 2017 21:35:47 +0200 Subject: [PATCH 185/233] Autogenerate stubs and the summary of the unstable book --- src/Cargo.lock | 7 + src/Cargo.toml | 1 + src/bootstrap/doc.rs | 27 +++- src/bootstrap/lib.rs | 5 + src/bootstrap/step.rs | 21 ++- .../src/language-features/asm.md | 2 +- .../{global_asm.md => global-asm.md} | 0 ...s_bytes.md => from-utf8-error-as-bytes.md} | 0 src/tools/tidy/src/features.rs | 66 ++++++-- src/tools/tidy/src/unstable_book.rs | 46 +++--- src/tools/unstable-book-gen/Cargo.toml | 9 ++ src/tools/unstable-book-gen/src/SUMMARY.md | 8 + src/tools/unstable-book-gen/src/main.rs | 149 ++++++++++++++++++ src/tools/unstable-book-gen/src/stub-issue.md | 7 + .../unstable-book-gen/src/stub-no-issue.md | 5 + 15 files changed, 308 insertions(+), 45 deletions(-) rename src/doc/unstable-book/src/language-features/{global_asm.md => global-asm.md} (100%) rename src/doc/unstable-book/src/library-features/{from_utf8_error_as_bytes.md => from-utf8-error-as-bytes.md} (100%) create mode 100644 src/tools/unstable-book-gen/Cargo.toml create mode 100644 src/tools/unstable-book-gen/src/SUMMARY.md create mode 100644 src/tools/unstable-book-gen/src/main.rs create mode 100644 src/tools/unstable-book-gen/src/stub-issue.md create mode 100644 src/tools/unstable-book-gen/src/stub-no-issue.md diff --git a/src/Cargo.lock b/src/Cargo.lock index efbbe36c981a..80e01baa5823 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -1892,6 +1892,13 @@ dependencies = [ "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "unstable-book-gen" +version = "0.1.0" +dependencies = [ + "tidy 0.1.0", +] + [[package]] name = "url" version = "1.4.0" diff --git a/src/Cargo.toml b/src/Cargo.toml index 85a6df3573ae..8efa484287a1 100644 --- a/src/Cargo.toml +++ b/src/Cargo.toml @@ -9,6 +9,7 @@ members = [ "tools/error_index_generator", "tools/linkchecker", "tools/rustbook", + "tools/unstable-book-gen", "tools/tidy", "tools/build-manifest", "tools/remote-test-client", diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index baee1ada508f..30f631ca2df6 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -27,18 +27,26 @@ use {Build, Compiler, Mode}; use util::{cp_r, symlink_dir}; use build_helper::up_to_date; -/// Invoke `rustbook` as compiled in `stage` for `target` for the doc book -/// `name` into the `out` path. +/// Invoke `rustbook` for `target` for the doc book `name`. /// /// This will not actually generate any documentation if the documentation has /// already been generated. pub fn rustbook(build: &Build, target: &str, name: &str) { + let src = build.src.join("src/doc"); + rustbook_src(build, target, name, &src); +} + +/// Invoke `rustbook` for `target` for the doc book `name` from the `src` path. +/// +/// This will not actually generate any documentation if the documentation has +/// already been generated. +pub fn rustbook_src(build: &Build, target: &str, name: &str, src: &Path) { let out = build.doc_out(target); t!(fs::create_dir_all(&out)); let out = out.join(name); let compiler = Compiler::new(0, &build.config.build); - let src = build.src.join("src/doc").join(name); + let src = src.join(name); let index = out.join("index.html"); let rustbook = build.tool(&compiler, "rustbook"); if up_to_date(&src, &index) && up_to_date(&rustbook, &index) { @@ -354,6 +362,19 @@ pub fn error_index(build: &Build, target: &str) { build.run(&mut index); } +pub fn unstable_book_gen(build: &Build, target: &str) { + println!("Generating unstable book md files ({})", target); + let out = build.md_doc_out(target).join("unstable-book"); + t!(fs::create_dir_all(&out)); + t!(fs::remove_dir_all(&out)); + let compiler = Compiler::new(0, &build.config.build); + let mut cmd = build.tool_cmd(&compiler, "unstable-book-gen"); + cmd.arg(build.src.join("src")); + cmd.arg(out); + + build.run(&mut cmd); +} + fn symlink_dir_force(src: &Path, dst: &Path) -> io::Result<()> { if let Ok(m) = fs::symlink_metadata(dst) { if m.file_type().is_dir() { diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 2fe6a2a3ae89..1c59debddbb1 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -677,6 +677,11 @@ impl Build { self.out.join(target).join("doc") } + /// Output directory for some generated md crate documentation for a target (temporary) + fn md_doc_out(&self, target: &str) -> PathBuf { + self.out.join(target).join("md-doc") + } + /// Output directory for all crate documentation for a target (temporary) /// /// The artifacts here are then copied into `doc_out` above. diff --git a/src/bootstrap/step.rs b/src/bootstrap/step.rs index 9e8b08a23b7e..684a00ce7f16 100644 --- a/src/bootstrap/step.rs +++ b/src/bootstrap/step.rs @@ -548,6 +548,10 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { .dep(|s| s.name("maybe-clean-tools")) .dep(|s| s.name("librustc-tool")) .run(move |s| compile::tool(build, s.stage, s.target, "error_index_generator")); + rules.build("tool-unstable-book-gen", "src/tools/unstable-book-gen") + .dep(|s| s.name("maybe-clean-tools")) + .dep(|s| s.name("libstd-tool")) + .run(move |s| compile::tool(build, s.stage, s.target, "unstable-book-gen")); rules.build("tool-tidy", "src/tools/tidy") .dep(|s| s.name("maybe-clean-tools")) .dep(|s| s.name("libstd-tool")) @@ -662,8 +666,17 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { .target(&build.config.build) .stage(0) }) + .dep(move |s| { + s.name("doc-unstable-book-gen") + .host(&build.config.build) + .target(&build.config.build) + .stage(0) + }) .default(build.config.docs) - .run(move |s| doc::rustbook(build, s.target, "unstable-book")); + .run(move |s| doc::rustbook_src(build, + s.target, + "unstable-book", + &build.md_doc_out(s.target))); rules.doc("doc-standalone", "src/doc") .dep(move |s| { s.name("rustc") @@ -679,6 +692,12 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { .default(build.config.docs) .host(true) .run(move |s| doc::error_index(build, s.target)); + rules.doc("doc-unstable-book-gen", "src/tools/unstable-book-gen") + .dep(move |s| s.name("tool-unstable-book-gen").target(&build.config.build).stage(0)) + .dep(move |s| s.name("librustc-link")) + .default(build.config.docs) + .host(true) + .run(move |s| doc::unstable_book_gen(build, s.target)); for (krate, path, default) in krates("std") { rules.doc(&krate.doc_step, path) .dep(|s| s.name("libstd-link")) diff --git a/src/doc/unstable-book/src/language-features/asm.md b/src/doc/unstable-book/src/language-features/asm.md index 8deb8f462562..f22095fe5de2 100644 --- a/src/doc/unstable-book/src/language-features/asm.md +++ b/src/doc/unstable-book/src/language-features/asm.md @@ -190,4 +190,4 @@ constraints, etc. [llvm-docs]: http://llvm.org/docs/LangRef.html#inline-assembler-expressions If you need more power and don't mind losing some of the niceties of -`asm!`, check out [global_asm](language-features/global_asm.html). +`asm!`, check out [global_asm](language-features/global-asm.html). diff --git a/src/doc/unstable-book/src/language-features/global_asm.md b/src/doc/unstable-book/src/language-features/global-asm.md similarity index 100% rename from src/doc/unstable-book/src/language-features/global_asm.md rename to src/doc/unstable-book/src/language-features/global-asm.md diff --git a/src/doc/unstable-book/src/library-features/from_utf8_error_as_bytes.md b/src/doc/unstable-book/src/library-features/from-utf8-error-as-bytes.md similarity index 100% rename from src/doc/unstable-book/src/library-features/from_utf8_error_as_bytes.md rename to src/doc/unstable-book/src/library-features/from-utf8-error-as-bytes.md diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs index e34821e3584c..81db23ccceb5 100644 --- a/src/tools/tidy/src/features.rs +++ b/src/tools/tidy/src/features.rs @@ -24,7 +24,7 @@ use std::fs::File; use std::io::prelude::*; use std::path::Path; -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub enum Status { Stable, Removed, @@ -42,13 +42,16 @@ impl fmt::Display for Status { } } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct Feature { pub level: Status, pub since: String, pub has_gate_test: bool, + pub tracking_issue: Option, } +pub type Features = HashMap; + pub fn check(path: &Path, bad: &mut bool, quiet: bool) { let mut features = collect_lang_features(path); assert!(!features.is_empty()); @@ -168,8 +171,7 @@ fn find_attr_val<'a>(line: &'a str, attr: &str) -> Option<&'a str> { .map(|(i, j)| &line[i..j]) } -fn test_filen_gate(filen_underscore: &str, - features: &mut HashMap) -> bool { +fn test_filen_gate(filen_underscore: &str, features: &mut Features) -> bool { if filen_underscore.starts_with("feature_gate") { for (n, f) in features.iter_mut() { if filen_underscore == format!("feature_gate_{}", n) { @@ -181,7 +183,7 @@ fn test_filen_gate(filen_underscore: &str, return false; } -pub fn collect_lang_features(base_src_path: &Path) -> HashMap { +pub fn collect_lang_features(base_src_path: &Path) -> Features { let mut contents = String::new(); let path = base_src_path.join("libsyntax/feature_gate.rs"); t!(t!(File::open(path)).read_to_string(&mut contents)); @@ -197,11 +199,19 @@ pub fn collect_lang_features(base_src_path: &Path) -> HashMap { }; let name = parts.next().unwrap().trim(); let since = parts.next().unwrap().trim().trim_matches('"'); + let issue_str = parts.next().unwrap().trim(); + let tracking_issue = if issue_str.starts_with("None") { + None + } else { + let s = issue_str.split("(").nth(1).unwrap().split(")").nth(0).unwrap(); + Some(s.parse().unwrap()) + }; Some((name.to_owned(), Feature { - level: level, + level, since: since.to_owned(), has_gate_test: false, + tracking_issue, })) }) .collect() @@ -209,8 +219,8 @@ pub fn collect_lang_features(base_src_path: &Path) -> HashMap { pub fn collect_lib_features(base_src_path: &Path, bad: &mut bool, - features: &HashMap) -> HashMap { - let mut lib_features = HashMap::::new(); + features: &Features) -> Features { + let mut lib_features = Features::new(); let mut contents = String::new(); super::walk(base_src_path, &mut |path| super::filter_dirs(path) || path.ends_with("src/test"), @@ -224,10 +234,32 @@ pub fn collect_lib_features(base_src_path: &Path, contents.truncate(0); t!(t!(File::open(&file), &file).read_to_string(&mut contents)); + let mut becoming_feature: Option<(String, Feature)> = None; for (i, line) in contents.lines().enumerate() { let mut err = |msg: &str| { tidy_error!(bad, "{}:{}: {}", file.display(), i + 1, msg); }; + if let Some((ref name, ref mut f)) = becoming_feature { + if f.tracking_issue.is_none() { + f.tracking_issue = find_attr_val(line, "issue") + .map(|s| s.parse().unwrap()); + } + if line.ends_with("]") { + lib_features.insert(name.to_owned(), f.clone()); + } else if !line.ends_with(",") && !line.ends_with("\\") { + // We need to bail here because we might have missed the + // end of a stability attribute above because the "]" + // might not have been at the end of the line. + // We could then get into the very unfortunate situation that + // we continue parsing the file assuming the current stability + // attribute has not ended, and ignoring possible feature + // attributes in the process. + err("malformed stability attribute"); + } else { + continue; + } + } + becoming_feature = None; let level = if line.contains("[unstable(") { Status::Unstable } else if line.contains("[stable(") { @@ -250,6 +282,7 @@ pub fn collect_lib_features(base_src_path: &Path, } None => "None", }; + let tracking_issue = find_attr_val(line, "issue").map(|s| s.parse().unwrap()); if features.contains_key(feature_name) { err("duplicating a lang feature"); @@ -263,12 +296,17 @@ pub fn collect_lib_features(base_src_path: &Path, } continue; } - lib_features.insert(feature_name.to_owned(), - Feature { - level: level, - since: since.to_owned(), - has_gate_test: false, - }); + let feature = Feature { + level, + since: since.to_owned(), + has_gate_test: false, + tracking_issue, + }; + if line.contains("]") { + lib_features.insert(feature_name.to_owned(), feature); + } else { + becoming_feature = Some((feature_name.to_owned(), feature)); + } } }); lib_features diff --git a/src/tools/tidy/src/unstable_book.rs b/src/tools/tidy/src/unstable_book.rs index 5a6524b3e88e..e05ab470eedc 100644 --- a/src/tools/tidy/src/unstable_book.rs +++ b/src/tools/tidy/src/unstable_book.rs @@ -11,26 +11,28 @@ use std::collections::HashSet; use std::fs; use std::path; -use features::{collect_lang_features, collect_lib_features, Status}; +use features::{collect_lang_features, collect_lib_features, Features, Status}; -const PATH_STR: &'static str = "doc/unstable-book/src"; +pub const PATH_STR: &str = "doc/unstable-book/src"; -const LANG_FEATURES_DIR: &'static str = "language-features"; +pub const COMPILER_FLAGS_DIR: &str = "compiler-flags"; -const LIB_FEATURES_DIR: &'static str = "library-features"; +pub const LANG_FEATURES_DIR: &str = "language-features"; + +pub const LIB_FEATURES_DIR: &str = "library-features"; /// Build the path to the Unstable Book source directory from the Rust 'src' directory -fn unstable_book_path(base_src_path: &path::Path) -> path::PathBuf { +pub fn unstable_book_path(base_src_path: &path::Path) -> path::PathBuf { base_src_path.join(PATH_STR) } /// Directory where the features are documented within the Unstable Book source directory -fn unstable_book_lang_features_path(base_src_path: &path::Path) -> path::PathBuf { +pub fn unstable_book_lang_features_path(base_src_path: &path::Path) -> path::PathBuf { unstable_book_path(base_src_path).join(LANG_FEATURES_DIR) } /// Directory where the features are documented within the Unstable Book source directory -fn unstable_book_lib_features_path(base_src_path: &path::Path) -> path::PathBuf { +pub fn unstable_book_lib_features_path(base_src_path: &path::Path) -> path::PathBuf { unstable_book_path(base_src_path).join(LIB_FEATURES_DIR) } @@ -42,27 +44,16 @@ fn dir_entry_is_file(dir_entry: &fs::DirEntry) -> bool { .is_file() } -/// Retrieve names of all lang-related unstable features -fn collect_unstable_lang_feature_names(base_src_path: &path::Path) -> HashSet { - collect_lang_features(base_src_path) - .into_iter() +/// Retrieve names of all unstable features +pub fn collect_unstable_feature_names(features: &Features) -> HashSet { + features + .iter() .filter(|&(_, ref f)| f.level == Status::Unstable) - .map(|(ref name, _)| name.to_owned()) + .map(|(name, _)| name.to_owned()) .collect() } -/// Retrieve names of all lib-related unstable features -fn collect_unstable_lib_feature_names(base_src_path: &path::Path) -> HashSet { - let mut bad = true; - let lang_features = collect_lang_features(base_src_path); - collect_lib_features(base_src_path, &mut bad, &lang_features) - .into_iter() - .filter(|&(_, ref f)| f.level == Status::Unstable) - .map(|(ref name, _)| name.to_owned()) - .collect() -} - -fn collect_unstable_book_section_file_names(dir: &path::Path) -> HashSet { +pub fn collect_unstable_book_section_file_names(dir: &path::Path) -> HashSet { fs::read_dir(dir) .expect("could not read directory") .into_iter() @@ -95,7 +86,10 @@ pub fn check(path: &path::Path, bad: &mut bool) { // Library features - let unstable_lib_feature_names = collect_unstable_lib_feature_names(path); + let lang_features = collect_lang_features(path); + let lib_features = collect_lib_features(path, bad, &lang_features); + + let unstable_lib_feature_names = collect_unstable_feature_names(&lib_features); let unstable_book_lib_features_section_file_names = collect_unstable_book_lib_features_section_file_names(path); @@ -119,7 +113,7 @@ pub fn check(path: &path::Path, bad: &mut bool) { // Language features - let unstable_lang_feature_names = collect_unstable_lang_feature_names(path); + let unstable_lang_feature_names = collect_unstable_feature_names(&lang_features); let unstable_book_lang_features_section_file_names = collect_unstable_book_lang_features_section_file_names(path); diff --git a/src/tools/unstable-book-gen/Cargo.toml b/src/tools/unstable-book-gen/Cargo.toml new file mode 100644 index 000000000000..4751a5e41510 --- /dev/null +++ b/src/tools/unstable-book-gen/Cargo.toml @@ -0,0 +1,9 @@ +[package] +authors = ["est31 ", + "The Rust Project Developers"] +name = "unstable-book-gen" +version = "0.1.0" +license = "MIT/Apache-2.0" + +[dependencies] +tidy = { path = "../tidy" } diff --git a/src/tools/unstable-book-gen/src/SUMMARY.md b/src/tools/unstable-book-gen/src/SUMMARY.md new file mode 100644 index 000000000000..933c928e2f09 --- /dev/null +++ b/src/tools/unstable-book-gen/src/SUMMARY.md @@ -0,0 +1,8 @@ +[The Unstable Book](the-unstable-book.md) + +- [Compiler flags](compiler-flags.md) +{compiler_flags} +- [Language features](language-features.md) +{language_features} +- [Library Features](library-features.md) +{library_features} diff --git a/src/tools/unstable-book-gen/src/main.rs b/src/tools/unstable-book-gen/src/main.rs new file mode 100644 index 000000000000..adec73d4a69b --- /dev/null +++ b/src/tools/unstable-book-gen/src/main.rs @@ -0,0 +1,149 @@ +// 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. + +//! Auto-generate stub docs for the unstable book + +#![deny(warnings)] + +extern crate tidy; + +use tidy::features::{Feature, Features, collect_lib_features, collect_lang_features}; +use tidy::unstable_book::{collect_unstable_feature_names, collect_unstable_book_section_file_names, + PATH_STR, LANG_FEATURES_DIR, LIB_FEATURES_DIR}; +use std::collections::HashSet; +use std::io::Write; +use std::fs::{self, File}; +use std::env; +use std::path::Path; + +/// A helper macro to `unwrap` a result except also print out details like: +/// +/// * The file/line of the panic +/// * The expression that failed +/// * The error itself +macro_rules! t { + ($e:expr) => (match $e { + Ok(e) => e, + Err(e) => panic!("{} failed with {}", stringify!($e), e), + }) +} + +fn generate_stub_issue(path: &Path, name: &str, issue: u32) { + let mut file = t!(File::create(path)); + t!(file.write_fmt(format_args!(include_str!("stub-issue.md"), + name = name, + issue = issue))); +} + +fn generate_stub_no_issue(path: &Path, name: &str) { + let mut file = t!(File::create(path)); + t!(file.write_fmt(format_args!(include_str!("stub-no-issue.md"), + name = name))); +} + +fn hset_to_summary_str(hset: HashSet, dir: &str +) -> String { + hset + .iter() + .map(|ref n| format!(" - [{}]({}/{}.md)", + n, + dir, + n.replace('_', "-"))) + .fold("".to_owned(), |s, a| s + &a + "\n") +} + +fn generate_summary(path: &Path, lang_features: &Features, lib_features: &Features) { + let compiler_flags = collect_unstable_book_section_file_names( + &path.join("compiler-flags")); + + let compiler_flags_str = hset_to_summary_str(compiler_flags, + "compiler-flags"); + + let unstable_lang_features = collect_unstable_feature_names(&lang_features); + let unstable_lib_features = collect_unstable_feature_names(&lib_features); + + let lang_features_str = hset_to_summary_str(unstable_lang_features, + LANG_FEATURES_DIR); + let lib_features_str = hset_to_summary_str(unstable_lib_features, + LIB_FEATURES_DIR); + + let mut file = t!(File::create(&path.join("SUMMARY.md"))); + t!(file.write_fmt(format_args!(include_str!("SUMMARY.md"), + compiler_flags = compiler_flags_str, + language_features = lang_features_str, + library_features = lib_features_str))); + +} + +fn has_valid_tracking_issue(f: &Feature) -> bool { + if let Some(n) = f.tracking_issue { + if n > 0 { + return true; + } + } + false +} + +fn generate_unstable_book_files(src :&Path, out: &Path, features :&Features) { + let unstable_features = collect_unstable_feature_names(features); + let unstable_section_file_names = collect_unstable_book_section_file_names(src); + t!(fs::create_dir_all(&out)); + for feature_name in &unstable_features - &unstable_section_file_names { + let file_name = format!("{}.md", feature_name.replace('_', "-")); + let out_file_path = out.join(&file_name); + let feature = &features[&feature_name]; + + if has_valid_tracking_issue(&feature) { + generate_stub_issue(&out_file_path, &feature_name, feature.tracking_issue.unwrap()); + } else { + generate_stub_no_issue(&out_file_path, &feature_name); + } + } +} + +fn copy_recursive(path: &Path, to: &Path) { + for entry in t!(fs::read_dir(path)) { + let e = t!(entry); + let t = t!(e.metadata()); + let dest = &to.join(e.file_name()); + if t.is_file() { + t!(fs::copy(&e.path(), dest)); + } else if t.is_dir() { + t!(fs::create_dir_all(dest)); + copy_recursive(&e.path(), dest); + } + } +} + +fn main() { + let src_path_str = env::args_os().skip(1).next().expect("source path required"); + let dest_path_str = env::args_os().skip(2).next().expect("destination path required"); + let src_path = Path::new(&src_path_str); + let dest_path = Path::new(&dest_path_str).join("src"); + + let lang_features = collect_lang_features(src_path); + let mut bad = false; + let lib_features = collect_lib_features(src_path, &mut bad, &lang_features); + + let doc_src_path = src_path.join(PATH_STR); + + t!(fs::create_dir_all(&dest_path)); + + generate_unstable_book_files(&doc_src_path.join(LANG_FEATURES_DIR), + &dest_path.join(LANG_FEATURES_DIR), + &lang_features); + generate_unstable_book_files(&doc_src_path.join(LIB_FEATURES_DIR), + &dest_path.join(LIB_FEATURES_DIR), + &lib_features); + + copy_recursive(&doc_src_path, &dest_path); + + generate_summary(&dest_path, &lang_features, &lib_features); +} diff --git a/src/tools/unstable-book-gen/src/stub-issue.md b/src/tools/unstable-book-gen/src/stub-issue.md new file mode 100644 index 000000000000..8698fb7278f6 --- /dev/null +++ b/src/tools/unstable-book-gen/src/stub-issue.md @@ -0,0 +1,7 @@ +# `{name}` + +The tracking issue for this feature is: [#{issue}] + +[#{issue}]: https://github.com/rust-lang/rust/issues/{issue} + +------------------------ diff --git a/src/tools/unstable-book-gen/src/stub-no-issue.md b/src/tools/unstable-book-gen/src/stub-no-issue.md new file mode 100644 index 000000000000..3da140633d0f --- /dev/null +++ b/src/tools/unstable-book-gen/src/stub-no-issue.md @@ -0,0 +1,5 @@ +# `{name}` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ From e69f9088a3065f304446c603dc6f56c6fa98c61a Mon Sep 17 00:00:00 2001 From: est31 Date: Mon, 12 Jun 2017 15:18:40 +0200 Subject: [PATCH 186/233] Don't require that stubs exist for features in the unstable book Also, remove stubs. --- .../src/language-features/abi-sysv64.md | 7 ---- .../language-features/abi-x86-interrupt.md | 7 ---- .../associated-type-defaults.md | 10 ------ .../language-features/cfg-target-feature.md | 10 ------ .../cfg-target-has-atomic.md | 10 ------ .../cfg-target-thread-local.md | 10 ------ .../language-features/cfg-target-vendor.md | 10 ------ .../src/language-features/custom-attribute.md | 10 ------ .../src/language-features/custom-derive.md | 10 ------ .../src/language-features/decl-macro.md | 10 ------ .../default-type-parameter-fallback.md | 10 ------ .../language-features/drop-types-in-const.md | 10 ------ .../src/language-features/dropck-eyepatch.md | 10 ------ .../language-features/dropck-parametricity.md | 10 ------ .../exclusive-range-pattern.md | 10 ------ .../src/language-features/fundamental.md | 10 ------ .../language-features/generic-param-attrs.md | 10 ------ .../src/language-features/link-cfg.md | 10 ------ .../language-features/link-llvm-intrinsics.md | 10 ------ .../src/language-features/linkage.md | 10 ------ .../src/language-features/log-syntax.md | 10 ------ .../src/language-features/macro-reexport.md | 10 ------ .../src/language-features/main.md | 10 ------ .../src/language-features/naked-functions.md | 10 ------ .../src/language-features/needs-allocator.md | 10 ------ .../language-features/needs-panic-runtime.md | 10 ------ .../src/language-features/never-type.md | 10 ------ .../src/language-features/no-core.md | 10 ------ .../src/language-features/no-debug.md | 10 ------ .../language-features/optin-builtin-traits.md | 9 ----- .../overlapping-marker-traits.md | 7 ---- .../src/language-features/panic-runtime.md | 10 ------ .../language-features/placement-in-syntax.md | 10 ------ .../language-features/platform-intrinsics.md | 10 ------ .../src/language-features/quote.md | 10 ------ .../src/language-features/repr-align.md | 11 ------- .../src/language-features/repr-simd.md | 10 ------ .../src/language-features/rustc-attrs.md | 10 ------ .../src/language-features/simd-ffi.md | 10 ------ .../src/language-features/simd.md | 10 ------ .../src/language-features/specialization.md | 10 ------ .../src/language-features/start.md | 10 ------ .../src/language-features/static-nobundle.md | 10 ------ .../language-features/stmt-expr-attributes.md | 10 ------ .../struct-field-attributes.md | 10 ------ .../src/language-features/structural-match.md | 10 ------ .../src/language-features/thread-local.md | 10 ------ .../src/language-features/trace-macros.md | 10 ------ .../src/language-features/type-ascription.md | 10 ------ .../src/language-features/unboxed-closures.md | 10 ------ .../src/language-features/untagged-unions.md | 10 ------ .../language-features/use-extern-macros.md | 10 ------ .../src/library-features/alloc.md | 7 ---- .../src/library-features/as-c-str.md | 8 ----- .../src/library-features/box-heap.md | 7 ---- .../src/library-features/char-escape-debug.md | 7 ---- .../src/library-features/coerce-unsized.md | 7 ---- .../library-features/collection-placement.md | 7 ---- .../src/library-features/collections-range.md | 7 ---- .../src/library-features/command-envs.md | 7 ---- .../library-features/concat-idents-macro.md | 7 ---- .../src/library-features/core-char-ext.md | 7 ---- .../src/library-features/core-float.md | 7 ---- .../src/library-features/core-slice-ext.md | 7 ---- .../src/library-features/core-str-ext.md | 7 ---- .../src/library-features/decode-utf8.md | 7 ---- .../library-features/discriminant-value.md | 7 ---- .../src/library-features/error-type-id.md | 7 ---- .../library-features/exact-size-is-empty.md | 7 ---- .../src/library-features/fixed-size-array.md | 7 ---- .../src/library-features/float-bits-conv.md | 7 ---- .../src/library-features/fmt-flags-align.md | 7 ---- .../src/library-features/fn-traits.md | 7 ---- .../src/library-features/fnbox.md | 7 ---- .../from-utf8-error-as-bytes.md | 7 ---- .../src/library-features/fused.md | 7 ---- .../src/library-features/get-type-id.md | 7 ---- .../src/library-features/heap-api.md | 7 ---- .../src/library-features/i128.md | 7 ---- .../src/library-features/inclusive-range.md | 7 ---- .../src/library-features/integer-atomics.md | 7 ---- .../src/library-features/into-boxed-c-str.md | 7 ---- .../src/library-features/into-boxed-os-str.md | 7 ---- .../src/library-features/into-boxed-path.md | 7 ---- .../unstable-book/src/library-features/io.md | 7 ---- .../unstable-book/src/library-features/ip.md | 7 ---- .../src/library-features/iter-rfind.md | 7 ---- .../src/library-features/iterator-step-by.md | 7 ---- .../library-features/linked-list-extras.md | 7 ---- .../src/library-features/lookup-host.md | 7 ---- .../src/library-features/needs-drop.md | 7 ---- .../src/library-features/never-type-impls.md | 7 ---- .../src/library-features/nonzero.md | 7 ---- .../src/library-features/offset-to.md | 7 ---- .../src/library-features/once-poison.md | 7 ---- .../unstable-book/src/library-features/oom.md | 7 ---- .../src/library-features/option-entry.md | 7 ---- .../osstring-shrink-to-fit.md | 7 ---- .../src/library-features/panic-abort.md | 7 ---- .../src/library-features/panic-unwind.md | 7 ---- .../src/library-features/pattern.md | 7 ---- .../src/library-features/placement-in.md | 7 ---- .../placement-new-protocol.md | 7 ---- .../library-features/proc-macro-internals.md | 7 ---- .../src/library-features/range-contains.md | 7 ---- .../unstable-book/src/library-features/raw.md | 7 ---- .../src/library-features/reverse-cmp-key.md | 7 ---- .../src/library-features/rustc-private.md | 7 ---- .../src/library-features/shared.md | 7 ---- .../src/library-features/sip-hash-13.md | 7 ---- .../src/library-features/slice-concat-ext.md | 7 ---- .../src/library-features/slice-get-slice.md | 7 ---- .../src/library-features/slice-rotate.md | 7 ---- .../src/library-features/step-by.md | 7 ---- .../src/library-features/step-trait.md | 7 ---- .../src/library-features/str-box-extras.md | 9 ----- .../library-features/str-checked-slicing.md | 7 ---- .../src/library-features/str-escape.md | 7 ---- .../src/library-features/str-mut-extras.md | 8 ----- .../src/library-features/thread-id.md | 7 ---- .../library-features/thread-local-state.md | 7 ---- .../library-features/toowned-clone-into.md | 7 ---- .../src/library-features/trusted-len.md | 7 ---- .../src/library-features/try-from.md | 7 ---- .../src/library-features/unicode.md | 7 ---- .../src/library-features/unique.md | 7 ---- .../src/library-features/unsize.md | 7 ---- .../library-features/utf8-error-error-len.md | 7 ---- .../src/library-features/vec-remove-item.md | 7 ---- .../library-features/vec-resize-default.md | 7 ---- src/tools/tidy/src/unstable_book.rs | 33 +++++++++---------- 131 files changed, 16 insertions(+), 1078 deletions(-) delete mode 100644 src/doc/unstable-book/src/language-features/abi-sysv64.md delete mode 100644 src/doc/unstable-book/src/language-features/abi-x86-interrupt.md delete mode 100644 src/doc/unstable-book/src/language-features/associated-type-defaults.md delete mode 100644 src/doc/unstable-book/src/language-features/cfg-target-feature.md delete mode 100644 src/doc/unstable-book/src/language-features/cfg-target-has-atomic.md delete mode 100644 src/doc/unstable-book/src/language-features/cfg-target-thread-local.md delete mode 100644 src/doc/unstable-book/src/language-features/cfg-target-vendor.md delete mode 100644 src/doc/unstable-book/src/language-features/custom-attribute.md delete mode 100644 src/doc/unstable-book/src/language-features/custom-derive.md delete mode 100644 src/doc/unstable-book/src/language-features/decl-macro.md delete mode 100644 src/doc/unstable-book/src/language-features/default-type-parameter-fallback.md delete mode 100644 src/doc/unstable-book/src/language-features/drop-types-in-const.md delete mode 100644 src/doc/unstable-book/src/language-features/dropck-eyepatch.md delete mode 100644 src/doc/unstable-book/src/language-features/dropck-parametricity.md delete mode 100644 src/doc/unstable-book/src/language-features/exclusive-range-pattern.md delete mode 100644 src/doc/unstable-book/src/language-features/fundamental.md delete mode 100644 src/doc/unstable-book/src/language-features/generic-param-attrs.md delete mode 100644 src/doc/unstable-book/src/language-features/link-cfg.md delete mode 100644 src/doc/unstable-book/src/language-features/link-llvm-intrinsics.md delete mode 100644 src/doc/unstable-book/src/language-features/linkage.md delete mode 100644 src/doc/unstable-book/src/language-features/log-syntax.md delete mode 100644 src/doc/unstable-book/src/language-features/macro-reexport.md delete mode 100644 src/doc/unstable-book/src/language-features/main.md delete mode 100644 src/doc/unstable-book/src/language-features/naked-functions.md delete mode 100644 src/doc/unstable-book/src/language-features/needs-allocator.md delete mode 100644 src/doc/unstable-book/src/language-features/needs-panic-runtime.md delete mode 100644 src/doc/unstable-book/src/language-features/never-type.md delete mode 100644 src/doc/unstable-book/src/language-features/no-core.md delete mode 100644 src/doc/unstable-book/src/language-features/no-debug.md delete mode 100644 src/doc/unstable-book/src/language-features/optin-builtin-traits.md delete mode 100644 src/doc/unstable-book/src/language-features/overlapping-marker-traits.md delete mode 100644 src/doc/unstable-book/src/language-features/panic-runtime.md delete mode 100644 src/doc/unstable-book/src/language-features/placement-in-syntax.md delete mode 100644 src/doc/unstable-book/src/language-features/platform-intrinsics.md delete mode 100644 src/doc/unstable-book/src/language-features/quote.md delete mode 100644 src/doc/unstable-book/src/language-features/repr-align.md delete mode 100644 src/doc/unstable-book/src/language-features/repr-simd.md delete mode 100644 src/doc/unstable-book/src/language-features/rustc-attrs.md delete mode 100644 src/doc/unstable-book/src/language-features/simd-ffi.md delete mode 100644 src/doc/unstable-book/src/language-features/simd.md delete mode 100644 src/doc/unstable-book/src/language-features/specialization.md delete mode 100644 src/doc/unstable-book/src/language-features/start.md delete mode 100644 src/doc/unstable-book/src/language-features/static-nobundle.md delete mode 100644 src/doc/unstable-book/src/language-features/stmt-expr-attributes.md delete mode 100644 src/doc/unstable-book/src/language-features/struct-field-attributes.md delete mode 100644 src/doc/unstable-book/src/language-features/structural-match.md delete mode 100644 src/doc/unstable-book/src/language-features/thread-local.md delete mode 100644 src/doc/unstable-book/src/language-features/trace-macros.md delete mode 100644 src/doc/unstable-book/src/language-features/type-ascription.md delete mode 100644 src/doc/unstable-book/src/language-features/unboxed-closures.md delete mode 100644 src/doc/unstable-book/src/language-features/untagged-unions.md delete mode 100644 src/doc/unstable-book/src/language-features/use-extern-macros.md delete mode 100644 src/doc/unstable-book/src/library-features/alloc.md delete mode 100644 src/doc/unstable-book/src/library-features/as-c-str.md delete mode 100644 src/doc/unstable-book/src/library-features/box-heap.md delete mode 100644 src/doc/unstable-book/src/library-features/char-escape-debug.md delete mode 100644 src/doc/unstable-book/src/library-features/coerce-unsized.md delete mode 100644 src/doc/unstable-book/src/library-features/collection-placement.md delete mode 100644 src/doc/unstable-book/src/library-features/collections-range.md delete mode 100644 src/doc/unstable-book/src/library-features/command-envs.md delete mode 100644 src/doc/unstable-book/src/library-features/concat-idents-macro.md delete mode 100644 src/doc/unstable-book/src/library-features/core-char-ext.md delete mode 100644 src/doc/unstable-book/src/library-features/core-float.md delete mode 100644 src/doc/unstable-book/src/library-features/core-slice-ext.md delete mode 100644 src/doc/unstable-book/src/library-features/core-str-ext.md delete mode 100644 src/doc/unstable-book/src/library-features/decode-utf8.md delete mode 100644 src/doc/unstable-book/src/library-features/discriminant-value.md delete mode 100644 src/doc/unstable-book/src/library-features/error-type-id.md delete mode 100644 src/doc/unstable-book/src/library-features/exact-size-is-empty.md delete mode 100644 src/doc/unstable-book/src/library-features/fixed-size-array.md delete mode 100644 src/doc/unstable-book/src/library-features/float-bits-conv.md delete mode 100644 src/doc/unstable-book/src/library-features/fmt-flags-align.md delete mode 100644 src/doc/unstable-book/src/library-features/fn-traits.md delete mode 100644 src/doc/unstable-book/src/library-features/fnbox.md delete mode 100644 src/doc/unstable-book/src/library-features/from-utf8-error-as-bytes.md delete mode 100644 src/doc/unstable-book/src/library-features/fused.md delete mode 100644 src/doc/unstable-book/src/library-features/get-type-id.md delete mode 100644 src/doc/unstable-book/src/library-features/heap-api.md delete mode 100644 src/doc/unstable-book/src/library-features/i128.md delete mode 100644 src/doc/unstable-book/src/library-features/inclusive-range.md delete mode 100644 src/doc/unstable-book/src/library-features/integer-atomics.md delete mode 100644 src/doc/unstable-book/src/library-features/into-boxed-c-str.md delete mode 100644 src/doc/unstable-book/src/library-features/into-boxed-os-str.md delete mode 100644 src/doc/unstable-book/src/library-features/into-boxed-path.md delete mode 100644 src/doc/unstable-book/src/library-features/io.md delete mode 100644 src/doc/unstable-book/src/library-features/ip.md delete mode 100644 src/doc/unstable-book/src/library-features/iter-rfind.md delete mode 100644 src/doc/unstable-book/src/library-features/iterator-step-by.md delete mode 100644 src/doc/unstable-book/src/library-features/linked-list-extras.md delete mode 100644 src/doc/unstable-book/src/library-features/lookup-host.md delete mode 100644 src/doc/unstable-book/src/library-features/needs-drop.md delete mode 100644 src/doc/unstable-book/src/library-features/never-type-impls.md delete mode 100644 src/doc/unstable-book/src/library-features/nonzero.md delete mode 100644 src/doc/unstable-book/src/library-features/offset-to.md delete mode 100644 src/doc/unstable-book/src/library-features/once-poison.md delete mode 100644 src/doc/unstable-book/src/library-features/oom.md delete mode 100644 src/doc/unstable-book/src/library-features/option-entry.md delete mode 100644 src/doc/unstable-book/src/library-features/osstring-shrink-to-fit.md delete mode 100644 src/doc/unstable-book/src/library-features/panic-abort.md delete mode 100644 src/doc/unstable-book/src/library-features/panic-unwind.md delete mode 100644 src/doc/unstable-book/src/library-features/pattern.md delete mode 100644 src/doc/unstable-book/src/library-features/placement-in.md delete mode 100644 src/doc/unstable-book/src/library-features/placement-new-protocol.md delete mode 100644 src/doc/unstable-book/src/library-features/proc-macro-internals.md delete mode 100644 src/doc/unstable-book/src/library-features/range-contains.md delete mode 100644 src/doc/unstable-book/src/library-features/raw.md delete mode 100644 src/doc/unstable-book/src/library-features/reverse-cmp-key.md delete mode 100644 src/doc/unstable-book/src/library-features/rustc-private.md delete mode 100644 src/doc/unstable-book/src/library-features/shared.md delete mode 100644 src/doc/unstable-book/src/library-features/sip-hash-13.md delete mode 100644 src/doc/unstable-book/src/library-features/slice-concat-ext.md delete mode 100644 src/doc/unstable-book/src/library-features/slice-get-slice.md delete mode 100644 src/doc/unstable-book/src/library-features/slice-rotate.md delete mode 100644 src/doc/unstable-book/src/library-features/step-by.md delete mode 100644 src/doc/unstable-book/src/library-features/step-trait.md delete mode 100644 src/doc/unstable-book/src/library-features/str-box-extras.md delete mode 100644 src/doc/unstable-book/src/library-features/str-checked-slicing.md delete mode 100644 src/doc/unstable-book/src/library-features/str-escape.md delete mode 100644 src/doc/unstable-book/src/library-features/str-mut-extras.md delete mode 100644 src/doc/unstable-book/src/library-features/thread-id.md delete mode 100644 src/doc/unstable-book/src/library-features/thread-local-state.md delete mode 100644 src/doc/unstable-book/src/library-features/toowned-clone-into.md delete mode 100644 src/doc/unstable-book/src/library-features/trusted-len.md delete mode 100644 src/doc/unstable-book/src/library-features/try-from.md delete mode 100644 src/doc/unstable-book/src/library-features/unicode.md delete mode 100644 src/doc/unstable-book/src/library-features/unique.md delete mode 100644 src/doc/unstable-book/src/library-features/unsize.md delete mode 100644 src/doc/unstable-book/src/library-features/utf8-error-error-len.md delete mode 100644 src/doc/unstable-book/src/library-features/vec-remove-item.md delete mode 100644 src/doc/unstable-book/src/library-features/vec-resize-default.md diff --git a/src/doc/unstable-book/src/language-features/abi-sysv64.md b/src/doc/unstable-book/src/language-features/abi-sysv64.md deleted file mode 100644 index 27f61d56342c..000000000000 --- a/src/doc/unstable-book/src/language-features/abi-sysv64.md +++ /dev/null @@ -1,7 +0,0 @@ -# `abi_sysv64` - -The tracking issue for this feature is: [#36167] - -[#36167]: https://github.com/rust-lang/rust/issues/36167 - ------------------------- diff --git a/src/doc/unstable-book/src/language-features/abi-x86-interrupt.md b/src/doc/unstable-book/src/language-features/abi-x86-interrupt.md deleted file mode 100644 index c89d2ee2106c..000000000000 --- a/src/doc/unstable-book/src/language-features/abi-x86-interrupt.md +++ /dev/null @@ -1,7 +0,0 @@ -# `abi_x86_interrupt` - -The tracking issue for this feature is: [#40180] - -[#40180]: https://github.com/rust-lang/rust/issues/40180 - ------------------------- diff --git a/src/doc/unstable-book/src/language-features/associated-type-defaults.md b/src/doc/unstable-book/src/language-features/associated-type-defaults.md deleted file mode 100644 index 56cc8a5b3060..000000000000 --- a/src/doc/unstable-book/src/language-features/associated-type-defaults.md +++ /dev/null @@ -1,10 +0,0 @@ -# `associated_type_defaults` - -The tracking issue for this feature is: [#29661] - -[#29661]: https://github.com/rust-lang/rust/issues/29661 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/cfg-target-feature.md b/src/doc/unstable-book/src/language-features/cfg-target-feature.md deleted file mode 100644 index ddd88bdc2cb1..000000000000 --- a/src/doc/unstable-book/src/language-features/cfg-target-feature.md +++ /dev/null @@ -1,10 +0,0 @@ -# `cfg_target_feature` - -The tracking issue for this feature is: [#29717] - -[#29717]: https://github.com/rust-lang/rust/issues/29717 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/cfg-target-has-atomic.md b/src/doc/unstable-book/src/language-features/cfg-target-has-atomic.md deleted file mode 100644 index 7496e42e1cd8..000000000000 --- a/src/doc/unstable-book/src/language-features/cfg-target-has-atomic.md +++ /dev/null @@ -1,10 +0,0 @@ -# `cfg_target_has_atomic` - -The tracking issue for this feature is: [#32976] - -[#32976]: https://github.com/rust-lang/rust/issues/32976 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/cfg-target-thread-local.md b/src/doc/unstable-book/src/language-features/cfg-target-thread-local.md deleted file mode 100644 index a5adb38db3df..000000000000 --- a/src/doc/unstable-book/src/language-features/cfg-target-thread-local.md +++ /dev/null @@ -1,10 +0,0 @@ -# `cfg_target_thread_local` - -The tracking issue for this feature is: [#29594] - -[#29594]: https://github.com/rust-lang/rust/issues/29594 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/cfg-target-vendor.md b/src/doc/unstable-book/src/language-features/cfg-target-vendor.md deleted file mode 100644 index ddd88bdc2cb1..000000000000 --- a/src/doc/unstable-book/src/language-features/cfg-target-vendor.md +++ /dev/null @@ -1,10 +0,0 @@ -# `cfg_target_feature` - -The tracking issue for this feature is: [#29717] - -[#29717]: https://github.com/rust-lang/rust/issues/29717 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/custom-attribute.md b/src/doc/unstable-book/src/language-features/custom-attribute.md deleted file mode 100644 index 838f09670d2c..000000000000 --- a/src/doc/unstable-book/src/language-features/custom-attribute.md +++ /dev/null @@ -1,10 +0,0 @@ -# `custom_attribute` - -The tracking issue for this feature is: [#29642] - -[#29642]: https://github.com/rust-lang/rust/issues/29642 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/custom-derive.md b/src/doc/unstable-book/src/language-features/custom-derive.md deleted file mode 100644 index d5fdd2b708bb..000000000000 --- a/src/doc/unstable-book/src/language-features/custom-derive.md +++ /dev/null @@ -1,10 +0,0 @@ -# `custom_derive` - -The tracking issue for this feature is: [#29644] - -[#29644]: https://github.com/rust-lang/rust/issues/29644 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/decl-macro.md b/src/doc/unstable-book/src/language-features/decl-macro.md deleted file mode 100644 index 4700b252e2d1..000000000000 --- a/src/doc/unstable-book/src/language-features/decl-macro.md +++ /dev/null @@ -1,10 +0,0 @@ -# `decl_macro` - -The tracking issue for this feature is: [#39412] - -[#39412]: https://github.com/rust-lang/rust/issues/39412 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/default-type-parameter-fallback.md b/src/doc/unstable-book/src/language-features/default-type-parameter-fallback.md deleted file mode 100644 index fd16dbf89853..000000000000 --- a/src/doc/unstable-book/src/language-features/default-type-parameter-fallback.md +++ /dev/null @@ -1,10 +0,0 @@ -# `default_type_parameter_fallback` - -The tracking issue for this feature is: [#27336] - -[#27336]: https://github.com/rust-lang/rust/issues/27336 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/drop-types-in-const.md b/src/doc/unstable-book/src/language-features/drop-types-in-const.md deleted file mode 100644 index b3367d0df445..000000000000 --- a/src/doc/unstable-book/src/language-features/drop-types-in-const.md +++ /dev/null @@ -1,10 +0,0 @@ -# `drop_types_in_const` - -The tracking issue for this feature is: [#33156] - -[#33156]: https://github.com/rust-lang/rust/issues/33156 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/dropck-eyepatch.md b/src/doc/unstable-book/src/language-features/dropck-eyepatch.md deleted file mode 100644 index 2f189e9b6454..000000000000 --- a/src/doc/unstable-book/src/language-features/dropck-eyepatch.md +++ /dev/null @@ -1,10 +0,0 @@ -# `dropck_eyepatch` - -The tracking issue for this feature is: [#34761] - -[#34761]: https://github.com/rust-lang/rust/issues/34761 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/dropck-parametricity.md b/src/doc/unstable-book/src/language-features/dropck-parametricity.md deleted file mode 100644 index c5ae721954b8..000000000000 --- a/src/doc/unstable-book/src/language-features/dropck-parametricity.md +++ /dev/null @@ -1,10 +0,0 @@ -# `dropck_parametricity` - -The tracking issue for this feature is: [#28498] - -[#28498]: https://github.com/rust-lang/rust/issues/28498 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/exclusive-range-pattern.md b/src/doc/unstable-book/src/language-features/exclusive-range-pattern.md deleted file mode 100644 index b669ce83132d..000000000000 --- a/src/doc/unstable-book/src/language-features/exclusive-range-pattern.md +++ /dev/null @@ -1,10 +0,0 @@ -# `exclusive_range_pattern` - -The tracking issue for this feature is: [#37854] - -[#37854]: https://github.com/rust-lang/rust/issues/37854 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/fundamental.md b/src/doc/unstable-book/src/language-features/fundamental.md deleted file mode 100644 index a068dadf95d1..000000000000 --- a/src/doc/unstable-book/src/language-features/fundamental.md +++ /dev/null @@ -1,10 +0,0 @@ -# `fundamental` - -The tracking issue for this feature is: [#29635] - -[#29635]: https://github.com/rust-lang/rust/issues/29635 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/generic-param-attrs.md b/src/doc/unstable-book/src/language-features/generic-param-attrs.md deleted file mode 100644 index ba49c850e4d6..000000000000 --- a/src/doc/unstable-book/src/language-features/generic-param-attrs.md +++ /dev/null @@ -1,10 +0,0 @@ -# `generic_param_attrs` - -The tracking issue for this feature is: [#34761] - -[#34761]: https://github.com/rust-lang/rust/issues/34761 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/link-cfg.md b/src/doc/unstable-book/src/language-features/link-cfg.md deleted file mode 100644 index 7393d0628e4f..000000000000 --- a/src/doc/unstable-book/src/language-features/link-cfg.md +++ /dev/null @@ -1,10 +0,0 @@ -# `link_cfg` - -The tracking issue for this feature is: [#37406] - -[#37406]: https://github.com/rust-lang/rust/issues/37406 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/link-llvm-intrinsics.md b/src/doc/unstable-book/src/language-features/link-llvm-intrinsics.md deleted file mode 100644 index ba639cb57fc6..000000000000 --- a/src/doc/unstable-book/src/language-features/link-llvm-intrinsics.md +++ /dev/null @@ -1,10 +0,0 @@ -# `link_llvm_intrinsics` - -The tracking issue for this feature is: [#29602] - -[#29602]: https://github.com/rust-lang/rust/issues/29602 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/linkage.md b/src/doc/unstable-book/src/language-features/linkage.md deleted file mode 100644 index 5773d28a00ec..000000000000 --- a/src/doc/unstable-book/src/language-features/linkage.md +++ /dev/null @@ -1,10 +0,0 @@ -# `linkage` - -The tracking issue for this feature is: [#29603] - -[#29603]: https://github.com/rust-lang/rust/issues/29603 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/log-syntax.md b/src/doc/unstable-book/src/language-features/log-syntax.md deleted file mode 100644 index b13f5ccfd917..000000000000 --- a/src/doc/unstable-book/src/language-features/log-syntax.md +++ /dev/null @@ -1,10 +0,0 @@ -# `log_syntax` - -The tracking issue for this feature is: [#29598] - -[#29598]: https://github.com/rust-lang/rust/issues/29598 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/macro-reexport.md b/src/doc/unstable-book/src/language-features/macro-reexport.md deleted file mode 100644 index 32ffa3b4c31e..000000000000 --- a/src/doc/unstable-book/src/language-features/macro-reexport.md +++ /dev/null @@ -1,10 +0,0 @@ -# `macro_reexport` - -The tracking issue for this feature is: [#29638] - -[#29638]: https://github.com/rust-lang/rust/issues/29638 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/main.md b/src/doc/unstable-book/src/language-features/main.md deleted file mode 100644 index 579aabfff88b..000000000000 --- a/src/doc/unstable-book/src/language-features/main.md +++ /dev/null @@ -1,10 +0,0 @@ -# `main` - -The tracking issue for this feature is: [#29634] - -[#29634]: https://github.com/rust-lang/rust/issues/29634 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/naked-functions.md b/src/doc/unstable-book/src/language-features/naked-functions.md deleted file mode 100644 index e56ce4770aab..000000000000 --- a/src/doc/unstable-book/src/language-features/naked-functions.md +++ /dev/null @@ -1,10 +0,0 @@ -# `naked_functions` - -The tracking issue for this feature is: [#32408] - -[#32408]: https://github.com/rust-lang/rust/issues/32408 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/needs-allocator.md b/src/doc/unstable-book/src/language-features/needs-allocator.md deleted file mode 100644 index 22aa10b2183c..000000000000 --- a/src/doc/unstable-book/src/language-features/needs-allocator.md +++ /dev/null @@ -1,10 +0,0 @@ -# `needs_allocator` - -The tracking issue for this feature is: [#27389] - -[#27389]: https://github.com/rust-lang/rust/issues/27389 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/needs-panic-runtime.md b/src/doc/unstable-book/src/language-features/needs-panic-runtime.md deleted file mode 100644 index 627c946c1bb2..000000000000 --- a/src/doc/unstable-book/src/language-features/needs-panic-runtime.md +++ /dev/null @@ -1,10 +0,0 @@ -# `needs_panic_runtime` - -The tracking issue for this feature is: [#32837] - -[#32837]: https://github.com/rust-lang/rust/issues/32837 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/never-type.md b/src/doc/unstable-book/src/language-features/never-type.md deleted file mode 100644 index 3b3729a4b21d..000000000000 --- a/src/doc/unstable-book/src/language-features/never-type.md +++ /dev/null @@ -1,10 +0,0 @@ -# `never_type` - -The tracking issue for this feature is: [#35121] - -[#35121]: https://github.com/rust-lang/rust/issues/35121 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/no-core.md b/src/doc/unstable-book/src/language-features/no-core.md deleted file mode 100644 index 6238753447c9..000000000000 --- a/src/doc/unstable-book/src/language-features/no-core.md +++ /dev/null @@ -1,10 +0,0 @@ -# `no_core` - -The tracking issue for this feature is: [#29639] - -[#29639]: https://github.com/rust-lang/rust/issues/29639 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/no-debug.md b/src/doc/unstable-book/src/language-features/no-debug.md deleted file mode 100644 index 7536ed9d4e10..000000000000 --- a/src/doc/unstable-book/src/language-features/no-debug.md +++ /dev/null @@ -1,10 +0,0 @@ -# `no_debug` - -The tracking issue for this feature is: [#29721] - -[#29721]: https://github.com/rust-lang/rust/issues/29721 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/optin-builtin-traits.md b/src/doc/unstable-book/src/language-features/optin-builtin-traits.md deleted file mode 100644 index 0b2d60accd59..000000000000 --- a/src/doc/unstable-book/src/language-features/optin-builtin-traits.md +++ /dev/null @@ -1,9 +0,0 @@ -# `optin_builtin_traits` - -The tracking issue for this feature is: [#13231] - -[#13231]: https://github.com/rust-lang/rust/issues/13231 - ------------------------- - - diff --git a/src/doc/unstable-book/src/language-features/overlapping-marker-traits.md b/src/doc/unstable-book/src/language-features/overlapping-marker-traits.md deleted file mode 100644 index a4920839c6ca..000000000000 --- a/src/doc/unstable-book/src/language-features/overlapping-marker-traits.md +++ /dev/null @@ -1,7 +0,0 @@ -# `overlapping_marker_traits` - -The tracking issue for this feature is: [#29864] - -[#29864]: https://github.com/rust-lang/rust/issues/29864 - ------------------------- diff --git a/src/doc/unstable-book/src/language-features/panic-runtime.md b/src/doc/unstable-book/src/language-features/panic-runtime.md deleted file mode 100644 index 65b067e82961..000000000000 --- a/src/doc/unstable-book/src/language-features/panic-runtime.md +++ /dev/null @@ -1,10 +0,0 @@ -# `panic_runtime` - -The tracking issue for this feature is: [#32837] - -[#32837]: https://github.com/rust-lang/rust/issues/32837 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/placement-in-syntax.md b/src/doc/unstable-book/src/language-features/placement-in-syntax.md deleted file mode 100644 index da12559a01b8..000000000000 --- a/src/doc/unstable-book/src/language-features/placement-in-syntax.md +++ /dev/null @@ -1,10 +0,0 @@ -# `placement_in_syntax` - -The tracking issue for this feature is: [#27779] - -[#27779]: https://github.com/rust-lang/rust/issues/27779 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/platform-intrinsics.md b/src/doc/unstable-book/src/language-features/platform-intrinsics.md deleted file mode 100644 index 377ac8f7342e..000000000000 --- a/src/doc/unstable-book/src/language-features/platform-intrinsics.md +++ /dev/null @@ -1,10 +0,0 @@ -# `platform_intrinsics` - -The tracking issue for this feature is: [#27731] - -[#27731]: https://github.com/rust-lang/rust/issues/27731 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/quote.md b/src/doc/unstable-book/src/language-features/quote.md deleted file mode 100644 index b4e078d920c4..000000000000 --- a/src/doc/unstable-book/src/language-features/quote.md +++ /dev/null @@ -1,10 +0,0 @@ -# `quote` - -The tracking issue for this feature is: [#29601] - -[#29601]: https://github.com/rust-lang/rust/issues/29601 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/repr-align.md b/src/doc/unstable-book/src/language-features/repr-align.md deleted file mode 100644 index deea04f4c51c..000000000000 --- a/src/doc/unstable-book/src/language-features/repr-align.md +++ /dev/null @@ -1,11 +0,0 @@ -# `repr_align` - -The tracking issue for this feature is: [#33626] - -[#33626]: https://github.com/rust-lang/rust/issues/33626 - ------------------------- - - - - diff --git a/src/doc/unstable-book/src/language-features/repr-simd.md b/src/doc/unstable-book/src/language-features/repr-simd.md deleted file mode 100644 index c6f051e4fffc..000000000000 --- a/src/doc/unstable-book/src/language-features/repr-simd.md +++ /dev/null @@ -1,10 +0,0 @@ -# `repr_simd` - -The tracking issue for this feature is: [#27731] - -[#27731]: https://github.com/rust-lang/rust/issues/27731 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/rustc-attrs.md b/src/doc/unstable-book/src/language-features/rustc-attrs.md deleted file mode 100644 index d1f18cead068..000000000000 --- a/src/doc/unstable-book/src/language-features/rustc-attrs.md +++ /dev/null @@ -1,10 +0,0 @@ -# `rustc_attrs` - -The tracking issue for this feature is: [#29642] - -[#29642]: https://github.com/rust-lang/rust/issues/29642 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/simd-ffi.md b/src/doc/unstable-book/src/language-features/simd-ffi.md deleted file mode 100644 index d85779c3d3dc..000000000000 --- a/src/doc/unstable-book/src/language-features/simd-ffi.md +++ /dev/null @@ -1,10 +0,0 @@ -# `simd_ffi` - -The tracking issue for this feature is: [#27731] - -[#27731]: https://github.com/rust-lang/rust/issues/27731 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/simd.md b/src/doc/unstable-book/src/language-features/simd.md deleted file mode 100644 index 13c9722c5243..000000000000 --- a/src/doc/unstable-book/src/language-features/simd.md +++ /dev/null @@ -1,10 +0,0 @@ -# `simd` - -The tracking issue for this feature is: [#27731] - -[#27731]: https://github.com/rust-lang/rust/issues/27731 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/specialization.md b/src/doc/unstable-book/src/language-features/specialization.md deleted file mode 100644 index efc380df6e11..000000000000 --- a/src/doc/unstable-book/src/language-features/specialization.md +++ /dev/null @@ -1,10 +0,0 @@ -# `specialization` - -The tracking issue for this feature is: [#31844] - -[#31844]: https://github.com/rust-lang/rust/issues/31844 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/start.md b/src/doc/unstable-book/src/language-features/start.md deleted file mode 100644 index 1ea6d59c78d5..000000000000 --- a/src/doc/unstable-book/src/language-features/start.md +++ /dev/null @@ -1,10 +0,0 @@ -# `start` - -The tracking issue for this feature is: [#29633] - -[#29633]: https://github.com/rust-lang/rust/issues/29633 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/static-nobundle.md b/src/doc/unstable-book/src/language-features/static-nobundle.md deleted file mode 100644 index 97b9d71d433a..000000000000 --- a/src/doc/unstable-book/src/language-features/static-nobundle.md +++ /dev/null @@ -1,10 +0,0 @@ -# `static_nobundle` - -The tracking issue for this feature is: [#37403] - -[#37403]: https://github.com/rust-lang/rust/issues/37403 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/stmt-expr-attributes.md b/src/doc/unstable-book/src/language-features/stmt-expr-attributes.md deleted file mode 100644 index 71092fcf2904..000000000000 --- a/src/doc/unstable-book/src/language-features/stmt-expr-attributes.md +++ /dev/null @@ -1,10 +0,0 @@ -# `stmt_expr_attributes` - -The tracking issue for this feature is: [#15701] - -[#15701]: https://github.com/rust-lang/rust/issues/15701 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/struct-field-attributes.md b/src/doc/unstable-book/src/language-features/struct-field-attributes.md deleted file mode 100644 index 1a94562968d1..000000000000 --- a/src/doc/unstable-book/src/language-features/struct-field-attributes.md +++ /dev/null @@ -1,10 +0,0 @@ -# `struct_field_attributes` - -The tracking issue for this feature is: [#38814] - -[#38814]: https://github.com/rust-lang/rust/issues/38814 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/structural-match.md b/src/doc/unstable-book/src/language-features/structural-match.md deleted file mode 100644 index b3ca26e6474d..000000000000 --- a/src/doc/unstable-book/src/language-features/structural-match.md +++ /dev/null @@ -1,10 +0,0 @@ -# `structural_match` - -The tracking issue for this feature is: [#31434] - -[#31434]: https://github.com/rust-lang/rust/issues/31434 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/thread-local.md b/src/doc/unstable-book/src/language-features/thread-local.md deleted file mode 100644 index 83de2f9cd4b5..000000000000 --- a/src/doc/unstable-book/src/language-features/thread-local.md +++ /dev/null @@ -1,10 +0,0 @@ -# `thread_local` - -The tracking issue for this feature is: [#29594] - -[#29594]: https://github.com/rust-lang/rust/issues/29594 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/trace-macros.md b/src/doc/unstable-book/src/language-features/trace-macros.md deleted file mode 100644 index 856f1b0a7bbb..000000000000 --- a/src/doc/unstable-book/src/language-features/trace-macros.md +++ /dev/null @@ -1,10 +0,0 @@ -# `trace_macros` - -The tracking issue for this feature is: [#29598] - -[#29598]: https://github.com/rust-lang/rust/issues/29598 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/type-ascription.md b/src/doc/unstable-book/src/language-features/type-ascription.md deleted file mode 100644 index 3ebd0d87ccff..000000000000 --- a/src/doc/unstable-book/src/language-features/type-ascription.md +++ /dev/null @@ -1,10 +0,0 @@ -# `type_ascription` - -The tracking issue for this feature is: [#23416] - -[#23416]: https://github.com/rust-lang/rust/issues/23416 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/unboxed-closures.md b/src/doc/unstable-book/src/language-features/unboxed-closures.md deleted file mode 100644 index 2cbb436ce0bb..000000000000 --- a/src/doc/unstable-book/src/language-features/unboxed-closures.md +++ /dev/null @@ -1,10 +0,0 @@ -# `unboxed_closures` - -The tracking issue for this feature is: [#29625] - -[#29625]: https://github.com/rust-lang/rust/issues/29625 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/untagged-unions.md b/src/doc/unstable-book/src/language-features/untagged-unions.md deleted file mode 100644 index 6fe4f088ac23..000000000000 --- a/src/doc/unstable-book/src/language-features/untagged-unions.md +++ /dev/null @@ -1,10 +0,0 @@ -# `untagged_unions` - -The tracking issue for this feature is: [#32836] - -[#32836]: https://github.com/rust-lang/rust/issues/32836 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/language-features/use-extern-macros.md b/src/doc/unstable-book/src/language-features/use-extern-macros.md deleted file mode 100644 index bc6149115028..000000000000 --- a/src/doc/unstable-book/src/language-features/use-extern-macros.md +++ /dev/null @@ -1,10 +0,0 @@ -# `use_extern_macros` - -The tracking issue for this feature is: [#35896] - -[#35896]: https://github.com/rust-lang/rust/issues/35896 - ------------------------- - - - diff --git a/src/doc/unstable-book/src/library-features/alloc.md b/src/doc/unstable-book/src/library-features/alloc.md deleted file mode 100644 index 47eeb0874fba..000000000000 --- a/src/doc/unstable-book/src/library-features/alloc.md +++ /dev/null @@ -1,7 +0,0 @@ -# `alloc` - -The tracking issue for this feature is: [#27783] - -[#27783]: https://github.com/rust-lang/rust/issues/27783 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/as-c-str.md b/src/doc/unstable-book/src/library-features/as-c-str.md deleted file mode 100644 index ed32eedb3481..000000000000 --- a/src/doc/unstable-book/src/library-features/as-c-str.md +++ /dev/null @@ -1,8 +0,0 @@ -# `as_c_str` - -The tracking issue for this feature is: [#40380] - -[#40380]: https://github.com/rust-lang/rust/issues/40380 - ------------------------- - diff --git a/src/doc/unstable-book/src/library-features/box-heap.md b/src/doc/unstable-book/src/library-features/box-heap.md deleted file mode 100644 index 0f3f01ba0e16..000000000000 --- a/src/doc/unstable-book/src/library-features/box-heap.md +++ /dev/null @@ -1,7 +0,0 @@ -# `box_heap` - -The tracking issue for this feature is: [#27779] - -[#27779]: https://github.com/rust-lang/rust/issues/27779 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/char-escape-debug.md b/src/doc/unstable-book/src/library-features/char-escape-debug.md deleted file mode 100644 index 21aa486219e0..000000000000 --- a/src/doc/unstable-book/src/library-features/char-escape-debug.md +++ /dev/null @@ -1,7 +0,0 @@ -# `char_escape_debug` - -The tracking issue for this feature is: [#35068] - -[#35068]: https://github.com/rust-lang/rust/issues/35068 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/coerce-unsized.md b/src/doc/unstable-book/src/library-features/coerce-unsized.md deleted file mode 100644 index 078d3faf42a7..000000000000 --- a/src/doc/unstable-book/src/library-features/coerce-unsized.md +++ /dev/null @@ -1,7 +0,0 @@ -# `coerce_unsized` - -The tracking issue for this feature is: [#27732] - -[#27732]: https://github.com/rust-lang/rust/issues/27732 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/collection-placement.md b/src/doc/unstable-book/src/library-features/collection-placement.md deleted file mode 100644 index 268ca6ea590d..000000000000 --- a/src/doc/unstable-book/src/library-features/collection-placement.md +++ /dev/null @@ -1,7 +0,0 @@ -# `collection_placement` - -The tracking issue for this feature is: [#30172] - -[#30172]: https://github.com/rust-lang/rust/issues/30172 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/collections-range.md b/src/doc/unstable-book/src/library-features/collections-range.md deleted file mode 100644 index ea4f999ba0f9..000000000000 --- a/src/doc/unstable-book/src/library-features/collections-range.md +++ /dev/null @@ -1,7 +0,0 @@ -# `collections_range` - -The tracking issue for this feature is: [#30877] - -[#30877]: https://github.com/rust-lang/rust/issues/30877 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/command-envs.md b/src/doc/unstable-book/src/library-features/command-envs.md deleted file mode 100644 index 0ab89e278cdf..000000000000 --- a/src/doc/unstable-book/src/library-features/command-envs.md +++ /dev/null @@ -1,7 +0,0 @@ -# `command_envs` - -The tracking issue for this feature is: [#38526] - -[#38526]: https://github.com/rust-lang/rust/issues/38526 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/concat-idents-macro.md b/src/doc/unstable-book/src/library-features/concat-idents-macro.md deleted file mode 100644 index ac2fdd4fceb6..000000000000 --- a/src/doc/unstable-book/src/library-features/concat-idents-macro.md +++ /dev/null @@ -1,7 +0,0 @@ -# `concat_idents_macro` - -The tracking issue for this feature is: [#29599] - -[#29599]: https://github.com/rust-lang/rust/issues/29599 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/core-char-ext.md b/src/doc/unstable-book/src/library-features/core-char-ext.md deleted file mode 100644 index d37d6b5c6d0b..000000000000 --- a/src/doc/unstable-book/src/library-features/core-char-ext.md +++ /dev/null @@ -1,7 +0,0 @@ -# `core_char_ext` - -The tracking issue for this feature is: [#32110] - -[#32110]: https://github.com/rust-lang/rust/issues/32110 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/core-float.md b/src/doc/unstable-book/src/library-features/core-float.md deleted file mode 100644 index 194b2608dd02..000000000000 --- a/src/doc/unstable-book/src/library-features/core-float.md +++ /dev/null @@ -1,7 +0,0 @@ -# `core_float` - -The tracking issue for this feature is: [#32110] - -[#32110]: https://github.com/rust-lang/rust/issues/32110 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/core-slice-ext.md b/src/doc/unstable-book/src/library-features/core-slice-ext.md deleted file mode 100644 index c50d44ac0ce3..000000000000 --- a/src/doc/unstable-book/src/library-features/core-slice-ext.md +++ /dev/null @@ -1,7 +0,0 @@ -# `core_slice_ext` - -The tracking issue for this feature is: [#32110] - -[#32110]: https://github.com/rust-lang/rust/issues/32110 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/core-str-ext.md b/src/doc/unstable-book/src/library-features/core-str-ext.md deleted file mode 100644 index 08c68f11c6ec..000000000000 --- a/src/doc/unstable-book/src/library-features/core-str-ext.md +++ /dev/null @@ -1,7 +0,0 @@ -# `core_str_ext` - -The tracking issue for this feature is: [#32110] - -[#32110]: https://github.com/rust-lang/rust/issues/32110 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/decode-utf8.md b/src/doc/unstable-book/src/library-features/decode-utf8.md deleted file mode 100644 index b96854ebcd46..000000000000 --- a/src/doc/unstable-book/src/library-features/decode-utf8.md +++ /dev/null @@ -1,7 +0,0 @@ -# `decode_utf8` - -The tracking issue for this feature is: [#27783] - -[#27783]: https://github.com/rust-lang/rust/issues/27783 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/discriminant-value.md b/src/doc/unstable-book/src/library-features/discriminant-value.md deleted file mode 100644 index 2f99f5ecab39..000000000000 --- a/src/doc/unstable-book/src/library-features/discriminant-value.md +++ /dev/null @@ -1,7 +0,0 @@ -# `discriminant_value` - -The tracking issue for this feature is: [#24263] - -[#24263]: https://github.com/rust-lang/rust/issues/24263 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/error-type-id.md b/src/doc/unstable-book/src/library-features/error-type-id.md deleted file mode 100644 index be7a3ffd4dc4..000000000000 --- a/src/doc/unstable-book/src/library-features/error-type-id.md +++ /dev/null @@ -1,7 +0,0 @@ -# `error_type_id` - -The tracking issue for this feature is: [#27745] - -[#27745]: https://github.com/rust-lang/rust/issues/27745 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/exact-size-is-empty.md b/src/doc/unstable-book/src/library-features/exact-size-is-empty.md deleted file mode 100644 index 200ec3872517..000000000000 --- a/src/doc/unstable-book/src/library-features/exact-size-is-empty.md +++ /dev/null @@ -1,7 +0,0 @@ -# `exact_size_is_empty` - -The tracking issue for this feature is: [#35428] - -[#35428]: https://github.com/rust-lang/rust/issues/35428 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/fixed-size-array.md b/src/doc/unstable-book/src/library-features/fixed-size-array.md deleted file mode 100644 index 9e24e6a0850d..000000000000 --- a/src/doc/unstable-book/src/library-features/fixed-size-array.md +++ /dev/null @@ -1,7 +0,0 @@ -# `fixed_size_array` - -The tracking issue for this feature is: [#27778] - -[#27778]: https://github.com/rust-lang/rust/issues/27778 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/float-bits-conv.md b/src/doc/unstable-book/src/library-features/float-bits-conv.md deleted file mode 100644 index f519545ac78b..000000000000 --- a/src/doc/unstable-book/src/library-features/float-bits-conv.md +++ /dev/null @@ -1,7 +0,0 @@ -# `float_bits_conv` - -The tracking issue for this feature is: [#40470] - -[#40470]: https://github.com/rust-lang/rust/issues/40470 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/fmt-flags-align.md b/src/doc/unstable-book/src/library-features/fmt-flags-align.md deleted file mode 100644 index 755263bd9a61..000000000000 --- a/src/doc/unstable-book/src/library-features/fmt-flags-align.md +++ /dev/null @@ -1,7 +0,0 @@ -# `fmt_flags_align` - -The tracking issue for this feature is: [#27726] - -[#27726]: https://github.com/rust-lang/rust/issues/27726 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/fn-traits.md b/src/doc/unstable-book/src/library-features/fn-traits.md deleted file mode 100644 index 3942cda55388..000000000000 --- a/src/doc/unstable-book/src/library-features/fn-traits.md +++ /dev/null @@ -1,7 +0,0 @@ -# `fn_traits` - -The tracking issue for this feature is: [#29625] - -[#29625]: https://github.com/rust-lang/rust/issues/29625 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/fnbox.md b/src/doc/unstable-book/src/library-features/fnbox.md deleted file mode 100644 index a9b74d4f0047..000000000000 --- a/src/doc/unstable-book/src/library-features/fnbox.md +++ /dev/null @@ -1,7 +0,0 @@ -# `fnbox` - -The tracking issue for this feature is: [#28796] - -[#28796]: https://github.com/rust-lang/rust/issues/28796 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/from-utf8-error-as-bytes.md b/src/doc/unstable-book/src/library-features/from-utf8-error-as-bytes.md deleted file mode 100644 index 570f779417f0..000000000000 --- a/src/doc/unstable-book/src/library-features/from-utf8-error-as-bytes.md +++ /dev/null @@ -1,7 +0,0 @@ -# `from_utf8_error_as_bytes` - -The tracking issue for this feature is: [#40895] - -[#40895]: https://github.com/rust-lang/rust/issues/40895 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/fused.md b/src/doc/unstable-book/src/library-features/fused.md deleted file mode 100644 index 460555bf1b0d..000000000000 --- a/src/doc/unstable-book/src/library-features/fused.md +++ /dev/null @@ -1,7 +0,0 @@ -# `fused` - -The tracking issue for this feature is: [#35602] - -[#35602]: https://github.com/rust-lang/rust/issues/35602 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/get-type-id.md b/src/doc/unstable-book/src/library-features/get-type-id.md deleted file mode 100644 index afdb030c406d..000000000000 --- a/src/doc/unstable-book/src/library-features/get-type-id.md +++ /dev/null @@ -1,7 +0,0 @@ -# `get_type_id` - -The tracking issue for this feature is: [#27745] - -[#27745]: https://github.com/rust-lang/rust/issues/27745 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/heap-api.md b/src/doc/unstable-book/src/library-features/heap-api.md deleted file mode 100644 index 01404e49dbda..000000000000 --- a/src/doc/unstable-book/src/library-features/heap-api.md +++ /dev/null @@ -1,7 +0,0 @@ -# `heap_api` - -The tracking issue for this feature is: [#27700] - -[#27700]: https://github.com/rust-lang/rust/issues/27700 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/i128.md b/src/doc/unstable-book/src/library-features/i128.md deleted file mode 100644 index a1a7ce8e63f4..000000000000 --- a/src/doc/unstable-book/src/library-features/i128.md +++ /dev/null @@ -1,7 +0,0 @@ -# `i128` - -The tracking issue for this feature is: [#35118] - -[#35118]: https://github.com/rust-lang/rust/issues/35118 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/inclusive-range.md b/src/doc/unstable-book/src/library-features/inclusive-range.md deleted file mode 100644 index 2e88e2047868..000000000000 --- a/src/doc/unstable-book/src/library-features/inclusive-range.md +++ /dev/null @@ -1,7 +0,0 @@ -# `inclusive_range` - -The tracking issue for this feature is: [#28237] - -[#28237]: https://github.com/rust-lang/rust/issues/28237 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/integer-atomics.md b/src/doc/unstable-book/src/library-features/integer-atomics.md deleted file mode 100644 index 50db9fd4ca45..000000000000 --- a/src/doc/unstable-book/src/library-features/integer-atomics.md +++ /dev/null @@ -1,7 +0,0 @@ -# `integer_atomics` - -The tracking issue for this feature is: [#32976] - -[#32976]: https://github.com/rust-lang/rust/issues/32976 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/into-boxed-c-str.md b/src/doc/unstable-book/src/library-features/into-boxed-c-str.md deleted file mode 100644 index 0d94b4fc5605..000000000000 --- a/src/doc/unstable-book/src/library-features/into-boxed-c-str.md +++ /dev/null @@ -1,7 +0,0 @@ -# `into_boxed_c_str` - -The tracking issue for this feature is: [#40380] - -[#40380]: https://github.com/rust-lang/rust/issues/40380 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/into-boxed-os-str.md b/src/doc/unstable-book/src/library-features/into-boxed-os-str.md deleted file mode 100644 index 7636e20b14d8..000000000000 --- a/src/doc/unstable-book/src/library-features/into-boxed-os-str.md +++ /dev/null @@ -1,7 +0,0 @@ -# `into_boxed_os_str` - -The tracking issue for this feature is: [#into_boxed_os_str] - -[#into_boxed_os_str]: https://github.com/rust-lang/rust/issues/40380 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/into-boxed-path.md b/src/doc/unstable-book/src/library-features/into-boxed-path.md deleted file mode 100644 index 754c6042f07f..000000000000 --- a/src/doc/unstable-book/src/library-features/into-boxed-path.md +++ /dev/null @@ -1,7 +0,0 @@ -# `into_boxed_path` - -The tracking issue for this feature is: [#40380] - -[#40380]: https://github.com/rust-lang/rust/issues/40380 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/io.md b/src/doc/unstable-book/src/library-features/io.md deleted file mode 100644 index ed6cae24e32d..000000000000 --- a/src/doc/unstable-book/src/library-features/io.md +++ /dev/null @@ -1,7 +0,0 @@ -# `io` - -The tracking issue for this feature is: [#27802] - -[#27802]: https://github.com/rust-lang/rust/issues/27802 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/ip.md b/src/doc/unstable-book/src/library-features/ip.md deleted file mode 100644 index 7e7d52adbdb0..000000000000 --- a/src/doc/unstable-book/src/library-features/ip.md +++ /dev/null @@ -1,7 +0,0 @@ -# `ip` - -The tracking issue for this feature is: [#27709] - -[#27709]: https://github.com/rust-lang/rust/issues/27709 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/iter-rfind.md b/src/doc/unstable-book/src/library-features/iter-rfind.md deleted file mode 100644 index 444714490345..000000000000 --- a/src/doc/unstable-book/src/library-features/iter-rfind.md +++ /dev/null @@ -1,7 +0,0 @@ -# `iter_rfind` - -The tracking issue for this feature is: [#39480] - -[#39480]: https://github.com/rust-lang/rust/issues/39480 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/iterator-step-by.md b/src/doc/unstable-book/src/library-features/iterator-step-by.md deleted file mode 100644 index 8467cb68862f..000000000000 --- a/src/doc/unstable-book/src/library-features/iterator-step-by.md +++ /dev/null @@ -1,7 +0,0 @@ -# `iterator_step_by` - -The tracking issue for this feature is: [#27741] - -[#27741]: https://github.com/rust-lang/rust/issues/27741 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/linked-list-extras.md b/src/doc/unstable-book/src/library-features/linked-list-extras.md deleted file mode 100644 index be3b96aea70d..000000000000 --- a/src/doc/unstable-book/src/library-features/linked-list-extras.md +++ /dev/null @@ -1,7 +0,0 @@ -# `linked_list_extras` - -The tracking issue for this feature is: [#27794] - -[#27794]: https://github.com/rust-lang/rust/issues/27794 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/lookup-host.md b/src/doc/unstable-book/src/library-features/lookup-host.md deleted file mode 100644 index b60e7a010945..000000000000 --- a/src/doc/unstable-book/src/library-features/lookup-host.md +++ /dev/null @@ -1,7 +0,0 @@ -# `lookup_host` - -The tracking issue for this feature is: [#27705] - -[#27705]: https://github.com/rust-lang/rust/issues/27705 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/needs-drop.md b/src/doc/unstable-book/src/library-features/needs-drop.md deleted file mode 100644 index 10ae95695a2d..000000000000 --- a/src/doc/unstable-book/src/library-features/needs-drop.md +++ /dev/null @@ -1,7 +0,0 @@ -# `needs_drop` - -The tracking issue for this feature is: [#41890] - -[#41890]: https://github.com/rust-lang/rust/issues/41890 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/never-type-impls.md b/src/doc/unstable-book/src/library-features/never-type-impls.md deleted file mode 100644 index 4063cd0db01d..000000000000 --- a/src/doc/unstable-book/src/library-features/never-type-impls.md +++ /dev/null @@ -1,7 +0,0 @@ -# `never_type_impls` - -The tracking issue for this feature is: [#35121] - -[#35121]: https://github.com/rust-lang/rust/issues/35121 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/nonzero.md b/src/doc/unstable-book/src/library-features/nonzero.md deleted file mode 100644 index f200f8e2786f..000000000000 --- a/src/doc/unstable-book/src/library-features/nonzero.md +++ /dev/null @@ -1,7 +0,0 @@ -# `nonzero` - -The tracking issue for this feature is: [#27730] - -[#27730]: https://github.com/rust-lang/rust/issues/27730 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/offset-to.md b/src/doc/unstable-book/src/library-features/offset-to.md deleted file mode 100644 index 03d990eb4ae9..000000000000 --- a/src/doc/unstable-book/src/library-features/offset-to.md +++ /dev/null @@ -1,7 +0,0 @@ -# `offset_to` - -The tracking issue for this feature is: [#41079] - -[#41079]: https://github.com/rust-lang/rust/issues/41079 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/once-poison.md b/src/doc/unstable-book/src/library-features/once-poison.md deleted file mode 100644 index 3c16cafae501..000000000000 --- a/src/doc/unstable-book/src/library-features/once-poison.md +++ /dev/null @@ -1,7 +0,0 @@ -# `once_poison` - -The tracking issue for this feature is: [#33577] - -[#33577]: https://github.com/rust-lang/rust/issues/33577 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/oom.md b/src/doc/unstable-book/src/library-features/oom.md deleted file mode 100644 index 908caeb75c60..000000000000 --- a/src/doc/unstable-book/src/library-features/oom.md +++ /dev/null @@ -1,7 +0,0 @@ -# `oom` - -The tracking issue for this feature is: [#27700] - -[#27700]: https://github.com/rust-lang/rust/issues/27700 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/option-entry.md b/src/doc/unstable-book/src/library-features/option-entry.md deleted file mode 100644 index edb4efc09e58..000000000000 --- a/src/doc/unstable-book/src/library-features/option-entry.md +++ /dev/null @@ -1,7 +0,0 @@ -# `option_entry` - -The tracking issue for this feature is: [#39288] - -[#39288]: https://github.com/rust-lang/rust/issues/39288 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/osstring-shrink-to-fit.md b/src/doc/unstable-book/src/library-features/osstring-shrink-to-fit.md deleted file mode 100644 index 21dc7d095c80..000000000000 --- a/src/doc/unstable-book/src/library-features/osstring-shrink-to-fit.md +++ /dev/null @@ -1,7 +0,0 @@ -# `osstring_shrink_to_fit` - -The tracking issue for this feature is: [#40421] - -[#40421]: https://github.com/rust-lang/rust/issues/40421 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/panic-abort.md b/src/doc/unstable-book/src/library-features/panic-abort.md deleted file mode 100644 index 07a957626905..000000000000 --- a/src/doc/unstable-book/src/library-features/panic-abort.md +++ /dev/null @@ -1,7 +0,0 @@ -# `panic_abort` - -The tracking issue for this feature is: [#32837] - -[#32837]: https://github.com/rust-lang/rust/issues/32837 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/panic-unwind.md b/src/doc/unstable-book/src/library-features/panic-unwind.md deleted file mode 100644 index 840e492597b5..000000000000 --- a/src/doc/unstable-book/src/library-features/panic-unwind.md +++ /dev/null @@ -1,7 +0,0 @@ -# `panic_unwind` - -The tracking issue for this feature is: [#32837] - -[#32837]: https://github.com/rust-lang/rust/issues/32837 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/pattern.md b/src/doc/unstable-book/src/library-features/pattern.md deleted file mode 100644 index e76ee6beb675..000000000000 --- a/src/doc/unstable-book/src/library-features/pattern.md +++ /dev/null @@ -1,7 +0,0 @@ -# `pattern` - -The tracking issue for this feature is: [#27721] - -[#27721]: https://github.com/rust-lang/rust/issues/27721 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/placement-in.md b/src/doc/unstable-book/src/library-features/placement-in.md deleted file mode 100644 index 6ff010b7e385..000000000000 --- a/src/doc/unstable-book/src/library-features/placement-in.md +++ /dev/null @@ -1,7 +0,0 @@ -# `placement_in` - -The tracking issue for this feature is: [#27779] - -[#27779]: https://github.com/rust-lang/rust/issues/27779 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/placement-new-protocol.md b/src/doc/unstable-book/src/library-features/placement-new-protocol.md deleted file mode 100644 index d53225f0a352..000000000000 --- a/src/doc/unstable-book/src/library-features/placement-new-protocol.md +++ /dev/null @@ -1,7 +0,0 @@ -# `placement_new_protocol` - -The tracking issue for this feature is: [#27779] - -[#27779]: https://github.com/rust-lang/rust/issues/27779 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/proc-macro-internals.md b/src/doc/unstable-book/src/library-features/proc-macro-internals.md deleted file mode 100644 index ea087c0a4f7b..000000000000 --- a/src/doc/unstable-book/src/library-features/proc-macro-internals.md +++ /dev/null @@ -1,7 +0,0 @@ -# `proc_macro_internals` - -The tracking issue for this feature is: [#27812] - -[#27812]: https://github.com/rust-lang/rust/issues/27812 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/range-contains.md b/src/doc/unstable-book/src/library-features/range-contains.md deleted file mode 100644 index ac4581faf2ae..000000000000 --- a/src/doc/unstable-book/src/library-features/range-contains.md +++ /dev/null @@ -1,7 +0,0 @@ -# `range_contains` - -The tracking issue for this feature is: [#32311] - -[#32311]: https://github.com/rust-lang/rust/issues/32311 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/raw.md b/src/doc/unstable-book/src/library-features/raw.md deleted file mode 100644 index d7caf22813dc..000000000000 --- a/src/doc/unstable-book/src/library-features/raw.md +++ /dev/null @@ -1,7 +0,0 @@ -# `raw` - -The tracking issue for this feature is: [#27751] - -[#27751]: https://github.com/rust-lang/rust/issues/27751 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/reverse-cmp-key.md b/src/doc/unstable-book/src/library-features/reverse-cmp-key.md deleted file mode 100644 index a1a851d6ed63..000000000000 --- a/src/doc/unstable-book/src/library-features/reverse-cmp-key.md +++ /dev/null @@ -1,7 +0,0 @@ -# `reverse_cmp_key` - -The tracking issue for this feature is: [#40893] - -[#40893]: https://github.com/rust-lang/rust/issues/40893 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/rustc-private.md b/src/doc/unstable-book/src/library-features/rustc-private.md deleted file mode 100644 index 2453475efe59..000000000000 --- a/src/doc/unstable-book/src/library-features/rustc-private.md +++ /dev/null @@ -1,7 +0,0 @@ -# `rustc_private` - -The tracking issue for this feature is: [#27812] - -[#27812]: https://github.com/rust-lang/rust/issues/27812 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/shared.md b/src/doc/unstable-book/src/library-features/shared.md deleted file mode 100644 index b79d1212c62f..000000000000 --- a/src/doc/unstable-book/src/library-features/shared.md +++ /dev/null @@ -1,7 +0,0 @@ -# `shared` - -The tracking issue for this feature is: [#27730] - -[#27730]: https://github.com/rust-lang/rust/issues/27730 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/sip-hash-13.md b/src/doc/unstable-book/src/library-features/sip-hash-13.md deleted file mode 100644 index 8f69c3ab2def..000000000000 --- a/src/doc/unstable-book/src/library-features/sip-hash-13.md +++ /dev/null @@ -1,7 +0,0 @@ -# `sip_hash_13` - -The tracking issue for this feature is: [#34767] - -[#34767]: https://github.com/rust-lang/rust/issues/34767 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/slice-concat-ext.md b/src/doc/unstable-book/src/library-features/slice-concat-ext.md deleted file mode 100644 index 9ba2de5adc72..000000000000 --- a/src/doc/unstable-book/src/library-features/slice-concat-ext.md +++ /dev/null @@ -1,7 +0,0 @@ -# `slice_concat_ext` - -The tracking issue for this feature is: [#27747] - -[#27747]: https://github.com/rust-lang/rust/issues/27747 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/slice-get-slice.md b/src/doc/unstable-book/src/library-features/slice-get-slice.md deleted file mode 100644 index 57e2c148e796..000000000000 --- a/src/doc/unstable-book/src/library-features/slice-get-slice.md +++ /dev/null @@ -1,7 +0,0 @@ -# `slice_get_slice` - -The tracking issue for this feature is: [#35729] - -[#35729]: https://github.com/rust-lang/rust/issues/35729 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/slice-rotate.md b/src/doc/unstable-book/src/library-features/slice-rotate.md deleted file mode 100644 index 77fd598f1ea9..000000000000 --- a/src/doc/unstable-book/src/library-features/slice-rotate.md +++ /dev/null @@ -1,7 +0,0 @@ -# `slice_rotate` - -The tracking issue for this feature is: [#41891] - -[#41891]: https://github.com/rust-lang/rust/issues/41891 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/step-by.md b/src/doc/unstable-book/src/library-features/step-by.md deleted file mode 100644 index b649496cdd80..000000000000 --- a/src/doc/unstable-book/src/library-features/step-by.md +++ /dev/null @@ -1,7 +0,0 @@ -# `step_by` - -The tracking issue for this feature is: [#27741] - -[#27741]: https://github.com/rust-lang/rust/issues/27741 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/step-trait.md b/src/doc/unstable-book/src/library-features/step-trait.md deleted file mode 100644 index 56050c20c691..000000000000 --- a/src/doc/unstable-book/src/library-features/step-trait.md +++ /dev/null @@ -1,7 +0,0 @@ -# `step_trait` - -The tracking issue for this feature is: [#42168] - -[#42168]: https://github.com/rust-lang/rust/issues/42168 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/str-box-extras.md b/src/doc/unstable-book/src/library-features/str-box-extras.md deleted file mode 100644 index d05dcafa84da..000000000000 --- a/src/doc/unstable-book/src/library-features/str-box-extras.md +++ /dev/null @@ -1,9 +0,0 @@ -# `str_box_extras` - -The tracking issue for this feature is: [#str_box_extras] - -[#str_box_extras]: https://github.com/rust-lang/rust/issues/41119 - ------------------------- - - diff --git a/src/doc/unstable-book/src/library-features/str-checked-slicing.md b/src/doc/unstable-book/src/library-features/str-checked-slicing.md deleted file mode 100644 index d390139a6bef..000000000000 --- a/src/doc/unstable-book/src/library-features/str-checked-slicing.md +++ /dev/null @@ -1,7 +0,0 @@ -# `str_checked_slicing` - -The tracking issue for this feature is: [#39932] - -[#39932]: https://github.com/rust-lang/rust/issues/39932 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/str-escape.md b/src/doc/unstable-book/src/library-features/str-escape.md deleted file mode 100644 index 61e31c894432..000000000000 --- a/src/doc/unstable-book/src/library-features/str-escape.md +++ /dev/null @@ -1,7 +0,0 @@ -# `str_escape` - -The tracking issue for this feature is: [#27791] - -[#27791]: https://github.com/rust-lang/rust/issues/27791 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/str-mut-extras.md b/src/doc/unstable-book/src/library-features/str-mut-extras.md deleted file mode 100644 index df4f35832cdc..000000000000 --- a/src/doc/unstable-book/src/library-features/str-mut-extras.md +++ /dev/null @@ -1,8 +0,0 @@ -# `str_mut_extras` - -The tracking issue for this feature is: [#str_mut_extras] - -[#str_mut_extras]: https://github.com/rust-lang/rust/issues/41119 - ------------------------- - diff --git a/src/doc/unstable-book/src/library-features/thread-id.md b/src/doc/unstable-book/src/library-features/thread-id.md deleted file mode 100644 index af3ea991025f..000000000000 --- a/src/doc/unstable-book/src/library-features/thread-id.md +++ /dev/null @@ -1,7 +0,0 @@ -# `thread_id` - -The tracking issue for this feature is: [#21507] - -[#21507]: https://github.com/rust-lang/rust/issues/21507 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/thread-local-state.md b/src/doc/unstable-book/src/library-features/thread-local-state.md deleted file mode 100644 index 113c1e910dca..000000000000 --- a/src/doc/unstable-book/src/library-features/thread-local-state.md +++ /dev/null @@ -1,7 +0,0 @@ -# `thread_local_state` - -The tracking issue for this feature is: [#27716] - -[#27716]: https://github.com/rust-lang/rust/issues/27716 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/toowned-clone-into.md b/src/doc/unstable-book/src/library-features/toowned-clone-into.md deleted file mode 100644 index eccc7e0e4dda..000000000000 --- a/src/doc/unstable-book/src/library-features/toowned-clone-into.md +++ /dev/null @@ -1,7 +0,0 @@ -# `toowned_clone_into` - -The tracking issue for this feature is: [#41263] - -[#41263]: https://github.com/rust-lang/rust/issues/41263 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/trusted-len.md b/src/doc/unstable-book/src/library-features/trusted-len.md deleted file mode 100644 index 80213cf1fdbb..000000000000 --- a/src/doc/unstable-book/src/library-features/trusted-len.md +++ /dev/null @@ -1,7 +0,0 @@ -# `trusted_len` - -The tracking issue for this feature is: [#37572] - -[#37572]: https://github.com/rust-lang/rust/issues/37572 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/try-from.md b/src/doc/unstable-book/src/library-features/try-from.md deleted file mode 100644 index d763caff5aac..000000000000 --- a/src/doc/unstable-book/src/library-features/try-from.md +++ /dev/null @@ -1,7 +0,0 @@ -# `try_from` - -The tracking issue for this feature is: [#33417] - -[#33417]: https://github.com/rust-lang/rust/issues/33417 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/unicode.md b/src/doc/unstable-book/src/library-features/unicode.md deleted file mode 100644 index 9fecec2ac36d..000000000000 --- a/src/doc/unstable-book/src/library-features/unicode.md +++ /dev/null @@ -1,7 +0,0 @@ -# `unicode` - -The tracking issue for this feature is: [#27783] - -[#27783]: https://github.com/rust-lang/rust/issues/27783 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/unique.md b/src/doc/unstable-book/src/library-features/unique.md deleted file mode 100644 index 99a3490d106b..000000000000 --- a/src/doc/unstable-book/src/library-features/unique.md +++ /dev/null @@ -1,7 +0,0 @@ -# `unique` - -The tracking issue for this feature is: [#27730] - -[#27730]: https://github.com/rust-lang/rust/issues/27730 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/unsize.md b/src/doc/unstable-book/src/library-features/unsize.md deleted file mode 100644 index 92807e2858ff..000000000000 --- a/src/doc/unstable-book/src/library-features/unsize.md +++ /dev/null @@ -1,7 +0,0 @@ -# `unsize` - -The tracking issue for this feature is: [#27732] - -[#27732]: https://github.com/rust-lang/rust/issues/27732 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/utf8-error-error-len.md b/src/doc/unstable-book/src/library-features/utf8-error-error-len.md deleted file mode 100644 index 1c14a5a9fa08..000000000000 --- a/src/doc/unstable-book/src/library-features/utf8-error-error-len.md +++ /dev/null @@ -1,7 +0,0 @@ -# `utf8_error_error_len` - -The tracking issue for this feature is: [#40494] - -[#40494]: https://github.com/rust-lang/rust/issues/40494 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/vec-remove-item.md b/src/doc/unstable-book/src/library-features/vec-remove-item.md deleted file mode 100644 index 2b8c9f046eef..000000000000 --- a/src/doc/unstable-book/src/library-features/vec-remove-item.md +++ /dev/null @@ -1,7 +0,0 @@ -# `vec_remove_item` - -The tracking issue for this feature is: [#40062] - -[#40062]: https://github.com/rust-lang/rust/issues/40062 - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/vec-resize-default.md b/src/doc/unstable-book/src/library-features/vec-resize-default.md deleted file mode 100644 index 5803d3215a54..000000000000 --- a/src/doc/unstable-book/src/library-features/vec-resize-default.md +++ /dev/null @@ -1,7 +0,0 @@ -# `vec_resize_default` - -The tracking issue for this feature is: [#41758] - -[#41758]: https://github.com/rust-lang/rust/issues/41758 - ------------------------- diff --git a/src/tools/tidy/src/unstable_book.rs b/src/tools/tidy/src/unstable_book.rs index e05ab470eedc..fd3ffc685d9b 100644 --- a/src/tools/tidy/src/unstable_book.rs +++ b/src/tools/tidy/src/unstable_book.rs @@ -93,15 +93,6 @@ pub fn check(path: &path::Path, bad: &mut bool) { let unstable_book_lib_features_section_file_names = collect_unstable_book_lib_features_section_file_names(path); - // Check for unstable features that don't have Unstable Book sections - for feature_name in &unstable_lib_feature_names - - &unstable_book_lib_features_section_file_names { - tidy_error!(bad, - "Unstable library feature '{}' needs to have a section within the \ - 'library features' section of The Unstable Book", - feature_name); - } - // Check for Unstable Book sections that don't have a corresponding unstable feature for feature_name in &unstable_book_lib_features_section_file_names - &unstable_lib_feature_names { @@ -117,14 +108,6 @@ pub fn check(path: &path::Path, bad: &mut bool) { let unstable_book_lang_features_section_file_names = collect_unstable_book_lang_features_section_file_names(path); - for feature_name in &unstable_lang_feature_names - - &unstable_book_lang_features_section_file_names { - tidy_error!(bad, - "Unstable language feature '{}' needs to have a section within the \ - 'language features' section of The Unstable Book", - feature_name); - } - // Check for Unstable Book sections that don't have a corresponding unstable feature for feature_name in &unstable_book_lang_features_section_file_names - &unstable_lang_feature_names { @@ -133,4 +116,20 @@ pub fn check(path: &path::Path, bad: &mut bool) { correspond to an unstable language feature", feature_name) } + + // List unstable features that don't have Unstable Book sections + // Remove the comment marker if you want the list printed + /* + println!("Lib features without unstable book sections:"); + for feature_name in &unstable_lang_feature_names - + &unstable_book_lang_features_section_file_names { + println!(" * {} {:?}", feature_name, lib_features[&feature_name].tracking_issue); + } + + println!("Lang features without unstable book sections:"); + for feature_name in &unstable_lib_feature_names- + &unstable_book_lib_features_section_file_names { + println!(" * {} {:?}", feature_name, lang_features[&feature_name].tracking_issue); + } + // */ } From 9f710530a7c0be1acaa099b12163ec1af8b8cf30 Mon Sep 17 00:00:00 2001 From: Taylor Cramer Date: Sun, 11 Jun 2017 21:16:26 -0700 Subject: [PATCH 187/233] On-demand is_const_fn --- src/librustc/dep_graph/dep_node.rs | 1 + src/librustc/middle/cstore.rs | 2 -- src/librustc/ty/maps.rs | 9 +++++++ src/librustc_const_eval/eval.rs | 2 +- src/librustc_driver/driver.rs | 1 + src/librustc_metadata/cstore.rs | 2 +- src/librustc_metadata/cstore_impl.rs | 26 +++++++++++++++----- src/librustc_mir/transform/copy_prop.rs | 3 +-- src/librustc_mir/transform/qualify_consts.rs | 17 ++----------- src/librustc_passes/consts.rs | 2 +- src/librustdoc/clean/inline.rs | 4 +-- 11 files changed, 39 insertions(+), 30 deletions(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index fda29ca73662..c987a37c420d 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -339,6 +339,7 @@ define_dep_nodes!( ItemSignature(DefId), ItemVarianceConstraints(DefId), ItemVariances(DefId), + IsConstFn(DefId), IsForeignItem(DefId), TypeParamPredicates { item_id: DefId, param_id: DefId }, SizedConstraint(DefId), diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 08c0adf110a3..735da5ca380c 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -243,7 +243,6 @@ pub trait CrateStore { fn associated_item_cloned(&self, def: DefId) -> ty::AssociatedItem; // flags - fn is_const_fn(&self, did: DefId) -> bool; fn is_dllimport_foreign_item(&self, def: DefId) -> bool; fn is_statically_included_foreign_item(&self, def_id: DefId) -> bool; @@ -364,7 +363,6 @@ impl CrateStore for DummyCrateStore { { bug!("associated_item_cloned") } // flags - fn is_const_fn(&self, did: DefId) -> bool { bug!("is_const_fn") } fn is_dllimport_foreign_item(&self, id: DefId) -> bool { false } fn is_statically_included_foreign_item(&self, def_id: DefId) -> bool { false } diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs index 162a734aa195..6ee5bf1392fc 100644 --- a/src/librustc/ty/maps.rs +++ b/src/librustc/ty/maps.rs @@ -476,6 +476,12 @@ impl<'tcx> QueryDescription for queries::is_object_safe<'tcx> { } } +impl<'tcx> QueryDescription for queries::is_const_fn<'tcx> { + fn describe(tcx: TyCtxt, def_id: DefId) -> String { + format!("checking if item is const fn: `{}`", tcx.item_path_str(def_id)) + } +} + macro_rules! define_maps { (<$tcx:tt> $($(#[$attr:meta])* @@ -791,6 +797,9 @@ define_maps! { <'tcx> [] adt_sized_constraint: SizedConstraint(DefId) -> &'tcx [Ty<'tcx>], [] adt_dtorck_constraint: DtorckConstraint(DefId) -> ty::DtorckConstraint<'tcx>, + /// True if this is a const fn + [] is_const_fn: IsConstFn(DefId) -> bool, + /// True if this is a foreign item (i.e., linked via `extern { ... }`). [] is_foreign_item: IsForeignItem(DefId) -> bool, diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index ec7510546a04..4ce985568ce2 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -351,7 +351,7 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>, signal!(e, TypeckError) } } else { - if tcx.sess.cstore.is_const_fn(def_id) { + if tcx.is_const_fn(def_id) { tcx.sess.cstore.item_body(tcx, def_id) } else { signal!(e, TypeckError) diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index bca82ff9a46d..ac26b04cb7a3 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -899,6 +899,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, reachable::provide(&mut local_providers); rustc_const_eval::provide(&mut local_providers); middle::region::provide(&mut local_providers); + cstore::provide_local(&mut local_providers); let mut extern_providers = ty::maps::Providers::default(); cstore::provide(&mut extern_providers); diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs index e572be9ffe7d..4e05244e2d56 100644 --- a/src/librustc_metadata/cstore.rs +++ b/src/librustc_metadata/cstore.rs @@ -34,7 +34,7 @@ pub use rustc::middle::cstore::{NativeLibrary, NativeLibraryKind, LinkagePrefere pub use rustc::middle::cstore::NativeLibraryKind::*; pub use rustc::middle::cstore::{CrateSource, LinkMeta, LibSource}; -pub use cstore_impl::provide; +pub use cstore_impl::{provide, provide_local}; // A map from external crate numbers (as decoded from some crate file) to // local crate numbers (as generated during this session). Each external diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 4cbcfe15c0c6..00c1fdb177db 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -23,6 +23,7 @@ use rustc::ty::{self, TyCtxt}; use rustc::ty::maps::Providers; use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc::hir::map::{DefKey, DefPath, DisambiguatedDefPathData, DefPathHash}; +use rustc::hir::map::blocks::FnLikeNode; use rustc::hir::map::definitions::{DefPathTable, GlobalMetaDataKind}; use rustc::util::nodemap::{NodeSet, DefIdMap}; use rustc_back::PanicStrategy; @@ -106,6 +107,7 @@ provide! { <'tcx> tcx, def_id, cdata closure_kind => { cdata.closure_kind(def_id.index) } closure_type => { cdata.closure_ty(def_id.index, tcx) } inherent_impls => { Rc::new(cdata.get_inherent_implementations_for_type(def_id.index)) } + is_const_fn => { cdata.is_const_fn(def_id.index) } is_foreign_item => { cdata.is_foreign_item(def_id.index) } is_default_impl => { cdata.is_default_impl(def_id.index) } describe_def => { cdata.get_def(def_id.index) } @@ -131,6 +133,24 @@ provide! { <'tcx> tcx, def_id, cdata is_mir_available => { cdata.is_item_mir_available(def_id.index) } } +pub fn provide_local<'tcx>(providers: &mut Providers<'tcx>) { + fn is_const_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> bool { + let node_id = tcx.hir.as_local_node_id(def_id) + .expect("Non-local call to local provider is_const_fn"); + + if let Some(fn_like) = FnLikeNode::from_node(tcx.hir.get(node_id)) { + fn_like.constness() == hir::Constness::Const + } else { + false + } + } + + *providers = Providers { + is_const_fn, + ..*providers + }; +} + impl CrateStore for cstore::CStore { fn crate_data_as_rc_any(&self, krate: CrateNum) -> Rc { self.get_crate_data(krate) @@ -172,12 +192,6 @@ impl CrateStore for cstore::CStore { self.get_crate_data(def.krate).get_associated_item(def.index) } - fn is_const_fn(&self, did: DefId) -> bool - { - self.read_dep_node(did); - self.get_crate_data(did.krate).is_const_fn(did.index) - } - fn is_statically_included_foreign_item(&self, def_id: DefId) -> bool { self.do_is_statically_included_foreign_item(def_id) diff --git a/src/librustc_mir/transform/copy_prop.rs b/src/librustc_mir/transform/copy_prop.rs index 08a4961c6cd1..dec0717e9e38 100644 --- a/src/librustc_mir/transform/copy_prop.rs +++ b/src/librustc_mir/transform/copy_prop.rs @@ -34,7 +34,6 @@ use rustc::mir::transform::{MirPass, MirSource}; use rustc::mir::visit::MutVisitor; use rustc::ty::TyCtxt; use util::def_use::DefUseAnalysis; -use transform::qualify_consts; pub struct CopyPropagation; @@ -55,7 +54,7 @@ impl MirPass for CopyPropagation { return } MirSource::Fn(function_node_id) => { - if qualify_consts::is_const_fn(tcx, tcx.hir.local_def_id(function_node_id)) { + if tcx.is_const_fn(tcx.hir.local_def_id(function_node_id)) { // Don't run on const functions, as, again, trans might not be able to evaluate // the optimized IR. return diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index d60e761bc0b9..8342d0ff491e 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -19,7 +19,6 @@ use rustc_data_structures::indexed_vec::{IndexVec, Idx}; use rustc::hir; use rustc::hir::map as hir_map; use rustc::hir::def_id::DefId; -use rustc::hir::map::blocks::FnLikeNode; use rustc::traits::{self, Reveal}; use rustc::ty::{self, TyCtxt, Ty, TypeFoldable}; use rustc::ty::cast::CastTy; @@ -109,18 +108,6 @@ impl fmt::Display for Mode { } } -pub fn is_const_fn(tcx: TyCtxt, def_id: DefId) -> bool { - if let Some(node_id) = tcx.hir.as_local_node_id(def_id) { - if let Some(fn_like) = FnLikeNode::from_node(tcx.hir.get(node_id)) { - fn_like.constness() == hir::Constness::Const - } else { - false - } - } else { - tcx.sess.cstore.is_const_fn(def_id) - } -} - struct Qualifier<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { mode: Mode, span: Span, @@ -766,7 +753,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { ty::TyFnDef(def_id, _, f) => { (f.abi() == Abi::PlatformIntrinsic && self.tcx.item_name(def_id).as_str().starts_with("simd_shuffle"), - is_const_fn(self.tcx, def_id)) + self.tcx.is_const_fn(def_id)) } _ => (false, false) }; @@ -957,7 +944,7 @@ impl MirPass for QualifyAndPromoteConstants { let def_id = tcx.hir.local_def_id(id); let mode = match src { MirSource::Fn(_) => { - if is_const_fn(tcx, def_id) { + if tcx.is_const_fn(def_id) { Mode::ConstFn } else { Mode::Fn diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs index e539cc1ae8bf..bec4c083905a 100644 --- a/src/librustc_passes/consts.rs +++ b/src/librustc_passes/consts.rs @@ -101,7 +101,7 @@ impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> { fn_like.constness() == hir::Constness::Const }) } else { - self.tcx.sess.cstore.is_const_fn(def_id) + self.tcx.is_const_fn(def_id) }; } } diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index a5797a5224d1..aeade4704822 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -151,7 +151,7 @@ pub fn build_external_trait(cx: &DocContext, did: DefId) -> clean::Trait { fn build_external_function(cx: &DocContext, did: DefId) -> clean::Function { let sig = cx.tcx.type_of(did).fn_sig(); - let constness = if cx.tcx.sess.cstore.is_const_fn(did) { + let constness = if cx.tcx.is_const_fn(did) { hir::Constness::Const } else { hir::Constness::NotConst @@ -352,7 +352,7 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec) { clean::TyMethodItem(clean::TyMethod { unsafety, decl, generics, abi }) => { - let constness = if tcx.sess.cstore.is_const_fn(item.def_id) { + let constness = if tcx.is_const_fn(item.def_id) { hir::Constness::Const } else { hir::Constness::NotConst From eadda7665eb31b1e7cb94a503b4d5cf5c75474c0 Mon Sep 17 00:00:00 2001 From: Murarth Date: Tue, 13 Jun 2017 15:52:59 -0700 Subject: [PATCH 188/233] Merge crate `collections` into `alloc` --- src/Cargo.lock | 11 +- src/bootstrap/dist.rs | 3 +- src/bootstrap/doc.rs | 2 +- src/doc/unstable-book/src/SUMMARY.md | 1 - .../src/library-features/collections.md | 5 - ...{libcollections.natvis => liballoc.natvis} | 14 +- src/etc/rust-windbg.cmd | 2 +- src/liballoc/Cargo.toml | 9 + src/liballoc/arc.rs | 5 +- .../benches/btree/map.rs | 0 .../benches/btree/mod.rs | 0 .../benches/lib.rs | 0 .../benches/linked_list.rs | 0 .../benches/slice.rs | 0 .../benches/str.rs | 0 .../benches/string.rs | 0 .../benches/vec.rs | 0 .../benches/vec_deque.rs | 0 .../binary_heap.rs | 0 src/{libcollections => liballoc}/borrow.rs | 0 src/liballoc/boxed.rs | 2 + src/{libcollections => liballoc}/btree/map.rs | 0 src/{libcollections => liballoc}/btree/mod.rs | 0 .../btree/node.rs | 2 +- .../btree/search.rs | 0 src/{libcollections => liballoc}/btree/set.rs | 0 src/{libcollections => liballoc}/fmt.rs | 0 src/liballoc/lib.rs | 160 +- .../linked_list.rs | 2 +- src/liballoc/macros.rs | 83 + src/{libcollections => liballoc}/range.rs | 16 +- src/liballoc/raw_vec.rs | 1 + src/{libcollections => liballoc}/slice.rs | 4 +- src/liballoc/str.rs | 1985 +++++++++++++++- src/{libcollections => liballoc}/string.rs | 6 +- .../tests/binary_heap.rs | 0 .../tests/btree/map.rs | 0 .../tests/btree/mod.rs | 0 .../tests/btree/set.rs | 0 .../tests/cow_str.rs | 0 src/{libcollections => liballoc}/tests/fmt.rs | 0 src/{libcollections => liballoc}/tests/lib.rs | 4 +- .../tests/linked_list.rs | 0 .../tests/slice.rs | 0 src/{libcollections => liballoc}/tests/str.rs | 0 .../tests/string.rs | 0 src/{libcollections => liballoc}/tests/vec.rs | 0 .../tests/vec_deque.rs | 0 src/{libcollections => liballoc}/vec.rs | 8 +- src/{libcollections => liballoc}/vec_deque.rs | 2 +- src/libcollections/Cargo.toml | 21 - src/libcollections/lib.rs | 192 -- src/libcollections/macros.rs | 92 - src/libcollections/str.rs | 1997 ----------------- src/libcore/str/mod.rs | 2 +- src/librustc_data_structures/fnv.rs | 2 +- src/librustc_data_structures/fx.rs | 2 +- src/librustc_resolve/diagnostics.rs | 18 +- src/librustc_typeck/diagnostics.rs | 4 +- src/libserialize/collection_impls.rs | 2 +- src/libserialize/lib.rs | 3 - src/libstd/Cargo.toml | 1 - src/libstd/collections/mod.rs | 12 +- src/libstd/lib.rs | 17 +- src/libstd_unicode/lib.rs | 2 +- src/libstd_unicode/u_str.rs | 2 +- src/test/compile-fail/E0254.rs | 10 +- src/test/compile-fail/E0259.rs | 10 +- src/test/compile-fail/E0260.rs | 12 +- .../compile-fail/lint-unused-extern-crate.rs | 4 +- .../compile-fail/resolve_self_super_hint.rs | 28 +- src/test/run-pass-fulldeps/issue-2804.rs | 2 - .../run-pass-fulldeps/regions-mock-tcx.rs | 3 +- .../run-pass/drop-with-type-ascription-2.rs | 2 - src/test/run-pass/for-loop-no-std.rs | 4 +- ...xternal-iterators-hashmap-break-restart.rs | 4 - .../foreach-external-iterators-hashmap.rs | 4 - src/test/run-pass/format-no-std.rs | 6 +- src/test/run-pass/issue-12860.rs | 4 - src/test/run-pass/issue-1696.rs | 4 - .../run-pass/issue-19811-escape-unicode.rs | 2 - src/test/run-pass/issue-2383.rs | 3 - src/test/run-pass/issue-2804-2.rs | 4 - src/test/run-pass/issue-3026.rs | 5 +- src/test/run-pass/issue-3559.rs | 4 - src/test/run-pass/issue-6128.rs | 5 +- src/test/run-pass/issue-7660.rs | 4 - src/test/run-pass/istr.rs | 2 - src/test/run-pass/new-unicode-escapes.rs | 2 - src/test/run-pass/option-ext.rs | 2 - src/test/run-pass/overloaded-autoderef.rs | 2 +- src/test/run-pass/overloaded-deref.rs | 2 - .../sync-send-iterators-in-libcollections.rs | 15 +- src/test/run-pass/utf8_chars.rs | 2 +- src/test/run-pass/vec-macro-no-std.rs | 6 +- src/test/run-pass/while-prelude-drop.rs | 2 - src/tools/linkchecker/main.rs | 10 +- 97 files changed, 2348 insertions(+), 2517 deletions(-) delete mode 100644 src/doc/unstable-book/src/library-features/collections.md rename src/etc/natvis/{libcollections.natvis => liballoc.natvis} (81%) rename src/{libcollections => liballoc}/benches/btree/map.rs (100%) rename src/{libcollections => liballoc}/benches/btree/mod.rs (100%) rename src/{libcollections => liballoc}/benches/lib.rs (100%) rename src/{libcollections => liballoc}/benches/linked_list.rs (100%) rename src/{libcollections => liballoc}/benches/slice.rs (100%) rename src/{libcollections => liballoc}/benches/str.rs (100%) rename src/{libcollections => liballoc}/benches/string.rs (100%) rename src/{libcollections => liballoc}/benches/vec.rs (100%) rename src/{libcollections => liballoc}/benches/vec_deque.rs (100%) rename src/{libcollections => liballoc}/binary_heap.rs (100%) rename src/{libcollections => liballoc}/borrow.rs (100%) rename src/{libcollections => liballoc}/btree/map.rs (100%) rename src/{libcollections => liballoc}/btree/mod.rs (100%) rename src/{libcollections => liballoc}/btree/node.rs (99%) rename src/{libcollections => liballoc}/btree/search.rs (100%) rename src/{libcollections => liballoc}/btree/set.rs (100%) rename src/{libcollections => liballoc}/fmt.rs (100%) rename src/{libcollections => liballoc}/linked_list.rs (99%) rename src/{libcollections => liballoc}/range.rs (92%) rename src/{libcollections => liballoc}/slice.rs (99%) rename src/{libcollections => liballoc}/string.rs (99%) rename src/{libcollections => liballoc}/tests/binary_heap.rs (100%) rename src/{libcollections => liballoc}/tests/btree/map.rs (100%) rename src/{libcollections => liballoc}/tests/btree/mod.rs (100%) rename src/{libcollections => liballoc}/tests/btree/set.rs (100%) rename src/{libcollections => liballoc}/tests/cow_str.rs (100%) rename src/{libcollections => liballoc}/tests/fmt.rs (100%) rename src/{libcollections => liballoc}/tests/lib.rs (96%) rename src/{libcollections => liballoc}/tests/linked_list.rs (100%) rename src/{libcollections => liballoc}/tests/slice.rs (100%) rename src/{libcollections => liballoc}/tests/str.rs (100%) rename src/{libcollections => liballoc}/tests/string.rs (100%) rename src/{libcollections => liballoc}/tests/vec.rs (100%) rename src/{libcollections => liballoc}/tests/vec_deque.rs (100%) rename src/{libcollections => liballoc}/vec.rs (99%) rename src/{libcollections => liballoc}/vec_deque.rs (99%) delete mode 100644 src/libcollections/Cargo.toml delete mode 100644 src/libcollections/lib.rs delete mode 100644 src/libcollections/macros.rs delete mode 100644 src/libcollections/str.rs diff --git a/src/Cargo.lock b/src/Cargo.lock index efbbe36c981a..43955db07a45 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -36,6 +36,7 @@ name = "alloc" version = "0.0.0" dependencies = [ "core 0.0.0", + "std_unicode 0.0.0", ] [[package]] @@ -250,15 +251,6 @@ dependencies = [ "gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "collections" -version = "0.0.0" -dependencies = [ - "alloc 0.0.0", - "core 0.0.0", - "std_unicode 0.0.0", -] - [[package]] name = "compiler_builtins" version = "0.0.0" @@ -1586,7 +1578,6 @@ dependencies = [ "alloc_jemalloc 0.0.0", "alloc_system 0.0.0", "build_helper 0.1.0", - "collections 0.0.0", "compiler_builtins 0.0.0", "core 0.0.0", "gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 26d44ae7693a..1af60cbd801b 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -376,8 +376,8 @@ pub fn debugger_scripts(build: &Build, install(&build.src.join("src/etc/rust-windbg.cmd"), &sysroot.join("bin"), 0o755); + cp_debugger_script("natvis/liballoc.natvis"); cp_debugger_script("natvis/libcore.natvis"); - cp_debugger_script("natvis/libcollections.natvis"); } else { cp_debugger_script("debugger_pretty_printers_common.py"); @@ -550,7 +550,6 @@ pub fn rust_src(build: &Build) { "src/liballoc_jemalloc", "src/liballoc_system", "src/libbacktrace", - "src/libcollections", "src/libcompiler_builtins", "src/libcore", "src/liblibc", diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index baee1ada508f..fc75b6ff5c3a 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -246,7 +246,7 @@ pub fn std(build: &Build, stage: u32, target: &str) { // for which docs must be built. if !build.config.compiler_docs { cargo.arg("--no-deps"); - for krate in &["alloc", "collections", "core", "std", "std_unicode"] { + for krate in &["alloc", "core", "std", "std_unicode"] { cargo.arg("-p").arg(krate); // Create all crate output directories first to make sure rustdoc uses // relative links. diff --git a/src/doc/unstable-book/src/SUMMARY.md b/src/doc/unstable-book/src/SUMMARY.md index b278b5dbb2ca..2c56ba9ad402 100644 --- a/src/doc/unstable-book/src/SUMMARY.md +++ b/src/doc/unstable-book/src/SUMMARY.md @@ -108,7 +108,6 @@ - [coerce_unsized](library-features/coerce-unsized.md) - [collection_placement](library-features/collection-placement.md) - [collections_range](library-features/collections-range.md) - - [collections](library-features/collections.md) - [command_envs](library-features/command-envs.md) - [compiler_builtins_lib](library-features/compiler-builtins-lib.md) - [compiler_fences](library-features/compiler-fences.md) diff --git a/src/doc/unstable-book/src/library-features/collections.md b/src/doc/unstable-book/src/library-features/collections.md deleted file mode 100644 index 5c937833c9e2..000000000000 --- a/src/doc/unstable-book/src/library-features/collections.md +++ /dev/null @@ -1,5 +0,0 @@ -# `collections` - -This feature is internal to the Rust compiler and is not intended for general use. - ------------------------- diff --git a/src/etc/natvis/libcollections.natvis b/src/etc/natvis/liballoc.natvis similarity index 81% rename from src/etc/natvis/libcollections.natvis rename to src/etc/natvis/liballoc.natvis index e7e93be98695..1f6d17748ab0 100644 --- a/src/etc/natvis/libcollections.natvis +++ b/src/etc/natvis/liballoc.natvis @@ -1,6 +1,6 @@ - + {{ size={len} }} len @@ -11,7 +11,7 @@ - + {{ size={tail <= head ? head - tail : buf.cap - tail + head} }} tail <= head ? head - tail : buf.cap - tail + head @@ -30,18 +30,18 @@ - + {{ size={len} }} len - *(collections::linked_list::Node<$T1> **)&head - *(collections::linked_list::Node<$T1> **)&next + *(alloc::linked_list::Node<$T1> **)&head + *(alloc::linked_list::Node<$T1> **)&next element - + {*(char**)this,[vec.len]} *(char**)this,[vec.len] @@ -53,4 +53,4 @@ - \ No newline at end of file + diff --git a/src/etc/rust-windbg.cmd b/src/etc/rust-windbg.cmd index 4cdd6b986099..b09b37c1db42 100644 --- a/src/etc/rust-windbg.cmd +++ b/src/etc/rust-windbg.cmd @@ -15,4 +15,4 @@ for /f "delims=" %%i in ('rustc --print=sysroot') do set rustc_sysroot=%%i set rust_etc=%rustc_sysroot%\lib\rustlib\etc -windbg -c ".nvload %rust_etc%\libcore.natvis;.nvload %rust_etc%\libcollections.natvis;" %* \ No newline at end of file +windbg -c ".nvload %rust_etc%\liballoc.natvis; .nvload %rust_etc%\libcore.natvis;" %* diff --git a/src/liballoc/Cargo.toml b/src/liballoc/Cargo.toml index 0889ca9fc84d..686e5681d12b 100644 --- a/src/liballoc/Cargo.toml +++ b/src/liballoc/Cargo.toml @@ -9,3 +9,12 @@ path = "lib.rs" [dependencies] core = { path = "../libcore" } +std_unicode = { path = "../libstd_unicode" } + +[[test]] +name = "collectionstests" +path = "../liballoc/tests/lib.rs" + +[[bench]] +name = "collectionsbenches" +path = "../liballoc/benches/lib.rs" diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs index 5ed41f6ffe62..7c51c4b161ca 100644 --- a/src/liballoc/arc.rs +++ b/src/liballoc/arc.rs @@ -1222,11 +1222,12 @@ mod tests { use std::sync::atomic; use std::sync::atomic::Ordering::{Acquire, SeqCst}; use std::thread; - use std::vec::Vec; - use super::{Arc, Weak}; use std::sync::Mutex; use std::convert::From; + use super::{Arc, Weak}; + use vec::Vec; + struct Canary(*mut atomic::AtomicUsize); impl Drop for Canary { diff --git a/src/libcollections/benches/btree/map.rs b/src/liballoc/benches/btree/map.rs similarity index 100% rename from src/libcollections/benches/btree/map.rs rename to src/liballoc/benches/btree/map.rs diff --git a/src/libcollections/benches/btree/mod.rs b/src/liballoc/benches/btree/mod.rs similarity index 100% rename from src/libcollections/benches/btree/mod.rs rename to src/liballoc/benches/btree/mod.rs diff --git a/src/libcollections/benches/lib.rs b/src/liballoc/benches/lib.rs similarity index 100% rename from src/libcollections/benches/lib.rs rename to src/liballoc/benches/lib.rs diff --git a/src/libcollections/benches/linked_list.rs b/src/liballoc/benches/linked_list.rs similarity index 100% rename from src/libcollections/benches/linked_list.rs rename to src/liballoc/benches/linked_list.rs diff --git a/src/libcollections/benches/slice.rs b/src/liballoc/benches/slice.rs similarity index 100% rename from src/libcollections/benches/slice.rs rename to src/liballoc/benches/slice.rs diff --git a/src/libcollections/benches/str.rs b/src/liballoc/benches/str.rs similarity index 100% rename from src/libcollections/benches/str.rs rename to src/liballoc/benches/str.rs diff --git a/src/libcollections/benches/string.rs b/src/liballoc/benches/string.rs similarity index 100% rename from src/libcollections/benches/string.rs rename to src/liballoc/benches/string.rs diff --git a/src/libcollections/benches/vec.rs b/src/liballoc/benches/vec.rs similarity index 100% rename from src/libcollections/benches/vec.rs rename to src/liballoc/benches/vec.rs diff --git a/src/libcollections/benches/vec_deque.rs b/src/liballoc/benches/vec_deque.rs similarity index 100% rename from src/libcollections/benches/vec_deque.rs rename to src/liballoc/benches/vec_deque.rs diff --git a/src/libcollections/binary_heap.rs b/src/liballoc/binary_heap.rs similarity index 100% rename from src/libcollections/binary_heap.rs rename to src/liballoc/binary_heap.rs diff --git a/src/libcollections/borrow.rs b/src/liballoc/borrow.rs similarity index 100% rename from src/libcollections/borrow.rs rename to src/liballoc/borrow.rs diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 8a39be8fae8a..2f867912f582 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -95,6 +95,7 @@ pub const HEAP: ExchangeHeapSingleton = ExchangeHeapSingleton { _force_singleton #[unstable(feature = "box_heap", reason = "may be renamed; uncertain about custom allocator design", issue = "27779")] +#[allow(missing_debug_implementations)] #[derive(Copy, Clone)] pub struct ExchangeHeapSingleton { _force_singleton: (), @@ -129,6 +130,7 @@ pub struct Box(Unique); #[unstable(feature = "placement_in", reason = "placement box design is still being worked out.", issue = "27779")] +#[allow(missing_debug_implementations)] pub struct IntermediateBox { ptr: *mut u8, size: usize, diff --git a/src/libcollections/btree/map.rs b/src/liballoc/btree/map.rs similarity index 100% rename from src/libcollections/btree/map.rs rename to src/liballoc/btree/map.rs diff --git a/src/libcollections/btree/mod.rs b/src/liballoc/btree/mod.rs similarity index 100% rename from src/libcollections/btree/mod.rs rename to src/liballoc/btree/mod.rs diff --git a/src/libcollections/btree/node.rs b/src/liballoc/btree/node.rs similarity index 99% rename from src/libcollections/btree/node.rs rename to src/liballoc/btree/node.rs index 52cdd39d8f96..811174b331e2 100644 --- a/src/libcollections/btree/node.rs +++ b/src/liballoc/btree/node.rs @@ -41,7 +41,6 @@ // - A node of length `n` has `n` keys, `n` values, and (in an internal node) `n + 1` edges. // This implies that even an empty internal node has at least one edge. -use alloc::heap; use core::marker::PhantomData; use core::mem; use core::nonzero::NonZero; @@ -49,6 +48,7 @@ use core::ptr::{self, Unique}; use core::slice; use boxed::Box; +use heap; const B: usize = 6; pub const MIN_LEN: usize = B - 1; diff --git a/src/libcollections/btree/search.rs b/src/liballoc/btree/search.rs similarity index 100% rename from src/libcollections/btree/search.rs rename to src/liballoc/btree/search.rs diff --git a/src/libcollections/btree/set.rs b/src/liballoc/btree/set.rs similarity index 100% rename from src/libcollections/btree/set.rs rename to src/liballoc/btree/set.rs diff --git a/src/libcollections/fmt.rs b/src/liballoc/fmt.rs similarity index 100% rename from src/libcollections/fmt.rs rename to src/liballoc/fmt.rs diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 418a084da678..5252dabc1279 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// Copyright 2014-2017 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -8,18 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! # The Rust core allocation library +//! # The Rust core allocation and collections library //! -//! This is the lowest level library through which allocation in Rust can be -//! performed. +//! This library provides smart pointers and collections for managing +//! heap-allocated values. //! //! This library, like libcore, is not intended for general usage, but rather as //! a building block of other libraries. The types and interfaces in this //! library are reexported through the [standard library](../std/index.html), //! and should not be used through this library. //! -//! Currently, there are four major definitions in this library. -//! //! ## Boxed values //! //! The [`Box`](boxed/index.html) type is a smart pointer type. There can @@ -51,6 +49,12 @@ //! paired with synchronization primitives such as mutexes to allow mutation of //! shared resources. //! +//! ## Collections +//! +//! Implementations of the most common general purpose data structures are +//! defined in this library. They are reexported through the +//! [standard collections library](../std/collections/index.html). +//! //! ## Heap interfaces //! //! The [`heap`](heap/index.html) module defines the low-level interface to the @@ -71,8 +75,20 @@ #![no_std] #![needs_allocator] #![deny(warnings)] +#![deny(missing_debug_implementations)] +#![cfg_attr(test, allow(deprecated))] // rand +#![cfg_attr(test, feature(placement_in))] +#![cfg_attr(not(test), feature(char_escape_debug))] +#![cfg_attr(not(test), feature(core_float))] +#![cfg_attr(not(test), feature(exact_size_is_empty))] +#![cfg_attr(not(test), feature(slice_rotate))] +#![cfg_attr(not(test), feature(sort_unstable))] +#![cfg_attr(not(test), feature(str_checked_slicing))] +#![cfg_attr(test, feature(rand, test))] #![feature(allocator)] +#![feature(allow_internal_unstable)] +#![feature(box_patterns)] #![feature(box_syntax)] #![feature(cfg_target_has_atomic)] #![feature(coerce_unsized)] @@ -80,16 +96,33 @@ #![feature(core_intrinsics)] #![feature(custom_attribute)] #![feature(dropck_eyepatch)] -#![cfg_attr(not(test), feature(exact_size_is_empty))] +#![feature(exact_size_is_empty)] +#![feature(fmt_internals)] #![feature(fundamental)] +#![feature(fused)] #![feature(generic_param_attrs)] +#![feature(i128_type)] +#![feature(inclusive_range)] #![feature(lang_items)] +#![feature(manually_drop)] #![feature(needs_allocator)] +#![feature(nonzero)] +#![feature(offset_to)] #![feature(optin_builtin_traits)] +#![feature(pattern)] #![feature(placement_in_syntax)] +#![feature(placement_new_protocol)] #![feature(shared)] +#![feature(slice_get_slice)] +#![feature(slice_patterns)] +#![feature(slice_rsplit)] +#![feature(specialization)] #![feature(staged_api)] +#![feature(str_internals)] +#![feature(str_mut_extras)] +#![feature(trusted_len)] #![feature(unboxed_closures)] +#![feature(unicode)] #![feature(unique)] #![feature(unsize)] @@ -101,6 +134,10 @@ #[cfg(test)] #[macro_use] extern crate std; +#[cfg(test)] +extern crate test; + +extern crate std_unicode; // Module with internal macros used by other modules (needs to be included before other modules). #[macro_use] @@ -120,7 +157,7 @@ pub mod heap; pub mod boxed; #[cfg(test)] mod boxed { - pub use std::boxed::{Box, HEAP}; + pub use std::boxed::{Box, IntermediateBox, HEAP}; } #[cfg(test)] mod boxed_test; @@ -128,8 +165,111 @@ mod boxed_test; pub mod arc; pub mod rc; pub mod raw_vec; -#[unstable(feature = "str_box_extras", issue = "41119")] -pub mod str; pub mod oom; +// collections modules +pub mod binary_heap; +mod btree; +pub mod borrow; +pub mod fmt; +pub mod linked_list; +pub mod range; +pub mod slice; +pub mod str; +pub mod string; +pub mod vec; +pub mod vec_deque; + +#[stable(feature = "rust1", since = "1.0.0")] +pub mod btree_map { + //! A map based on a B-Tree. + #[stable(feature = "rust1", since = "1.0.0")] + pub use btree::map::*; +} + +#[stable(feature = "rust1", since = "1.0.0")] +pub mod btree_set { + //! A set based on a B-Tree. + #[stable(feature = "rust1", since = "1.0.0")] + pub use btree::set::*; +} + +#[cfg(not(test))] +mod std { + pub use core::ops; // RangeFull +} + +/// An endpoint of a range of keys. +/// +/// # Examples +/// +/// `Bound`s are range endpoints: +/// +/// ``` +/// #![feature(collections_range)] +/// +/// use std::collections::range::RangeArgument; +/// use std::collections::Bound::*; +/// +/// assert_eq!((..100).start(), Unbounded); +/// assert_eq!((1..12).start(), Included(&1)); +/// assert_eq!((1..12).end(), Excluded(&12)); +/// ``` +/// +/// Using a tuple of `Bound`s as an argument to [`BTreeMap::range`]. +/// Note that in most cases, it's better to use range syntax (`1..5`) instead. +/// +/// ``` +/// use std::collections::BTreeMap; +/// use std::collections::Bound::{Excluded, Included, Unbounded}; +/// +/// let mut map = BTreeMap::new(); +/// map.insert(3, "a"); +/// map.insert(5, "b"); +/// map.insert(8, "c"); +/// +/// for (key, value) in map.range((Excluded(3), Included(8))) { +/// println!("{}: {}", key, value); +/// } +/// +/// assert_eq!(Some((&3, &"a")), map.range((Unbounded, Included(5))).next()); +/// ``` +/// +/// [`BTreeMap::range`]: btree_map/struct.BTreeMap.html#method.range +#[stable(feature = "collections_bound", since = "1.17.0")] +#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] +pub enum Bound { + /// An inclusive bound. + #[stable(feature = "collections_bound", since = "1.17.0")] + Included(T), + /// An exclusive bound. + #[stable(feature = "collections_bound", since = "1.17.0")] + Excluded(T), + /// An infinite endpoint. Indicates that there is no bound in this direction. + #[stable(feature = "collections_bound", since = "1.17.0")] + Unbounded, +} + +/// An intermediate trait for specialization of `Extend`. +#[doc(hidden)] +trait SpecExtend { + /// Extends `self` with the contents of the given iterator. + fn spec_extend(&mut self, iter: I); +} + pub use oom::oom; + +#[doc(no_inline)] +pub use binary_heap::BinaryHeap; +#[doc(no_inline)] +pub use btree_map::BTreeMap; +#[doc(no_inline)] +pub use btree_set::BTreeSet; +#[doc(no_inline)] +pub use linked_list::LinkedList; +#[doc(no_inline)] +pub use vec_deque::VecDeque; +#[doc(no_inline)] +pub use string::String; +#[doc(no_inline)] +pub use vec::Vec; diff --git a/src/libcollections/linked_list.rs b/src/liballoc/linked_list.rs similarity index 99% rename from src/libcollections/linked_list.rs rename to src/liballoc/linked_list.rs index ae258083546f..e8973b7d2853 100644 --- a/src/libcollections/linked_list.rs +++ b/src/liballoc/linked_list.rs @@ -22,7 +22,6 @@ #![stable(feature = "rust1", since = "1.0.0")] -use alloc::boxed::{Box, IntermediateBox}; use core::cmp::Ordering; use core::fmt; use core::hash::{Hasher, Hash}; @@ -32,6 +31,7 @@ use core::mem; use core::ops::{BoxPlace, InPlace, Place, Placer}; use core::ptr::{self, Shared}; +use boxed::{Box, IntermediateBox}; use super::SpecExtend; /// A doubly-linked list with owned nodes. diff --git a/src/liballoc/macros.rs b/src/liballoc/macros.rs index 7da91c87e967..763f04fcd0dc 100644 --- a/src/liballoc/macros.rs +++ b/src/liballoc/macros.rs @@ -8,6 +8,89 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +/// Creates a `Vec` containing the arguments. +/// +/// `vec!` allows `Vec`s to be defined with the same syntax as array expressions. +/// There are two forms of this macro: +/// +/// - Create a `Vec` containing a given list of elements: +/// +/// ``` +/// let v = vec![1, 2, 3]; +/// assert_eq!(v[0], 1); +/// assert_eq!(v[1], 2); +/// assert_eq!(v[2], 3); +/// ``` +/// +/// - Create a `Vec` from a given element and size: +/// +/// ``` +/// let v = vec![1; 3]; +/// assert_eq!(v, [1, 1, 1]); +/// ``` +/// +/// Note that unlike array expressions this syntax supports all elements +/// which implement `Clone` and the number of elements doesn't have to be +/// a constant. +/// +/// This will use `clone()` to duplicate an expression, so one should be careful +/// using this with types having a nonstandard `Clone` implementation. For +/// example, `vec![Rc::new(1); 5]` will create a vector of five references +/// to the same boxed integer value, not five references pointing to independently +/// boxed integers. +#[cfg(not(test))] +#[macro_export] +#[stable(feature = "rust1", since = "1.0.0")] +#[allow_internal_unstable] +macro_rules! vec { + ($elem:expr; $n:expr) => ( + $crate::vec::from_elem($elem, $n) + ); + ($($x:expr),*) => ( + <[_]>::into_vec(box [$($x),*]) + ); + ($($x:expr,)*) => (vec![$($x),*]) +} + +// HACK(japaric): with cfg(test) the inherent `[T]::into_vec` method, which is +// required for this macro definition, is not available. Instead use the +// `slice::into_vec` function which is only available with cfg(test) +// NB see the slice::hack module in slice.rs for more information +#[cfg(test)] +macro_rules! vec { + ($elem:expr; $n:expr) => ( + $crate::vec::from_elem($elem, $n) + ); + ($($x:expr),*) => ( + $crate::slice::into_vec(box [$($x),*]) + ); + ($($x:expr,)*) => (vec![$($x),*]) +} + +/// Use the syntax described in `std::fmt` to create a value of type `String`. +/// See [`std::fmt`][fmt] for more information. +/// +/// [fmt]: ../std/fmt/index.html +/// +/// # Panics +/// +/// `format!` panics if a formatting trait implementation returns an error. +/// This indicates an incorrect implementation +/// since `fmt::Write for String` never returns an error itself. +/// +/// # Examples +/// +/// ``` +/// format!("test"); +/// format!("hello {}", "world!"); +/// format!("x = {}, y = {y}", 10, y = 30); +/// ``` +#[macro_export] +#[stable(feature = "rust1", since = "1.0.0")] +macro_rules! format { + ($($arg:tt)*) => ($crate::fmt::format(format_args!($($arg)*))) +} + // Private macro to get the offset of a struct field in bytes from the address of the struct. macro_rules! offset_of { ($container:path, $field:ident) => {{ diff --git a/src/libcollections/range.rs b/src/liballoc/range.rs similarity index 92% rename from src/libcollections/range.rs rename to src/liballoc/range.rs index bc8566e8cbeb..f862da0d61e0 100644 --- a/src/libcollections/range.rs +++ b/src/liballoc/range.rs @@ -27,14 +27,14 @@ pub trait RangeArgument { /// # Examples /// /// ``` - /// #![feature(collections)] + /// #![feature(alloc)] /// #![feature(collections_range)] /// - /// extern crate collections; + /// extern crate alloc; /// /// # fn main() { - /// use collections::range::RangeArgument; - /// use collections::Bound::*; + /// use alloc::range::RangeArgument; + /// use alloc::Bound::*; /// /// assert_eq!((..10).start(), Unbounded); /// assert_eq!((3..10).start(), Included(&3)); @@ -49,14 +49,14 @@ pub trait RangeArgument { /// # Examples /// /// ``` - /// #![feature(collections)] + /// #![feature(alloc)] /// #![feature(collections_range)] /// - /// extern crate collections; + /// extern crate alloc; /// /// # fn main() { - /// use collections::range::RangeArgument; - /// use collections::Bound::*; + /// use alloc::range::RangeArgument; + /// use alloc::Bound::*; /// /// assert_eq!((3..).end(), Unbounded); /// assert_eq!((3..10).end(), Excluded(&10)); diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs index 7edf07944ec5..34ab0a19d4e0 100644 --- a/src/liballoc/raw_vec.rs +++ b/src/liballoc/raw_vec.rs @@ -44,6 +44,7 @@ use core::cmp; /// `shrink_to_fit`, and `from_box` will actually set RawVec's private capacity /// field. This allows zero-sized types to not be special-cased by consumers of /// this type. +#[allow(missing_debug_implementations)] pub struct RawVec { ptr: Unique, cap: usize, diff --git a/src/libcollections/slice.rs b/src/liballoc/slice.rs similarity index 99% rename from src/libcollections/slice.rs rename to src/liballoc/slice.rs index 97d6687c79b5..88876999d765 100644 --- a/src/libcollections/slice.rs +++ b/src/liballoc/slice.rs @@ -97,7 +97,6 @@ // It's cleaner to just turn off the unused_imports warning than to fix them. #![cfg_attr(test, allow(unused_imports, dead_code))] -use alloc::boxed::Box; use core::cmp::Ordering::{self, Less}; use core::mem::size_of; use core::mem; @@ -105,6 +104,7 @@ use core::ptr; use core::slice as core_slice; use borrow::{Borrow, BorrowMut, ToOwned}; +use boxed::Box; use vec::Vec; #[stable(feature = "rust1", since = "1.0.0")] @@ -141,7 +141,7 @@ pub use self::hack::to_vec; // `core::slice::SliceExt` - we need to supply these functions for the // `test_permutations` test mod hack { - use alloc::boxed::Box; + use boxed::Box; use core::mem; #[cfg(test)] diff --git a/src/liballoc/str.rs b/src/liballoc/str.rs index c87db16a0f41..f56288c30132 100644 --- a/src/liballoc/str.rs +++ b/src/liballoc/str.rs @@ -8,11 +8,1992 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Methods for dealing with boxed strings. -use core::mem; +//! Unicode string slices. +//! +//! The `&str` type is one of the two main string types, the other being `String`. +//! Unlike its `String` counterpart, its contents are borrowed. +//! +//! # Basic Usage +//! +//! A basic string declaration of `&str` type: +//! +//! ``` +//! let hello_world = "Hello, World!"; +//! ``` +//! +//! Here we have declared a string literal, also known as a string slice. +//! String literals have a static lifetime, which means the string `hello_world` +//! is guaranteed to be valid for the duration of the entire program. +//! We can explicitly specify `hello_world`'s lifetime as well: +//! +//! ``` +//! let hello_world: &'static str = "Hello, world!"; +//! ``` +//! +//! *[See also the `str` primitive type](../../std/primitive.str.html).* +#![stable(feature = "rust1", since = "1.0.0")] + +// Many of the usings in this module are only used in the test configuration. +// It's cleaner to just turn off the unused_imports warning than to fix them. +#![allow(unused_imports)] + +use core::fmt; +use core::str as core_str; +use core::str::pattern::Pattern; +use core::str::pattern::{Searcher, ReverseSearcher, DoubleEndedSearcher}; +use core::mem; +use core::iter::FusedIterator; +use std_unicode::str::{UnicodeStr, Utf16Encoder}; + +use vec_deque::VecDeque; +use borrow::{Borrow, ToOwned}; +use string::String; +use std_unicode; +use vec::Vec; +use slice::{SliceConcatExt, SliceIndex}; use boxed::Box; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::str::{FromStr, Utf8Error}; +#[allow(deprecated)] +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::str::{Lines, LinesAny}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::str::{Split, RSplit}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::str::{SplitN, RSplitN}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::str::{SplitTerminator, RSplitTerminator}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::str::{Matches, RMatches}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::str::{MatchIndices, RMatchIndices}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::str::{from_utf8, from_utf8_mut, Chars, CharIndices, Bytes}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::str::{from_utf8_unchecked, from_utf8_unchecked_mut, ParseBoolError}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use std_unicode::str::SplitWhitespace; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::str::pattern; + + +#[unstable(feature = "slice_concat_ext", + reason = "trait should not have to exist", + issue = "27747")] +impl> SliceConcatExt for [S] { + type Output = String; + + fn concat(&self) -> String { + if self.is_empty() { + return String::new(); + } + + // `len` calculation may overflow but push_str will check boundaries + let len = self.iter().map(|s| s.borrow().len()).sum(); + let mut result = String::with_capacity(len); + + for s in self { + result.push_str(s.borrow()) + } + + result + } + + fn join(&self, sep: &str) -> String { + if self.is_empty() { + return String::new(); + } + + // concat is faster + if sep.is_empty() { + return self.concat(); + } + + // this is wrong without the guarantee that `self` is non-empty + // `len` calculation may overflow but push_str but will check boundaries + let len = sep.len() * (self.len() - 1) + + self.iter().map(|s| s.borrow().len()).sum::(); + let mut result = String::with_capacity(len); + let mut first = true; + + for s in self { + if first { + first = false; + } else { + result.push_str(sep); + } + result.push_str(s.borrow()); + } + result + } + + fn connect(&self, sep: &str) -> String { + self.join(sep) + } +} + +/// An iterator of [`u16`] over the string encoded as UTF-16. +/// +/// [`u16`]: ../../std/primitive.u16.html +/// +/// This struct is created by the [`encode_utf16`] method on [`str`]. +/// See its documentation for more. +/// +/// [`encode_utf16`]: ../../std/primitive.str.html#method.encode_utf16 +/// [`str`]: ../../std/primitive.str.html +#[derive(Clone)] +#[stable(feature = "encode_utf16", since = "1.8.0")] +pub struct EncodeUtf16<'a> { + encoder: Utf16Encoder>, +} + +#[stable(feature = "collection_debug", since = "1.17.0")] +impl<'a> fmt::Debug for EncodeUtf16<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("EncodeUtf16 { .. }") + } +} + +#[stable(feature = "encode_utf16", since = "1.8.0")] +impl<'a> Iterator for EncodeUtf16<'a> { + type Item = u16; + + #[inline] + fn next(&mut self) -> Option { + self.encoder.next() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.encoder.size_hint() + } +} + +#[unstable(feature = "fused", issue = "35602")] +impl<'a> FusedIterator for EncodeUtf16<'a> {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Borrow for String { + #[inline] + fn borrow(&self) -> &str { + &self[..] + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ToOwned for str { + type Owned = String; + fn to_owned(&self) -> String { + unsafe { String::from_utf8_unchecked(self.as_bytes().to_owned()) } + } + + fn clone_into(&self, target: &mut String) { + let mut b = mem::replace(target, String::new()).into_bytes(); + self.as_bytes().clone_into(&mut b); + *target = unsafe { String::from_utf8_unchecked(b) } + } +} + +/// Methods for string slices. +#[lang = "str"] +#[cfg(not(test))] +impl str { + /// Returns the length of `self`. + /// + /// This length is in bytes, not [`char`]s or graphemes. In other words, + /// it may not be what a human considers the length of the string. + /// + /// [`char`]: primitive.char.html + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let len = "foo".len(); + /// assert_eq!(3, len); + /// + /// let len = "ƒoo".len(); // fancy f! + /// assert_eq!(4, len); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn len(&self) -> usize { + core_str::StrExt::len(self) + } + + /// Returns `true` if `self` has a length of zero bytes. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let s = ""; + /// assert!(s.is_empty()); + /// + /// let s = "not empty"; + /// assert!(!s.is_empty()); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn is_empty(&self) -> bool { + core_str::StrExt::is_empty(self) + } + + /// Checks that `index`-th byte lies at the start and/or end of a + /// UTF-8 code point sequence. + /// + /// The start and end of the string (when `index == self.len()`) are + /// considered to be + /// boundaries. + /// + /// Returns `false` if `index` is greater than `self.len()`. + /// + /// # Examples + /// + /// ``` + /// let s = "Löwe 老虎 Léopard"; + /// assert!(s.is_char_boundary(0)); + /// // start of `老` + /// assert!(s.is_char_boundary(6)); + /// assert!(s.is_char_boundary(s.len())); + /// + /// // second byte of `ö` + /// assert!(!s.is_char_boundary(2)); + /// + /// // third byte of `老` + /// assert!(!s.is_char_boundary(8)); + /// ``` + #[stable(feature = "is_char_boundary", since = "1.9.0")] + #[inline] + pub fn is_char_boundary(&self, index: usize) -> bool { + core_str::StrExt::is_char_boundary(self, index) + } + + /// Converts a string slice to a byte slice. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let bytes = "bors".as_bytes(); + /// assert_eq!(b"bors", bytes); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline(always)] + pub fn as_bytes(&self) -> &[u8] { + core_str::StrExt::as_bytes(self) + } + + /// Converts a mutable string slice to a mutable byte slice. + #[unstable(feature = "str_mut_extras", issue = "41119")] + #[inline(always)] + pub unsafe fn as_bytes_mut(&mut self) -> &mut [u8] { + core_str::StrExt::as_bytes_mut(self) + } + + /// Converts a string slice to a raw pointer. + /// + /// As string slices are a slice of bytes, the raw pointer points to a + /// [`u8`]. This pointer will be pointing to the first byte of the string + /// slice. + /// + /// [`u8`]: primitive.u8.html + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let s = "Hello"; + /// let ptr = s.as_ptr(); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn as_ptr(&self) -> *const u8 { + core_str::StrExt::as_ptr(self) + } + + /// Returns a subslice of `str`. + /// + /// This is the non-panicking alternative to indexing the `str`. Returns + /// [`None`] whenever equivalent indexing operation would panic. + /// + /// [`None`]: option/enum.Option.html#variant.None + /// + /// # Examples + /// + /// ``` + /// # #![feature(str_checked_slicing)] + /// let v = "🗻∈🌏"; + /// assert_eq!(Some("🗻"), v.get(0..4)); + /// assert!(v.get(1..).is_none()); + /// assert!(v.get(..8).is_none()); + /// assert!(v.get(..42).is_none()); + /// ``` + #[unstable(feature = "str_checked_slicing", issue = "39932")] + #[inline] + pub fn get>(&self, i: I) -> Option<&I::Output> { + core_str::StrExt::get(self, i) + } + + /// Returns a mutable subslice of `str`. + /// + /// This is the non-panicking alternative to indexing the `str`. Returns + /// [`None`] whenever equivalent indexing operation would panic. + /// + /// [`None`]: option/enum.Option.html#variant.None + /// + /// # Examples + /// + /// ``` + /// # #![feature(str_checked_slicing)] + /// let mut v = String::from("🗻∈🌏"); + /// assert_eq!(Some("🗻"), v.get_mut(0..4).map(|v| &*v)); + /// assert!(v.get_mut(1..).is_none()); + /// assert!(v.get_mut(..8).is_none()); + /// assert!(v.get_mut(..42).is_none()); + /// ``` + #[unstable(feature = "str_checked_slicing", issue = "39932")] + #[inline] + pub fn get_mut>(&mut self, i: I) -> Option<&mut I::Output> { + core_str::StrExt::get_mut(self, i) + } + + /// Returns a unchecked subslice of `str`. + /// + /// This is the unchecked alternative to indexing the `str`. + /// + /// # Safety + /// + /// Callers of this function are responsible that these preconditions are + /// satisfied: + /// + /// * The starting index must come before the ending index; + /// * Indexes must be within bounds of the original slice; + /// * Indexes must lie on UTF-8 sequence boundaries. + /// + /// Failing that, the returned string slice may reference invalid memory or + /// violate the invariants communicated by the `str` type. + /// + /// # Examples + /// + /// ``` + /// # #![feature(str_checked_slicing)] + /// let v = "🗻∈🌏"; + /// unsafe { + /// assert_eq!("🗻", v.get_unchecked(0..4)); + /// assert_eq!("∈", v.get_unchecked(4..7)); + /// assert_eq!("🌏", v.get_unchecked(7..11)); + /// } + /// ``` + #[unstable(feature = "str_checked_slicing", issue = "39932")] + #[inline] + pub unsafe fn get_unchecked>(&self, i: I) -> &I::Output { + core_str::StrExt::get_unchecked(self, i) + } + + /// Returns a mutable, unchecked subslice of `str`. + /// + /// This is the unchecked alternative to indexing the `str`. + /// + /// # Safety + /// + /// Callers of this function are responsible that these preconditions are + /// satisfied: + /// + /// * The starting index must come before the ending index; + /// * Indexes must be within bounds of the original slice; + /// * Indexes must lie on UTF-8 sequence boundaries. + /// + /// Failing that, the returned string slice may reference invalid memory or + /// violate the invariants communicated by the `str` type. + /// + /// # Examples + /// + /// ``` + /// # #![feature(str_checked_slicing)] + /// let mut v = String::from("🗻∈🌏"); + /// unsafe { + /// assert_eq!("🗻", v.get_unchecked_mut(0..4)); + /// assert_eq!("∈", v.get_unchecked_mut(4..7)); + /// assert_eq!("🌏", v.get_unchecked_mut(7..11)); + /// } + /// ``` + #[unstable(feature = "str_checked_slicing", issue = "39932")] + #[inline] + pub unsafe fn get_unchecked_mut>(&mut self, i: I) -> &mut I::Output { + core_str::StrExt::get_unchecked_mut(self, i) + } + + /// Creates a string slice from another string slice, bypassing safety + /// checks. + /// + /// This is generally not recommended, use with caution! For a safe + /// alternative see [`str`] and [`Index`]. + /// + /// [`str`]: primitive.str.html + /// [`Index`]: ops/trait.Index.html + /// + /// This new slice goes from `begin` to `end`, including `begin` but + /// excluding `end`. + /// + /// To get a mutable string slice instead, see the + /// [`slice_mut_unchecked`] method. + /// + /// [`slice_mut_unchecked`]: #method.slice_mut_unchecked + /// + /// # Safety + /// + /// Callers of this function are responsible that three preconditions are + /// satisfied: + /// + /// * `begin` must come before `end`. + /// * `begin` and `end` must be byte positions within the string slice. + /// * `begin` and `end` must lie on UTF-8 sequence boundaries. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let s = "Löwe 老虎 Léopard"; + /// + /// unsafe { + /// assert_eq!("Löwe 老虎 Léopard", s.slice_unchecked(0, 21)); + /// } + /// + /// let s = "Hello, world!"; + /// + /// unsafe { + /// assert_eq!("world", s.slice_unchecked(7, 12)); + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub unsafe fn slice_unchecked(&self, begin: usize, end: usize) -> &str { + core_str::StrExt::slice_unchecked(self, begin, end) + } + + /// Creates a string slice from another string slice, bypassing safety + /// checks. + /// This is generally not recommended, use with caution! For a safe + /// alternative see [`str`] and [`IndexMut`]. + /// + /// [`str`]: primitive.str.html + /// [`IndexMut`]: ops/trait.IndexMut.html + /// + /// This new slice goes from `begin` to `end`, including `begin` but + /// excluding `end`. + /// + /// To get an immutable string slice instead, see the + /// [`slice_unchecked`] method. + /// + /// [`slice_unchecked`]: #method.slice_unchecked + /// + /// # Safety + /// + /// Callers of this function are responsible that three preconditions are + /// satisfied: + /// + /// * `begin` must come before `end`. + /// * `begin` and `end` must be byte positions within the string slice. + /// * `begin` and `end` must lie on UTF-8 sequence boundaries. + #[stable(feature = "str_slice_mut", since = "1.5.0")] + #[inline] + pub unsafe fn slice_mut_unchecked(&mut self, begin: usize, end: usize) -> &mut str { + core_str::StrExt::slice_mut_unchecked(self, begin, end) + } + + /// Divide one string slice into two at an index. + /// + /// The argument, `mid`, should be a byte offset from the start of the + /// string. It must also be on the boundary of a UTF-8 code point. + /// + /// The two slices returned go from the start of the string slice to `mid`, + /// and from `mid` to the end of the string slice. + /// + /// To get mutable string slices instead, see the [`split_at_mut`] + /// method. + /// + /// [`split_at_mut`]: #method.split_at_mut + /// + /// # Panics + /// + /// Panics if `mid` is not on a UTF-8 code point boundary, or if it is + /// beyond the last code point of the string slice. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let s = "Per Martin-Löf"; + /// + /// let (first, last) = s.split_at(3); + /// + /// assert_eq!("Per", first); + /// assert_eq!(" Martin-Löf", last); + /// ``` + #[inline] + #[stable(feature = "str_split_at", since = "1.4.0")] + pub fn split_at(&self, mid: usize) -> (&str, &str) { + core_str::StrExt::split_at(self, mid) + } + + /// Divide one mutable string slice into two at an index. + /// + /// The argument, `mid`, should be a byte offset from the start of the + /// string. It must also be on the boundary of a UTF-8 code point. + /// + /// The two slices returned go from the start of the string slice to `mid`, + /// and from `mid` to the end of the string slice. + /// + /// To get immutable string slices instead, see the [`split_at`] method. + /// + /// [`split_at`]: #method.split_at + /// + /// # Panics + /// + /// Panics if `mid` is not on a UTF-8 code point boundary, or if it is + /// beyond the last code point of the string slice. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let mut s = "Per Martin-Löf".to_string(); + /// + /// let (first, last) = s.split_at_mut(3); + /// + /// assert_eq!("Per", first); + /// assert_eq!(" Martin-Löf", last); + /// ``` + #[inline] + #[stable(feature = "str_split_at", since = "1.4.0")] + pub fn split_at_mut(&mut self, mid: usize) -> (&mut str, &mut str) { + core_str::StrExt::split_at_mut(self, mid) + } + + /// Returns an iterator over the [`char`]s of a string slice. + /// + /// As a string slice consists of valid UTF-8, we can iterate through a + /// string slice by [`char`]. This method returns such an iterator. + /// + /// It's important to remember that [`char`] represents a Unicode Scalar + /// Value, and may not match your idea of what a 'character' is. Iteration + /// over grapheme clusters may be what you actually want. + /// + /// [`char`]: primitive.char.html + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let word = "goodbye"; + /// + /// let count = word.chars().count(); + /// assert_eq!(7, count); + /// + /// let mut chars = word.chars(); + /// + /// assert_eq!(Some('g'), chars.next()); + /// assert_eq!(Some('o'), chars.next()); + /// assert_eq!(Some('o'), chars.next()); + /// assert_eq!(Some('d'), chars.next()); + /// assert_eq!(Some('b'), chars.next()); + /// assert_eq!(Some('y'), chars.next()); + /// assert_eq!(Some('e'), chars.next()); + /// + /// assert_eq!(None, chars.next()); + /// ``` + /// + /// Remember, [`char`]s may not match your human intuition about characters: + /// + /// ``` + /// let y = "y̆"; + /// + /// let mut chars = y.chars(); + /// + /// assert_eq!(Some('y'), chars.next()); // not 'y̆' + /// assert_eq!(Some('\u{0306}'), chars.next()); + /// + /// assert_eq!(None, chars.next()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn chars(&self) -> Chars { + core_str::StrExt::chars(self) + } + /// Returns an iterator over the [`char`]s of a string slice, and their + /// positions. + /// + /// As a string slice consists of valid UTF-8, we can iterate through a + /// string slice by [`char`]. This method returns an iterator of both + /// these [`char`]s, as well as their byte positions. + /// + /// The iterator yields tuples. The position is first, the [`char`] is + /// second. + /// + /// [`char`]: primitive.char.html + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let word = "goodbye"; + /// + /// let count = word.char_indices().count(); + /// assert_eq!(7, count); + /// + /// let mut char_indices = word.char_indices(); + /// + /// assert_eq!(Some((0, 'g')), char_indices.next()); + /// assert_eq!(Some((1, 'o')), char_indices.next()); + /// assert_eq!(Some((2, 'o')), char_indices.next()); + /// assert_eq!(Some((3, 'd')), char_indices.next()); + /// assert_eq!(Some((4, 'b')), char_indices.next()); + /// assert_eq!(Some((5, 'y')), char_indices.next()); + /// assert_eq!(Some((6, 'e')), char_indices.next()); + /// + /// assert_eq!(None, char_indices.next()); + /// ``` + /// + /// Remember, [`char`]s may not match your human intuition about characters: + /// + /// ``` + /// let y = "y̆"; + /// + /// let mut char_indices = y.char_indices(); + /// + /// assert_eq!(Some((0, 'y')), char_indices.next()); // not (0, 'y̆') + /// assert_eq!(Some((1, '\u{0306}')), char_indices.next()); + /// + /// assert_eq!(None, char_indices.next()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn char_indices(&self) -> CharIndices { + core_str::StrExt::char_indices(self) + } + + /// An iterator over the bytes of a string slice. + /// + /// As a string slice consists of a sequence of bytes, we can iterate + /// through a string slice by byte. This method returns such an iterator. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let mut bytes = "bors".bytes(); + /// + /// assert_eq!(Some(b'b'), bytes.next()); + /// assert_eq!(Some(b'o'), bytes.next()); + /// assert_eq!(Some(b'r'), bytes.next()); + /// assert_eq!(Some(b's'), bytes.next()); + /// + /// assert_eq!(None, bytes.next()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn bytes(&self) -> Bytes { + core_str::StrExt::bytes(self) + } + + /// Split a string slice by whitespace. + /// + /// The iterator returned will return string slices that are sub-slices of + /// the original string slice, separated by any amount of whitespace. + /// + /// 'Whitespace' is defined according to the terms of the Unicode Derived + /// Core Property `White_Space`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let mut iter = "A few words".split_whitespace(); + /// + /// assert_eq!(Some("A"), iter.next()); + /// assert_eq!(Some("few"), iter.next()); + /// assert_eq!(Some("words"), iter.next()); + /// + /// assert_eq!(None, iter.next()); + /// ``` + /// + /// All kinds of whitespace are considered: + /// + /// ``` + /// let mut iter = " Mary had\ta\u{2009}little \n\t lamb".split_whitespace(); + /// assert_eq!(Some("Mary"), iter.next()); + /// assert_eq!(Some("had"), iter.next()); + /// assert_eq!(Some("a"), iter.next()); + /// assert_eq!(Some("little"), iter.next()); + /// assert_eq!(Some("lamb"), iter.next()); + /// + /// assert_eq!(None, iter.next()); + /// ``` + #[stable(feature = "split_whitespace", since = "1.1.0")] + #[inline] + pub fn split_whitespace(&self) -> SplitWhitespace { + UnicodeStr::split_whitespace(self) + } + + /// An iterator over the lines of a string, as string slices. + /// + /// Lines are ended with either a newline (`\n`) or a carriage return with + /// a line feed (`\r\n`). + /// + /// The final line ending is optional. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let text = "foo\r\nbar\n\nbaz\n"; + /// let mut lines = text.lines(); + /// + /// assert_eq!(Some("foo"), lines.next()); + /// assert_eq!(Some("bar"), lines.next()); + /// assert_eq!(Some(""), lines.next()); + /// assert_eq!(Some("baz"), lines.next()); + /// + /// assert_eq!(None, lines.next()); + /// ``` + /// + /// The final line ending isn't required: + /// + /// ``` + /// let text = "foo\nbar\n\r\nbaz"; + /// let mut lines = text.lines(); + /// + /// assert_eq!(Some("foo"), lines.next()); + /// assert_eq!(Some("bar"), lines.next()); + /// assert_eq!(Some(""), lines.next()); + /// assert_eq!(Some("baz"), lines.next()); + /// + /// assert_eq!(None, lines.next()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn lines(&self) -> Lines { + core_str::StrExt::lines(self) + } + + /// An iterator over the lines of a string. + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_deprecated(since = "1.4.0", reason = "use lines() instead now")] + #[inline] + #[allow(deprecated)] + pub fn lines_any(&self) -> LinesAny { + core_str::StrExt::lines_any(self) + } + + /// Returns an iterator of `u16` over the string encoded as UTF-16. + #[stable(feature = "encode_utf16", since = "1.8.0")] + pub fn encode_utf16(&self) -> EncodeUtf16 { + EncodeUtf16 { encoder: Utf16Encoder::new(self[..].chars()) } + } + + /// Returns `true` if the given pattern matches a sub-slice of + /// this string slice. + /// + /// Returns `false` if it does not. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let bananas = "bananas"; + /// + /// assert!(bananas.contains("nana")); + /// assert!(!bananas.contains("apples")); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn contains<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool { + core_str::StrExt::contains(self, pat) + } + + /// Returns `true` if the given pattern matches a prefix of this + /// string slice. + /// + /// Returns `false` if it does not. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let bananas = "bananas"; + /// + /// assert!(bananas.starts_with("bana")); + /// assert!(!bananas.starts_with("nana")); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn starts_with<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool { + core_str::StrExt::starts_with(self, pat) + } + + /// Returns `true` if the given pattern matches a suffix of this + /// string slice. + /// + /// Returns `false` if it does not. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let bananas = "bananas"; + /// + /// assert!(bananas.ends_with("anas")); + /// assert!(!bananas.ends_with("nana")); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn ends_with<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool + where P::Searcher: ReverseSearcher<'a> + { + core_str::StrExt::ends_with(self, pat) + } + + /// Returns the byte index of the first character of this string slice that + /// matches the pattern. + /// + /// Returns [`None`] if the pattern doesn't match. + /// + /// The pattern can be a `&str`, [`char`], or a closure that determines if + /// a character matches. + /// + /// [`char`]: primitive.char.html + /// [`None`]: option/enum.Option.html#variant.None + /// + /// # Examples + /// + /// Simple patterns: + /// + /// ``` + /// let s = "Löwe 老虎 Léopard"; + /// + /// assert_eq!(s.find('L'), Some(0)); + /// assert_eq!(s.find('é'), Some(14)); + /// assert_eq!(s.find("Léopard"), Some(13)); + /// ``` + /// + /// More complex patterns with closures: + /// + /// ``` + /// let s = "Löwe 老虎 Léopard"; + /// + /// assert_eq!(s.find(char::is_whitespace), Some(5)); + /// assert_eq!(s.find(char::is_lowercase), Some(1)); + /// ``` + /// + /// Not finding the pattern: + /// + /// ``` + /// let s = "Löwe 老虎 Léopard"; + /// let x: &[_] = &['1', '2']; + /// + /// assert_eq!(s.find(x), None); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn find<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option { + core_str::StrExt::find(self, pat) + } + + /// Returns the byte index of the last character of this string slice that + /// matches the pattern. + /// + /// Returns [`None`] if the pattern doesn't match. + /// + /// The pattern can be a `&str`, [`char`], or a closure that determines if + /// a character matches. + /// + /// [`char`]: primitive.char.html + /// [`None`]: option/enum.Option.html#variant.None + /// + /// # Examples + /// + /// Simple patterns: + /// + /// ``` + /// let s = "Löwe 老虎 Léopard"; + /// + /// assert_eq!(s.rfind('L'), Some(13)); + /// assert_eq!(s.rfind('é'), Some(14)); + /// ``` + /// + /// More complex patterns with closures: + /// + /// ``` + /// let s = "Löwe 老虎 Léopard"; + /// + /// assert_eq!(s.rfind(char::is_whitespace), Some(12)); + /// assert_eq!(s.rfind(char::is_lowercase), Some(20)); + /// ``` + /// + /// Not finding the pattern: + /// + /// ``` + /// let s = "Löwe 老虎 Léopard"; + /// let x: &[_] = &['1', '2']; + /// + /// assert_eq!(s.rfind(x), None); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn rfind<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option + where P::Searcher: ReverseSearcher<'a> + { + core_str::StrExt::rfind(self, pat) + } + + /// An iterator over substrings of this string slice, separated by + /// characters matched by a pattern. + /// + /// The pattern can be a `&str`, [`char`], or a closure that determines the + /// split. + /// + /// # Iterator behavior + /// + /// The returned iterator will be a [`DoubleEndedIterator`] if the pattern + /// allows a reverse search and forward/reverse search yields the same + /// elements. This is true for, eg, [`char`] but not for `&str`. + /// + /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html + /// + /// If the pattern allows a reverse search but its results might differ + /// from a forward search, the [`rsplit`] method can be used. + /// + /// [`char`]: primitive.char.html + /// [`rsplit`]: #method.rsplit + /// + /// # Examples + /// + /// Simple patterns: + /// + /// ``` + /// let v: Vec<&str> = "Mary had a little lamb".split(' ').collect(); + /// assert_eq!(v, ["Mary", "had", "a", "little", "lamb"]); + /// + /// let v: Vec<&str> = "".split('X').collect(); + /// assert_eq!(v, [""]); + /// + /// let v: Vec<&str> = "lionXXtigerXleopard".split('X').collect(); + /// assert_eq!(v, ["lion", "", "tiger", "leopard"]); + /// + /// let v: Vec<&str> = "lion::tiger::leopard".split("::").collect(); + /// assert_eq!(v, ["lion", "tiger", "leopard"]); + /// + /// let v: Vec<&str> = "abc1def2ghi".split(char::is_numeric).collect(); + /// assert_eq!(v, ["abc", "def", "ghi"]); + /// + /// let v: Vec<&str> = "lionXtigerXleopard".split(char::is_uppercase).collect(); + /// assert_eq!(v, ["lion", "tiger", "leopard"]); + /// ``` + /// + /// A more complex pattern, using a closure: + /// + /// ``` + /// let v: Vec<&str> = "abc1defXghi".split(|c| c == '1' || c == 'X').collect(); + /// assert_eq!(v, ["abc", "def", "ghi"]); + /// ``` + /// + /// If a string contains multiple contiguous separators, you will end up + /// with empty strings in the output: + /// + /// ``` + /// let x = "||||a||b|c".to_string(); + /// let d: Vec<_> = x.split('|').collect(); + /// + /// assert_eq!(d, &["", "", "", "", "a", "", "b", "c"]); + /// ``` + /// + /// Contiguous separators are separated by the empty string. + /// + /// ``` + /// let x = "(///)".to_string(); + /// let d: Vec<_> = x.split('/').collect(); + /// + /// assert_eq!(d, &["(", "", "", ")"]); + /// ``` + /// + /// Separators at the start or end of a string are neighbored + /// by empty strings. + /// + /// ``` + /// let d: Vec<_> = "010".split("0").collect(); + /// assert_eq!(d, &["", "1", ""]); + /// ``` + /// + /// When the empty string is used as a separator, it separates + /// every character in the string, along with the beginning + /// and end of the string. + /// + /// ``` + /// let f: Vec<_> = "rust".split("").collect(); + /// assert_eq!(f, &["", "r", "u", "s", "t", ""]); + /// ``` + /// + /// Contiguous separators can lead to possibly surprising behavior + /// when whitespace is used as the separator. This code is correct: + /// + /// ``` + /// let x = " a b c".to_string(); + /// let d: Vec<_> = x.split(' ').collect(); + /// + /// assert_eq!(d, &["", "", "", "", "a", "", "b", "c"]); + /// ``` + /// + /// It does _not_ give you: + /// + /// ```,ignore + /// assert_eq!(d, &["a", "b", "c"]); + /// ``` + /// + /// Use [`split_whitespace`] for this behavior. + /// + /// [`split_whitespace`]: #method.split_whitespace + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn split<'a, P: Pattern<'a>>(&'a self, pat: P) -> Split<'a, P> { + core_str::StrExt::split(self, pat) + } + + /// An iterator over substrings of the given string slice, separated by + /// characters matched by a pattern and yielded in reverse order. + /// + /// The pattern can be a `&str`, [`char`], or a closure that determines the + /// split. + /// + /// [`char`]: primitive.char.html + /// + /// # Iterator behavior + /// + /// The returned iterator requires that the pattern supports a reverse + /// search, and it will be a [`DoubleEndedIterator`] if a forward/reverse + /// search yields the same elements. + /// + /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html + /// + /// For iterating from the front, the [`split`] method can be used. + /// + /// [`split`]: #method.split + /// + /// # Examples + /// + /// Simple patterns: + /// + /// ``` + /// let v: Vec<&str> = "Mary had a little lamb".rsplit(' ').collect(); + /// assert_eq!(v, ["lamb", "little", "a", "had", "Mary"]); + /// + /// let v: Vec<&str> = "".rsplit('X').collect(); + /// assert_eq!(v, [""]); + /// + /// let v: Vec<&str> = "lionXXtigerXleopard".rsplit('X').collect(); + /// assert_eq!(v, ["leopard", "tiger", "", "lion"]); + /// + /// let v: Vec<&str> = "lion::tiger::leopard".rsplit("::").collect(); + /// assert_eq!(v, ["leopard", "tiger", "lion"]); + /// ``` + /// + /// A more complex pattern, using a closure: + /// + /// ``` + /// let v: Vec<&str> = "abc1defXghi".rsplit(|c| c == '1' || c == 'X').collect(); + /// assert_eq!(v, ["ghi", "def", "abc"]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn rsplit<'a, P: Pattern<'a>>(&'a self, pat: P) -> RSplit<'a, P> + where P::Searcher: ReverseSearcher<'a> + { + core_str::StrExt::rsplit(self, pat) + } + + /// An iterator over substrings of the given string slice, separated by + /// characters matched by a pattern. + /// + /// The pattern can be a `&str`, [`char`], or a closure that determines the + /// split. + /// + /// Equivalent to [`split`], except that the trailing substring + /// is skipped if empty. + /// + /// [`split`]: #method.split + /// + /// This method can be used for string data that is _terminated_, + /// rather than _separated_ by a pattern. + /// + /// # Iterator behavior + /// + /// The returned iterator will be a [`DoubleEndedIterator`] if the pattern + /// allows a reverse search and forward/reverse search yields the same + /// elements. This is true for, eg, [`char`] but not for `&str`. + /// + /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html + /// [`char`]: primitive.char.html + /// + /// If the pattern allows a reverse search but its results might differ + /// from a forward search, the [`rsplit_terminator`] method can be used. + /// + /// [`rsplit_terminator`]: #method.rsplit_terminator + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let v: Vec<&str> = "A.B.".split_terminator('.').collect(); + /// assert_eq!(v, ["A", "B"]); + /// + /// let v: Vec<&str> = "A..B..".split_terminator(".").collect(); + /// assert_eq!(v, ["A", "", "B", ""]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn split_terminator<'a, P: Pattern<'a>>(&'a self, pat: P) -> SplitTerminator<'a, P> { + core_str::StrExt::split_terminator(self, pat) + } + + /// An iterator over substrings of `self`, separated by characters + /// matched by a pattern and yielded in reverse order. + /// + /// The pattern can be a simple `&str`, [`char`], or a closure that + /// determines the split. + /// Additional libraries might provide more complex patterns like + /// regular expressions. + /// + /// [`char`]: primitive.char.html + /// + /// Equivalent to [`split`], except that the trailing substring is + /// skipped if empty. + /// + /// [`split`]: #method.split + /// + /// This method can be used for string data that is _terminated_, + /// rather than _separated_ by a pattern. + /// + /// # Iterator behavior + /// + /// The returned iterator requires that the pattern supports a + /// reverse search, and it will be double ended if a forward/reverse + /// search yields the same elements. + /// + /// For iterating from the front, the [`split_terminator`] method can be + /// used. + /// + /// [`split_terminator`]: #method.split_terminator + /// + /// # Examples + /// + /// ``` + /// let v: Vec<&str> = "A.B.".rsplit_terminator('.').collect(); + /// assert_eq!(v, ["B", "A"]); + /// + /// let v: Vec<&str> = "A..B..".rsplit_terminator(".").collect(); + /// assert_eq!(v, ["", "B", "", "A"]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn rsplit_terminator<'a, P: Pattern<'a>>(&'a self, pat: P) -> RSplitTerminator<'a, P> + where P::Searcher: ReverseSearcher<'a> + { + core_str::StrExt::rsplit_terminator(self, pat) + } + + /// An iterator over substrings of the given string slice, separated by a + /// pattern, restricted to returning at most `n` items. + /// + /// If `n` substrings are returned, the last substring (the `n`th substring) + /// will contain the remainder of the string. + /// + /// The pattern can be a `&str`, [`char`], or a closure that determines the + /// split. + /// + /// [`char`]: primitive.char.html + /// + /// # Iterator behavior + /// + /// The returned iterator will not be double ended, because it is + /// not efficient to support. + /// + /// If the pattern allows a reverse search, the [`rsplitn`] method can be + /// used. + /// + /// [`rsplitn`]: #method.rsplitn + /// + /// # Examples + /// + /// Simple patterns: + /// + /// ``` + /// let v: Vec<&str> = "Mary had a little lambda".splitn(3, ' ').collect(); + /// assert_eq!(v, ["Mary", "had", "a little lambda"]); + /// + /// let v: Vec<&str> = "lionXXtigerXleopard".splitn(3, "X").collect(); + /// assert_eq!(v, ["lion", "", "tigerXleopard"]); + /// + /// let v: Vec<&str> = "abcXdef".splitn(1, 'X').collect(); + /// assert_eq!(v, ["abcXdef"]); + /// + /// let v: Vec<&str> = "".splitn(1, 'X').collect(); + /// assert_eq!(v, [""]); + /// ``` + /// + /// A more complex pattern, using a closure: + /// + /// ``` + /// let v: Vec<&str> = "abc1defXghi".splitn(2, |c| c == '1' || c == 'X').collect(); + /// assert_eq!(v, ["abc", "defXghi"]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn splitn<'a, P: Pattern<'a>>(&'a self, n: usize, pat: P) -> SplitN<'a, P> { + core_str::StrExt::splitn(self, n, pat) + } + + /// An iterator over substrings of this string slice, separated by a + /// pattern, starting from the end of the string, restricted to returning + /// at most `n` items. + /// + /// If `n` substrings are returned, the last substring (the `n`th substring) + /// will contain the remainder of the string. + /// + /// The pattern can be a `&str`, [`char`], or a closure that + /// determines the split. + /// + /// [`char`]: primitive.char.html + /// + /// # Iterator behavior + /// + /// The returned iterator will not be double ended, because it is not + /// efficient to support. + /// + /// For splitting from the front, the [`splitn`] method can be used. + /// + /// [`splitn`]: #method.splitn + /// + /// # Examples + /// + /// Simple patterns: + /// + /// ``` + /// let v: Vec<&str> = "Mary had a little lamb".rsplitn(3, ' ').collect(); + /// assert_eq!(v, ["lamb", "little", "Mary had a"]); + /// + /// let v: Vec<&str> = "lionXXtigerXleopard".rsplitn(3, 'X').collect(); + /// assert_eq!(v, ["leopard", "tiger", "lionX"]); + /// + /// let v: Vec<&str> = "lion::tiger::leopard".rsplitn(2, "::").collect(); + /// assert_eq!(v, ["leopard", "lion::tiger"]); + /// ``` + /// + /// A more complex pattern, using a closure: + /// + /// ``` + /// let v: Vec<&str> = "abc1defXghi".rsplitn(2, |c| c == '1' || c == 'X').collect(); + /// assert_eq!(v, ["ghi", "abc1def"]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn rsplitn<'a, P: Pattern<'a>>(&'a self, n: usize, pat: P) -> RSplitN<'a, P> + where P::Searcher: ReverseSearcher<'a> + { + core_str::StrExt::rsplitn(self, n, pat) + } + + /// An iterator over the disjoint matches of a pattern within the given string + /// slice. + /// + /// The pattern can be a `&str`, [`char`], or a closure that + /// determines if a character matches. + /// + /// [`char`]: primitive.char.html + /// + /// # Iterator behavior + /// + /// The returned iterator will be a [`DoubleEndedIterator`] if the pattern + /// allows a reverse search and forward/reverse search yields the same + /// elements. This is true for, eg, [`char`] but not for `&str`. + /// + /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html + /// [`char`]: primitive.char.html + /// + /// If the pattern allows a reverse search but its results might differ + /// from a forward search, the [`rmatches`] method can be used. + /// + /// [`rmatches`]: #method.rmatches + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let v: Vec<&str> = "abcXXXabcYYYabc".matches("abc").collect(); + /// assert_eq!(v, ["abc", "abc", "abc"]); + /// + /// let v: Vec<&str> = "1abc2abc3".matches(char::is_numeric).collect(); + /// assert_eq!(v, ["1", "2", "3"]); + /// ``` + #[stable(feature = "str_matches", since = "1.2.0")] + #[inline] + pub fn matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> Matches<'a, P> { + core_str::StrExt::matches(self, pat) + } + + /// An iterator over the disjoint matches of a pattern within this string slice, + /// yielded in reverse order. + /// + /// The pattern can be a `&str`, [`char`], or a closure that determines if + /// a character matches. + /// + /// [`char`]: primitive.char.html + /// + /// # Iterator behavior + /// + /// The returned iterator requires that the pattern supports a reverse + /// search, and it will be a [`DoubleEndedIterator`] if a forward/reverse + /// search yields the same elements. + /// + /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html + /// + /// For iterating from the front, the [`matches`] method can be used. + /// + /// [`matches`]: #method.matches + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let v: Vec<&str> = "abcXXXabcYYYabc".rmatches("abc").collect(); + /// assert_eq!(v, ["abc", "abc", "abc"]); + /// + /// let v: Vec<&str> = "1abc2abc3".rmatches(char::is_numeric).collect(); + /// assert_eq!(v, ["3", "2", "1"]); + /// ``` + #[stable(feature = "str_matches", since = "1.2.0")] + #[inline] + pub fn rmatches<'a, P: Pattern<'a>>(&'a self, pat: P) -> RMatches<'a, P> + where P::Searcher: ReverseSearcher<'a> + { + core_str::StrExt::rmatches(self, pat) + } + + /// An iterator over the disjoint matches of a pattern within this string + /// slice as well as the index that the match starts at. + /// + /// For matches of `pat` within `self` that overlap, only the indices + /// corresponding to the first match are returned. + /// + /// The pattern can be a `&str`, [`char`], or a closure that determines + /// if a character matches. + /// + /// [`char`]: primitive.char.html + /// + /// # Iterator behavior + /// + /// The returned iterator will be a [`DoubleEndedIterator`] if the pattern + /// allows a reverse search and forward/reverse search yields the same + /// elements. This is true for, eg, [`char`] but not for `&str`. + /// + /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html + /// + /// If the pattern allows a reverse search but its results might differ + /// from a forward search, the [`rmatch_indices`] method can be used. + /// + /// [`rmatch_indices`]: #method.rmatch_indices + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let v: Vec<_> = "abcXXXabcYYYabc".match_indices("abc").collect(); + /// assert_eq!(v, [(0, "abc"), (6, "abc"), (12, "abc")]); + /// + /// let v: Vec<_> = "1abcabc2".match_indices("abc").collect(); + /// assert_eq!(v, [(1, "abc"), (4, "abc")]); + /// + /// let v: Vec<_> = "ababa".match_indices("aba").collect(); + /// assert_eq!(v, [(0, "aba")]); // only the first `aba` + /// ``` + #[stable(feature = "str_match_indices", since = "1.5.0")] + #[inline] + pub fn match_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> MatchIndices<'a, P> { + core_str::StrExt::match_indices(self, pat) + } + + /// An iterator over the disjoint matches of a pattern within `self`, + /// yielded in reverse order along with the index of the match. + /// + /// For matches of `pat` within `self` that overlap, only the indices + /// corresponding to the last match are returned. + /// + /// The pattern can be a `&str`, [`char`], or a closure that determines if a + /// character matches. + /// + /// [`char`]: primitive.char.html + /// + /// # Iterator behavior + /// + /// The returned iterator requires that the pattern supports a reverse + /// search, and it will be a [`DoubleEndedIterator`] if a forward/reverse + /// search yields the same elements. + /// + /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html + /// + /// For iterating from the front, the [`match_indices`] method can be used. + /// + /// [`match_indices`]: #method.match_indices + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let v: Vec<_> = "abcXXXabcYYYabc".rmatch_indices("abc").collect(); + /// assert_eq!(v, [(12, "abc"), (6, "abc"), (0, "abc")]); + /// + /// let v: Vec<_> = "1abcabc2".rmatch_indices("abc").collect(); + /// assert_eq!(v, [(4, "abc"), (1, "abc")]); + /// + /// let v: Vec<_> = "ababa".rmatch_indices("aba").collect(); + /// assert_eq!(v, [(2, "aba")]); // only the last `aba` + /// ``` + #[stable(feature = "str_match_indices", since = "1.5.0")] + #[inline] + pub fn rmatch_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> RMatchIndices<'a, P> + where P::Searcher: ReverseSearcher<'a> + { + core_str::StrExt::rmatch_indices(self, pat) + } + + /// Returns a string slice with leading and trailing whitespace removed. + /// + /// 'Whitespace' is defined according to the terms of the Unicode Derived + /// Core Property `White_Space`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let s = " Hello\tworld\t"; + /// + /// assert_eq!("Hello\tworld", s.trim()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn trim(&self) -> &str { + UnicodeStr::trim(self) + } + + /// Returns a string slice with leading whitespace removed. + /// + /// 'Whitespace' is defined according to the terms of the Unicode Derived + /// Core Property `White_Space`. + /// + /// # Text directionality + /// + /// A string is a sequence of bytes. 'Left' in this context means the first + /// position of that byte string; for a language like Arabic or Hebrew + /// which are 'right to left' rather than 'left to right', this will be + /// the _right_ side, not the left. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let s = " Hello\tworld\t"; + /// + /// assert_eq!("Hello\tworld\t", s.trim_left()); + /// ``` + /// + /// Directionality: + /// + /// ``` + /// let s = " English"; + /// assert!(Some('E') == s.trim_left().chars().next()); + /// + /// let s = " עברית"; + /// assert!(Some('ע') == s.trim_left().chars().next()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn trim_left(&self) -> &str { + UnicodeStr::trim_left(self) + } + + /// Returns a string slice with trailing whitespace removed. + /// + /// 'Whitespace' is defined according to the terms of the Unicode Derived + /// Core Property `White_Space`. + /// + /// # Text directionality + /// + /// A string is a sequence of bytes. 'Right' in this context means the last + /// position of that byte string; for a language like Arabic or Hebrew + /// which are 'right to left' rather than 'left to right', this will be + /// the _left_ side, not the right. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let s = " Hello\tworld\t"; + /// + /// assert_eq!(" Hello\tworld", s.trim_right()); + /// ``` + /// + /// Directionality: + /// + /// ``` + /// let s = "English "; + /// assert!(Some('h') == s.trim_right().chars().rev().next()); + /// + /// let s = "עברית "; + /// assert!(Some('ת') == s.trim_right().chars().rev().next()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn trim_right(&self) -> &str { + UnicodeStr::trim_right(self) + } + + /// Returns a string slice with all prefixes and suffixes that match a + /// pattern repeatedly removed. + /// + /// The pattern can be a [`char`] or a closure that determines if a + /// character matches. + /// + /// [`char`]: primitive.char.html + /// + /// # Examples + /// + /// Simple patterns: + /// + /// ``` + /// assert_eq!("11foo1bar11".trim_matches('1'), "foo1bar"); + /// assert_eq!("123foo1bar123".trim_matches(char::is_numeric), "foo1bar"); + /// + /// let x: &[_] = &['1', '2']; + /// assert_eq!("12foo1bar12".trim_matches(x), "foo1bar"); + /// ``` + /// + /// A more complex pattern, using a closure: + /// + /// ``` + /// assert_eq!("1foo1barXX".trim_matches(|c| c == '1' || c == 'X'), "foo1bar"); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn trim_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str + where P::Searcher: DoubleEndedSearcher<'a> + { + core_str::StrExt::trim_matches(self, pat) + } + + /// Returns a string slice with all prefixes that match a pattern + /// repeatedly removed. + /// + /// The pattern can be a `&str`, [`char`], or a closure that determines if + /// a character matches. + /// + /// [`char`]: primitive.char.html + /// + /// # Text directionality + /// + /// A string is a sequence of bytes. 'Left' in this context means the first + /// position of that byte string; for a language like Arabic or Hebrew + /// which are 'right to left' rather than 'left to right', this will be + /// the _right_ side, not the left. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// assert_eq!("11foo1bar11".trim_left_matches('1'), "foo1bar11"); + /// assert_eq!("123foo1bar123".trim_left_matches(char::is_numeric), "foo1bar123"); + /// + /// let x: &[_] = &['1', '2']; + /// assert_eq!("12foo1bar12".trim_left_matches(x), "foo1bar12"); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn trim_left_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str { + core_str::StrExt::trim_left_matches(self, pat) + } + + /// Returns a string slice with all suffixes that match a pattern + /// repeatedly removed. + /// + /// The pattern can be a `&str`, [`char`], or a closure that + /// determines if a character matches. + /// + /// [`char`]: primitive.char.html + /// + /// # Text directionality + /// + /// A string is a sequence of bytes. 'Right' in this context means the last + /// position of that byte string; for a language like Arabic or Hebrew + /// which are 'right to left' rather than 'left to right', this will be + /// the _left_ side, not the right. + /// + /// # Examples + /// + /// Simple patterns: + /// + /// ``` + /// assert_eq!("11foo1bar11".trim_right_matches('1'), "11foo1bar"); + /// assert_eq!("123foo1bar123".trim_right_matches(char::is_numeric), "123foo1bar"); + /// + /// let x: &[_] = &['1', '2']; + /// assert_eq!("12foo1bar12".trim_right_matches(x), "12foo1bar"); + /// ``` + /// + /// A more complex pattern, using a closure: + /// + /// ``` + /// assert_eq!("1fooX".trim_left_matches(|c| c == '1' || c == 'X'), "fooX"); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn trim_right_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str + where P::Searcher: ReverseSearcher<'a> + { + core_str::StrExt::trim_right_matches(self, pat) + } + + /// Parses this string slice into another type. + /// + /// Because `parse` is so general, it can cause problems with type + /// inference. As such, `parse` is one of the few times you'll see + /// the syntax affectionately known as the 'turbofish': `::<>`. This + /// helps the inference algorithm understand specifically which type + /// you're trying to parse into. + /// + /// `parse` can parse any type that implements the [`FromStr`] trait. + /// + /// [`FromStr`]: str/trait.FromStr.html + /// + /// # Errors + /// + /// Will return [`Err`] if it's not possible to parse this string slice into + /// the desired type. + /// + /// [`Err`]: str/trait.FromStr.html#associatedtype.Err + /// + /// # Example + /// + /// Basic usage + /// + /// ``` + /// let four: u32 = "4".parse().unwrap(); + /// + /// assert_eq!(4, four); + /// ``` + /// + /// Using the 'turbofish' instead of annotating `four`: + /// + /// ``` + /// let four = "4".parse::(); + /// + /// assert_eq!(Ok(4), four); + /// ``` + /// + /// Failing to parse: + /// + /// ``` + /// let nope = "j".parse::(); + /// + /// assert!(nope.is_err()); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn parse(&self) -> Result { + core_str::StrExt::parse(self) + } + + /// Converts a `Box` into a `Box<[u8]>` without copying or allocating. + #[unstable(feature = "str_box_extras", issue = "41119")] + pub fn into_boxed_bytes(self: Box) -> Box<[u8]> { + self.into() + } + + /// Replaces all matches of a pattern with another string. + /// + /// `replace` creates a new [`String`], and copies the data from this string slice into it. + /// While doing so, it attempts to find matches of a pattern. If it finds any, it + /// replaces them with the replacement string slice. + /// + /// [`String`]: string/struct.String.html + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let s = "this is old"; + /// + /// assert_eq!("this is new", s.replace("old", "new")); + /// ``` + /// + /// When the pattern doesn't match: + /// + /// ``` + /// let s = "this is old"; + /// assert_eq!(s, s.replace("cookie monster", "little lamb")); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn replace<'a, P: Pattern<'a>>(&'a self, from: P, to: &str) -> String { + let mut result = String::new(); + let mut last_end = 0; + for (start, part) in self.match_indices(from) { + result.push_str(unsafe { self.slice_unchecked(last_end, start) }); + result.push_str(to); + last_end = start + part.len(); + } + result.push_str(unsafe { self.slice_unchecked(last_end, self.len()) }); + result + } + + /// Replaces first N matches of a pattern with another string. + /// + /// `replacen` creates a new [`String`], and copies the data from this string slice into it. + /// While doing so, it attempts to find matches of a pattern. If it finds any, it + /// replaces them with the replacement string slice at most `count` times. + /// + /// [`String`]: string/struct.String.html + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let s = "foo foo 123 foo"; + /// assert_eq!("new new 123 foo", s.replacen("foo", "new", 2)); + /// assert_eq!("faa fao 123 foo", s.replacen('o', "a", 3)); + /// assert_eq!("foo foo new23 foo", s.replacen(char::is_numeric, "new", 1)); + /// ``` + /// + /// When the pattern doesn't match: + /// + /// ``` + /// let s = "this is old"; + /// assert_eq!(s, s.replacen("cookie monster", "little lamb", 10)); + /// ``` + #[stable(feature = "str_replacen", since = "1.16.0")] + pub fn replacen<'a, P: Pattern<'a>>(&'a self, pat: P, to: &str, count: usize) -> String { + // Hope to reduce the times of re-allocation + let mut result = String::with_capacity(32); + let mut last_end = 0; + for (start, part) in self.match_indices(pat).take(count) { + result.push_str(unsafe { self.slice_unchecked(last_end, start) }); + result.push_str(to); + last_end = start + part.len(); + } + result.push_str(unsafe { self.slice_unchecked(last_end, self.len()) }); + result + } + + /// Returns the lowercase equivalent of this string slice, as a new [`String`]. + /// + /// 'Lowercase' is defined according to the terms of the Unicode Derived Core Property + /// `Lowercase`. + /// + /// Since some characters can expand into multiple characters when changing + /// the case, this function returns a [`String`] instead of modifying the + /// parameter in-place. + /// + /// [`String`]: string/struct.String.html + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let s = "HELLO"; + /// + /// assert_eq!("hello", s.to_lowercase()); + /// ``` + /// + /// A tricky example, with sigma: + /// + /// ``` + /// let sigma = "Σ"; + /// + /// assert_eq!("σ", sigma.to_lowercase()); + /// + /// // but at the end of a word, it's ς, not σ: + /// let odysseus = "ὈΔΥΣΣΕΎΣ"; + /// + /// assert_eq!("ὀδυσσεύς", odysseus.to_lowercase()); + /// ``` + /// + /// Languages without case are not changed: + /// + /// ``` + /// let new_year = "农历新年"; + /// + /// assert_eq!(new_year, new_year.to_lowercase()); + /// ``` + #[stable(feature = "unicode_case_mapping", since = "1.2.0")] + pub fn to_lowercase(&self) -> String { + let mut s = String::with_capacity(self.len()); + for (i, c) in self[..].char_indices() { + if c == 'Σ' { + // Σ maps to σ, except at the end of a word where it maps to ς. + // This is the only conditional (contextual) but language-independent mapping + // in `SpecialCasing.txt`, + // so hard-code it rather than have a generic "condition" mechanism. + // See https://github.com/rust-lang/rust/issues/26035 + map_uppercase_sigma(self, i, &mut s) + } else { + s.extend(c.to_lowercase()); + } + } + return s; + + fn map_uppercase_sigma(from: &str, i: usize, to: &mut String) { + // See http://www.unicode.org/versions/Unicode7.0.0/ch03.pdf#G33992 + // for the definition of `Final_Sigma`. + debug_assert!('Σ'.len_utf8() == 2); + let is_word_final = case_ignoreable_then_cased(from[..i].chars().rev()) && + !case_ignoreable_then_cased(from[i + 2..].chars()); + to.push_str(if is_word_final { "ς" } else { "σ" }); + } + + fn case_ignoreable_then_cased>(iter: I) -> bool { + use std_unicode::derived_property::{Cased, Case_Ignorable}; + match iter.skip_while(|&c| Case_Ignorable(c)).next() { + Some(c) => Cased(c), + None => false, + } + } + } + + /// Returns the uppercase equivalent of this string slice, as a new [`String`]. + /// + /// 'Uppercase' is defined according to the terms of the Unicode Derived Core Property + /// `Uppercase`. + /// + /// Since some characters can expand into multiple characters when changing + /// the case, this function returns a [`String`] instead of modifying the + /// parameter in-place. + /// + /// [`String`]: string/struct.String.html + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let s = "hello"; + /// + /// assert_eq!("HELLO", s.to_uppercase()); + /// ``` + /// + /// Scripts without case are not changed: + /// + /// ``` + /// let new_year = "农历新年"; + /// + /// assert_eq!(new_year, new_year.to_uppercase()); + /// ``` + #[stable(feature = "unicode_case_mapping", since = "1.2.0")] + pub fn to_uppercase(&self) -> String { + let mut s = String::with_capacity(self.len()); + s.extend(self.chars().flat_map(|c| c.to_uppercase())); + return s; + } + + /// Escapes each char in `s` with [`char::escape_debug`]. + /// + /// [`char::escape_debug`]: primitive.char.html#method.escape_debug + #[unstable(feature = "str_escape", + reason = "return type may change to be an iterator", + issue = "27791")] + pub fn escape_debug(&self) -> String { + self.chars().flat_map(|c| c.escape_debug()).collect() + } + + /// Escapes each char in `s` with [`char::escape_default`]. + /// + /// [`char::escape_default`]: primitive.char.html#method.escape_default + #[unstable(feature = "str_escape", + reason = "return type may change to be an iterator", + issue = "27791")] + pub fn escape_default(&self) -> String { + self.chars().flat_map(|c| c.escape_default()).collect() + } + + /// Escapes each char in `s` with [`char::escape_unicode`]. + /// + /// [`char::escape_unicode`]: primitive.char.html#method.escape_unicode + #[unstable(feature = "str_escape", + reason = "return type may change to be an iterator", + issue = "27791")] + pub fn escape_unicode(&self) -> String { + self.chars().flat_map(|c| c.escape_unicode()).collect() + } + + /// Converts a [`Box`] into a [`String`] without copying or allocating. + /// + /// [`String`]: string/struct.String.html + /// [`Box`]: boxed/struct.Box.html + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let string = String::from("birthday gift"); + /// let boxed_str = string.clone().into_boxed_str(); + /// + /// assert_eq!(boxed_str.into_string(), string); + /// ``` + #[stable(feature = "box_str", since = "1.4.0")] + pub fn into_string(self: Box) -> String { + unsafe { + let slice = mem::transmute::, Box<[u8]>>(self); + String::from_utf8_unchecked(slice.into_vec()) + } + } + + /// Create a [`String`] by repeating a string `n` times. + /// + /// [`String`]: string/struct.String.html + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// assert_eq!("abc".repeat(4), String::from("abcabcabcabc")); + /// ``` + #[stable(feature = "repeat_str", since = "1.16.0")] + pub fn repeat(&self, n: usize) -> String { + let mut s = String::with_capacity(self.len() * n); + s.extend((0..n).map(|_| self)); + s + } +} + /// Converts a boxed slice of bytes to a boxed string slice without checking /// that the string contains valid UTF-8. #[unstable(feature = "str_box_extras", issue = "41119")] diff --git a/src/libcollections/string.rs b/src/liballoc/string.rs similarity index 99% rename from src/libcollections/string.rs rename to src/liballoc/string.rs index 55f0e01548fe..1d98626e90b0 100644 --- a/src/libcollections/string.rs +++ b/src/liballoc/string.rs @@ -56,8 +56,6 @@ #![stable(feature = "rust1", since = "1.0.0")] -use alloc::str as alloc_str; - use core::fmt; use core::hash; use core::iter::{FromIterator, FusedIterator}; @@ -70,7 +68,7 @@ use std_unicode::char::{decode_utf16, REPLACEMENT_CHARACTER}; use borrow::{Cow, ToOwned}; use range::RangeArgument; use Bound::{Excluded, Included, Unbounded}; -use str::{self, FromStr, Utf8Error, Chars}; +use str::{self, from_boxed_utf8_unchecked, FromStr, Utf8Error, Chars}; use vec::Vec; use boxed::Box; @@ -1464,7 +1462,7 @@ impl String { #[stable(feature = "box_str", since = "1.4.0")] pub fn into_boxed_str(self) -> Box { let slice = self.vec.into_boxed_slice(); - unsafe { alloc_str::from_boxed_utf8_unchecked(slice) } + unsafe { from_boxed_utf8_unchecked(slice) } } } diff --git a/src/libcollections/tests/binary_heap.rs b/src/liballoc/tests/binary_heap.rs similarity index 100% rename from src/libcollections/tests/binary_heap.rs rename to src/liballoc/tests/binary_heap.rs diff --git a/src/libcollections/tests/btree/map.rs b/src/liballoc/tests/btree/map.rs similarity index 100% rename from src/libcollections/tests/btree/map.rs rename to src/liballoc/tests/btree/map.rs diff --git a/src/libcollections/tests/btree/mod.rs b/src/liballoc/tests/btree/mod.rs similarity index 100% rename from src/libcollections/tests/btree/mod.rs rename to src/liballoc/tests/btree/mod.rs diff --git a/src/libcollections/tests/btree/set.rs b/src/liballoc/tests/btree/set.rs similarity index 100% rename from src/libcollections/tests/btree/set.rs rename to src/liballoc/tests/btree/set.rs diff --git a/src/libcollections/tests/cow_str.rs b/src/liballoc/tests/cow_str.rs similarity index 100% rename from src/libcollections/tests/cow_str.rs rename to src/liballoc/tests/cow_str.rs diff --git a/src/libcollections/tests/fmt.rs b/src/liballoc/tests/fmt.rs similarity index 100% rename from src/libcollections/tests/fmt.rs rename to src/liballoc/tests/fmt.rs diff --git a/src/libcollections/tests/lib.rs b/src/liballoc/tests/lib.rs similarity index 96% rename from src/libcollections/tests/lib.rs rename to src/liballoc/tests/lib.rs index c6f0b4436bb3..c6d70ee7575f 100644 --- a/src/libcollections/tests/lib.rs +++ b/src/liballoc/tests/lib.rs @@ -10,11 +10,11 @@ #![deny(warnings)] +#![feature(alloc)] #![feature(attr_literals)] #![feature(box_syntax)] #![feature(inclusive_range_syntax)] #![feature(collection_placement)] -#![feature(collections)] #![feature(const_fn)] #![feature(exact_size_is_empty)] #![feature(iterator_step_by)] @@ -31,7 +31,7 @@ #![feature(unicode)] #![feature(utf8_error_error_len)] -extern crate collections; +extern crate alloc; extern crate test; extern crate std_unicode; extern crate core; diff --git a/src/libcollections/tests/linked_list.rs b/src/liballoc/tests/linked_list.rs similarity index 100% rename from src/libcollections/tests/linked_list.rs rename to src/liballoc/tests/linked_list.rs diff --git a/src/libcollections/tests/slice.rs b/src/liballoc/tests/slice.rs similarity index 100% rename from src/libcollections/tests/slice.rs rename to src/liballoc/tests/slice.rs diff --git a/src/libcollections/tests/str.rs b/src/liballoc/tests/str.rs similarity index 100% rename from src/libcollections/tests/str.rs rename to src/liballoc/tests/str.rs diff --git a/src/libcollections/tests/string.rs b/src/liballoc/tests/string.rs similarity index 100% rename from src/libcollections/tests/string.rs rename to src/liballoc/tests/string.rs diff --git a/src/libcollections/tests/vec.rs b/src/liballoc/tests/vec.rs similarity index 100% rename from src/libcollections/tests/vec.rs rename to src/liballoc/tests/vec.rs diff --git a/src/libcollections/tests/vec_deque.rs b/src/liballoc/tests/vec_deque.rs similarity index 100% rename from src/libcollections/tests/vec_deque.rs rename to src/liballoc/tests/vec_deque.rs diff --git a/src/libcollections/vec.rs b/src/liballoc/vec.rs similarity index 99% rename from src/libcollections/vec.rs rename to src/liballoc/vec.rs index 2de27725e956..8bb16febb048 100644 --- a/src/libcollections/vec.rs +++ b/src/liballoc/vec.rs @@ -66,10 +66,6 @@ #![stable(feature = "rust1", since = "1.0.0")] -use alloc::boxed::Box; -use alloc::raw_vec::RawVec; -use borrow::ToOwned; -use borrow::Cow; use core::cmp::Ordering; use core::fmt; use core::hash::{self, Hash}; @@ -84,6 +80,10 @@ use core::ptr; use core::ptr::Shared; use core::slice; +use borrow::ToOwned; +use borrow::Cow; +use boxed::Box; +use raw_vec::RawVec; use super::range::RangeArgument; use Bound::{Excluded, Included, Unbounded}; diff --git a/src/libcollections/vec_deque.rs b/src/liballoc/vec_deque.rs similarity index 99% rename from src/libcollections/vec_deque.rs rename to src/liballoc/vec_deque.rs index e826c9432b51..18175a5d01bd 100644 --- a/src/libcollections/vec_deque.rs +++ b/src/liballoc/vec_deque.rs @@ -29,7 +29,7 @@ use core::slice; use core::hash::{Hash, Hasher}; use core::cmp; -use alloc::raw_vec::RawVec; +use raw_vec::RawVec; use super::range::RangeArgument; use Bound::{Excluded, Included, Unbounded}; diff --git a/src/libcollections/Cargo.toml b/src/libcollections/Cargo.toml deleted file mode 100644 index 7e92404bc0d6..000000000000 --- a/src/libcollections/Cargo.toml +++ /dev/null @@ -1,21 +0,0 @@ -[package] -authors = ["The Rust Project Developers"] -name = "collections" -version = "0.0.0" - -[lib] -name = "collections" -path = "lib.rs" - -[dependencies] -alloc = { path = "../liballoc" } -core = { path = "../libcore" } -std_unicode = { path = "../libstd_unicode" } - -[[test]] -name = "collectionstests" -path = "../libcollections/tests/lib.rs" - -[[bench]] -name = "collectionsbenches" -path = "../libcollections/benches/lib.rs" diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs deleted file mode 100644 index 34626326c221..000000000000 --- a/src/libcollections/lib.rs +++ /dev/null @@ -1,192 +0,0 @@ -// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Collection types. -//! -//! See [`std::collections`](../std/collections/index.html) for a detailed -//! discussion of collections in Rust. - -#![crate_name = "collections"] -#![crate_type = "rlib"] -#![unstable(feature = "collections", - reason = "library is unlikely to be stabilized with the current \ - layout and name, use std::collections instead", - issue = "27783")] -#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", - html_favicon_url = "https://doc.rust-lang.org/favicon.ico", - html_root_url = "https://doc.rust-lang.org/nightly/", - html_playground_url = "https://play.rust-lang.org/", - issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/", - test(no_crate_inject, attr(allow(unused_variables), deny(warnings))))] - -#![cfg_attr(test, allow(deprecated))] // rand -#![deny(warnings)] -#![deny(missing_debug_implementations)] - -#![feature(alloc)] -#![feature(allow_internal_unstable)] -#![feature(box_patterns)] -#![feature(box_syntax)] -#![cfg_attr(not(test), feature(char_escape_debug))] -#![cfg_attr(not(test), feature(core_float))] -#![feature(core_intrinsics)] -#![feature(dropck_eyepatch)] -#![feature(exact_size_is_empty)] -#![feature(fmt_internals)] -#![feature(fused)] -#![feature(generic_param_attrs)] -#![feature(heap_api)] -#![feature(i128_type)] -#![feature(inclusive_range)] -#![feature(lang_items)] -#![feature(manually_drop)] -#![feature(nonzero)] -#![feature(pattern)] -#![feature(placement_in)] -#![feature(placement_in_syntax)] -#![feature(placement_new_protocol)] -#![feature(shared)] -#![feature(slice_get_slice)] -#![feature(slice_patterns)] -#![cfg_attr(not(test), feature(slice_rotate))] -#![feature(slice_rsplit)] -#![cfg_attr(not(test), feature(sort_unstable))] -#![feature(specialization)] -#![feature(staged_api)] -#![feature(str_internals)] -#![feature(str_box_extras)] -#![feature(str_mut_extras)] -#![feature(trusted_len)] -#![feature(unicode)] -#![feature(unique)] -#![cfg_attr(not(test), feature(str_checked_slicing))] -#![cfg_attr(test, feature(rand, test))] -#![feature(offset_to)] - -#![no_std] - -extern crate std_unicode; -extern crate alloc; - -#[cfg(test)] -#[macro_use] -extern crate std; -#[cfg(test)] -extern crate test; - -#[doc(no_inline)] -pub use binary_heap::BinaryHeap; -#[doc(no_inline)] -pub use btree_map::BTreeMap; -#[doc(no_inline)] -pub use btree_set::BTreeSet; -#[doc(no_inline)] -pub use linked_list::LinkedList; -#[doc(no_inline)] -pub use vec_deque::VecDeque; -#[doc(no_inline)] -pub use string::String; -#[doc(no_inline)] -pub use vec::Vec; - -// Needed for the vec! macro -pub use alloc::boxed; - -#[macro_use] -mod macros; - -pub mod binary_heap; -mod btree; -pub mod borrow; -pub mod fmt; -pub mod linked_list; -pub mod range; -pub mod slice; -pub mod str; -pub mod string; -pub mod vec; -pub mod vec_deque; - -#[stable(feature = "rust1", since = "1.0.0")] -pub mod btree_map { - //! A map based on a B-Tree. - #[stable(feature = "rust1", since = "1.0.0")] - pub use btree::map::*; -} - -#[stable(feature = "rust1", since = "1.0.0")] -pub mod btree_set { - //! A set based on a B-Tree. - #[stable(feature = "rust1", since = "1.0.0")] - pub use btree::set::*; -} - -#[cfg(not(test))] -mod std { - pub use core::ops; // RangeFull -} - -/// An endpoint of a range of keys. -/// -/// # Examples -/// -/// `Bound`s are range endpoints: -/// -/// ``` -/// #![feature(collections_range)] -/// -/// use std::collections::range::RangeArgument; -/// use std::collections::Bound::*; -/// -/// assert_eq!((..100).start(), Unbounded); -/// assert_eq!((1..12).start(), Included(&1)); -/// assert_eq!((1..12).end(), Excluded(&12)); -/// ``` -/// -/// Using a tuple of `Bound`s as an argument to [`BTreeMap::range`]. -/// Note that in most cases, it's better to use range syntax (`1..5`) instead. -/// -/// ``` -/// use std::collections::BTreeMap; -/// use std::collections::Bound::{Excluded, Included, Unbounded}; -/// -/// let mut map = BTreeMap::new(); -/// map.insert(3, "a"); -/// map.insert(5, "b"); -/// map.insert(8, "c"); -/// -/// for (key, value) in map.range((Excluded(3), Included(8))) { -/// println!("{}: {}", key, value); -/// } -/// -/// assert_eq!(Some((&3, &"a")), map.range((Unbounded, Included(5))).next()); -/// ``` -/// -/// [`BTreeMap::range`]: btree_map/struct.BTreeMap.html#method.range -#[stable(feature = "collections_bound", since = "1.17.0")] -#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] -pub enum Bound { - /// An inclusive bound. - #[stable(feature = "collections_bound", since = "1.17.0")] - Included(T), - /// An exclusive bound. - #[stable(feature = "collections_bound", since = "1.17.0")] - Excluded(T), - /// An infinite endpoint. Indicates that there is no bound in this direction. - #[stable(feature = "collections_bound", since = "1.17.0")] - Unbounded, -} - -/// An intermediate trait for specialization of `Extend`. -#[doc(hidden)] -trait SpecExtend { - /// Extends `self` with the contents of the given iterator. - fn spec_extend(&mut self, iter: I); -} diff --git a/src/libcollections/macros.rs b/src/libcollections/macros.rs deleted file mode 100644 index 396a917dfde2..000000000000 --- a/src/libcollections/macros.rs +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -/// Creates a `Vec` containing the arguments. -/// -/// `vec!` allows `Vec`s to be defined with the same syntax as array expressions. -/// There are two forms of this macro: -/// -/// - Create a `Vec` containing a given list of elements: -/// -/// ``` -/// let v = vec![1, 2, 3]; -/// assert_eq!(v[0], 1); -/// assert_eq!(v[1], 2); -/// assert_eq!(v[2], 3); -/// ``` -/// -/// - Create a `Vec` from a given element and size: -/// -/// ``` -/// let v = vec![1; 3]; -/// assert_eq!(v, [1, 1, 1]); -/// ``` -/// -/// Note that unlike array expressions this syntax supports all elements -/// which implement `Clone` and the number of elements doesn't have to be -/// a constant. -/// -/// This will use `clone()` to duplicate an expression, so one should be careful -/// using this with types having a nonstandard `Clone` implementation. For -/// example, `vec![Rc::new(1); 5]` will create a vector of five references -/// to the same boxed integer value, not five references pointing to independently -/// boxed integers. -#[cfg(not(test))] -#[macro_export] -#[stable(feature = "rust1", since = "1.0.0")] -#[allow_internal_unstable] -macro_rules! vec { - ($elem:expr; $n:expr) => ( - $crate::vec::from_elem($elem, $n) - ); - ($($x:expr),*) => ( - <[_]>::into_vec(box [$($x),*]) - ); - ($($x:expr,)*) => (vec![$($x),*]) -} - -// HACK(japaric): with cfg(test) the inherent `[T]::into_vec` method, which is -// required for this macro definition, is not available. Instead use the -// `slice::into_vec` function which is only available with cfg(test) -// NB see the slice::hack module in slice.rs for more information -#[cfg(test)] -macro_rules! vec { - ($elem:expr; $n:expr) => ( - $crate::vec::from_elem($elem, $n) - ); - ($($x:expr),*) => ( - $crate::slice::into_vec(box [$($x),*]) - ); - ($($x:expr,)*) => (vec![$($x),*]) -} - -/// Use the syntax described in `std::fmt` to create a value of type `String`. -/// See [`std::fmt`][fmt] for more information. -/// -/// [fmt]: ../std/fmt/index.html -/// -/// # Panics -/// -/// `format!` panics if a formatting trait implementation returns an error. -/// This indicates an incorrect implementation -/// since `fmt::Write for String` never returns an error itself. -/// -/// # Examples -/// -/// ``` -/// format!("test"); -/// format!("hello {}", "world!"); -/// format!("x = {}, y = {y}", 10, y = 30); -/// ``` -#[macro_export] -#[stable(feature = "rust1", since = "1.0.0")] -macro_rules! format { - ($($arg:tt)*) => ($crate::fmt::format(format_args!($($arg)*))) -} diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs deleted file mode 100644 index fdb6ee42127b..000000000000 --- a/src/libcollections/str.rs +++ /dev/null @@ -1,1997 +0,0 @@ -// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Unicode string slices. -//! -//! The `&str` type is one of the two main string types, the other being `String`. -//! Unlike its `String` counterpart, its contents are borrowed. -//! -//! # Basic Usage -//! -//! A basic string declaration of `&str` type: -//! -//! ``` -//! let hello_world = "Hello, World!"; -//! ``` -//! -//! Here we have declared a string literal, also known as a string slice. -//! String literals have a static lifetime, which means the string `hello_world` -//! is guaranteed to be valid for the duration of the entire program. -//! We can explicitly specify `hello_world`'s lifetime as well: -//! -//! ``` -//! let hello_world: &'static str = "Hello, world!"; -//! ``` -//! -//! *[See also the `str` primitive type](../../std/primitive.str.html).* - -#![stable(feature = "rust1", since = "1.0.0")] - -// Many of the usings in this module are only used in the test configuration. -// It's cleaner to just turn off the unused_imports warning than to fix them. -#![allow(unused_imports)] - -use core::fmt; -use core::str as core_str; -use core::str::pattern::Pattern; -use core::str::pattern::{Searcher, ReverseSearcher, DoubleEndedSearcher}; -use core::mem; -use core::iter::FusedIterator; -use std_unicode::str::{UnicodeStr, Utf16Encoder}; - -use vec_deque::VecDeque; -use borrow::{Borrow, ToOwned}; -use string::String; -use std_unicode; -use vec::Vec; -use slice::{SliceConcatExt, SliceIndex}; -use boxed::Box; - -#[stable(feature = "rust1", since = "1.0.0")] -pub use core::str::{FromStr, Utf8Error}; -#[allow(deprecated)] -#[stable(feature = "rust1", since = "1.0.0")] -pub use core::str::{Lines, LinesAny}; -#[stable(feature = "rust1", since = "1.0.0")] -pub use core::str::{Split, RSplit}; -#[stable(feature = "rust1", since = "1.0.0")] -pub use core::str::{SplitN, RSplitN}; -#[stable(feature = "rust1", since = "1.0.0")] -pub use core::str::{SplitTerminator, RSplitTerminator}; -#[stable(feature = "rust1", since = "1.0.0")] -pub use core::str::{Matches, RMatches}; -#[stable(feature = "rust1", since = "1.0.0")] -pub use core::str::{MatchIndices, RMatchIndices}; -#[stable(feature = "rust1", since = "1.0.0")] -pub use core::str::{from_utf8, from_utf8_mut, Chars, CharIndices, Bytes}; -#[stable(feature = "rust1", since = "1.0.0")] -pub use core::str::{from_utf8_unchecked, from_utf8_unchecked_mut, ParseBoolError}; -#[unstable(feature = "str_box_extras", issue = "41119")] -pub use alloc::str::from_boxed_utf8_unchecked; -#[stable(feature = "rust1", since = "1.0.0")] -pub use std_unicode::str::SplitWhitespace; -#[stable(feature = "rust1", since = "1.0.0")] -pub use core::str::pattern; - - -#[unstable(feature = "slice_concat_ext", - reason = "trait should not have to exist", - issue = "27747")] -impl> SliceConcatExt for [S] { - type Output = String; - - fn concat(&self) -> String { - if self.is_empty() { - return String::new(); - } - - // `len` calculation may overflow but push_str will check boundaries - let len = self.iter().map(|s| s.borrow().len()).sum(); - let mut result = String::with_capacity(len); - - for s in self { - result.push_str(s.borrow()) - } - - result - } - - fn join(&self, sep: &str) -> String { - if self.is_empty() { - return String::new(); - } - - // concat is faster - if sep.is_empty() { - return self.concat(); - } - - // this is wrong without the guarantee that `self` is non-empty - // `len` calculation may overflow but push_str but will check boundaries - let len = sep.len() * (self.len() - 1) + - self.iter().map(|s| s.borrow().len()).sum::(); - let mut result = String::with_capacity(len); - let mut first = true; - - for s in self { - if first { - first = false; - } else { - result.push_str(sep); - } - result.push_str(s.borrow()); - } - result - } - - fn connect(&self, sep: &str) -> String { - self.join(sep) - } -} - -/// An iterator of [`u16`] over the string encoded as UTF-16. -/// -/// [`u16`]: ../../std/primitive.u16.html -/// -/// This struct is created by the [`encode_utf16`] method on [`str`]. -/// See its documentation for more. -/// -/// [`encode_utf16`]: ../../std/primitive.str.html#method.encode_utf16 -/// [`str`]: ../../std/primitive.str.html -#[derive(Clone)] -#[stable(feature = "encode_utf16", since = "1.8.0")] -pub struct EncodeUtf16<'a> { - encoder: Utf16Encoder>, -} - -#[stable(feature = "collection_debug", since = "1.17.0")] -impl<'a> fmt::Debug for EncodeUtf16<'a> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.pad("EncodeUtf16 { .. }") - } -} - -#[stable(feature = "encode_utf16", since = "1.8.0")] -impl<'a> Iterator for EncodeUtf16<'a> { - type Item = u16; - - #[inline] - fn next(&mut self) -> Option { - self.encoder.next() - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - self.encoder.size_hint() - } -} - -#[unstable(feature = "fused", issue = "35602")] -impl<'a> FusedIterator for EncodeUtf16<'a> {} - -#[stable(feature = "rust1", since = "1.0.0")] -impl Borrow for String { - #[inline] - fn borrow(&self) -> &str { - &self[..] - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl ToOwned for str { - type Owned = String; - fn to_owned(&self) -> String { - unsafe { String::from_utf8_unchecked(self.as_bytes().to_owned()) } - } - - fn clone_into(&self, target: &mut String) { - let mut b = mem::replace(target, String::new()).into_bytes(); - self.as_bytes().clone_into(&mut b); - *target = unsafe { String::from_utf8_unchecked(b) } - } -} - -/// Methods for string slices. -#[lang = "str"] -#[cfg(not(test))] -impl str { - /// Returns the length of `self`. - /// - /// This length is in bytes, not [`char`]s or graphemes. In other words, - /// it may not be what a human considers the length of the string. - /// - /// [`char`]: primitive.char.html - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let len = "foo".len(); - /// assert_eq!(3, len); - /// - /// let len = "ƒoo".len(); // fancy f! - /// assert_eq!(4, len); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn len(&self) -> usize { - core_str::StrExt::len(self) - } - - /// Returns `true` if `self` has a length of zero bytes. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let s = ""; - /// assert!(s.is_empty()); - /// - /// let s = "not empty"; - /// assert!(!s.is_empty()); - /// ``` - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn is_empty(&self) -> bool { - core_str::StrExt::is_empty(self) - } - - /// Checks that `index`-th byte lies at the start and/or end of a - /// UTF-8 code point sequence. - /// - /// The start and end of the string (when `index == self.len()`) are - /// considered to be - /// boundaries. - /// - /// Returns `false` if `index` is greater than `self.len()`. - /// - /// # Examples - /// - /// ``` - /// let s = "Löwe 老虎 Léopard"; - /// assert!(s.is_char_boundary(0)); - /// // start of `老` - /// assert!(s.is_char_boundary(6)); - /// assert!(s.is_char_boundary(s.len())); - /// - /// // second byte of `ö` - /// assert!(!s.is_char_boundary(2)); - /// - /// // third byte of `老` - /// assert!(!s.is_char_boundary(8)); - /// ``` - #[stable(feature = "is_char_boundary", since = "1.9.0")] - #[inline] - pub fn is_char_boundary(&self, index: usize) -> bool { - core_str::StrExt::is_char_boundary(self, index) - } - - /// Converts a string slice to a byte slice. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let bytes = "bors".as_bytes(); - /// assert_eq!(b"bors", bytes); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline(always)] - pub fn as_bytes(&self) -> &[u8] { - core_str::StrExt::as_bytes(self) - } - - /// Converts a mutable string slice to a mutable byte slice. - #[unstable(feature = "str_mut_extras", issue = "41119")] - #[inline(always)] - pub unsafe fn as_bytes_mut(&mut self) -> &mut [u8] { - core_str::StrExt::as_bytes_mut(self) - } - - /// Converts a string slice to a raw pointer. - /// - /// As string slices are a slice of bytes, the raw pointer points to a - /// [`u8`]. This pointer will be pointing to the first byte of the string - /// slice. - /// - /// [`u8`]: primitive.u8.html - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let s = "Hello"; - /// let ptr = s.as_ptr(); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn as_ptr(&self) -> *const u8 { - core_str::StrExt::as_ptr(self) - } - - /// Returns a subslice of `str`. - /// - /// This is the non-panicking alternative to indexing the `str`. Returns - /// [`None`] whenever equivalent indexing operation would panic. - /// - /// [`None`]: option/enum.Option.html#variant.None - /// - /// # Examples - /// - /// ``` - /// # #![feature(str_checked_slicing)] - /// let v = "🗻∈🌏"; - /// assert_eq!(Some("🗻"), v.get(0..4)); - /// assert!(v.get(1..).is_none()); - /// assert!(v.get(..8).is_none()); - /// assert!(v.get(..42).is_none()); - /// ``` - #[unstable(feature = "str_checked_slicing", issue = "39932")] - #[inline] - pub fn get>(&self, i: I) -> Option<&I::Output> { - core_str::StrExt::get(self, i) - } - - /// Returns a mutable subslice of `str`. - /// - /// This is the non-panicking alternative to indexing the `str`. Returns - /// [`None`] whenever equivalent indexing operation would panic. - /// - /// [`None`]: option/enum.Option.html#variant.None - /// - /// # Examples - /// - /// ``` - /// # #![feature(str_checked_slicing)] - /// let mut v = String::from("🗻∈🌏"); - /// assert_eq!(Some("🗻"), v.get_mut(0..4).map(|v| &*v)); - /// assert!(v.get_mut(1..).is_none()); - /// assert!(v.get_mut(..8).is_none()); - /// assert!(v.get_mut(..42).is_none()); - /// ``` - #[unstable(feature = "str_checked_slicing", issue = "39932")] - #[inline] - pub fn get_mut>(&mut self, i: I) -> Option<&mut I::Output> { - core_str::StrExt::get_mut(self, i) - } - - /// Returns a unchecked subslice of `str`. - /// - /// This is the unchecked alternative to indexing the `str`. - /// - /// # Safety - /// - /// Callers of this function are responsible that these preconditions are - /// satisfied: - /// - /// * The starting index must come before the ending index; - /// * Indexes must be within bounds of the original slice; - /// * Indexes must lie on UTF-8 sequence boundaries. - /// - /// Failing that, the returned string slice may reference invalid memory or - /// violate the invariants communicated by the `str` type. - /// - /// # Examples - /// - /// ``` - /// # #![feature(str_checked_slicing)] - /// let v = "🗻∈🌏"; - /// unsafe { - /// assert_eq!("🗻", v.get_unchecked(0..4)); - /// assert_eq!("∈", v.get_unchecked(4..7)); - /// assert_eq!("🌏", v.get_unchecked(7..11)); - /// } - /// ``` - #[unstable(feature = "str_checked_slicing", issue = "39932")] - #[inline] - pub unsafe fn get_unchecked>(&self, i: I) -> &I::Output { - core_str::StrExt::get_unchecked(self, i) - } - - /// Returns a mutable, unchecked subslice of `str`. - /// - /// This is the unchecked alternative to indexing the `str`. - /// - /// # Safety - /// - /// Callers of this function are responsible that these preconditions are - /// satisfied: - /// - /// * The starting index must come before the ending index; - /// * Indexes must be within bounds of the original slice; - /// * Indexes must lie on UTF-8 sequence boundaries. - /// - /// Failing that, the returned string slice may reference invalid memory or - /// violate the invariants communicated by the `str` type. - /// - /// # Examples - /// - /// ``` - /// # #![feature(str_checked_slicing)] - /// let mut v = String::from("🗻∈🌏"); - /// unsafe { - /// assert_eq!("🗻", v.get_unchecked_mut(0..4)); - /// assert_eq!("∈", v.get_unchecked_mut(4..7)); - /// assert_eq!("🌏", v.get_unchecked_mut(7..11)); - /// } - /// ``` - #[unstable(feature = "str_checked_slicing", issue = "39932")] - #[inline] - pub unsafe fn get_unchecked_mut>(&mut self, i: I) -> &mut I::Output { - core_str::StrExt::get_unchecked_mut(self, i) - } - - /// Creates a string slice from another string slice, bypassing safety - /// checks. - /// - /// This is generally not recommended, use with caution! For a safe - /// alternative see [`str`] and [`Index`]. - /// - /// [`str`]: primitive.str.html - /// [`Index`]: ops/trait.Index.html - /// - /// This new slice goes from `begin` to `end`, including `begin` but - /// excluding `end`. - /// - /// To get a mutable string slice instead, see the - /// [`slice_mut_unchecked`] method. - /// - /// [`slice_mut_unchecked`]: #method.slice_mut_unchecked - /// - /// # Safety - /// - /// Callers of this function are responsible that three preconditions are - /// satisfied: - /// - /// * `begin` must come before `end`. - /// * `begin` and `end` must be byte positions within the string slice. - /// * `begin` and `end` must lie on UTF-8 sequence boundaries. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let s = "Löwe 老虎 Léopard"; - /// - /// unsafe { - /// assert_eq!("Löwe 老虎 Léopard", s.slice_unchecked(0, 21)); - /// } - /// - /// let s = "Hello, world!"; - /// - /// unsafe { - /// assert_eq!("world", s.slice_unchecked(7, 12)); - /// } - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub unsafe fn slice_unchecked(&self, begin: usize, end: usize) -> &str { - core_str::StrExt::slice_unchecked(self, begin, end) - } - - /// Creates a string slice from another string slice, bypassing safety - /// checks. - /// This is generally not recommended, use with caution! For a safe - /// alternative see [`str`] and [`IndexMut`]. - /// - /// [`str`]: primitive.str.html - /// [`IndexMut`]: ops/trait.IndexMut.html - /// - /// This new slice goes from `begin` to `end`, including `begin` but - /// excluding `end`. - /// - /// To get an immutable string slice instead, see the - /// [`slice_unchecked`] method. - /// - /// [`slice_unchecked`]: #method.slice_unchecked - /// - /// # Safety - /// - /// Callers of this function are responsible that three preconditions are - /// satisfied: - /// - /// * `begin` must come before `end`. - /// * `begin` and `end` must be byte positions within the string slice. - /// * `begin` and `end` must lie on UTF-8 sequence boundaries. - #[stable(feature = "str_slice_mut", since = "1.5.0")] - #[inline] - pub unsafe fn slice_mut_unchecked(&mut self, begin: usize, end: usize) -> &mut str { - core_str::StrExt::slice_mut_unchecked(self, begin, end) - } - - /// Divide one string slice into two at an index. - /// - /// The argument, `mid`, should be a byte offset from the start of the - /// string. It must also be on the boundary of a UTF-8 code point. - /// - /// The two slices returned go from the start of the string slice to `mid`, - /// and from `mid` to the end of the string slice. - /// - /// To get mutable string slices instead, see the [`split_at_mut`] - /// method. - /// - /// [`split_at_mut`]: #method.split_at_mut - /// - /// # Panics - /// - /// Panics if `mid` is not on a UTF-8 code point boundary, or if it is - /// beyond the last code point of the string slice. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let s = "Per Martin-Löf"; - /// - /// let (first, last) = s.split_at(3); - /// - /// assert_eq!("Per", first); - /// assert_eq!(" Martin-Löf", last); - /// ``` - #[inline] - #[stable(feature = "str_split_at", since = "1.4.0")] - pub fn split_at(&self, mid: usize) -> (&str, &str) { - core_str::StrExt::split_at(self, mid) - } - - /// Divide one mutable string slice into two at an index. - /// - /// The argument, `mid`, should be a byte offset from the start of the - /// string. It must also be on the boundary of a UTF-8 code point. - /// - /// The two slices returned go from the start of the string slice to `mid`, - /// and from `mid` to the end of the string slice. - /// - /// To get immutable string slices instead, see the [`split_at`] method. - /// - /// [`split_at`]: #method.split_at - /// - /// # Panics - /// - /// Panics if `mid` is not on a UTF-8 code point boundary, or if it is - /// beyond the last code point of the string slice. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let mut s = "Per Martin-Löf".to_string(); - /// - /// let (first, last) = s.split_at_mut(3); - /// - /// assert_eq!("Per", first); - /// assert_eq!(" Martin-Löf", last); - /// ``` - #[inline] - #[stable(feature = "str_split_at", since = "1.4.0")] - pub fn split_at_mut(&mut self, mid: usize) -> (&mut str, &mut str) { - core_str::StrExt::split_at_mut(self, mid) - } - - /// Returns an iterator over the [`char`]s of a string slice. - /// - /// As a string slice consists of valid UTF-8, we can iterate through a - /// string slice by [`char`]. This method returns such an iterator. - /// - /// It's important to remember that [`char`] represents a Unicode Scalar - /// Value, and may not match your idea of what a 'character' is. Iteration - /// over grapheme clusters may be what you actually want. - /// - /// [`char`]: primitive.char.html - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let word = "goodbye"; - /// - /// let count = word.chars().count(); - /// assert_eq!(7, count); - /// - /// let mut chars = word.chars(); - /// - /// assert_eq!(Some('g'), chars.next()); - /// assert_eq!(Some('o'), chars.next()); - /// assert_eq!(Some('o'), chars.next()); - /// assert_eq!(Some('d'), chars.next()); - /// assert_eq!(Some('b'), chars.next()); - /// assert_eq!(Some('y'), chars.next()); - /// assert_eq!(Some('e'), chars.next()); - /// - /// assert_eq!(None, chars.next()); - /// ``` - /// - /// Remember, [`char`]s may not match your human intuition about characters: - /// - /// ``` - /// let y = "y̆"; - /// - /// let mut chars = y.chars(); - /// - /// assert_eq!(Some('y'), chars.next()); // not 'y̆' - /// assert_eq!(Some('\u{0306}'), chars.next()); - /// - /// assert_eq!(None, chars.next()); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn chars(&self) -> Chars { - core_str::StrExt::chars(self) - } - /// Returns an iterator over the [`char`]s of a string slice, and their - /// positions. - /// - /// As a string slice consists of valid UTF-8, we can iterate through a - /// string slice by [`char`]. This method returns an iterator of both - /// these [`char`]s, as well as their byte positions. - /// - /// The iterator yields tuples. The position is first, the [`char`] is - /// second. - /// - /// [`char`]: primitive.char.html - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let word = "goodbye"; - /// - /// let count = word.char_indices().count(); - /// assert_eq!(7, count); - /// - /// let mut char_indices = word.char_indices(); - /// - /// assert_eq!(Some((0, 'g')), char_indices.next()); - /// assert_eq!(Some((1, 'o')), char_indices.next()); - /// assert_eq!(Some((2, 'o')), char_indices.next()); - /// assert_eq!(Some((3, 'd')), char_indices.next()); - /// assert_eq!(Some((4, 'b')), char_indices.next()); - /// assert_eq!(Some((5, 'y')), char_indices.next()); - /// assert_eq!(Some((6, 'e')), char_indices.next()); - /// - /// assert_eq!(None, char_indices.next()); - /// ``` - /// - /// Remember, [`char`]s may not match your human intuition about characters: - /// - /// ``` - /// let y = "y̆"; - /// - /// let mut char_indices = y.char_indices(); - /// - /// assert_eq!(Some((0, 'y')), char_indices.next()); // not (0, 'y̆') - /// assert_eq!(Some((1, '\u{0306}')), char_indices.next()); - /// - /// assert_eq!(None, char_indices.next()); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn char_indices(&self) -> CharIndices { - core_str::StrExt::char_indices(self) - } - - /// An iterator over the bytes of a string slice. - /// - /// As a string slice consists of a sequence of bytes, we can iterate - /// through a string slice by byte. This method returns such an iterator. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let mut bytes = "bors".bytes(); - /// - /// assert_eq!(Some(b'b'), bytes.next()); - /// assert_eq!(Some(b'o'), bytes.next()); - /// assert_eq!(Some(b'r'), bytes.next()); - /// assert_eq!(Some(b's'), bytes.next()); - /// - /// assert_eq!(None, bytes.next()); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn bytes(&self) -> Bytes { - core_str::StrExt::bytes(self) - } - - /// Split a string slice by whitespace. - /// - /// The iterator returned will return string slices that are sub-slices of - /// the original string slice, separated by any amount of whitespace. - /// - /// 'Whitespace' is defined according to the terms of the Unicode Derived - /// Core Property `White_Space`. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let mut iter = "A few words".split_whitespace(); - /// - /// assert_eq!(Some("A"), iter.next()); - /// assert_eq!(Some("few"), iter.next()); - /// assert_eq!(Some("words"), iter.next()); - /// - /// assert_eq!(None, iter.next()); - /// ``` - /// - /// All kinds of whitespace are considered: - /// - /// ``` - /// let mut iter = " Mary had\ta\u{2009}little \n\t lamb".split_whitespace(); - /// assert_eq!(Some("Mary"), iter.next()); - /// assert_eq!(Some("had"), iter.next()); - /// assert_eq!(Some("a"), iter.next()); - /// assert_eq!(Some("little"), iter.next()); - /// assert_eq!(Some("lamb"), iter.next()); - /// - /// assert_eq!(None, iter.next()); - /// ``` - #[stable(feature = "split_whitespace", since = "1.1.0")] - #[inline] - pub fn split_whitespace(&self) -> SplitWhitespace { - UnicodeStr::split_whitespace(self) - } - - /// An iterator over the lines of a string, as string slices. - /// - /// Lines are ended with either a newline (`\n`) or a carriage return with - /// a line feed (`\r\n`). - /// - /// The final line ending is optional. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let text = "foo\r\nbar\n\nbaz\n"; - /// let mut lines = text.lines(); - /// - /// assert_eq!(Some("foo"), lines.next()); - /// assert_eq!(Some("bar"), lines.next()); - /// assert_eq!(Some(""), lines.next()); - /// assert_eq!(Some("baz"), lines.next()); - /// - /// assert_eq!(None, lines.next()); - /// ``` - /// - /// The final line ending isn't required: - /// - /// ``` - /// let text = "foo\nbar\n\r\nbaz"; - /// let mut lines = text.lines(); - /// - /// assert_eq!(Some("foo"), lines.next()); - /// assert_eq!(Some("bar"), lines.next()); - /// assert_eq!(Some(""), lines.next()); - /// assert_eq!(Some("baz"), lines.next()); - /// - /// assert_eq!(None, lines.next()); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn lines(&self) -> Lines { - core_str::StrExt::lines(self) - } - - /// An iterator over the lines of a string. - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_deprecated(since = "1.4.0", reason = "use lines() instead now")] - #[inline] - #[allow(deprecated)] - pub fn lines_any(&self) -> LinesAny { - core_str::StrExt::lines_any(self) - } - - /// Returns an iterator of `u16` over the string encoded as UTF-16. - #[stable(feature = "encode_utf16", since = "1.8.0")] - pub fn encode_utf16(&self) -> EncodeUtf16 { - EncodeUtf16 { encoder: Utf16Encoder::new(self[..].chars()) } - } - - /// Returns `true` if the given pattern matches a sub-slice of - /// this string slice. - /// - /// Returns `false` if it does not. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let bananas = "bananas"; - /// - /// assert!(bananas.contains("nana")); - /// assert!(!bananas.contains("apples")); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn contains<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool { - core_str::StrExt::contains(self, pat) - } - - /// Returns `true` if the given pattern matches a prefix of this - /// string slice. - /// - /// Returns `false` if it does not. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let bananas = "bananas"; - /// - /// assert!(bananas.starts_with("bana")); - /// assert!(!bananas.starts_with("nana")); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn starts_with<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool { - core_str::StrExt::starts_with(self, pat) - } - - /// Returns `true` if the given pattern matches a suffix of this - /// string slice. - /// - /// Returns `false` if it does not. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let bananas = "bananas"; - /// - /// assert!(bananas.ends_with("anas")); - /// assert!(!bananas.ends_with("nana")); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn ends_with<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool - where P::Searcher: ReverseSearcher<'a> - { - core_str::StrExt::ends_with(self, pat) - } - - /// Returns the byte index of the first character of this string slice that - /// matches the pattern. - /// - /// Returns [`None`] if the pattern doesn't match. - /// - /// The pattern can be a `&str`, [`char`], or a closure that determines if - /// a character matches. - /// - /// [`char`]: primitive.char.html - /// [`None`]: option/enum.Option.html#variant.None - /// - /// # Examples - /// - /// Simple patterns: - /// - /// ``` - /// let s = "Löwe 老虎 Léopard"; - /// - /// assert_eq!(s.find('L'), Some(0)); - /// assert_eq!(s.find('é'), Some(14)); - /// assert_eq!(s.find("Léopard"), Some(13)); - /// ``` - /// - /// More complex patterns with closures: - /// - /// ``` - /// let s = "Löwe 老虎 Léopard"; - /// - /// assert_eq!(s.find(char::is_whitespace), Some(5)); - /// assert_eq!(s.find(char::is_lowercase), Some(1)); - /// ``` - /// - /// Not finding the pattern: - /// - /// ``` - /// let s = "Löwe 老虎 Léopard"; - /// let x: &[_] = &['1', '2']; - /// - /// assert_eq!(s.find(x), None); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn find<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option { - core_str::StrExt::find(self, pat) - } - - /// Returns the byte index of the last character of this string slice that - /// matches the pattern. - /// - /// Returns [`None`] if the pattern doesn't match. - /// - /// The pattern can be a `&str`, [`char`], or a closure that determines if - /// a character matches. - /// - /// [`char`]: primitive.char.html - /// [`None`]: option/enum.Option.html#variant.None - /// - /// # Examples - /// - /// Simple patterns: - /// - /// ``` - /// let s = "Löwe 老虎 Léopard"; - /// - /// assert_eq!(s.rfind('L'), Some(13)); - /// assert_eq!(s.rfind('é'), Some(14)); - /// ``` - /// - /// More complex patterns with closures: - /// - /// ``` - /// let s = "Löwe 老虎 Léopard"; - /// - /// assert_eq!(s.rfind(char::is_whitespace), Some(12)); - /// assert_eq!(s.rfind(char::is_lowercase), Some(20)); - /// ``` - /// - /// Not finding the pattern: - /// - /// ``` - /// let s = "Löwe 老虎 Léopard"; - /// let x: &[_] = &['1', '2']; - /// - /// assert_eq!(s.rfind(x), None); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn rfind<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option - where P::Searcher: ReverseSearcher<'a> - { - core_str::StrExt::rfind(self, pat) - } - - /// An iterator over substrings of this string slice, separated by - /// characters matched by a pattern. - /// - /// The pattern can be a `&str`, [`char`], or a closure that determines the - /// split. - /// - /// # Iterator behavior - /// - /// The returned iterator will be a [`DoubleEndedIterator`] if the pattern - /// allows a reverse search and forward/reverse search yields the same - /// elements. This is true for, eg, [`char`] but not for `&str`. - /// - /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html - /// - /// If the pattern allows a reverse search but its results might differ - /// from a forward search, the [`rsplit`] method can be used. - /// - /// [`char`]: primitive.char.html - /// [`rsplit`]: #method.rsplit - /// - /// # Examples - /// - /// Simple patterns: - /// - /// ``` - /// let v: Vec<&str> = "Mary had a little lamb".split(' ').collect(); - /// assert_eq!(v, ["Mary", "had", "a", "little", "lamb"]); - /// - /// let v: Vec<&str> = "".split('X').collect(); - /// assert_eq!(v, [""]); - /// - /// let v: Vec<&str> = "lionXXtigerXleopard".split('X').collect(); - /// assert_eq!(v, ["lion", "", "tiger", "leopard"]); - /// - /// let v: Vec<&str> = "lion::tiger::leopard".split("::").collect(); - /// assert_eq!(v, ["lion", "tiger", "leopard"]); - /// - /// let v: Vec<&str> = "abc1def2ghi".split(char::is_numeric).collect(); - /// assert_eq!(v, ["abc", "def", "ghi"]); - /// - /// let v: Vec<&str> = "lionXtigerXleopard".split(char::is_uppercase).collect(); - /// assert_eq!(v, ["lion", "tiger", "leopard"]); - /// ``` - /// - /// A more complex pattern, using a closure: - /// - /// ``` - /// let v: Vec<&str> = "abc1defXghi".split(|c| c == '1' || c == 'X').collect(); - /// assert_eq!(v, ["abc", "def", "ghi"]); - /// ``` - /// - /// If a string contains multiple contiguous separators, you will end up - /// with empty strings in the output: - /// - /// ``` - /// let x = "||||a||b|c".to_string(); - /// let d: Vec<_> = x.split('|').collect(); - /// - /// assert_eq!(d, &["", "", "", "", "a", "", "b", "c"]); - /// ``` - /// - /// Contiguous separators are separated by the empty string. - /// - /// ``` - /// let x = "(///)".to_string(); - /// let d: Vec<_> = x.split('/').collect(); - /// - /// assert_eq!(d, &["(", "", "", ")"]); - /// ``` - /// - /// Separators at the start or end of a string are neighbored - /// by empty strings. - /// - /// ``` - /// let d: Vec<_> = "010".split("0").collect(); - /// assert_eq!(d, &["", "1", ""]); - /// ``` - /// - /// When the empty string is used as a separator, it separates - /// every character in the string, along with the beginning - /// and end of the string. - /// - /// ``` - /// let f: Vec<_> = "rust".split("").collect(); - /// assert_eq!(f, &["", "r", "u", "s", "t", ""]); - /// ``` - /// - /// Contiguous separators can lead to possibly surprising behavior - /// when whitespace is used as the separator. This code is correct: - /// - /// ``` - /// let x = " a b c".to_string(); - /// let d: Vec<_> = x.split(' ').collect(); - /// - /// assert_eq!(d, &["", "", "", "", "a", "", "b", "c"]); - /// ``` - /// - /// It does _not_ give you: - /// - /// ```,ignore - /// assert_eq!(d, &["a", "b", "c"]); - /// ``` - /// - /// Use [`split_whitespace`] for this behavior. - /// - /// [`split_whitespace`]: #method.split_whitespace - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn split<'a, P: Pattern<'a>>(&'a self, pat: P) -> Split<'a, P> { - core_str::StrExt::split(self, pat) - } - - /// An iterator over substrings of the given string slice, separated by - /// characters matched by a pattern and yielded in reverse order. - /// - /// The pattern can be a `&str`, [`char`], or a closure that determines the - /// split. - /// - /// [`char`]: primitive.char.html - /// - /// # Iterator behavior - /// - /// The returned iterator requires that the pattern supports a reverse - /// search, and it will be a [`DoubleEndedIterator`] if a forward/reverse - /// search yields the same elements. - /// - /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html - /// - /// For iterating from the front, the [`split`] method can be used. - /// - /// [`split`]: #method.split - /// - /// # Examples - /// - /// Simple patterns: - /// - /// ``` - /// let v: Vec<&str> = "Mary had a little lamb".rsplit(' ').collect(); - /// assert_eq!(v, ["lamb", "little", "a", "had", "Mary"]); - /// - /// let v: Vec<&str> = "".rsplit('X').collect(); - /// assert_eq!(v, [""]); - /// - /// let v: Vec<&str> = "lionXXtigerXleopard".rsplit('X').collect(); - /// assert_eq!(v, ["leopard", "tiger", "", "lion"]); - /// - /// let v: Vec<&str> = "lion::tiger::leopard".rsplit("::").collect(); - /// assert_eq!(v, ["leopard", "tiger", "lion"]); - /// ``` - /// - /// A more complex pattern, using a closure: - /// - /// ``` - /// let v: Vec<&str> = "abc1defXghi".rsplit(|c| c == '1' || c == 'X').collect(); - /// assert_eq!(v, ["ghi", "def", "abc"]); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn rsplit<'a, P: Pattern<'a>>(&'a self, pat: P) -> RSplit<'a, P> - where P::Searcher: ReverseSearcher<'a> - { - core_str::StrExt::rsplit(self, pat) - } - - /// An iterator over substrings of the given string slice, separated by - /// characters matched by a pattern. - /// - /// The pattern can be a `&str`, [`char`], or a closure that determines the - /// split. - /// - /// Equivalent to [`split`], except that the trailing substring - /// is skipped if empty. - /// - /// [`split`]: #method.split - /// - /// This method can be used for string data that is _terminated_, - /// rather than _separated_ by a pattern. - /// - /// # Iterator behavior - /// - /// The returned iterator will be a [`DoubleEndedIterator`] if the pattern - /// allows a reverse search and forward/reverse search yields the same - /// elements. This is true for, eg, [`char`] but not for `&str`. - /// - /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html - /// [`char`]: primitive.char.html - /// - /// If the pattern allows a reverse search but its results might differ - /// from a forward search, the [`rsplit_terminator`] method can be used. - /// - /// [`rsplit_terminator`]: #method.rsplit_terminator - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let v: Vec<&str> = "A.B.".split_terminator('.').collect(); - /// assert_eq!(v, ["A", "B"]); - /// - /// let v: Vec<&str> = "A..B..".split_terminator(".").collect(); - /// assert_eq!(v, ["A", "", "B", ""]); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn split_terminator<'a, P: Pattern<'a>>(&'a self, pat: P) -> SplitTerminator<'a, P> { - core_str::StrExt::split_terminator(self, pat) - } - - /// An iterator over substrings of `self`, separated by characters - /// matched by a pattern and yielded in reverse order. - /// - /// The pattern can be a simple `&str`, [`char`], or a closure that - /// determines the split. - /// Additional libraries might provide more complex patterns like - /// regular expressions. - /// - /// [`char`]: primitive.char.html - /// - /// Equivalent to [`split`], except that the trailing substring is - /// skipped if empty. - /// - /// [`split`]: #method.split - /// - /// This method can be used for string data that is _terminated_, - /// rather than _separated_ by a pattern. - /// - /// # Iterator behavior - /// - /// The returned iterator requires that the pattern supports a - /// reverse search, and it will be double ended if a forward/reverse - /// search yields the same elements. - /// - /// For iterating from the front, the [`split_terminator`] method can be - /// used. - /// - /// [`split_terminator`]: #method.split_terminator - /// - /// # Examples - /// - /// ``` - /// let v: Vec<&str> = "A.B.".rsplit_terminator('.').collect(); - /// assert_eq!(v, ["B", "A"]); - /// - /// let v: Vec<&str> = "A..B..".rsplit_terminator(".").collect(); - /// assert_eq!(v, ["", "B", "", "A"]); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn rsplit_terminator<'a, P: Pattern<'a>>(&'a self, pat: P) -> RSplitTerminator<'a, P> - where P::Searcher: ReverseSearcher<'a> - { - core_str::StrExt::rsplit_terminator(self, pat) - } - - /// An iterator over substrings of the given string slice, separated by a - /// pattern, restricted to returning at most `n` items. - /// - /// If `n` substrings are returned, the last substring (the `n`th substring) - /// will contain the remainder of the string. - /// - /// The pattern can be a `&str`, [`char`], or a closure that determines the - /// split. - /// - /// [`char`]: primitive.char.html - /// - /// # Iterator behavior - /// - /// The returned iterator will not be double ended, because it is - /// not efficient to support. - /// - /// If the pattern allows a reverse search, the [`rsplitn`] method can be - /// used. - /// - /// [`rsplitn`]: #method.rsplitn - /// - /// # Examples - /// - /// Simple patterns: - /// - /// ``` - /// let v: Vec<&str> = "Mary had a little lambda".splitn(3, ' ').collect(); - /// assert_eq!(v, ["Mary", "had", "a little lambda"]); - /// - /// let v: Vec<&str> = "lionXXtigerXleopard".splitn(3, "X").collect(); - /// assert_eq!(v, ["lion", "", "tigerXleopard"]); - /// - /// let v: Vec<&str> = "abcXdef".splitn(1, 'X').collect(); - /// assert_eq!(v, ["abcXdef"]); - /// - /// let v: Vec<&str> = "".splitn(1, 'X').collect(); - /// assert_eq!(v, [""]); - /// ``` - /// - /// A more complex pattern, using a closure: - /// - /// ``` - /// let v: Vec<&str> = "abc1defXghi".splitn(2, |c| c == '1' || c == 'X').collect(); - /// assert_eq!(v, ["abc", "defXghi"]); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn splitn<'a, P: Pattern<'a>>(&'a self, n: usize, pat: P) -> SplitN<'a, P> { - core_str::StrExt::splitn(self, n, pat) - } - - /// An iterator over substrings of this string slice, separated by a - /// pattern, starting from the end of the string, restricted to returning - /// at most `n` items. - /// - /// If `n` substrings are returned, the last substring (the `n`th substring) - /// will contain the remainder of the string. - /// - /// The pattern can be a `&str`, [`char`], or a closure that - /// determines the split. - /// - /// [`char`]: primitive.char.html - /// - /// # Iterator behavior - /// - /// The returned iterator will not be double ended, because it is not - /// efficient to support. - /// - /// For splitting from the front, the [`splitn`] method can be used. - /// - /// [`splitn`]: #method.splitn - /// - /// # Examples - /// - /// Simple patterns: - /// - /// ``` - /// let v: Vec<&str> = "Mary had a little lamb".rsplitn(3, ' ').collect(); - /// assert_eq!(v, ["lamb", "little", "Mary had a"]); - /// - /// let v: Vec<&str> = "lionXXtigerXleopard".rsplitn(3, 'X').collect(); - /// assert_eq!(v, ["leopard", "tiger", "lionX"]); - /// - /// let v: Vec<&str> = "lion::tiger::leopard".rsplitn(2, "::").collect(); - /// assert_eq!(v, ["leopard", "lion::tiger"]); - /// ``` - /// - /// A more complex pattern, using a closure: - /// - /// ``` - /// let v: Vec<&str> = "abc1defXghi".rsplitn(2, |c| c == '1' || c == 'X').collect(); - /// assert_eq!(v, ["ghi", "abc1def"]); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn rsplitn<'a, P: Pattern<'a>>(&'a self, n: usize, pat: P) -> RSplitN<'a, P> - where P::Searcher: ReverseSearcher<'a> - { - core_str::StrExt::rsplitn(self, n, pat) - } - - /// An iterator over the disjoint matches of a pattern within the given string - /// slice. - /// - /// The pattern can be a `&str`, [`char`], or a closure that - /// determines if a character matches. - /// - /// [`char`]: primitive.char.html - /// - /// # Iterator behavior - /// - /// The returned iterator will be a [`DoubleEndedIterator`] if the pattern - /// allows a reverse search and forward/reverse search yields the same - /// elements. This is true for, eg, [`char`] but not for `&str`. - /// - /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html - /// [`char`]: primitive.char.html - /// - /// If the pattern allows a reverse search but its results might differ - /// from a forward search, the [`rmatches`] method can be used. - /// - /// [`rmatches`]: #method.rmatches - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let v: Vec<&str> = "abcXXXabcYYYabc".matches("abc").collect(); - /// assert_eq!(v, ["abc", "abc", "abc"]); - /// - /// let v: Vec<&str> = "1abc2abc3".matches(char::is_numeric).collect(); - /// assert_eq!(v, ["1", "2", "3"]); - /// ``` - #[stable(feature = "str_matches", since = "1.2.0")] - #[inline] - pub fn matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> Matches<'a, P> { - core_str::StrExt::matches(self, pat) - } - - /// An iterator over the disjoint matches of a pattern within this string slice, - /// yielded in reverse order. - /// - /// The pattern can be a `&str`, [`char`], or a closure that determines if - /// a character matches. - /// - /// [`char`]: primitive.char.html - /// - /// # Iterator behavior - /// - /// The returned iterator requires that the pattern supports a reverse - /// search, and it will be a [`DoubleEndedIterator`] if a forward/reverse - /// search yields the same elements. - /// - /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html - /// - /// For iterating from the front, the [`matches`] method can be used. - /// - /// [`matches`]: #method.matches - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let v: Vec<&str> = "abcXXXabcYYYabc".rmatches("abc").collect(); - /// assert_eq!(v, ["abc", "abc", "abc"]); - /// - /// let v: Vec<&str> = "1abc2abc3".rmatches(char::is_numeric).collect(); - /// assert_eq!(v, ["3", "2", "1"]); - /// ``` - #[stable(feature = "str_matches", since = "1.2.0")] - #[inline] - pub fn rmatches<'a, P: Pattern<'a>>(&'a self, pat: P) -> RMatches<'a, P> - where P::Searcher: ReverseSearcher<'a> - { - core_str::StrExt::rmatches(self, pat) - } - - /// An iterator over the disjoint matches of a pattern within this string - /// slice as well as the index that the match starts at. - /// - /// For matches of `pat` within `self` that overlap, only the indices - /// corresponding to the first match are returned. - /// - /// The pattern can be a `&str`, [`char`], or a closure that determines - /// if a character matches. - /// - /// [`char`]: primitive.char.html - /// - /// # Iterator behavior - /// - /// The returned iterator will be a [`DoubleEndedIterator`] if the pattern - /// allows a reverse search and forward/reverse search yields the same - /// elements. This is true for, eg, [`char`] but not for `&str`. - /// - /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html - /// - /// If the pattern allows a reverse search but its results might differ - /// from a forward search, the [`rmatch_indices`] method can be used. - /// - /// [`rmatch_indices`]: #method.rmatch_indices - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let v: Vec<_> = "abcXXXabcYYYabc".match_indices("abc").collect(); - /// assert_eq!(v, [(0, "abc"), (6, "abc"), (12, "abc")]); - /// - /// let v: Vec<_> = "1abcabc2".match_indices("abc").collect(); - /// assert_eq!(v, [(1, "abc"), (4, "abc")]); - /// - /// let v: Vec<_> = "ababa".match_indices("aba").collect(); - /// assert_eq!(v, [(0, "aba")]); // only the first `aba` - /// ``` - #[stable(feature = "str_match_indices", since = "1.5.0")] - #[inline] - pub fn match_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> MatchIndices<'a, P> { - core_str::StrExt::match_indices(self, pat) - } - - /// An iterator over the disjoint matches of a pattern within `self`, - /// yielded in reverse order along with the index of the match. - /// - /// For matches of `pat` within `self` that overlap, only the indices - /// corresponding to the last match are returned. - /// - /// The pattern can be a `&str`, [`char`], or a closure that determines if a - /// character matches. - /// - /// [`char`]: primitive.char.html - /// - /// # Iterator behavior - /// - /// The returned iterator requires that the pattern supports a reverse - /// search, and it will be a [`DoubleEndedIterator`] if a forward/reverse - /// search yields the same elements. - /// - /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html - /// - /// For iterating from the front, the [`match_indices`] method can be used. - /// - /// [`match_indices`]: #method.match_indices - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let v: Vec<_> = "abcXXXabcYYYabc".rmatch_indices("abc").collect(); - /// assert_eq!(v, [(12, "abc"), (6, "abc"), (0, "abc")]); - /// - /// let v: Vec<_> = "1abcabc2".rmatch_indices("abc").collect(); - /// assert_eq!(v, [(4, "abc"), (1, "abc")]); - /// - /// let v: Vec<_> = "ababa".rmatch_indices("aba").collect(); - /// assert_eq!(v, [(2, "aba")]); // only the last `aba` - /// ``` - #[stable(feature = "str_match_indices", since = "1.5.0")] - #[inline] - pub fn rmatch_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> RMatchIndices<'a, P> - where P::Searcher: ReverseSearcher<'a> - { - core_str::StrExt::rmatch_indices(self, pat) - } - - /// Returns a string slice with leading and trailing whitespace removed. - /// - /// 'Whitespace' is defined according to the terms of the Unicode Derived - /// Core Property `White_Space`. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let s = " Hello\tworld\t"; - /// - /// assert_eq!("Hello\tworld", s.trim()); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn trim(&self) -> &str { - UnicodeStr::trim(self) - } - - /// Returns a string slice with leading whitespace removed. - /// - /// 'Whitespace' is defined according to the terms of the Unicode Derived - /// Core Property `White_Space`. - /// - /// # Text directionality - /// - /// A string is a sequence of bytes. 'Left' in this context means the first - /// position of that byte string; for a language like Arabic or Hebrew - /// which are 'right to left' rather than 'left to right', this will be - /// the _right_ side, not the left. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let s = " Hello\tworld\t"; - /// - /// assert_eq!("Hello\tworld\t", s.trim_left()); - /// ``` - /// - /// Directionality: - /// - /// ``` - /// let s = " English"; - /// assert!(Some('E') == s.trim_left().chars().next()); - /// - /// let s = " עברית"; - /// assert!(Some('ע') == s.trim_left().chars().next()); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn trim_left(&self) -> &str { - UnicodeStr::trim_left(self) - } - - /// Returns a string slice with trailing whitespace removed. - /// - /// 'Whitespace' is defined according to the terms of the Unicode Derived - /// Core Property `White_Space`. - /// - /// # Text directionality - /// - /// A string is a sequence of bytes. 'Right' in this context means the last - /// position of that byte string; for a language like Arabic or Hebrew - /// which are 'right to left' rather than 'left to right', this will be - /// the _left_ side, not the right. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let s = " Hello\tworld\t"; - /// - /// assert_eq!(" Hello\tworld", s.trim_right()); - /// ``` - /// - /// Directionality: - /// - /// ``` - /// let s = "English "; - /// assert!(Some('h') == s.trim_right().chars().rev().next()); - /// - /// let s = "עברית "; - /// assert!(Some('ת') == s.trim_right().chars().rev().next()); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn trim_right(&self) -> &str { - UnicodeStr::trim_right(self) - } - - /// Returns a string slice with all prefixes and suffixes that match a - /// pattern repeatedly removed. - /// - /// The pattern can be a [`char`] or a closure that determines if a - /// character matches. - /// - /// [`char`]: primitive.char.html - /// - /// # Examples - /// - /// Simple patterns: - /// - /// ``` - /// assert_eq!("11foo1bar11".trim_matches('1'), "foo1bar"); - /// assert_eq!("123foo1bar123".trim_matches(char::is_numeric), "foo1bar"); - /// - /// let x: &[_] = &['1', '2']; - /// assert_eq!("12foo1bar12".trim_matches(x), "foo1bar"); - /// ``` - /// - /// A more complex pattern, using a closure: - /// - /// ``` - /// assert_eq!("1foo1barXX".trim_matches(|c| c == '1' || c == 'X'), "foo1bar"); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn trim_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str - where P::Searcher: DoubleEndedSearcher<'a> - { - core_str::StrExt::trim_matches(self, pat) - } - - /// Returns a string slice with all prefixes that match a pattern - /// repeatedly removed. - /// - /// The pattern can be a `&str`, [`char`], or a closure that determines if - /// a character matches. - /// - /// [`char`]: primitive.char.html - /// - /// # Text directionality - /// - /// A string is a sequence of bytes. 'Left' in this context means the first - /// position of that byte string; for a language like Arabic or Hebrew - /// which are 'right to left' rather than 'left to right', this will be - /// the _right_ side, not the left. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// assert_eq!("11foo1bar11".trim_left_matches('1'), "foo1bar11"); - /// assert_eq!("123foo1bar123".trim_left_matches(char::is_numeric), "foo1bar123"); - /// - /// let x: &[_] = &['1', '2']; - /// assert_eq!("12foo1bar12".trim_left_matches(x), "foo1bar12"); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn trim_left_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str { - core_str::StrExt::trim_left_matches(self, pat) - } - - /// Returns a string slice with all suffixes that match a pattern - /// repeatedly removed. - /// - /// The pattern can be a `&str`, [`char`], or a closure that - /// determines if a character matches. - /// - /// [`char`]: primitive.char.html - /// - /// # Text directionality - /// - /// A string is a sequence of bytes. 'Right' in this context means the last - /// position of that byte string; for a language like Arabic or Hebrew - /// which are 'right to left' rather than 'left to right', this will be - /// the _left_ side, not the right. - /// - /// # Examples - /// - /// Simple patterns: - /// - /// ``` - /// assert_eq!("11foo1bar11".trim_right_matches('1'), "11foo1bar"); - /// assert_eq!("123foo1bar123".trim_right_matches(char::is_numeric), "123foo1bar"); - /// - /// let x: &[_] = &['1', '2']; - /// assert_eq!("12foo1bar12".trim_right_matches(x), "12foo1bar"); - /// ``` - /// - /// A more complex pattern, using a closure: - /// - /// ``` - /// assert_eq!("1fooX".trim_left_matches(|c| c == '1' || c == 'X'), "fooX"); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn trim_right_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str - where P::Searcher: ReverseSearcher<'a> - { - core_str::StrExt::trim_right_matches(self, pat) - } - - /// Parses this string slice into another type. - /// - /// Because `parse` is so general, it can cause problems with type - /// inference. As such, `parse` is one of the few times you'll see - /// the syntax affectionately known as the 'turbofish': `::<>`. This - /// helps the inference algorithm understand specifically which type - /// you're trying to parse into. - /// - /// `parse` can parse any type that implements the [`FromStr`] trait. - /// - /// [`FromStr`]: str/trait.FromStr.html - /// - /// # Errors - /// - /// Will return [`Err`] if it's not possible to parse this string slice into - /// the desired type. - /// - /// [`Err`]: str/trait.FromStr.html#associatedtype.Err - /// - /// # Example - /// - /// Basic usage - /// - /// ``` - /// let four: u32 = "4".parse().unwrap(); - /// - /// assert_eq!(4, four); - /// ``` - /// - /// Using the 'turbofish' instead of annotating `four`: - /// - /// ``` - /// let four = "4".parse::(); - /// - /// assert_eq!(Ok(4), four); - /// ``` - /// - /// Failing to parse: - /// - /// ``` - /// let nope = "j".parse::(); - /// - /// assert!(nope.is_err()); - /// ``` - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn parse(&self) -> Result { - core_str::StrExt::parse(self) - } - - /// Converts a `Box` into a `Box<[u8]>` without copying or allocating. - #[unstable(feature = "str_box_extras", issue = "41119")] - pub fn into_boxed_bytes(self: Box) -> Box<[u8]> { - self.into() - } - - /// Replaces all matches of a pattern with another string. - /// - /// `replace` creates a new [`String`], and copies the data from this string slice into it. - /// While doing so, it attempts to find matches of a pattern. If it finds any, it - /// replaces them with the replacement string slice. - /// - /// [`String`]: string/struct.String.html - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let s = "this is old"; - /// - /// assert_eq!("this is new", s.replace("old", "new")); - /// ``` - /// - /// When the pattern doesn't match: - /// - /// ``` - /// let s = "this is old"; - /// assert_eq!(s, s.replace("cookie monster", "little lamb")); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn replace<'a, P: Pattern<'a>>(&'a self, from: P, to: &str) -> String { - let mut result = String::new(); - let mut last_end = 0; - for (start, part) in self.match_indices(from) { - result.push_str(unsafe { self.slice_unchecked(last_end, start) }); - result.push_str(to); - last_end = start + part.len(); - } - result.push_str(unsafe { self.slice_unchecked(last_end, self.len()) }); - result - } - - /// Replaces first N matches of a pattern with another string. - /// - /// `replacen` creates a new [`String`], and copies the data from this string slice into it. - /// While doing so, it attempts to find matches of a pattern. If it finds any, it - /// replaces them with the replacement string slice at most `count` times. - /// - /// [`String`]: string/struct.String.html - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let s = "foo foo 123 foo"; - /// assert_eq!("new new 123 foo", s.replacen("foo", "new", 2)); - /// assert_eq!("faa fao 123 foo", s.replacen('o', "a", 3)); - /// assert_eq!("foo foo new23 foo", s.replacen(char::is_numeric, "new", 1)); - /// ``` - /// - /// When the pattern doesn't match: - /// - /// ``` - /// let s = "this is old"; - /// assert_eq!(s, s.replacen("cookie monster", "little lamb", 10)); - /// ``` - #[stable(feature = "str_replacen", since = "1.16.0")] - pub fn replacen<'a, P: Pattern<'a>>(&'a self, pat: P, to: &str, count: usize) -> String { - // Hope to reduce the times of re-allocation - let mut result = String::with_capacity(32); - let mut last_end = 0; - for (start, part) in self.match_indices(pat).take(count) { - result.push_str(unsafe { self.slice_unchecked(last_end, start) }); - result.push_str(to); - last_end = start + part.len(); - } - result.push_str(unsafe { self.slice_unchecked(last_end, self.len()) }); - result - } - - /// Returns the lowercase equivalent of this string slice, as a new [`String`]. - /// - /// 'Lowercase' is defined according to the terms of the Unicode Derived Core Property - /// `Lowercase`. - /// - /// Since some characters can expand into multiple characters when changing - /// the case, this function returns a [`String`] instead of modifying the - /// parameter in-place. - /// - /// [`String`]: string/struct.String.html - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let s = "HELLO"; - /// - /// assert_eq!("hello", s.to_lowercase()); - /// ``` - /// - /// A tricky example, with sigma: - /// - /// ``` - /// let sigma = "Σ"; - /// - /// assert_eq!("σ", sigma.to_lowercase()); - /// - /// // but at the end of a word, it's ς, not σ: - /// let odysseus = "ὈΔΥΣΣΕΎΣ"; - /// - /// assert_eq!("ὀδυσσεύς", odysseus.to_lowercase()); - /// ``` - /// - /// Languages without case are not changed: - /// - /// ``` - /// let new_year = "农历新年"; - /// - /// assert_eq!(new_year, new_year.to_lowercase()); - /// ``` - #[stable(feature = "unicode_case_mapping", since = "1.2.0")] - pub fn to_lowercase(&self) -> String { - let mut s = String::with_capacity(self.len()); - for (i, c) in self[..].char_indices() { - if c == 'Σ' { - // Σ maps to σ, except at the end of a word where it maps to ς. - // This is the only conditional (contextual) but language-independent mapping - // in `SpecialCasing.txt`, - // so hard-code it rather than have a generic "condition" mechanism. - // See https://github.com/rust-lang/rust/issues/26035 - map_uppercase_sigma(self, i, &mut s) - } else { - s.extend(c.to_lowercase()); - } - } - return s; - - fn map_uppercase_sigma(from: &str, i: usize, to: &mut String) { - // See http://www.unicode.org/versions/Unicode7.0.0/ch03.pdf#G33992 - // for the definition of `Final_Sigma`. - debug_assert!('Σ'.len_utf8() == 2); - let is_word_final = case_ignoreable_then_cased(from[..i].chars().rev()) && - !case_ignoreable_then_cased(from[i + 2..].chars()); - to.push_str(if is_word_final { "ς" } else { "σ" }); - } - - fn case_ignoreable_then_cased>(iter: I) -> bool { - use std_unicode::derived_property::{Cased, Case_Ignorable}; - match iter.skip_while(|&c| Case_Ignorable(c)).next() { - Some(c) => Cased(c), - None => false, - } - } - } - - /// Returns the uppercase equivalent of this string slice, as a new [`String`]. - /// - /// 'Uppercase' is defined according to the terms of the Unicode Derived Core Property - /// `Uppercase`. - /// - /// Since some characters can expand into multiple characters when changing - /// the case, this function returns a [`String`] instead of modifying the - /// parameter in-place. - /// - /// [`String`]: string/struct.String.html - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let s = "hello"; - /// - /// assert_eq!("HELLO", s.to_uppercase()); - /// ``` - /// - /// Scripts without case are not changed: - /// - /// ``` - /// let new_year = "农历新年"; - /// - /// assert_eq!(new_year, new_year.to_uppercase()); - /// ``` - #[stable(feature = "unicode_case_mapping", since = "1.2.0")] - pub fn to_uppercase(&self) -> String { - let mut s = String::with_capacity(self.len()); - s.extend(self.chars().flat_map(|c| c.to_uppercase())); - return s; - } - - /// Escapes each char in `s` with [`char::escape_debug`]. - /// - /// [`char::escape_debug`]: primitive.char.html#method.escape_debug - #[unstable(feature = "str_escape", - reason = "return type may change to be an iterator", - issue = "27791")] - pub fn escape_debug(&self) -> String { - self.chars().flat_map(|c| c.escape_debug()).collect() - } - - /// Escapes each char in `s` with [`char::escape_default`]. - /// - /// [`char::escape_default`]: primitive.char.html#method.escape_default - #[unstable(feature = "str_escape", - reason = "return type may change to be an iterator", - issue = "27791")] - pub fn escape_default(&self) -> String { - self.chars().flat_map(|c| c.escape_default()).collect() - } - - /// Escapes each char in `s` with [`char::escape_unicode`]. - /// - /// [`char::escape_unicode`]: primitive.char.html#method.escape_unicode - #[unstable(feature = "str_escape", - reason = "return type may change to be an iterator", - issue = "27791")] - pub fn escape_unicode(&self) -> String { - self.chars().flat_map(|c| c.escape_unicode()).collect() - } - - /// Converts a [`Box`] into a [`String`] without copying or allocating. - /// - /// [`String`]: string/struct.String.html - /// [`Box`]: boxed/struct.Box.html - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let string = String::from("birthday gift"); - /// let boxed_str = string.clone().into_boxed_str(); - /// - /// assert_eq!(boxed_str.into_string(), string); - /// ``` - #[stable(feature = "box_str", since = "1.4.0")] - pub fn into_string(self: Box) -> String { - unsafe { - let slice = mem::transmute::, Box<[u8]>>(self); - String::from_utf8_unchecked(slice.into_vec()) - } - } - - /// Create a [`String`] by repeating a string `n` times. - /// - /// [`String`]: string/struct.String.html - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// assert_eq!("abc".repeat(4), String::from("abcabcabcabc")); - /// ``` - #[stable(feature = "repeat_str", since = "1.16.0")] - pub fn repeat(&self, n: usize) -> String { - let mut s = String::with_capacity(self.len() * n); - s.extend((0..n).map(|_| self)); - s - } -} diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 34aca592b1e9..c374f4009744 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -2015,7 +2015,7 @@ mod traits { issue = "32110")] pub trait StrExt { // NB there are no docs here are they're all located on the StrExt trait in - // libcollections, not here. + // liballoc, not here. #[stable(feature = "core", since = "1.6.0")] fn contains<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool; diff --git a/src/librustc_data_structures/fnv.rs b/src/librustc_data_structures/fnv.rs index ae90c2fac832..5bd57236e7c2 100644 --- a/src/librustc_data_structures/fnv.rs +++ b/src/librustc_data_structures/fnv.rs @@ -26,7 +26,7 @@ pub fn FnvHashSet() -> FnvHashSet { } /// A speedy hash algorithm for node ids and def ids. The hashmap in -/// libcollections by default uses SipHash which isn't quite as speedy as we +/// liballoc by default uses SipHash which isn't quite as speedy as we /// want. In the compiler we're not really worried about DOS attempts, so we /// just default to a non-cryptographic hash. /// diff --git a/src/librustc_data_structures/fx.rs b/src/librustc_data_structures/fx.rs index 1fb7673521d8..00dfc1617a8b 100644 --- a/src/librustc_data_structures/fx.rs +++ b/src/librustc_data_structures/fx.rs @@ -26,7 +26,7 @@ pub fn FxHashSet() -> FxHashSet { HashSet::default() } -/// A speedy hash algorithm for use within rustc. The hashmap in libcollections +/// A speedy hash algorithm for use within rustc. The hashmap in liballoc /// by default uses SipHash which isn't quite as speedy as we want. In the /// compiler we're not really worried about DOS attempts, so we use a fast /// non-cryptographic hash. diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 1a5cf89f9699..87c85a5fc96b 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -188,16 +188,16 @@ already been imported. Erroneous code example: ```compile_fail,E0254 -extern crate collections; +extern crate alloc; mod foo { - pub trait collections { + pub trait alloc { fn do_something(); } } -use foo::collections; // error: an extern crate named `collections` has already - // been imported in this module +use foo::alloc; // error: an extern crate named `alloc` has already + // been imported in this module fn main() {} ``` @@ -206,15 +206,15 @@ To fix issue issue, you have to rename at least one of the two imports. Example: ```ignore -extern crate collections as libcollections; // ok! +extern crate alloc as liballoc; // ok! mod foo { - pub trait collections { + pub trait alloc { fn do_something(); } } -use foo::collections; +use foo::alloc; fn main() {} ``` @@ -1425,7 +1425,7 @@ Erroneous code example: ```compile_fail,E0469 #[macro_use(drink, be_merry)] // error: imported macro not found -extern crate collections; +extern crate alloc; fn main() { // ... @@ -1467,7 +1467,7 @@ Erroneous code example: ```compile_fail,E0470 #[macro_reexport(drink, be_merry)] -extern crate collections; +extern crate alloc; fn main() { // ... diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 76c664d7997a..87cb807c70c5 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -2265,8 +2265,8 @@ If `ForeignTrait` is a trait defined in some external crate `foo`, then the following trait `impl` is an error: ```compile_fail,E0210 -extern crate collections; -use collections::range::RangeArgument; +extern crate alloc; +use alloc::range::RangeArgument; impl RangeArgument for T { } // error diff --git a/src/libserialize/collection_impls.rs b/src/libserialize/collection_impls.rs index 05cfb6352fbb..1a995276931d 100644 --- a/src/libserialize/collection_impls.rs +++ b/src/libserialize/collection_impls.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Implementations of serialization for structures found in libcollections +//! Implementations of serialization for structures found in liballoc use std::hash::{Hash, BuildHasher}; diff --git a/src/libserialize/lib.rs b/src/libserialize/lib.rs index 4eb2cad5c91b..ca27b34d6810 100644 --- a/src/libserialize/lib.rs +++ b/src/libserialize/lib.rs @@ -28,15 +28,12 @@ Core encoding and decoding interfaces. #![deny(warnings)] #![feature(box_syntax)] -#![feature(collections)] #![feature(core_intrinsics)] #![feature(i128_type)] #![feature(specialization)] #![cfg_attr(stage0, feature(staged_api))] #![cfg_attr(test, feature(test))] -extern crate collections; - pub use self::serialize::{Decoder, Encoder, Decodable, Encodable}; pub use self::serialize::{SpecializationError, SpecializedEncoder, SpecializedDecoder}; diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index e17918506fe5..47949566d042 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -15,7 +15,6 @@ alloc_jemalloc = { path = "../liballoc_jemalloc", optional = true } alloc_system = { path = "../liballoc_system" } panic_unwind = { path = "../libpanic_unwind", optional = true } panic_abort = { path = "../libpanic_abort" } -collections = { path = "../libcollections" } core = { path = "../libcore" } libc = { path = "../rustc/libc_shim" } rand = { path = "../librand" } diff --git a/src/libstd/collections/mod.rs b/src/libstd/collections/mod.rs index 506bf717337b..b8a6a66eaa65 100644 --- a/src/libstd/collections/mod.rs +++ b/src/libstd/collections/mod.rs @@ -420,15 +420,15 @@ #![stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")] -pub use core_collections::Bound; +pub use alloc::Bound; #[stable(feature = "rust1", since = "1.0.0")] -pub use core_collections::{BinaryHeap, BTreeMap, BTreeSet}; +pub use alloc::{BinaryHeap, BTreeMap, BTreeSet}; #[stable(feature = "rust1", since = "1.0.0")] -pub use core_collections::{LinkedList, VecDeque}; +pub use alloc::{LinkedList, VecDeque}; #[stable(feature = "rust1", since = "1.0.0")] -pub use core_collections::{binary_heap, btree_map, btree_set}; +pub use alloc::{binary_heap, btree_map, btree_set}; #[stable(feature = "rust1", since = "1.0.0")] -pub use core_collections::{linked_list, vec_deque}; +pub use alloc::{linked_list, vec_deque}; #[stable(feature = "rust1", since = "1.0.0")] pub use self::hash_map::HashMap; @@ -436,7 +436,7 @@ pub use self::hash_map::HashMap; pub use self::hash_set::HashSet; #[stable(feature = "rust1", since = "1.0.0")] -pub use core_collections::range; +pub use alloc::range; mod hash; diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index b0820d6f05a0..f307fbb7c003 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -254,7 +254,6 @@ #![feature(cfg_target_vendor)] #![feature(char_escape_debug)] #![feature(char_internals)] -#![feature(collections)] #![feature(collections_range)] #![feature(compiler_builtins_lib)] #![feature(const_fn)] @@ -337,11 +336,9 @@ use prelude::v1::*; debug_assert_ne, unreachable, unimplemented, write, writeln, try)] extern crate core as __core; +#[allow(deprecated)] extern crate rand as core_rand; #[macro_use] #[macro_reexport(vec, format)] -extern crate collections as core_collections; - -#[allow(deprecated)] extern crate rand as core_rand; extern crate alloc; extern crate std_unicode; extern crate libc; @@ -430,17 +427,17 @@ pub use alloc::boxed; #[stable(feature = "rust1", since = "1.0.0")] pub use alloc::rc; #[stable(feature = "rust1", since = "1.0.0")] -pub use core_collections::borrow; +pub use alloc::borrow; #[stable(feature = "rust1", since = "1.0.0")] -pub use core_collections::fmt; +pub use alloc::fmt; #[stable(feature = "rust1", since = "1.0.0")] -pub use core_collections::slice; +pub use alloc::slice; #[stable(feature = "rust1", since = "1.0.0")] -pub use core_collections::str; +pub use alloc::str; #[stable(feature = "rust1", since = "1.0.0")] -pub use core_collections::string; +pub use alloc::string; #[stable(feature = "rust1", since = "1.0.0")] -pub use core_collections::vec; +pub use alloc::vec; #[stable(feature = "rust1", since = "1.0.0")] pub use std_unicode::char; #[unstable(feature = "i128", issue = "35118")] diff --git a/src/libstd_unicode/lib.rs b/src/libstd_unicode/lib.rs index d63878a7a7c2..19f2ad1c56f2 100644 --- a/src/libstd_unicode/lib.rs +++ b/src/libstd_unicode/lib.rs @@ -52,7 +52,7 @@ pub mod str { pub use u_str::Utf16Encoder; } -// For use in libcollections, not re-exported in libstd. +// For use in liballoc, not re-exported in libstd. pub mod derived_property { pub use tables::derived_property::{Case_Ignorable, Cased}; } diff --git a/src/libstd_unicode/u_str.rs b/src/libstd_unicode/u_str.rs index 1454168d2d5c..54a5288a57c8 100644 --- a/src/libstd_unicode/u_str.rs +++ b/src/libstd_unicode/u_str.rs @@ -32,7 +32,7 @@ pub struct SplitWhitespace<'a> { } /// Methods for Unicode string slices -#[allow(missing_docs)] // docs in libcollections +#[allow(missing_docs)] // docs in liballoc pub trait UnicodeStr { fn split_whitespace<'a>(&'a self) -> SplitWhitespace<'a>; fn is_whitespace(&self) -> bool; diff --git a/src/test/compile-fail/E0254.rs b/src/test/compile-fail/E0254.rs index fe7ee1c129f8..bc17a46a0172 100644 --- a/src/test/compile-fail/E0254.rs +++ b/src/test/compile-fail/E0254.rs @@ -8,18 +8,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(collections)] +#![feature(alloc)] -extern crate collections; -//~^ NOTE previous import of `collections` here +extern crate alloc; +//~^ NOTE previous import of `alloc` here mod foo { - pub trait collections { + pub trait alloc { fn do_something(); } } -use foo::collections; +use foo::alloc; //~^ ERROR E0254 //~| NOTE already imported diff --git a/src/test/compile-fail/E0259.rs b/src/test/compile-fail/E0259.rs index b2129902ef9c..259d67fe7cd6 100644 --- a/src/test/compile-fail/E0259.rs +++ b/src/test/compile-fail/E0259.rs @@ -8,13 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(collections, libc)] +#![feature(alloc, libc)] -extern crate collections; -//~^ NOTE previous import of `collections` here +extern crate alloc; +//~^ NOTE previous import of `alloc` here -extern crate libc as collections; +extern crate libc as alloc; //~^ ERROR E0259 -//~| NOTE `collections` already imported +//~| NOTE `alloc` already imported fn main() {} diff --git a/src/test/compile-fail/E0260.rs b/src/test/compile-fail/E0260.rs index ae018d2ada93..08d78782e4cd 100644 --- a/src/test/compile-fail/E0260.rs +++ b/src/test/compile-fail/E0260.rs @@ -8,14 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(collections)] +#![feature(alloc)] -extern crate collections; -//~^ NOTE previous import of `collections` here +extern crate alloc; +//~^ NOTE previous import of `alloc` here -mod collections { -//~^ ERROR `collections` has already been imported in this module [E0260] -//~| NOTE `collections` already imported +mod alloc { +//~^ ERROR `alloc` has already been imported in this module [E0260] +//~| NOTE `alloc` already imported pub trait MyTrait { fn do_something(); } diff --git a/src/test/compile-fail/lint-unused-extern-crate.rs b/src/test/compile-fail/lint-unused-extern-crate.rs index 40671353f8ac..010c55afb2b8 100644 --- a/src/test/compile-fail/lint-unused-extern-crate.rs +++ b/src/test/compile-fail/lint-unused-extern-crate.rs @@ -13,13 +13,13 @@ #![deny(unused_extern_crates)] #![allow(unused_variables)] #![allow(deprecated)] +#![feature(alloc)] #![feature(libc)] -#![feature(collections)] #![feature(rand)] extern crate libc; //~ ERROR: unused extern crate -extern crate collections as collecs; // no error, it is used +extern crate alloc as collecs; // no error, it is used extern crate rand; // no error, the use marks it as used // even if imported objects aren't used diff --git a/src/test/compile-fail/resolve_self_super_hint.rs b/src/test/compile-fail/resolve_self_super_hint.rs index 530dc873f750..d49f136f11f3 100644 --- a/src/test/compile-fail/resolve_self_super_hint.rs +++ b/src/test/compile-fail/resolve_self_super_hint.rs @@ -8,25 +8,25 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(collections)] +#![feature(alloc)] mod a { - extern crate collections; - use collections::HashMap; - //~^ ERROR unresolved import `collections::HashMap` [E0432] - //~| Did you mean `self::collections`? + extern crate alloc; + use alloc::HashMap; + //~^ ERROR unresolved import `alloc::HashMap` [E0432] + //~| Did you mean `self::alloc`? mod b { - use collections::HashMap; - //~^ ERROR unresolved import `collections::HashMap` [E0432] - //~| Did you mean `a::collections`? + use alloc::HashMap; + //~^ ERROR unresolved import `alloc::HashMap` [E0432] + //~| Did you mean `a::alloc`? mod c { - use collections::HashMap; - //~^ ERROR unresolved import `collections::HashMap` [E0432] - //~| Did you mean `a::collections`? + use alloc::HashMap; + //~^ ERROR unresolved import `alloc::HashMap` [E0432] + //~| Did you mean `a::alloc`? mod d { - use collections::HashMap; - //~^ ERROR unresolved import `collections::HashMap` [E0432] - //~| Did you mean `a::collections`? + use alloc::HashMap; + //~^ ERROR unresolved import `alloc::HashMap` [E0432] + //~| Did you mean `a::alloc`? } } } diff --git a/src/test/run-pass-fulldeps/issue-2804.rs b/src/test/run-pass-fulldeps/issue-2804.rs index a2b4e218a079..f999d2d0ed99 100644 --- a/src/test/run-pass-fulldeps/issue-2804.rs +++ b/src/test/run-pass-fulldeps/issue-2804.rs @@ -8,10 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(collections)] #![feature(rustc_private)] -extern crate collections; extern crate serialize; use std::collections::HashMap; diff --git a/src/test/run-pass-fulldeps/regions-mock-tcx.rs b/src/test/run-pass-fulldeps/regions-mock-tcx.rs index ed3cec465eff..670f5380d81f 100644 --- a/src/test/run-pass-fulldeps/regions-mock-tcx.rs +++ b/src/test/run-pass-fulldeps/regions-mock-tcx.rs @@ -15,10 +15,9 @@ // - Multiple lifetime parameters // - Arenas -#![feature(rustc_private, libc, collections)] +#![feature(rustc_private, libc)] extern crate arena; -extern crate collections; extern crate libc; use TypeStructure::{TypeInt, TypeFunction}; diff --git a/src/test/run-pass/drop-with-type-ascription-2.rs b/src/test/run-pass/drop-with-type-ascription-2.rs index 53005ea5291f..1f486c1834c0 100644 --- a/src/test/run-pass/drop-with-type-ascription-2.rs +++ b/src/test/run-pass/drop-with-type-ascription-2.rs @@ -9,8 +9,6 @@ // except according to those terms. -#![feature(collections)] - fn main() { let args = vec!["foobie", "asdf::asdf"]; let arr: Vec<&str> = args[1].split("::").collect(); diff --git a/src/test/run-pass/for-loop-no-std.rs b/src/test/run-pass/for-loop-no-std.rs index 73de1fa9c0de..856857156c94 100644 --- a/src/test/run-pass/for-loop-no-std.rs +++ b/src/test/run-pass/for-loop-no-std.rs @@ -8,12 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(lang_items, start, collections)] +#![feature(lang_items, start, alloc)] #![no_std] extern crate std as other; -#[macro_use] extern crate collections; +#[macro_use] extern crate alloc; #[start] fn start(_argc: isize, _argv: *const *const u8) -> isize { diff --git a/src/test/run-pass/foreach-external-iterators-hashmap-break-restart.rs b/src/test/run-pass/foreach-external-iterators-hashmap-break-restart.rs index cedb96014314..232af7eca419 100644 --- a/src/test/run-pass/foreach-external-iterators-hashmap-break-restart.rs +++ b/src/test/run-pass/foreach-external-iterators-hashmap-break-restart.rs @@ -9,10 +9,6 @@ // except according to those terms. -#![feature(collections)] - -extern crate collections; - use std::collections::HashMap; // This is a fancy one: it uses an external iterator established diff --git a/src/test/run-pass/foreach-external-iterators-hashmap.rs b/src/test/run-pass/foreach-external-iterators-hashmap.rs index 79304fce5c16..2ef420187ded 100644 --- a/src/test/run-pass/foreach-external-iterators-hashmap.rs +++ b/src/test/run-pass/foreach-external-iterators-hashmap.rs @@ -9,10 +9,6 @@ // except according to those terms. -#![feature(collections)] - -extern crate collections; - use std::collections::HashMap; pub fn main() { diff --git a/src/test/run-pass/format-no-std.rs b/src/test/run-pass/format-no-std.rs index 1b9b4ab32ca4..9e8a32185188 100644 --- a/src/test/run-pass/format-no-std.rs +++ b/src/test/run-pass/format-no-std.rs @@ -10,14 +10,14 @@ // ignore-emscripten missing rust_begin_unwind -#![feature(lang_items, start, collections)] +#![feature(lang_items, start, alloc)] #![no_std] extern crate std as other; -#[macro_use] extern crate collections; +#[macro_use] extern crate alloc; -use collections::string::ToString; +use alloc::string::ToString; #[start] fn start(_argc: isize, _argv: *const *const u8) -> isize { diff --git a/src/test/run-pass/issue-12860.rs b/src/test/run-pass/issue-12860.rs index 5c9ee74472b1..58ce390cac69 100644 --- a/src/test/run-pass/issue-12860.rs +++ b/src/test/run-pass/issue-12860.rs @@ -8,10 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(collections)] - -extern crate collections; - use std::collections::HashSet; #[derive(Copy, Clone, PartialEq, Eq, Hash)] diff --git a/src/test/run-pass/issue-1696.rs b/src/test/run-pass/issue-1696.rs index 4c6c200c7164..b06285b06a5e 100644 --- a/src/test/run-pass/issue-1696.rs +++ b/src/test/run-pass/issue-1696.rs @@ -8,10 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(collections)] - -extern crate collections; - use std::collections::HashMap; pub fn main() { diff --git a/src/test/run-pass/issue-19811-escape-unicode.rs b/src/test/run-pass/issue-19811-escape-unicode.rs index cff431065ffe..b447ffd69b4c 100644 --- a/src/test/run-pass/issue-19811-escape-unicode.rs +++ b/src/test/run-pass/issue-19811-escape-unicode.rs @@ -9,8 +9,6 @@ // except according to those terms. -#![feature(collections)] - fn main() { let mut escaped = String::from(""); for c in '\u{10401}'.escape_unicode() { diff --git a/src/test/run-pass/issue-2383.rs b/src/test/run-pass/issue-2383.rs index 9c400aac1dcf..a497a9fda6a6 100644 --- a/src/test/run-pass/issue-2383.rs +++ b/src/test/run-pass/issue-2383.rs @@ -10,9 +10,6 @@ // pretty-expanded FIXME #23616 -#![feature(collections)] - -extern crate collections; use std::collections::VecDeque; pub fn main() { diff --git a/src/test/run-pass/issue-2804-2.rs b/src/test/run-pass/issue-2804-2.rs index 6afb31619d1c..e428ecd4e5bb 100644 --- a/src/test/run-pass/issue-2804-2.rs +++ b/src/test/run-pass/issue-2804-2.rs @@ -11,10 +11,6 @@ // Minimized version of issue-2804.rs. Both check that callee IDs don't // clobber the previous node ID in a macro expr -#![feature(collections)] - -extern crate collections; - use std::collections::HashMap; fn add_interfaces(managed_ip: String, device: HashMap) { diff --git a/src/test/run-pass/issue-3026.rs b/src/test/run-pass/issue-3026.rs index d8499992f94d..7c0dc8a00489 100644 --- a/src/test/run-pass/issue-3026.rs +++ b/src/test/run-pass/issue-3026.rs @@ -10,10 +10,7 @@ // pretty-expanded FIXME #23616 -#![allow(unknown_features)] -#![feature(box_syntax, collections)] - -extern crate collections; +#![feature(box_syntax)] use std::collections::HashMap; diff --git a/src/test/run-pass/issue-3559.rs b/src/test/run-pass/issue-3559.rs index c2ea24ac6ba9..64f053d9a8c6 100644 --- a/src/test/run-pass/issue-3559.rs +++ b/src/test/run-pass/issue-3559.rs @@ -8,10 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(collections)] - -extern crate collections; - use std::collections::HashMap; fn check_strs(actual: &str, expected: &str) -> bool { diff --git a/src/test/run-pass/issue-6128.rs b/src/test/run-pass/issue-6128.rs index 5fb24fe3ef1a..8725b1378965 100644 --- a/src/test/run-pass/issue-6128.rs +++ b/src/test/run-pass/issue-6128.rs @@ -9,10 +9,7 @@ // except according to those terms. -#![allow(unknown_features)] -#![feature(box_syntax, collections)] - -extern crate collections; +#![feature(box_syntax)] use std::collections::HashMap; diff --git a/src/test/run-pass/issue-7660.rs b/src/test/run-pass/issue-7660.rs index b0ebc6c9cc82..3f3e11a2ddb0 100644 --- a/src/test/run-pass/issue-7660.rs +++ b/src/test/run-pass/issue-7660.rs @@ -13,10 +13,6 @@ // pretty-expanded FIXME #23616 -#![feature(collections)] - -extern crate collections; - use std::collections::HashMap; struct A(isize, isize); diff --git a/src/test/run-pass/istr.rs b/src/test/run-pass/istr.rs index 3197d7f0160a..7ebeb79f5666 100644 --- a/src/test/run-pass/istr.rs +++ b/src/test/run-pass/istr.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(collections)] - use std::string::String; fn test_stack_assign() { diff --git a/src/test/run-pass/new-unicode-escapes.rs b/src/test/run-pass/new-unicode-escapes.rs index 83c2dadcd2f7..2c0417576052 100644 --- a/src/test/run-pass/new-unicode-escapes.rs +++ b/src/test/run-pass/new-unicode-escapes.rs @@ -9,8 +9,6 @@ // except according to those terms. -#![feature(collections)] - pub fn main() { let s = "\u{2603}"; assert_eq!(s, "☃"); diff --git a/src/test/run-pass/option-ext.rs b/src/test/run-pass/option-ext.rs index 03ba6097cd92..c054171ff008 100644 --- a/src/test/run-pass/option-ext.rs +++ b/src/test/run-pass/option-ext.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(collections)] - pub fn main() { let thing = "{{ f }}"; let f = thing.find("{{"); diff --git a/src/test/run-pass/overloaded-autoderef.rs b/src/test/run-pass/overloaded-autoderef.rs index 97da5fc8c09e..d9ffbe51aa59 100644 --- a/src/test/run-pass/overloaded-autoderef.rs +++ b/src/test/run-pass/overloaded-autoderef.rs @@ -9,7 +9,7 @@ // except according to those terms. #![allow(unknown_features)] -#![feature(box_syntax, collections, core)] +#![feature(box_syntax, core)] use std::cell::RefCell; use std::rc::Rc; diff --git a/src/test/run-pass/overloaded-deref.rs b/src/test/run-pass/overloaded-deref.rs index e2ca880719a8..9cdf45b485c1 100644 --- a/src/test/run-pass/overloaded-deref.rs +++ b/src/test/run-pass/overloaded-deref.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(collections)] - use std::cell::RefCell; use std::rc::Rc; use std::string::String; diff --git a/src/test/run-pass/sync-send-iterators-in-libcollections.rs b/src/test/run-pass/sync-send-iterators-in-libcollections.rs index ea154590deef..903532e9bc80 100644 --- a/src/test/run-pass/sync-send-iterators-in-libcollections.rs +++ b/src/test/run-pass/sync-send-iterators-in-libcollections.rs @@ -9,21 +9,16 @@ // except according to those terms. #![allow(warnings)] -#![feature(collections)] #![feature(drain, collections_bound, btree_range, vecmap)] -extern crate collections; - -use collections::BinaryHeap; -use collections::{BTreeMap, BTreeSet}; -use collections::LinkedList; -use collections::String; -use collections::Vec; -use collections::VecDeque; +use std::collections::BinaryHeap; +use std::collections::{BTreeMap, BTreeSet}; +use std::collections::LinkedList; +use std::collections::VecDeque; use std::collections::HashMap; use std::collections::HashSet; -use collections::Bound::Included; +use std::collections::Bound::Included; use std::mem; fn is_sync(_: T) where T: Sync {} diff --git a/src/test/run-pass/utf8_chars.rs b/src/test/run-pass/utf8_chars.rs index 0a984429fabb..b54aed79665a 100644 --- a/src/test/run-pass/utf8_chars.rs +++ b/src/test/run-pass/utf8_chars.rs @@ -9,7 +9,7 @@ // except according to those terms. // -#![feature(collections, core, str_char)] +#![feature(core, str_char)] use std::str; diff --git a/src/test/run-pass/vec-macro-no-std.rs b/src/test/run-pass/vec-macro-no-std.rs index a51ef7322646..5dd551ff5137 100644 --- a/src/test/run-pass/vec-macro-no-std.rs +++ b/src/test/run-pass/vec-macro-no-std.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(lang_items, start, libc, collections)] +#![feature(lang_items, start, libc, alloc)] #![no_std] extern crate std as other; @@ -16,9 +16,9 @@ extern crate std as other; extern crate libc; #[macro_use] -extern crate collections; +extern crate alloc; -use collections::vec::Vec; +use alloc::vec::Vec; // Issue #16806 diff --git a/src/test/run-pass/while-prelude-drop.rs b/src/test/run-pass/while-prelude-drop.rs index e4ca5515653c..39ed4f53cf7e 100644 --- a/src/test/run-pass/while-prelude-drop.rs +++ b/src/test/run-pass/while-prelude-drop.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(collections)] - use std::string::String; #[derive(PartialEq)] diff --git a/src/tools/linkchecker/main.rs b/src/tools/linkchecker/main.rs index 1b55dc792c2e..3ea2e6313af4 100644 --- a/src/tools/linkchecker/main.rs +++ b/src/tools/linkchecker/main.rs @@ -118,15 +118,15 @@ fn check(cache: &mut Cache, return None; } // FIXME(#32553) - if file.ends_with("collections/string/struct.String.html") { + if file.ends_with("string/struct.String.html") { return None; } // FIXME(#32130) if file.ends_with("btree_set/struct.BTreeSet.html") || - file.ends_with("collections/struct.BTreeSet.html") || - file.ends_with("collections/btree_map/struct.BTreeMap.html") || - file.ends_with("collections/hash_map/struct.HashMap.html") || - file.ends_with("collections/hash_set/struct.HashSet.html") { + file.ends_with("struct.BTreeSet.html") || + file.ends_with("btree_map/struct.BTreeMap.html") || + file.ends_with("hash_map/struct.HashMap.html") || + file.ends_with("hash_set/struct.HashSet.html") { return None; } From 532a08b94726a399a4203b54536e63f7b634d36d Mon Sep 17 00:00:00 2001 From: Taylor Cramer Date: Sun, 11 Jun 2017 21:58:12 -0700 Subject: [PATCH 189/233] Add CrateNum-taking ability to the provide macro --- src/librustc/dep_graph/dep_node.rs | 1 + src/librustc_metadata/cstore_impl.rs | 155 +++++++++++++++------------ 2 files changed, 90 insertions(+), 66 deletions(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index c987a37c420d..6c4c90585b3c 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -305,6 +305,7 @@ define_dep_nodes!( // Represents the metadata for a given HIR node, typically found // in an extern crate. MetaData(DefId), + MetaDataByCrateNum(CrateNum), // Represents some artifact that we save to disk. Note that these // do not have a def-id as part of their identifier. diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 00c1fdb177db..6314ffd30204 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -40,10 +40,17 @@ use rustc::hir::svh::Svh; use rustc::hir; macro_rules! provide { - (<$lt:tt> $tcx:ident, $def_id:ident, $cdata:ident $($name:ident => $compute:block)*) => { + (<$lt:tt> $tcx:ident, $def_id:ident, $cdata:ident, $cnum:ident, + ByDefId { + $($cdata_fn_name:ident => $cdata_fn_compute:block)* + } + ByCrateNum { + $($cnum_fn_name:ident => $cnum_fn_compute:block)* + } + )=> { pub fn provide<$lt>(providers: &mut Providers<$lt>) { - $(fn $name<'a, $lt:$lt>($tcx: TyCtxt<'a, $lt, $lt>, $def_id: DefId) - -> as + $(fn $cdata_fn_name<'a, $lt:$lt>($tcx: TyCtxt<'a, $lt, $lt>, $def_id: DefId) + -> as DepTrackingMapConfig>::Value { assert!(!$def_id.is_local()); @@ -55,82 +62,98 @@ macro_rules! provide { let $cdata = $tcx.sess.cstore.crate_data_as_rc_any($def_id.krate); let $cdata = $cdata.downcast_ref::() .expect("CrateStore crated ata is not a CrateMetadata"); - $compute + $cdata_fn_compute + })* + + $(fn $cnum_fn_name<'a, $lt:$lt>($tcx: TyCtxt<'a, $lt, $lt>, $cnum: CrateNum) + -> as + DepTrackingMapConfig>::Value { + let $cdata = $tcx.sess.cstore.crate_data_as_rc_any($cnum); + let $cdata = $cdata.downcast_ref::() + .expect("CrateStore crated ata is not a CrateMetadata"); + $cnum_fn_compute })* *providers = Providers { - $($name,)* + $($cdata_fn_name,)* + $($cnum_fn_name,)* ..*providers }; } } } -provide! { <'tcx> tcx, def_id, cdata - type_of => { cdata.get_type(def_id.index, tcx) } - generics_of => { tcx.alloc_generics(cdata.get_generics(def_id.index)) } - predicates_of => { cdata.get_predicates(def_id.index, tcx) } - super_predicates_of => { cdata.get_super_predicates(def_id.index, tcx) } - trait_def => { - tcx.alloc_trait_def(cdata.get_trait_def(def_id.index)) - } - adt_def => { cdata.get_adt_def(def_id.index, tcx) } - adt_destructor => { - let _ = cdata; - tcx.calculate_dtor(def_id, &mut |_,_| Ok(())) - } - variances_of => { Rc::new(cdata.get_item_variances(def_id.index)) } - associated_item_def_ids => { - let mut result = vec![]; - cdata.each_child_of_item(def_id.index, |child| result.push(child.def.def_id()), tcx.sess); - Rc::new(result) - } - associated_item => { cdata.get_associated_item(def_id.index) } - impl_trait_ref => { cdata.get_impl_trait(def_id.index, tcx) } - impl_polarity => { cdata.get_impl_polarity(def_id.index) } - coerce_unsized_info => { - cdata.get_coerce_unsized_info(def_id.index).unwrap_or_else(|| { - bug!("coerce_unsized_info: `{:?}` is missing its info", def_id); - }) - } - optimized_mir => { - let mir = cdata.maybe_get_optimized_mir(tcx, def_id.index).unwrap_or_else(|| { - bug!("get_optimized_mir: missing MIR for `{:?}`", def_id) - }); +provide! { <'tcx> tcx, def_id, cdata, cnum, + ByDefId { + type_of => { cdata.get_type(def_id.index, tcx) } + generics_of => { tcx.alloc_generics(cdata.get_generics(def_id.index)) } + predicates_of => { cdata.get_predicates(def_id.index, tcx) } + super_predicates_of => { cdata.get_super_predicates(def_id.index, tcx) } + trait_def => { + tcx.alloc_trait_def(cdata.get_trait_def(def_id.index)) + } + adt_def => { cdata.get_adt_def(def_id.index, tcx) } + adt_destructor => { + let _ = cdata; + tcx.calculate_dtor(def_id, &mut |_,_| Ok(())) + } + variances_of => { Rc::new(cdata.get_item_variances(def_id.index)) } + associated_item_def_ids => { + let mut result = vec![]; + cdata.each_child_of_item(def_id.index, + |child| result.push(child.def.def_id()), tcx.sess); + Rc::new(result) + } + associated_item => { cdata.get_associated_item(def_id.index) } + impl_trait_ref => { cdata.get_impl_trait(def_id.index, tcx) } + impl_polarity => { cdata.get_impl_polarity(def_id.index) } + coerce_unsized_info => { + cdata.get_coerce_unsized_info(def_id.index).unwrap_or_else(|| { + bug!("coerce_unsized_info: `{:?}` is missing its info", def_id); + }) + } + optimized_mir => { + let mir = cdata.maybe_get_optimized_mir(tcx, def_id.index).unwrap_or_else(|| { + bug!("get_optimized_mir: missing MIR for `{:?}`", def_id) + }); - let mir = tcx.alloc_mir(mir); + let mir = tcx.alloc_mir(mir); - mir + mir + } + mir_const_qualif => { cdata.mir_const_qualif(def_id.index) } + typeck_tables_of => { cdata.item_body_tables(def_id.index, tcx) } + closure_kind => { cdata.closure_kind(def_id.index) } + closure_type => { cdata.closure_ty(def_id.index, tcx) } + inherent_impls => { Rc::new(cdata.get_inherent_implementations_for_type(def_id.index)) } + is_const_fn => { cdata.is_const_fn(def_id.index) } + is_foreign_item => { cdata.is_foreign_item(def_id.index) } + is_default_impl => { cdata.is_default_impl(def_id.index) } + describe_def => { cdata.get_def(def_id.index) } + def_span => { cdata.get_span(def_id.index, &tcx.sess) } + stability => { cdata.get_stability(def_id.index) } + deprecation => { cdata.get_deprecation(def_id.index) } + item_attrs => { cdata.get_item_attrs(def_id.index, &tcx.dep_graph) } + // FIXME(#38501) We've skipped a `read` on the `HirBody` of + // a `fn` when encoding, so the dep-tracking wouldn't work. + // This is only used by rustdoc anyway, which shouldn't have + // incremental recompilation ever enabled. + fn_arg_names => { cdata.get_fn_arg_names(def_id.index) } + impl_parent => { cdata.get_parent_impl(def_id.index) } + trait_of_item => { cdata.get_trait_of_item(def_id.index) } + is_exported_symbol => { + let dep_node = cdata.metadata_dep_node(GlobalMetaDataKind::ExportedSymbols); + cdata.exported_symbols.get(&tcx.dep_graph, dep_node).contains(&def_id.index) + } + item_body_nested_bodies => { Rc::new(cdata.item_body_nested_bodies(def_id.index)) } + const_is_rvalue_promotable_to_static => { + cdata.const_is_rvalue_promotable_to_static(def_id.index) + } + is_mir_available => { cdata.is_item_mir_available(def_id.index) } } - mir_const_qualif => { cdata.mir_const_qualif(def_id.index) } - typeck_tables_of => { cdata.item_body_tables(def_id.index, tcx) } - closure_kind => { cdata.closure_kind(def_id.index) } - closure_type => { cdata.closure_ty(def_id.index, tcx) } - inherent_impls => { Rc::new(cdata.get_inherent_implementations_for_type(def_id.index)) } - is_const_fn => { cdata.is_const_fn(def_id.index) } - is_foreign_item => { cdata.is_foreign_item(def_id.index) } - is_default_impl => { cdata.is_default_impl(def_id.index) } - describe_def => { cdata.get_def(def_id.index) } - def_span => { cdata.get_span(def_id.index, &tcx.sess) } - stability => { cdata.get_stability(def_id.index) } - deprecation => { cdata.get_deprecation(def_id.index) } - item_attrs => { cdata.get_item_attrs(def_id.index, &tcx.dep_graph) } - // FIXME(#38501) We've skipped a `read` on the `HirBody` of - // a `fn` when encoding, so the dep-tracking wouldn't work. - // This is only used by rustdoc anyway, which shouldn't have - // incremental recompilation ever enabled. - fn_arg_names => { cdata.get_fn_arg_names(def_id.index) } - impl_parent => { cdata.get_parent_impl(def_id.index) } - trait_of_item => { cdata.get_trait_of_item(def_id.index) } - is_exported_symbol => { - let dep_node = cdata.metadata_dep_node(GlobalMetaDataKind::ExportedSymbols); - cdata.exported_symbols.get(&tcx.dep_graph, dep_node).contains(&def_id.index) + + ByCrateNum { } - item_body_nested_bodies => { Rc::new(cdata.item_body_nested_bodies(def_id.index)) } - const_is_rvalue_promotable_to_static => { - cdata.const_is_rvalue_promotable_to_static(def_id.index) - } - is_mir_available => { cdata.is_item_mir_available(def_id.index) } } pub fn provide_local<'tcx>(providers: &mut Providers<'tcx>) { From 328c6c81bf7c1093b6bca34286d86f193a7d054e Mon Sep 17 00:00:00 2001 From: Taylor Cramer Date: Sun, 11 Jun 2017 22:40:14 -0700 Subject: [PATCH 190/233] on-demand dylib dependency formats --- src/librustc/middle/cstore.rs | 5 ----- src/librustc/middle/dependency_format.rs | 17 +++++++++++------ src/librustc/ty/maps.rs | 10 ++++++++++ src/librustc_driver/driver.rs | 2 +- src/librustc_metadata/cstore_impl.rs | 7 +------ 5 files changed, 23 insertions(+), 18 deletions(-) diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 735da5ca380c..2c4634f52e9f 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -247,8 +247,6 @@ pub trait CrateStore { fn is_statically_included_foreign_item(&self, def_id: DefId) -> bool; // crate metadata - fn dylib_dependency_formats(&self, cnum: CrateNum) - -> Vec<(CrateNum, LinkagePreference)>; fn dep_kind(&self, cnum: CrateNum) -> DepKind; fn export_macros(&self, cnum: CrateNum); fn lang_items(&self, cnum: CrateNum) -> Vec<(DefIndex, usize)>; @@ -367,9 +365,6 @@ impl CrateStore for DummyCrateStore { fn is_statically_included_foreign_item(&self, def_id: DefId) -> bool { false } // crate metadata - fn dylib_dependency_formats(&self, cnum: CrateNum) - -> Vec<(CrateNum, LinkagePreference)> - { bug!("dylib_dependency_formats") } fn lang_items(&self, cnum: CrateNum) -> Vec<(DefIndex, usize)> { bug!("lang_items") } fn missing_lang_items(&self, cnum: CrateNum) -> Vec diff --git a/src/librustc/middle/dependency_format.rs b/src/librustc/middle/dependency_format.rs index e60d0533c9f8..be9c5cfafe02 100644 --- a/src/librustc/middle/dependency_format.rs +++ b/src/librustc/middle/dependency_format.rs @@ -65,6 +65,7 @@ use hir::def_id::CrateNum; use session; use session::config; +use ty::TyCtxt; use middle::cstore::DepKind; use middle::cstore::LinkagePreference::{self, RequireStatic, RequireDynamic}; use util::nodemap::FxHashMap; @@ -91,18 +92,22 @@ pub enum Linkage { Dynamic, } -pub fn calculate(sess: &session::Session) { +pub fn calculate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { + let sess = &tcx.sess; let mut fmts = sess.dependency_formats.borrow_mut(); for &ty in sess.crate_types.borrow().iter() { - let linkage = calculate_type(sess, ty); + let linkage = calculate_type(tcx, ty); verify_ok(sess, &linkage); fmts.insert(ty, linkage); } sess.abort_if_errors(); } -fn calculate_type(sess: &session::Session, - ty: config::CrateType) -> DependencyList { +fn calculate_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + ty: config::CrateType) -> DependencyList { + + let sess = &tcx.sess; + if !sess.opts.output_types.should_trans() { return Vec::new(); } @@ -167,8 +172,8 @@ fn calculate_type(sess: &session::Session, if src.dylib.is_some() { info!("adding dylib: {}", name); add_library(sess, cnum, RequireDynamic, &mut formats); - let deps = sess.cstore.dylib_dependency_formats(cnum); - for &(depnum, style) in &deps { + let deps = tcx.dylib_dependency_formats(cnum); + for &(depnum, style) in deps.iter() { info!("adding {:?}: {}", style, sess.cstore.crate_name(depnum)); add_library(sess, depnum, style, &mut formats); diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs index 6ee5bf1392fc..981a0b9f4034 100644 --- a/src/librustc/ty/maps.rs +++ b/src/librustc/ty/maps.rs @@ -13,6 +13,7 @@ use hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, LOCAL_CRATE}; use hir::def::Def; use hir; use middle::const_val; +use middle::cstore::LinkagePreference; use middle::privacy::AccessLevels; use middle::region::RegionMaps; use mir; @@ -482,6 +483,12 @@ impl<'tcx> QueryDescription for queries::is_const_fn<'tcx> { } } +impl<'tcx> QueryDescription for queries::dylib_dependency_formats<'tcx> { + fn describe(_: TyCtxt, _: CrateNum) -> String { + "dylib dependency formats of crate".to_string() + } +} + macro_rules! define_maps { (<$tcx:tt> $($(#[$attr:meta])* @@ -938,6 +945,9 @@ define_maps! { <'tcx> [] needs_drop_raw: needs_drop_dep_node(ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool, [] layout_raw: layout_dep_node(ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> Result<&'tcx Layout, LayoutError<'tcx>>, + + [] dylib_dependency_formats: MetaDataByCrateNum(CrateNum) + -> Rc>, } fn type_param_predicates((item_id, param_id): (DefId, DefId)) -> DepConstructor { diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index ac26b04cb7a3..527fc04fe922 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -1049,7 +1049,7 @@ pub fn phase_4_translate_to_llvm<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, time(time_passes, "resolving dependency formats", - || dependency_format::calculate(&tcx.sess)); + || dependency_format::calculate(tcx)); let translation = time(time_passes, diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 6314ffd30204..e289c4d92075 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -153,6 +153,7 @@ provide! { <'tcx> tcx, def_id, cdata, cnum, } ByCrateNum { + dylib_dependency_formats => { Rc::new(cdata.get_dylib_dependency_formats(&tcx.dep_graph)) } } } @@ -229,12 +230,6 @@ impl CrateStore for cstore::CStore { } } - fn dylib_dependency_formats(&self, cnum: CrateNum) - -> Vec<(CrateNum, LinkagePreference)> - { - self.get_crate_data(cnum).get_dylib_dependency_formats(&self.dep_graph) - } - fn dep_kind(&self, cnum: CrateNum) -> DepKind { let data = self.get_crate_data(cnum); From b0f05d4bc5f6ee7d6f5e10f20675a7a7076520b0 Mon Sep 17 00:00:00 2001 From: Taylor Cramer Date: Mon, 12 Jun 2017 00:11:24 -0700 Subject: [PATCH 191/233] On-demandify is_allocator and is_panic_runtime --- src/librustc/middle/cstore.rs | 4 ---- src/librustc/middle/dependency_format.rs | 26 +++++++++++++----------- src/librustc/ty/maps.rs | 15 ++++++++++++++ src/librustc_metadata/cstore_impl.rs | 12 ++--------- src/librustc_trans/back/symbol_export.rs | 4 ++-- 5 files changed, 33 insertions(+), 28 deletions(-) diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 2c4634f52e9f..6631e919e425 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -251,8 +251,6 @@ pub trait CrateStore { fn export_macros(&self, cnum: CrateNum); fn lang_items(&self, cnum: CrateNum) -> Vec<(DefIndex, usize)>; fn missing_lang_items(&self, cnum: CrateNum) -> Vec; - fn is_allocator(&self, cnum: CrateNum) -> bool; - fn is_panic_runtime(&self, cnum: CrateNum) -> bool; fn is_compiler_builtins(&self, cnum: CrateNum) -> bool; fn is_sanitizer_runtime(&self, cnum: CrateNum) -> bool; fn panic_strategy(&self, cnum: CrateNum) -> PanicStrategy; @@ -371,8 +369,6 @@ impl CrateStore for DummyCrateStore { { bug!("missing_lang_items") } fn dep_kind(&self, cnum: CrateNum) -> DepKind { bug!("is_explicitly_linked") } fn export_macros(&self, cnum: CrateNum) { bug!("export_macros") } - fn is_allocator(&self, cnum: CrateNum) -> bool { bug!("is_allocator") } - fn is_panic_runtime(&self, cnum: CrateNum) -> bool { bug!("is_panic_runtime") } fn is_compiler_builtins(&self, cnum: CrateNum) -> bool { bug!("is_compiler_builtins") } fn is_sanitizer_runtime(&self, cnum: CrateNum) -> bool { bug!("is_sanitizer_runtime") } fn panic_strategy(&self, cnum: CrateNum) -> PanicStrategy { diff --git a/src/librustc/middle/dependency_format.rs b/src/librustc/middle/dependency_format.rs index be9c5cfafe02..da217d7a1733 100644 --- a/src/librustc/middle/dependency_format.rs +++ b/src/librustc/middle/dependency_format.rs @@ -97,7 +97,7 @@ pub fn calculate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { let mut fmts = sess.dependency_formats.borrow_mut(); for &ty in sess.crate_types.borrow().iter() { let linkage = calculate_type(tcx, ty); - verify_ok(sess, &linkage); + verify_ok(tcx, &linkage); fmts.insert(ty, linkage); } sess.abort_if_errors(); @@ -116,7 +116,7 @@ fn calculate_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // If the global prefer_dynamic switch is turned off, first attempt // static linkage (this can fail). config::CrateTypeExecutable if !sess.opts.cg.prefer_dynamic => { - if let Some(v) = attempt_static(sess) { + if let Some(v) = attempt_static(tcx) { return v; } } @@ -129,7 +129,7 @@ fn calculate_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // to be found, we generate some nice pretty errors. config::CrateTypeStaticlib | config::CrateTypeCdylib => { - if let Some(v) = attempt_static(sess) { + if let Some(v) = attempt_static(tcx) { return v; } for cnum in sess.cstore.crates() { @@ -146,7 +146,7 @@ fn calculate_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // to try to eagerly statically link all dependencies. This is normally // done for end-product dylibs, not intermediate products. config::CrateTypeDylib if !sess.opts.cg.prefer_dynamic => { - if let Some(v) = attempt_static(sess) { + if let Some(v) = attempt_static(tcx) { return v; } } @@ -215,9 +215,9 @@ fn calculate_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Things like allocators and panic runtimes may not have been activated // quite yet, so do so here. activate_injected_dep(sess.injected_allocator.get(), &mut ret, - &|cnum| sess.cstore.is_allocator(cnum)); + &|cnum| tcx.is_allocator(cnum)); activate_injected_dep(sess.injected_panic_runtime.get(), &mut ret, - &|cnum| sess.cstore.is_panic_runtime(cnum)); + &|cnum| tcx.is_panic_runtime(cnum)); // When dylib B links to dylib A, then when using B we must also link to A. // It could be the case, however, that the rlib for A is present (hence we @@ -274,7 +274,8 @@ fn add_library(sess: &session::Session, } } -fn attempt_static(sess: &session::Session) -> Option { +fn attempt_static<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option { + let sess = &tcx.sess; let crates = sess.cstore.used_crates(RequireStatic); if !crates.iter().by_ref().all(|&(_, ref p)| p.is_some()) { return None @@ -295,9 +296,9 @@ fn attempt_static(sess: &session::Session) -> Option { // explicitly linked, which is the case for any injected dependency. Handle // that here and activate them. activate_injected_dep(sess.injected_allocator.get(), &mut ret, - &|cnum| sess.cstore.is_allocator(cnum)); + &|cnum| tcx.is_allocator(cnum)); activate_injected_dep(sess.injected_panic_runtime.get(), &mut ret, - &|cnum| sess.cstore.is_panic_runtime(cnum)); + &|cnum| tcx.is_panic_runtime(cnum)); Some(ret) } @@ -332,7 +333,8 @@ fn activate_injected_dep(injected: Option, // After the linkage for a crate has been determined we need to verify that // there's only going to be one allocator in the output. -fn verify_ok(sess: &session::Session, list: &[Linkage]) { +fn verify_ok<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, list: &[Linkage]) { + let sess = &tcx.sess; if list.len() == 0 { return } @@ -343,7 +345,7 @@ fn verify_ok(sess: &session::Session, list: &[Linkage]) { continue } let cnum = CrateNum::new(i + 1); - if sess.cstore.is_allocator(cnum) { + if tcx.is_allocator(cnum) { if let Some(prev) = allocator { let prev_name = sess.cstore.crate_name(prev); let cur_name = sess.cstore.crate_name(cnum); @@ -354,7 +356,7 @@ fn verify_ok(sess: &session::Session, list: &[Linkage]) { allocator = Some(cnum); } - if sess.cstore.is_panic_runtime(cnum) { + if tcx.is_panic_runtime(cnum) { if let Some((prev, _)) = panic_runtime { let prev_name = sess.cstore.crate_name(prev); let cur_name = sess.cstore.crate_name(cnum); diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs index 981a0b9f4034..abfd021e4f11 100644 --- a/src/librustc/ty/maps.rs +++ b/src/librustc/ty/maps.rs @@ -489,6 +489,18 @@ impl<'tcx> QueryDescription for queries::dylib_dependency_formats<'tcx> { } } +impl<'tcx> QueryDescription for queries::is_allocator<'tcx> { + fn describe(_: TyCtxt, _: CrateNum) -> String { + "checking if the crate is_allocator".to_string() + } +} + +impl<'tcx> QueryDescription for queries::is_panic_runtime<'tcx> { + fn describe(_: TyCtxt, _: CrateNum) -> String { + "checking if the crate is_panic_runtime".to_string() + } +} + macro_rules! define_maps { (<$tcx:tt> $($(#[$attr:meta])* @@ -948,6 +960,9 @@ define_maps! { <'tcx> [] dylib_dependency_formats: MetaDataByCrateNum(CrateNum) -> Rc>, + + [] is_allocator: MetaDataByCrateNum(CrateNum) -> bool, + [] is_panic_runtime: MetaDataByCrateNum(CrateNum) -> bool, } fn type_param_predicates((item_id, param_id): (DefId, DefId)) -> DepConstructor { diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index e289c4d92075..ca45696360e9 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -154,6 +154,8 @@ provide! { <'tcx> tcx, def_id, cdata, cnum, ByCrateNum { dylib_dependency_formats => { Rc::new(cdata.get_dylib_dependency_formats(&tcx.dep_graph)) } + is_allocator => { cdata.is_allocator(&tcx.dep_graph) } + is_panic_runtime => { cdata.is_panic_runtime(&tcx.dep_graph) } } } @@ -259,16 +261,6 @@ impl CrateStore for cstore::CStore { self.get_crate_data(cnum).get_missing_lang_items(&self.dep_graph) } - fn is_allocator(&self, cnum: CrateNum) -> bool - { - self.get_crate_data(cnum).is_allocator(&self.dep_graph) - } - - fn is_panic_runtime(&self, cnum: CrateNum) -> bool - { - self.get_crate_data(cnum).is_panic_runtime(&self.dep_graph) - } - fn is_compiler_builtins(&self, cnum: CrateNum) -> bool { self.get_crate_data(cnum).is_compiler_builtins(&self.dep_graph) } diff --git a/src/librustc_trans/back/symbol_export.rs b/src/librustc_trans/back/symbol_export.rs index ef75de04045e..8eb7ccd48220 100644 --- a/src/librustc_trans/back/symbol_export.rs +++ b/src/librustc_trans/back/symbol_export.rs @@ -92,8 +92,8 @@ impl ExportedSymbols { // Down below we'll hardwire all of the symbols to the `Rust` export // level instead. let special_runtime_crate = - scx.sess().cstore.is_allocator(cnum) || - scx.sess().cstore.is_panic_runtime(cnum) || + scx.tcx().is_allocator(cnum) || + scx.tcx().is_panic_runtime(cnum) || scx.sess().cstore.is_compiler_builtins(cnum); let crate_exports = scx From 48356987c18d77605342d3bd5f5dc98d88f1d245 Mon Sep 17 00:00:00 2001 From: Taylor Cramer Date: Mon, 12 Jun 2017 00:59:22 -0700 Subject: [PATCH 192/233] On-demandify extern_crate --- src/librustc/middle/cstore.rs | 2 -- src/librustc/ty/item_path.rs | 6 +++--- src/librustc/ty/maps.rs | 10 +++++++++- src/librustc_metadata/cstore_impl.rs | 8 ++------ src/librustc_save_analysis/lib.rs | 2 +- 5 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 6631e919e425..0a4cc937739a 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -254,7 +254,6 @@ pub trait CrateStore { fn is_compiler_builtins(&self, cnum: CrateNum) -> bool; fn is_sanitizer_runtime(&self, cnum: CrateNum) -> bool; fn panic_strategy(&self, cnum: CrateNum) -> PanicStrategy; - fn extern_crate(&self, cnum: CrateNum) -> Option; /// The name of the crate as it is referred to in source code of the current /// crate. fn crate_name(&self, cnum: CrateNum) -> Symbol; @@ -374,7 +373,6 @@ impl CrateStore for DummyCrateStore { fn panic_strategy(&self, cnum: CrateNum) -> PanicStrategy { bug!("panic_strategy") } - fn extern_crate(&self, cnum: CrateNum) -> Option { bug!("extern_crate") } fn crate_name(&self, cnum: CrateNum) -> Symbol { bug!("crate_name") } fn original_crate_name(&self, cnum: CrateNum) -> Symbol { bug!("original_crate_name") diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index 30dcc3fc8109..e63fe42877fe 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -100,7 +100,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // // Returns `None` for the local crate. if cnum != LOCAL_CRATE { - let opt_extern_crate = self.sess.cstore.extern_crate(cnum); + let opt_extern_crate = self.extern_crate(cnum); let opt_extern_crate = opt_extern_crate.and_then(|extern_crate| { if extern_crate.direct { Some(extern_crate.def_id) @@ -136,8 +136,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // If `cur_def` is a direct or injected extern crate, push the path to the crate // followed by the path to the item within the crate and return. if cur_def.index == CRATE_DEF_INDEX { - match self.sess.cstore.extern_crate(cur_def.krate) { - Some(extern_crate) if extern_crate.direct => { + match *self.extern_crate(cur_def.krate) { + Some(ref extern_crate) if extern_crate.direct => { self.push_item_path(buffer, extern_crate.def_id); cur_path.iter().rev().map(|segment| buffer.push(&segment.as_str())).count(); return true; diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs index abfd021e4f11..27713f728ac5 100644 --- a/src/librustc/ty/maps.rs +++ b/src/librustc/ty/maps.rs @@ -13,7 +13,7 @@ use hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, LOCAL_CRATE}; use hir::def::Def; use hir; use middle::const_val; -use middle::cstore::LinkagePreference; +use middle::cstore::{ExternCrate, LinkagePreference}; use middle::privacy::AccessLevels; use middle::region::RegionMaps; use mir; @@ -501,6 +501,12 @@ impl<'tcx> QueryDescription for queries::is_panic_runtime<'tcx> { } } +impl<'tcx> QueryDescription for queries::extern_crate<'tcx> { + fn describe(_: TyCtxt, _: CrateNum) -> String { + "getting crate's ExternCrateData".to_string() + } +} + macro_rules! define_maps { (<$tcx:tt> $($(#[$attr:meta])* @@ -963,6 +969,8 @@ define_maps! { <'tcx> [] is_allocator: MetaDataByCrateNum(CrateNum) -> bool, [] is_panic_runtime: MetaDataByCrateNum(CrateNum) -> bool, + + [] extern_crate: MetaDataByCrateNum(CrateNum) -> Rc>, } fn type_param_predicates((item_id, param_id): (DefId, DefId)) -> DepConstructor { diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index ca45696360e9..9522d9625c94 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -14,7 +14,7 @@ use schema; use rustc::dep_graph::DepTrackingMapConfig; use rustc::middle::cstore::{CrateStore, CrateSource, LibSource, DepKind, - ExternCrate, NativeLibrary, MetadataLoader, LinkMeta, + NativeLibrary, MetadataLoader, LinkMeta, LinkagePreference, LoadedMacro, EncodedMetadata}; use rustc::hir::def; use rustc::middle::lang_items; @@ -156,6 +156,7 @@ provide! { <'tcx> tcx, def_id, cdata, cnum, dylib_dependency_formats => { Rc::new(cdata.get_dylib_dependency_formats(&tcx.dep_graph)) } is_allocator => { cdata.is_allocator(&tcx.dep_graph) } is_panic_runtime => { cdata.is_panic_runtime(&tcx.dep_graph) } + extern_crate => { Rc::new(cdata.extern_crate.get()) } } } @@ -283,11 +284,6 @@ impl CrateStore for cstore::CStore { self.get_crate_data(cnum).name() } - fn extern_crate(&self, cnum: CrateNum) -> Option - { - self.get_crate_data(cnum).extern_crate.get() - } - fn crate_hash(&self, cnum: CrateNum) -> Svh { self.get_crate_hash(cnum) diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 4802494f08ea..814a45ef636b 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -107,7 +107,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { let mut result = Vec::new(); for n in self.tcx.sess.cstore.crates() { - let span = match self.tcx.sess.cstore.extern_crate(n) { + let span = match *self.tcx.extern_crate(n) { Some(ref c) => c.span, None => { debug!("Skipping crate {}, no data", n); From 3cb78259862d37da082f628af3ccb54edf264fd0 Mon Sep 17 00:00:00 2001 From: Wonwoo Choi Date: Tue, 13 Jun 2017 01:30:08 +0900 Subject: [PATCH 193/233] Update older URLs pointing to the first edition of the Book `compiler-plugins.html` is moved into the Unstable Book. Explanation is slightly modified to match the change. --- src/libcore/borrow.rs | 2 +- src/libcore/convert.rs | 4 ++-- src/libcore/macros.rs | 2 +- src/libcore/marker.rs | 4 ++-- src/libcore/ops/deref.rs | 4 ++-- src/libproc_macro/lib.rs | 2 +- src/librustc/diagnostics.rs | 8 ++++---- src/librustc_borrowck/diagnostics.rs | 14 +++++++------- src/librustc_metadata/diagnostics.rs | 3 ++- src/librustc_plugin/lib.rs | 4 ++-- src/librustc_typeck/diagnostics.rs | 13 +++++++------ src/libstd/io/mod.rs | 2 +- src/libstd/macros.rs | 2 +- src/libstd/prelude/mod.rs | 8 ++++---- src/libtest/lib.rs | 2 +- 15 files changed, 38 insertions(+), 36 deletions(-) diff --git a/src/libcore/borrow.rs b/src/libcore/borrow.rs index 3d223465c88a..61558034e63e 100644 --- a/src/libcore/borrow.rs +++ b/src/libcore/borrow.rs @@ -31,7 +31,7 @@ /// `Borrow` is very similar to, but different than, `AsRef`. See /// [the book][book] for more. /// -/// [book]: ../../book/borrow-and-asref.html +/// [book]: ../../book/first-edition/borrow-and-asref.html #[stable(feature = "rust1", since = "1.0.0")] pub trait Borrow { /// Immutably borrows from an owned value. diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs index 11a360ff900f..6f3c3863fae1 100644 --- a/src/libcore/convert.rs +++ b/src/libcore/convert.rs @@ -71,7 +71,7 @@ use str::FromStr; /// /// See [the book][book] for a more detailed comparison. /// -/// [book]: ../../book/borrow-and-asref.html +/// [book]: ../../book/first-edition/borrow-and-asref.html /// [`Borrow`]: ../../std/borrow/trait.Borrow.html /// /// **Note: this trait must not fail**. If the conversion can fail, use a @@ -305,7 +305,7 @@ pub trait Into: Sized { /// [`String`]: ../../std/string/struct.String.html /// [`Into`]: trait.Into.html /// [`from`]: trait.From.html#tymethod.from -/// [book]: ../../book/error-handling.html +/// [book]: ../../book/first-edition/error-handling.html #[stable(feature = "rust1", since = "1.0.0")] pub trait From: Sized { /// Performs the conversion. diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index d68fad4972c6..91ee064aaba6 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -54,7 +54,7 @@ macro_rules! panic { /// /// [`panic!`]: macro.panic.html /// [`debug_assert!`]: macro.debug_assert.html -/// [testing]: ../book/testing.html +/// [testing]: ../book/first-edition/testing.html /// /// # Examples /// diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index 05df84708e05..3bed425943f7 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -85,7 +85,7 @@ impl !Send for *mut T { } /// // be made into an object /// ``` /// -/// [trait object]: ../../book/trait-objects.html +/// [trait object]: ../../book/first-edition/trait-objects.html #[stable(feature = "rust1", since = "1.0.0")] #[lang = "sized"] #[rustc_on_unimplemented = "`{Self}` does not have a constant size known at compile-time"] @@ -493,7 +493,7 @@ macro_rules! impls{ /// types. We track the Rust type using a phantom type parameter on /// the struct `ExternalResource` which wraps a handle. /// -/// [FFI]: ../../book/ffi.html +/// [FFI]: ../../book/first-edition/ffi.html /// /// ``` /// # #![allow(dead_code)] diff --git a/src/libcore/ops/deref.rs b/src/libcore/ops/deref.rs index 3f4dabbbc0ce..18cf20ac411d 100644 --- a/src/libcore/ops/deref.rs +++ b/src/libcore/ops/deref.rs @@ -13,7 +13,7 @@ /// /// `Deref` also enables ['`Deref` coercions'][coercions]. /// -/// [coercions]: ../../book/deref-coercions.html +/// [coercions]: ../../book/first-edition/deref-coercions.html /// /// # Examples /// @@ -71,7 +71,7 @@ impl<'a, T: ?Sized> Deref for &'a mut T { /// /// `DerefMut` also enables ['`Deref` coercions'][coercions]. /// -/// [coercions]: ../../book/deref-coercions.html +/// [coercions]: ../../book/first-edition/deref-coercions.html /// /// # Examples /// diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs index 0ab0550469ba..f3d0521a2af6 100644 --- a/src/libproc_macro/lib.rs +++ b/src/libproc_macro/lib.rs @@ -21,7 +21,7 @@ //! This functionality is intended to be expanded over time as more surface //! area for macro authors is stabilized. //! -//! See [the book](../book/procedural-macros.html) for more. +//! See [the book](../book/first-edition/procedural-macros.html) for more. #![crate_name = "proc_macro"] #![stable(feature = "proc_macro_lib", since = "1.15.0")] diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index 800e678405aa..28fb96aa2032 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -405,7 +405,7 @@ impl Quux for Foo { } Lifetime elision in implementation headers was part of the lifetime elision RFC. It is, however, [currently unimplemented][iss15872]. -[book-le]: https://doc.rust-lang.org/nightly/book/lifetimes.html#lifetime-elision +[book-le]: https://doc.rust-lang.org/nightly/book/first-edition/lifetimes.html#lifetime-elision [iss15872]: https://github.com/rust-lang/rust/issues/15872 "##, @@ -501,7 +501,7 @@ fn main() { } ``` -See also https://doc.rust-lang.org/book/unsafe.html +See also https://doc.rust-lang.org/book/first-edition/unsafe.html "##, // This shouldn't really ever trigger since the repeated value error comes first @@ -666,7 +666,7 @@ attributes: #![no_std] ``` -See also https://doc.rust-lang.org/book/no-stdlib.html +See also https://doc.rust-lang.org/book/first-edition/no-stdlib.html "##, E0261: r##" @@ -1779,7 +1779,7 @@ fn main() { ``` To understand better how closures work in Rust, read: -https://doc.rust-lang.org/book/closures.html +https://doc.rust-lang.org/book/first-edition/closures.html "##, E0580: r##" diff --git a/src/librustc_borrowck/diagnostics.rs b/src/librustc_borrowck/diagnostics.rs index 2a38dcfd26e1..c114c66559ff 100644 --- a/src/librustc_borrowck/diagnostics.rs +++ b/src/librustc_borrowck/diagnostics.rs @@ -144,7 +144,7 @@ that at most one writer or multiple readers can access the data at any one time. If you wish to learn more about ownership in Rust, start with the chapter in the Book: -https://doc.rust-lang.org/book/ownership.html +https://doc.rust-lang.org/book/first-edition/ownership.html "##, E0383: r##" @@ -366,8 +366,8 @@ let mut a = &mut i; Please note that in rust, you can either have many immutable references, or one mutable reference. Take a look at -https://doc.rust-lang.org/stable/book/references-and-borrowing.html for more -information. Example: +https://doc.rust-lang.org/book/first-edition/references-and-borrowing.html +for more information. Example: ``` @@ -533,7 +533,7 @@ fn foo(a: &mut i32) { ``` For more information on the rust ownership system, take a look at -https://doc.rust-lang.org/stable/book/references-and-borrowing.html. +https://doc.rust-lang.org/book/first-edition/references-and-borrowing.html. "##, E0503: r##" @@ -589,7 +589,7 @@ fn main() { ``` You can find more information about borrowing in the rust-book: -http://doc.rust-lang.org/stable/book/references-and-borrowing.html +http://doc.rust-lang.org/book/first-edition/references-and-borrowing.html "##, E0504: r##" @@ -773,7 +773,7 @@ fn main() { ``` You can find more information about borrowing in the rust-book: -http://doc.rust-lang.org/stable/book/references-and-borrowing.html +http://doc.rust-lang.org/book/first-edition/references-and-borrowing.html "##, E0506: r##" @@ -972,7 +972,7 @@ fn main() { ``` You can find more information about borrowing in the rust-book: -http://doc.rust-lang.org/stable/book/references-and-borrowing.html +http://doc.rust-lang.org/book/first-edition/references-and-borrowing.html "##, E0508: r##" diff --git a/src/librustc_metadata/diagnostics.rs b/src/librustc_metadata/diagnostics.rs index fbdc4695cf82..9a174e05eabd 100644 --- a/src/librustc_metadata/diagnostics.rs +++ b/src/librustc_metadata/diagnostics.rs @@ -44,7 +44,8 @@ To solve this error you can use conditional compilation: extern {} ``` -See more: https://doc.rust-lang.org/book/conditional-compilation.html +See more: +https://doc.rust-lang.org/book/first-edition/conditional-compilation.html "##, E0458: r##" diff --git a/src/librustc_plugin/lib.rs b/src/librustc_plugin/lib.rs index 16ab593e47a7..0df82be3adc9 100644 --- a/src/librustc_plugin/lib.rs +++ b/src/librustc_plugin/lib.rs @@ -47,8 +47,8 @@ //! #![plugin(myplugin)] //! ``` //! -//! See the [Plugins Chapter](../../book/compiler-plugins.html) of the book -//! for more examples. +//! See the [`plugin` feature](../../unstable-book/language-features/plugin.html) of +//! the Unstable Book for more examples. #![crate_name = "rustc_plugin"] #![crate_type = "dylib"] diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 76c664d7997a..9cdde0797a0c 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -1642,7 +1642,7 @@ fn f() {} It is not possible to declare type parameters on a function that has the `start` attribute. Such a function must have the following type signature (for more -information: http://doc.rust-lang.org/stable/book/no-stdlib.html): +information: http://doc.rust-lang.org/stable/book/first-edition/no-stdlib.html): ```ignore fn(isize, *const *const u8) -> isize; @@ -3186,7 +3186,7 @@ impl Baz for Bar { } // Note: This is OK E0374: r##" A struct without a field containing an unsized type cannot implement `CoerceUnsized`. An -[unsized type](https://doc.rust-lang.org/book/unsized-types.html) +[unsized type](https://doc.rust-lang.org/book/first-edition/unsized-types.html) is any type that the compiler doesn't know the length or alignment of at compile time. Any struct containing an unsized type is also unsized. @@ -3245,9 +3245,9 @@ A struct with more than one field containing an unsized type cannot implement `CoerceUnsized`. This only occurs when you are trying to coerce one of the types in your struct to another type in the struct. In this case we try to impl `CoerceUnsized` from `T` to `U` which are both types that the struct -takes. An [unsized type](https://doc.rust-lang.org/book/unsized-types.html) -is any type that the compiler doesn't know the length or alignment of at -compile time. Any struct containing an unsized type is also unsized. +takes. An [unsized type] is any type that the compiler doesn't know the length +or alignment of at compile time. Any struct containing an unsized type is also +unsized. Example of erroneous code: @@ -3292,6 +3292,7 @@ fn coerce_foo, U>(t: T) -> Foo { } ``` +[unsized type]: https://doc.rust-lang.org/book/first-edition/unsized-types.html "##, E0376: r##" @@ -3300,7 +3301,7 @@ The type you are trying to impl `CoerceUnsized` for is not a struct. already able to be coerced without an implementation of `CoerceUnsized` whereas a struct containing an unsized type needs to know the unsized type field it's containing is able to be coerced. An -[unsized type](https://doc.rust-lang.org/book/unsized-types.html) +[unsized type](https://doc.rust-lang.org/book/first-edition/unsized-types.html) is any type that the compiler doesn't know the length or alignment of at compile time. Any struct containing an unsized type is also unsized. diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index c872a8e52611..061e807dace2 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -263,7 +263,7 @@ //! [`println!`]: ../macro.println.html //! [`Lines`]: struct.Lines.html //! [`io::Result`]: type.Result.html -//! [`?` operator]: ../../book/syntax-index.html +//! [`?` operator]: ../../book/first-edition/syntax-index.html //! [`Read::read`]: trait.Read.html#tymethod.read #![stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index df3fce0da765..496c014f70e2 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -486,7 +486,7 @@ pub mod builtin { /// leads to less duplicated code. /// /// The syntax given to this macro is the same syntax as [the `cfg` - /// attribute](../book/conditional-compilation.html). + /// attribute](../book/first-edition/conditional-compilation.html). /// /// # Examples /// diff --git a/src/libstd/prelude/mod.rs b/src/libstd/prelude/mod.rs index 86e661d7948f..195662637f01 100644 --- a/src/libstd/prelude/mod.rs +++ b/src/libstd/prelude/mod.rs @@ -136,10 +136,10 @@ //! [`std::string`]: ../string/index.html //! [`std::vec`]: ../vec/index.html //! [`to_owned`]: ../borrow/trait.ToOwned.html#tymethod.to_owned -//! [book-closures]: ../../book/closures.html -//! [book-dtor]: ../../book/drop.html -//! [book-enums]: ../../book/enums.html -//! [book-iter]: ../../book/iterators.html +//! [book-closures]: ../../book/first-edition/closures.html +//! [book-dtor]: ../../book/first-edition/drop.html +//! [book-enums]: ../../book/first-edition/enums.html +//! [book-iter]: ../../book/first-edition/iterators.html #![stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index ef048ac8ca35..74212625eea0 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -16,7 +16,7 @@ //! benchmarks themselves) should be done via the `#[test]` and //! `#[bench]` attributes. //! -//! See the [Testing Chapter](../book/testing.html) of the book for more details. +//! See the [Testing Chapter](../book/first-edition/testing.html) of the book for more details. // Currently, not much of this is meant for users. It is intended to // support the simplest interface possible for representing and From 79f173ad21277cda8938ecd2b8186e737177ac5c Mon Sep 17 00:00:00 2001 From: Wonwoo Choi Date: Wed, 14 Jun 2017 13:03:48 +0900 Subject: [PATCH 194/233] Remove struct_field_attributes feature gate --- src/librustc_data_structures/lib.rs | 2 +- src/libsyntax/config.rs | 28 ------------------- src/libsyntax/feature_gate.rs | 5 ++-- .../struct-field-attr-feature-gate.rs | 22 --------------- src/test/compile-fail/struct-field-cfg.rs | 2 -- 5 files changed, 3 insertions(+), 56 deletions(-) delete mode 100644 src/test/compile-fail/struct-field-attr-feature-gate.rs diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs index 83cd5cef00cf..cc0e5dec266d 100644 --- a/src/librustc_data_structures/lib.rs +++ b/src/librustc_data_structures/lib.rs @@ -36,11 +36,11 @@ #![feature(discriminant_value)] #![feature(specialization)] #![feature(manually_drop)] -#![feature(struct_field_attributes)] #![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))] #![cfg_attr(stage0, feature(rustc_private))] #![cfg_attr(stage0, feature(staged_api))] +#![cfg_attr(stage0, feature(struct_field_attributes))] #![cfg_attr(unix, feature(libc))] #![cfg_attr(test, feature(test))] diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs index 2e98c7d96260..54e6dde41e6d 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -223,7 +223,6 @@ impl<'a> StripUnconfigured<'a> { ast::ExprKind::Struct(path, fields, base) => { let fields = fields.into_iter() .filter_map(|field| { - self.visit_struct_field_attrs(field.attrs()); self.configure(field) }) .collect(); @@ -256,17 +255,6 @@ impl<'a> StripUnconfigured<'a> { } pub fn configure_struct_expr_field(&mut self, field: ast::Field) -> Option { - if !self.features.map(|features| features.struct_field_attributes).unwrap_or(true) { - if !field.attrs.is_empty() { - let mut err = feature_err(self.sess, - "struct_field_attributes", - field.span, - GateIssue::Language, - "attributes on struct literal fields are unstable"); - err.emit(); - } - } - self.configure(field) } @@ -275,7 +263,6 @@ impl<'a> StripUnconfigured<'a> { if let ast::PatKind::Struct(path, fields, etc) = pattern.node { let fields = fields.into_iter() .filter_map(|field| { - self.visit_struct_field_attrs(field.attrs()); self.configure(field) }) .collect(); @@ -284,21 +271,6 @@ impl<'a> StripUnconfigured<'a> { pattern }) } - - fn visit_struct_field_attrs(&mut self, attrs: &[ast::Attribute]) { - // flag the offending attributes - for attr in attrs.iter() { - if !self.features.map(|features| features.struct_field_attributes).unwrap_or(true) { - let mut err = feature_err( - self.sess, - "struct_field_attributes", - attr.span, - GateIssue::Language, - "attributes on struct pattern or literal fields are unstable"); - err.emit(); - } - } - } } impl<'a> fold::Folder for StripUnconfigured<'a> { diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 7ab0529f518a..4543378789df 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -312,9 +312,6 @@ declare_features! ( // Declarative macros 2.0 (`macro`). (active, decl_macro, "1.17.0", Some(39412)), - // Allows attributes on struct literal fields. - (active, struct_field_attributes, "1.16.0", Some(38814)), - // Allows #[link(kind="static-nobundle"...] (active, static_nobundle, "1.16.0", Some(37403)), @@ -430,6 +427,8 @@ declare_features! ( (accepted, relaxed_adts, "1.19.0", Some(35626)), // Coerces non capturing closures to function pointers (accepted, closure_to_fn_coercion, "1.19.0", Some(39817)), + // Allows attributes on struct literal fields. + (accepted, struct_field_attributes, "1.20.0", Some(38814)), ); // If you change this, please modify src/doc/unstable-book as well. You must diff --git a/src/test/compile-fail/struct-field-attr-feature-gate.rs b/src/test/compile-fail/struct-field-attr-feature-gate.rs deleted file mode 100644 index 47495be4ad2c..000000000000 --- a/src/test/compile-fail/struct-field-attr-feature-gate.rs +++ /dev/null @@ -1,22 +0,0 @@ -// 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. - -// gate-test-struct_field_attributes - -struct Foo { - present: (), -} - -fn main() { - let foo = Foo { #[cfg(all())] present: () }; - //~^ ERROR attributes on struct pattern or literal fields are unstable - let Foo { #[cfg(all())] present: () } = foo; - //~^ ERROR attributes on struct pattern or literal fields are unstable -} diff --git a/src/test/compile-fail/struct-field-cfg.rs b/src/test/compile-fail/struct-field-cfg.rs index 9fb130f4d54f..974d500d9cbd 100644 --- a/src/test/compile-fail/struct-field-cfg.rs +++ b/src/test/compile-fail/struct-field-cfg.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(struct_field_attributes)] - struct Foo { present: (), } From ba6cf1d80ac6f5ff3c36c7f6111197d429369d86 Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Sun, 4 Jun 2017 21:39:00 +0300 Subject: [PATCH 195/233] Re-implement float min/max in rust See #42423 --- src/libcore/num/f32.rs | 28 +++++++++++++++++++ src/libcore/num/f64.rs | 28 +++++++++++++++++++ src/libcore/num/mod.rs | 7 +++++ src/libcore/tests/lib.rs | 1 + src/libcore/tests/num/mod.rs | 54 ++++++++++++++++++++++++++++++++++++ src/libstd/f32.rs | 6 ++-- src/libstd/f64.rs | 6 ++-- 7 files changed, 122 insertions(+), 8 deletions(-) diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index 91ca213e96e0..cb28035682d6 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -242,4 +242,32 @@ impl Float for f32 { let value: f32 = consts::PI; self * (value / 180.0f32) } + + /// Returns the maximum of the two numbers. + #[inline] + fn max(self, other: f32) -> f32 { + // IEEE754 says: maxNum(x, y) is the canonicalized number y if x < y, x if y < x, the + // canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it + // is either x or y, canonicalized (this means results might differ among implementations). + // When either x or y is a signalingNaN, then the result is according to 6.2. + // + // Since we do not support sNaN in Rust yet, we do not need to handle them. + // FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by + // multiplying by 1.0. Should switch to the `canonicalize` when it works. + (if self < other || self.is_nan() { other } else { self }) * 1.0 + } + + /// Returns the minimum of the two numbers. + #[inline] + fn min(self, other: f32) -> f32 { + // IEEE754 says: minNum(x, y) is the canonicalized number x if x < y, y if y < x, the + // canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it + // is either x or y, canonicalized (this means results might differ among implementations). + // When either x or y is a signalingNaN, then the result is according to 6.2. + // + // Since we do not support sNaN in Rust yet, we do not need to handle them. + // FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by + // multiplying by 1.0. Should switch to the `canonicalize` when it works. + (if self < other || other.is_nan() { self } else { other }) * 1.0 + } } diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index 7d6d6cef0497..ac6b1e67cd27 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -242,4 +242,32 @@ impl Float for f64 { let value: f64 = consts::PI; self * (value / 180.0) } + + /// Returns the maximum of the two numbers. + #[inline] + fn max(self, other: f64) -> f64 { + // IEEE754 says: maxNum(x, y) is the canonicalized number y if x < y, x if y < x, the + // canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it + // is either x or y, canonicalized (this means results might differ among implementations). + // When either x or y is a signalingNaN, then the result is according to 6.2. + // + // Since we do not support sNaN in Rust yet, we do not need to handle them. + // FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by + // multiplying by 1.0. Should switch to the `canonicalize` when it works. + (if self < other || self.is_nan() { other } else { self }) * 1.0 + } + + /// Returns the minimum of the two numbers. + #[inline] + fn min(self, other: f64) -> f64 { + // IEEE754 says: minNum(x, y) is the canonicalized number x if x < y, y if y < x, the + // canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it + // is either x or y, canonicalized (this means results might differ among implementations). + // When either x or y is a signalingNaN, then the result is according to 6.2. + // + // Since we do not support sNaN in Rust yet, we do not need to handle them. + // FIXME(nagisa): due to https://bugs.llvm.org/show_bug.cgi?id=33303 we canonicalize by + // multiplying by 1.0. Should switch to the `canonicalize` when it works. + (if self < other || other.is_nan() { self } else { other }) * 1.0 + } } diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index be093cca6a1b..b252d50b02a0 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -2428,6 +2428,13 @@ pub trait Float: Sized { /// Convert degrees to radians. #[stable(feature = "deg_rad_conversions", since="1.7.0")] fn to_radians(self) -> Self; + + /// Returns the maximum of the two numbers. + #[stable(feature = "core_float_min_max", since="1.20.0")] + fn max(self, other: Self) -> Self; + /// Returns the minimum of the two numbers. + #[stable(feature = "core_float_min_max", since="1.20.0")] + fn min(self, other: Self) -> Self; } macro_rules! from_str_radix_int_impl { diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index 505e51fa80b3..054f724959fa 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -13,6 +13,7 @@ #![feature(box_syntax)] #![feature(char_escape_debug)] #![feature(const_fn)] +#![feature(core_float)] #![feature(core_private_bignum)] #![feature(core_private_diy_float)] #![feature(dec2flt)] diff --git a/src/libcore/tests/num/mod.rs b/src/libcore/tests/num/mod.rs index 51737c9c3b48..bc6a6800e0ad 100644 --- a/src/libcore/tests/num/mod.rs +++ b/src/libcore/tests/num/mod.rs @@ -398,3 +398,57 @@ test_impl_try_from_signed_to_unsigned_err! { test_try_i32u16, i32, u16 } test_impl_try_from_signed_to_unsigned_err! { test_try_i64u8, i64, u8 } test_impl_try_from_signed_to_unsigned_err! { test_try_i64u16, i64, u16 } test_impl_try_from_signed_to_unsigned_err! { test_try_i64u32, i64, u32 } + +macro_rules! test_float { + ($modname: ident, $fty: ty, $inf: expr, $neginf: expr, $nan: expr) => { mod $modname { + use core::num::Float; + // FIXME(nagisa): these tests should test for sign of -0.0 + #[test] + fn min() { + assert_eq!(0.0.min(0.0), 0.0); + assert_eq!((-0.0).min(-0.0), -0.0); + assert_eq!(9.0.min(9.0), 9.0); + assert_eq!((-9.0).min(0.0), -9.0); + assert_eq!(0.0.min(9.0), 0.0); + assert_eq!((-0.0).min(-9.0), -9.0); + assert_eq!($inf.min(9.0), 9.0); + assert_eq!(9.0.min($inf), 9.0); + assert_eq!($inf.min(-9.0), -9.0); + assert_eq!((-9.0).min($inf), -9.0); + assert_eq!($neginf.min(9.0), $neginf); + assert_eq!(9.0.min($neginf), $neginf); + assert_eq!($neginf.min(-9.0), $neginf); + assert_eq!((-9.0).min($neginf), $neginf); + assert_eq!($nan.min(9.0), 9.0); + assert_eq!($nan.min(-9.0), -9.0); + assert_eq!(9.0.min($nan), 9.0); + assert_eq!((-9.0).min($nan), -9.0); + assert!($nan.min($nan).is_nan()); + } + #[test] + fn max() { + assert_eq!(0.0.max(0.0), 0.0); + assert_eq!((-0.0).max(-0.0), -0.0); + assert_eq!(9.0.max(9.0), 9.0); + assert_eq!((-9.0).max(0.0), 0.0); + assert_eq!(0.0.max(9.0), 9.0); + assert_eq!((-0.0).max(-9.0), -0.0); + assert_eq!($inf.max(9.0), $inf); + assert_eq!(9.0.max($inf), $inf); + assert_eq!($inf.max(-9.0), $inf); + assert_eq!((-9.0).max($inf), $inf); + assert_eq!($neginf.max(9.0), 9.0); + assert_eq!(9.0.max($neginf), 9.0); + assert_eq!($neginf.max(-9.0), -9.0); + assert_eq!((-9.0).max($neginf), -9.0); + assert_eq!($nan.max(9.0), 9.0); + assert_eq!($nan.max(-9.0), -9.0); + assert_eq!(9.0.max($nan), 9.0); + assert_eq!((-9.0).max($nan), -9.0); + assert!($nan.max($nan).is_nan()); + } + } } +} + +test_float!(f32, f32, ::core::f32::INFINITY, ::core::f32::NEG_INFINITY, ::core::f32::NAN); +test_float!(f64, f64, ::core::f64::INFINITY, ::core::f64::NEG_INFINITY, ::core::f64::NAN); diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs index 4abad7e24f81..6134b0b882c5 100644 --- a/src/libstd/f32.rs +++ b/src/libstd/f32.rs @@ -46,8 +46,6 @@ mod cmath { pub fn erfcf(n: c_float) -> c_float; pub fn expm1f(n: c_float) -> c_float; pub fn fdimf(a: c_float, b: c_float) -> c_float; - pub fn fmaxf(a: c_float, b: c_float) -> c_float; - pub fn fminf(a: c_float, b: c_float) -> c_float; pub fn fmodf(a: c_float, b: c_float) -> c_float; pub fn ilogbf(n: c_float) -> c_int; pub fn logbf(n: c_float) -> c_float; @@ -673,7 +671,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn max(self, other: f32) -> f32 { - unsafe { cmath::fmaxf(self, other) } + num::Float::max(self, other) } /// Returns the minimum of the two numbers. @@ -689,7 +687,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn min(self, other: f32) -> f32 { - unsafe { cmath::fminf(self, other) } + num::Float::min(self, other) } /// The positive difference of two numbers. diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs index 82e3903eec7b..e9b5e4c88696 100644 --- a/src/libstd/f64.rs +++ b/src/libstd/f64.rs @@ -51,8 +51,6 @@ mod cmath { pub fn erfc(n: c_double) -> c_double; pub fn expm1(n: c_double) -> c_double; pub fn fdim(a: c_double, b: c_double) -> c_double; - pub fn fmax(a: c_double, b: c_double) -> c_double; - pub fn fmin(a: c_double, b: c_double) -> c_double; pub fn fmod(a: c_double, b: c_double) -> c_double; pub fn frexp(n: c_double, value: &mut c_int) -> c_double; pub fn ilogb(n: c_double) -> c_int; @@ -587,7 +585,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn max(self, other: f64) -> f64 { - unsafe { cmath::fmax(self, other) } + num::Float::max(self, other) } /// Returns the minimum of the two numbers. @@ -603,7 +601,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn min(self, other: f64) -> f64 { - unsafe { cmath::fmin(self, other) } + num::Float::min(self, other) } /// The positive difference of two numbers. From 15ace49d2e082a6e4e54deff2b436a2fc120637d Mon Sep 17 00:00:00 2001 From: steveklabnik Date: Wed, 14 Jun 2017 15:48:43 -0400 Subject: [PATCH 196/233] update book with redirect fixes Fixes #42632 --- src/doc/book | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/book b/src/doc/book index f746084b0990..325c3da0814f 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit f746084b099060f55ac5e7d8050797593fcedd6e +Subproject commit 325c3da0814f44916bef00ff225f934f2d613203 From 7b9519a5d47879c37f0ac6871cee2e1cb8eca1cc Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Mon, 8 May 2017 19:45:27 +0300 Subject: [PATCH 197/233] suppress trait errors that are implied by other errors Instead of suppressing only trait errors that are "exact duplicates", display only the "most high-level" error when there are multiple trait errors with the same span that imply each-other. e.g. when there are both `[closure]: Fn` and `[closure]: FnOnce`, omit displaying the `[closure]: FnOnce` bound. --- src/librustc/infer/error_reporting/mod.rs | 1 + .../infer/error_reporting/need_type_info.rs | 153 ++++++++++ src/librustc/infer/mod.rs | 7 +- src/librustc/traits/error_reporting.rs | 274 +++++++----------- src/librustc/traits/mod.rs | 1 - src/librustc_driver/lib.rs | 5 +- .../compile-fail/extern-wrong-value-type.rs | 1 - src/test/compile-fail/fn-trait-formatting.rs | 1 - src/test/compile-fail/issue-22034.rs | 1 - src/test/compile-fail/issue-23966.rs | 1 - src/test/compile-fail/range_traits-1.rs | 31 +- src/test/compile-fail/str-mut-idx.rs | 3 +- .../unboxed-closures-unsafe-extern-fn.rs | 2 - .../unboxed-closures-wrong-abi.rs | 2 - ...boxed-closures-wrong-arg-type-extern-fn.rs | 2 - src/test/compile-fail/unsized6.rs | 12 +- src/test/ui/mismatched_types/E0281.stderr | 11 - src/test/ui/mismatched_types/binops.stderr | 8 - .../mismatched_types/closure-arg-count.stderr | 24 -- .../ui/mismatched_types/issue-36053-2.stderr | 9 - .../unboxed-closures-vtable-mismatch.rs | 1 - .../unboxed-closures-vtable-mismatch.stderr | 14 - src/test/ui/type-check/issue-40294.stderr | 6 +- 23 files changed, 291 insertions(+), 279 deletions(-) create mode 100644 src/librustc/infer/error_reporting/need_type_info.rs diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 0515e1cc3043..11bac21bc429 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -74,6 +74,7 @@ use syntax_pos::{Pos, Span}; use errors::{DiagnosticBuilder, DiagnosticStyledString}; mod note; +mod need_type_info; impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn note_and_explain_region(self, diff --git a/src/librustc/infer/error_reporting/need_type_info.rs b/src/librustc/infer/error_reporting/need_type_info.rs new file mode 100644 index 000000000000..7361d66428f6 --- /dev/null +++ b/src/librustc/infer/error_reporting/need_type_info.rs @@ -0,0 +1,153 @@ +// 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 hir::{self, map, Local, Pat, Body}; +use hir::intravisit::{self, Visitor, NestedVisitorMap}; +use infer::InferCtxt; +use infer::type_variable::TypeVariableOrigin; +use ty::{self, Ty, TyInfer, TyVar}; + +use syntax::ast::NodeId; +use syntax_pos::Span; + +struct FindLocalByTypeVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { + infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, + target_ty: &'a Ty<'tcx>, + hir_map: &'a hir::map::Map<'gcx>, + found_local_pattern: Option<&'gcx Pat>, + found_arg_pattern: Option<&'gcx Pat>, +} + +impl<'a, 'gcx, 'tcx> FindLocalByTypeVisitor<'a, 'gcx, 'tcx> { + fn node_matches_type(&mut self, node_id: NodeId) -> bool { + let ty_opt = self.infcx.in_progress_tables.and_then(|tables| { + tables.borrow().node_id_to_type_opt(node_id) + }); + match ty_opt { + Some(ty) => { + let ty = self.infcx.resolve_type_vars_if_possible(&ty); + ty.walk().any(|inner_ty| { + inner_ty == *self.target_ty || match (&inner_ty.sty, &self.target_ty.sty) { + (&TyInfer(TyVar(a_vid)), &TyInfer(TyVar(b_vid))) => { + self.infcx + .type_variables + .borrow_mut() + .sub_unified(a_vid, b_vid) + } + _ => false, + } + }) + } + None => false, + } + } +} + +impl<'a, 'gcx, 'tcx> Visitor<'gcx> for FindLocalByTypeVisitor<'a, 'gcx, 'tcx> { + fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> { + NestedVisitorMap::OnlyBodies(&self.hir_map) + } + + fn visit_local(&mut self, local: &'gcx Local) { + if self.found_local_pattern.is_none() && self.node_matches_type(local.id) { + self.found_local_pattern = Some(&*local.pat); + } + intravisit::walk_local(self, local); + } + + fn visit_body(&mut self, body: &'gcx Body) { + for argument in &body.arguments { + if self.found_arg_pattern.is_none() && self.node_matches_type(argument.id) { + self.found_arg_pattern = Some(&*argument.pat); + } + } + intravisit::walk_body(self, body); + } +} + + +impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { + fn extract_type_name(&self, ty: &'a Ty<'tcx>) -> String { + if let ty::TyInfer(ty::TyVar(ty_vid)) = (*ty).sty { + let ty_vars = self.type_variables.borrow(); + if let TypeVariableOrigin::TypeParameterDefinition(_, name) = + *ty_vars.var_origin(ty_vid) { + name.to_string() + } else { + ty.to_string() + } + } else { + ty.to_string() + } + } + + pub fn need_type_info(&self, body_id: hir::BodyId, span: Span, ty: Ty<'tcx>) { + let ty = self.resolve_type_vars_if_possible(&ty); + let name = self.extract_type_name(&ty); + + let mut err_span = span; + let mut labels = vec![(span, format!("cannot infer type for `{}`", name))]; + + let mut local_visitor = FindLocalByTypeVisitor { + infcx: &self, + target_ty: &ty, + hir_map: &self.tcx.hir, + found_local_pattern: None, + found_arg_pattern: None, + }; + + // #40294: cause.body_id can also be a fn declaration. + // Currently, if it's anything other than NodeExpr, we just ignore it + match self.tcx.hir.find(body_id.node_id) { + Some(map::NodeExpr(expr)) => local_visitor.visit_expr(expr), + _ => () + } + + if let Some(pattern) = local_visitor.found_arg_pattern { + err_span = pattern.span; + // We don't want to show the default label for closures. + // + // So, before clearing, the output would look something like this: + // ``` + // let x = |_| { }; + // - ^^^^ cannot infer type for `[_; 0]` + // | + // consider giving this closure parameter a type + // ``` + // + // After clearing, it looks something like this: + // ``` + // let x = |_| { }; + // ^ consider giving this closure parameter a type + // ``` + labels.clear(); + labels.push((pattern.span, format!("consider giving this closure parameter a type"))); + } + + if let Some(pattern) = local_visitor.found_local_pattern { + if let Some(simple_name) = pattern.simple_name() { + labels.push((pattern.span, format!("consider giving `{}` a type", simple_name))); + } else { + labels.push((pattern.span, format!("consider giving the pattern a type"))); + } + } + + let mut err = struct_span_err!(self.tcx.sess, + err_span, + E0282, + "type annotations needed"); + + for (target_span, label_message) in labels { + err.span_label(target_span, label_message); + } + + err.emit(); + } +} diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 4bc0005d568a..f96e8c389d68 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -36,7 +36,7 @@ use std::fmt; use syntax::ast; use errors::DiagnosticBuilder; use syntax_pos::{self, Span, DUMMY_SP}; -use util::nodemap::{FxHashMap, FxHashSet}; +use util::nodemap::FxHashMap; use arena::DroplessArena; use self::combine::CombineFields; @@ -110,7 +110,7 @@ pub struct InferCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { // the set of predicates on which errors have been reported, to // avoid reporting the same error twice. - pub reported_trait_errors: RefCell>>, + pub reported_trait_errors: RefCell>>>, // When an error occurs, we want to avoid reporting "derived" // errors that are due to this original failure. Normally, we @@ -350,6 +350,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> { global_tcx: self, arena: DroplessArena::new(), fresh_tables: None, + } } } @@ -381,7 +382,7 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> { region_vars: RegionVarBindings::new(tcx), selection_cache: traits::SelectionCache::new(), evaluation_cache: traits::EvaluationCache::new(), - reported_trait_errors: RefCell::new(FxHashSet()), + reported_trait_errors: RefCell::new(FxHashMap()), tainted_by_errors_flag: Cell::new(false), err_count_on_creation: tcx.sess.err_count(), in_snapshot: Cell::new(false), diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 64438f586d7f..247fb079fe7e 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -18,6 +18,7 @@ use super::{ OutputTypeParameterMismatch, TraitNotObjectSafe, PredicateObligation, + Reveal, SelectionContext, SelectionError, ObjectSafetyViolation, @@ -25,16 +26,14 @@ use super::{ use errors::DiagnosticBuilder; use fmt_macros::{Parser, Piece, Position}; -use hir::{self, intravisit, Local, Pat, Body}; -use hir::intravisit::{Visitor, NestedVisitorMap}; -use hir::map::NodeExpr; +use hir; use hir::def_id::DefId; use infer::{self, InferCtxt}; use infer::type_variable::TypeVariableOrigin; use rustc::lint::builtin::EXTRA_REQUIREMENT_IN_IMPL; use std::fmt; -use syntax::ast::{self, NodeId}; -use ty::{self, AdtKind, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable, TyInfer, TyVar}; +use syntax::ast; +use ty::{self, AdtKind, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable}; use ty::error::{ExpectedFound, TypeError}; use ty::fast_reject; use ty::fold::TypeFolder; @@ -44,96 +43,113 @@ use util::nodemap::{FxHashMap, FxHashSet}; use syntax_pos::{DUMMY_SP, Span}; - -#[derive(Debug, PartialEq, Eq, Hash)] -pub struct TraitErrorKey<'tcx> { - span: Span, - predicate: ty::Predicate<'tcx> -} - -impl<'a, 'gcx, 'tcx> TraitErrorKey<'tcx> { - fn from_error(infcx: &InferCtxt<'a, 'gcx, 'tcx>, - e: &FulfillmentError<'tcx>) -> Self { - let predicate = - infcx.resolve_type_vars_if_possible(&e.obligation.predicate); - TraitErrorKey { - span: e.obligation.cause.span, - predicate: infcx.tcx.erase_regions(&predicate) - } - } -} - -struct FindLocalByTypeVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { - infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, - target_ty: &'a Ty<'tcx>, - hir_map: &'a hir::map::Map<'gcx>, - found_local_pattern: Option<&'gcx Pat>, - found_arg_pattern: Option<&'gcx Pat>, -} - -impl<'a, 'gcx, 'tcx> FindLocalByTypeVisitor<'a, 'gcx, 'tcx> { - fn node_matches_type(&mut self, node_id: NodeId) -> bool { - let ty_opt = self.infcx.in_progress_tables.and_then(|tables| { - tables.borrow().node_id_to_type_opt(node_id) - }); - match ty_opt { - Some(ty) => { - let ty = self.infcx.resolve_type_vars_if_possible(&ty); - ty.walk().any(|inner_ty| { - inner_ty == *self.target_ty || match (&inner_ty.sty, &self.target_ty.sty) { - (&TyInfer(TyVar(a_vid)), &TyInfer(TyVar(b_vid))) => { - self.infcx - .type_variables - .borrow_mut() - .sub_unified(a_vid, b_vid) - } - _ => false, - } - }) - } - None => false, - } - } -} - -impl<'a, 'gcx, 'tcx> Visitor<'gcx> for FindLocalByTypeVisitor<'a, 'gcx, 'tcx> { - fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> { - NestedVisitorMap::OnlyBodies(&self.hir_map) - } - - fn visit_local(&mut self, local: &'gcx Local) { - if self.found_local_pattern.is_none() && self.node_matches_type(local.id) { - self.found_local_pattern = Some(&*local.pat); - } - intravisit::walk_local(self, local); - } - - fn visit_body(&mut self, body: &'gcx Body) { - for argument in &body.arguments { - if self.found_arg_pattern.is_none() && self.node_matches_type(argument.id) { - self.found_arg_pattern = Some(&*argument.pat); - } - } - intravisit::walk_body(self, body); - } -} - impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { - pub fn report_fulfillment_errors(&self, errors: &Vec>) { - for error in errors { - self.report_fulfillment_error(error); + pub fn report_fulfillment_errors(&self, + errors: &Vec>) { + #[derive(Debug)] + struct ErrorDescriptor<'tcx> { + predicate: ty::Predicate<'tcx>, + index: Option, // None if this is an old error + } + + let mut error_map : FxHashMap<_, _> = + self.reported_trait_errors.borrow().iter().map(|(&span, predicates)| { + (span, predicates.iter().map(|predicate| ErrorDescriptor { + predicate: predicate.clone(), + index: None + }).collect()) + }).collect(); + + for (index, error) in errors.iter().enumerate() { + error_map.entry(error.obligation.cause.span).or_insert(Vec::new()).push( + ErrorDescriptor { + predicate: error.obligation.predicate.clone(), + index: Some(index) + }); + + self.reported_trait_errors.borrow_mut() + .entry(error.obligation.cause.span).or_insert(Vec::new()) + .push(error.obligation.predicate.clone()); + } + + // We do this in 2 passes because we want to display errors in order, tho + // maybe it *is* better to sort errors by span or something. + let mut is_suppressed: Vec = errors.iter().map(|_| false).collect(); + for (_, error_set) in error_map.iter() { + // We want to suppress "duplicate" errors with the same span. + for error in error_set { + if let Some(index) = error.index { + // Suppress errors that are either: + // 1) strictly implied by another error. + // 2) implied by an error with a smaller index. + for error2 in error_set { + if error2.index.map_or(false, |index2| is_suppressed[index2]) { + // Avoid errors being suppressed by already-suppressed + // errors, to prevent all errors from being suppressed + // at once. + continue + } + + if self.error_implies(&error2.predicate, &error.predicate) && + !(error2.index >= error.index && + self.error_implies(&error.predicate, &error2.predicate)) + { + info!("skipping {:?} (implied by {:?})", error, error2); + is_suppressed[index] = true; + break + } + } + } + } + } + + for (error, suppressed) in errors.iter().zip(is_suppressed) { + if !suppressed { + self.report_fulfillment_error(error); + } } } - fn report_fulfillment_error(&self, - error: &FulfillmentError<'tcx>) { - let error_key = TraitErrorKey::from_error(self, error); - debug!("report_fulfillment_errors({:?}) - key={:?}", - error, error_key); - if !self.reported_trait_errors.borrow_mut().insert(error_key) { - debug!("report_fulfillment_errors: skipping duplicate"); - return; + // returns if `cond` not occuring implies that `error` does not occur - i.e. that + // `error` occuring implies that `cond` occurs. + fn error_implies(&self, + cond: &ty::Predicate<'tcx>, + error: &ty::Predicate<'tcx>) + -> bool + { + if cond == error { + return true } + + let (cond, error) = match (cond, error) { + (&ty::Predicate::Trait(..), &ty::Predicate::Trait(ref error)) + => (cond, error), + _ => { + // FIXME: make this work in other cases too. + return false + } + }; + + for implication in super::elaborate_predicates(self.tcx, vec![cond.clone()]) { + if let ty::Predicate::Trait(implication) = implication { + let error = error.to_poly_trait_ref(); + let implication = implication.to_poly_trait_ref(); + // FIXME: I'm just not taking associated types at all here. + // Eventually I'll need to implement param-env-aware + // `Γ₁ ⊦ φ₁ => Γ₂ ⊦ φ₂` logic. + let param_env = ty::ParamEnv::empty(Reveal::UserFacing); + if let Ok(_) = self.can_sub(param_env, error, implication) { + debug!("error_implies: {:?} -> {:?} -> {:?}", cond, error, implication); + return true + } + } + } + + false + } + + fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>) { + debug!("report_fulfillment_errors({:?})", error); match error.code { FulfillmentErrorCode::CodeSelectionError(ref e) => { self.report_selection_error(&error.obligation, e); @@ -1008,83 +1024,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { }) } - fn extract_type_name(&self, ty: &'a Ty<'tcx>) -> String { - if let ty::TyInfer(ty::TyVar(ty_vid)) = (*ty).sty { - let ty_vars = self.type_variables.borrow(); - if let TypeVariableOrigin::TypeParameterDefinition(_, name) = - *ty_vars.var_origin(ty_vid) { - name.to_string() - } else { - ty.to_string() - } - } else { - ty.to_string() - } - } - - pub fn need_type_info(&self, body_id: hir::BodyId, span: Span, ty: Ty<'tcx>) { - let ty = self.resolve_type_vars_if_possible(&ty); - let name = self.extract_type_name(&ty); - - let mut err_span = span; - let mut labels = vec![(span, format!("cannot infer type for `{}`", name))]; - - let mut local_visitor = FindLocalByTypeVisitor { - infcx: &self, - target_ty: &ty, - hir_map: &self.tcx.hir, - found_local_pattern: None, - found_arg_pattern: None, - }; - - // #40294: cause.body_id can also be a fn declaration. - // Currently, if it's anything other than NodeExpr, we just ignore it - match self.tcx.hir.find(body_id.node_id) { - Some(NodeExpr(expr)) => local_visitor.visit_expr(expr), - _ => () - } - - if let Some(pattern) = local_visitor.found_arg_pattern { - err_span = pattern.span; - // We don't want to show the default label for closures. - // - // So, before clearing, the output would look something like this: - // ``` - // let x = |_| { }; - // - ^^^^ cannot infer type for `[_; 0]` - // | - // consider giving this closure parameter a type - // ``` - // - // After clearing, it looks something like this: - // ``` - // let x = |_| { }; - // ^ consider giving this closure parameter a type - // ``` - labels.clear(); - labels.push((pattern.span, format!("consider giving this closure parameter a type"))); - } - - if let Some(pattern) = local_visitor.found_local_pattern { - if let Some(simple_name) = pattern.simple_name() { - labels.push((pattern.span, format!("consider giving `{}` a type", simple_name))); - } else { - labels.push((pattern.span, format!("consider giving the pattern a type"))); - } - } - - let mut err = struct_span_err!(self.tcx.sess, - err_span, - E0282, - "type annotations needed"); - - for (target_span, label_message) in labels { - err.span_label(target_span, label_message); - } - - err.emit(); - } - fn note_obligation_cause(&self, err: &mut DiagnosticBuilder, obligation: &Obligation<'tcx, T>) @@ -1205,4 +1144,3 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { suggested_limit)); } } - diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 3ce7ee847cca..e9196cd12431 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -28,7 +28,6 @@ use std::rc::Rc; use syntax::ast; use syntax_pos::{Span, DUMMY_SP}; -pub use self::error_reporting::TraitErrorKey; pub use self::coherence::orphan_check; pub use self::coherence::overlapping_impls; pub use self::coherence::OrphanCheckErr; diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index c5f89e861fa1..8bd992b12e62 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -1101,7 +1101,10 @@ pub fn monitor(f: F) { } let xs = ["the compiler unexpectedly panicked. this is a bug.".to_string(), - format!("we would appreciate a bug report: {}", BUG_REPORT_URL)]; + format!("we would appreciate a bug report: {}", BUG_REPORT_URL), + format!("rustc {} running on {}", + option_env!("CFG_VERSION").unwrap_or("unknown_version"), + config::host_triple())]; for note in &xs { handler.emit(&MultiSpan::new(), ¬e, diff --git a/src/test/compile-fail/extern-wrong-value-type.rs b/src/test/compile-fail/extern-wrong-value-type.rs index 576368aef312..66b06c505e47 100644 --- a/src/test/compile-fail/extern-wrong-value-type.rs +++ b/src/test/compile-fail/extern-wrong-value-type.rs @@ -18,5 +18,4 @@ fn main() { let _x: extern "C" fn() = f; // OK is_fn(f); //~^ ERROR `extern "C" fn() {f}: std::ops::Fn<()>` is not satisfied - //~| ERROR `extern "C" fn() {f}: std::ops::FnOnce<()>` is not satisfied } diff --git a/src/test/compile-fail/fn-trait-formatting.rs b/src/test/compile-fail/fn-trait-formatting.rs index 6377550d3d22..6d70f54edb42 100644 --- a/src/test/compile-fail/fn-trait-formatting.rs +++ b/src/test/compile-fail/fn-trait-formatting.rs @@ -28,5 +28,4 @@ fn main() { needs_fn(1); //~^ ERROR : std::ops::Fn<(isize,)>` - //~| ERROR : std::ops::FnOnce<(isize,)>` } diff --git a/src/test/compile-fail/issue-22034.rs b/src/test/compile-fail/issue-22034.rs index dfa9520f38bb..5271ea799178 100644 --- a/src/test/compile-fail/issue-22034.rs +++ b/src/test/compile-fail/issue-22034.rs @@ -17,6 +17,5 @@ fn main() { let _: &mut Fn() = unsafe { &mut *(ptr as *mut Fn()) //~^ ERROR `(): std::ops::Fn<()>` is not satisfied - //~| ERROR `(): std::ops::FnOnce<()>` is not satisfied }; } diff --git a/src/test/compile-fail/issue-23966.rs b/src/test/compile-fail/issue-23966.rs index 7f9c7a292f2b..544d3c8af205 100644 --- a/src/test/compile-fail/issue-23966.rs +++ b/src/test/compile-fail/issue-23966.rs @@ -11,5 +11,4 @@ fn main() { "".chars().fold(|_, _| (), ()); //~^ ERROR E0277 - //~| ERROR E0277 } diff --git a/src/test/compile-fail/range_traits-1.rs b/src/test/compile-fail/range_traits-1.rs index 852197177585..cf5c40bd1761 100644 --- a/src/test/compile-fail/range_traits-1.rs +++ b/src/test/compile-fail/range_traits-1.rs @@ -17,8 +17,8 @@ use std::ops::*; struct AllTheRanges { a: Range, //~^ ERROR PartialOrd - //~^^ ERROR PartialOrd - //~^^^ ERROR Ord + //~^^ ERROR Ord + //~^^^ ERROR binary operation //~^^^^ ERROR binary operation //~^^^^^ ERROR binary operation //~^^^^^^ ERROR binary operation @@ -26,11 +26,10 @@ struct AllTheRanges { //~^^^^^^^^ ERROR binary operation //~^^^^^^^^^ ERROR binary operation //~^^^^^^^^^^ ERROR binary operation - //~^^^^^^^^^^^ ERROR binary operation b: RangeTo, //~^ ERROR PartialOrd - //~^^ ERROR PartialOrd - //~^^^ ERROR Ord + //~^^ ERROR Ord + //~^^^ ERROR binary operation //~^^^^ ERROR binary operation //~^^^^^ ERROR binary operation //~^^^^^^ ERROR binary operation @@ -38,11 +37,10 @@ struct AllTheRanges { //~^^^^^^^^ ERROR binary operation //~^^^^^^^^^ ERROR binary operation //~^^^^^^^^^^ ERROR binary operation - //~^^^^^^^^^^^ ERROR binary operation c: RangeFrom, //~^ ERROR PartialOrd - //~^^ ERROR PartialOrd - //~^^^ ERROR Ord + //~^^ ERROR Ord + //~^^^ ERROR binary operation //~^^^^ ERROR binary operation //~^^^^^ ERROR binary operation //~^^^^^^ ERROR binary operation @@ -50,11 +48,10 @@ struct AllTheRanges { //~^^^^^^^^ ERROR binary operation //~^^^^^^^^^ ERROR binary operation //~^^^^^^^^^^ ERROR binary operation - //~^^^^^^^^^^^ ERROR binary operation d: RangeFull, //~^ ERROR PartialOrd - //~^^ ERROR PartialOrd - //~^^^ ERROR Ord + //~^^ ERROR Ord + //~^^^ ERROR binary operation //~^^^^ ERROR binary operation //~^^^^^ ERROR binary operation //~^^^^^^ ERROR binary operation @@ -62,11 +59,10 @@ struct AllTheRanges { //~^^^^^^^^ ERROR binary operation //~^^^^^^^^^ ERROR binary operation //~^^^^^^^^^^ ERROR binary operation - //~^^^^^^^^^^^ ERROR binary operation e: RangeInclusive, //~^ ERROR PartialOrd - //~^^ ERROR PartialOrd - //~^^^ ERROR Ord + //~^^ ERROR Ord + //~^^^ ERROR binary operation //~^^^^ ERROR binary operation //~^^^^^ ERROR binary operation //~^^^^^^ ERROR binary operation @@ -74,11 +70,10 @@ struct AllTheRanges { //~^^^^^^^^ ERROR binary operation //~^^^^^^^^^ ERROR binary operation //~^^^^^^^^^^ ERROR binary operation - //~^^^^^^^^^^^ ERROR binary operation f: RangeToInclusive, //~^ ERROR PartialOrd - //~^^ ERROR PartialOrd - //~^^^ ERROR Ord + //~^^ ERROR Ord + //~^^^ ERROR binary operation //~^^^^ ERROR binary operation //~^^^^^ ERROR binary operation //~^^^^^^ ERROR binary operation @@ -86,8 +81,6 @@ struct AllTheRanges { //~^^^^^^^^ ERROR binary operation //~^^^^^^^^^ ERROR binary operation //~^^^^^^^^^^ ERROR binary operation - //~^^^^^^^^^^^ ERROR binary operation } fn main() {} - diff --git a/src/test/compile-fail/str-mut-idx.rs b/src/test/compile-fail/str-mut-idx.rs index 8851e5e07973..219fcdfd7026 100644 --- a/src/test/compile-fail/str-mut-idx.rs +++ b/src/test/compile-fail/str-mut-idx.rs @@ -15,8 +15,7 @@ fn mutate(s: &mut str) { //~^ ERROR `str: std::marker::Sized` is not satisfied //~| ERROR `str: std::marker::Sized` is not satisfied s[1usize] = bot(); - //~^ ERROR `str: std::ops::Index` is not satisfied - //~| ERROR `str: std::ops::IndexMut` is not satisfied + //~^ ERROR `str: std::ops::IndexMut` is not satisfied } pub fn main() {} diff --git a/src/test/compile-fail/unboxed-closures-unsafe-extern-fn.rs b/src/test/compile-fail/unboxed-closures-unsafe-extern-fn.rs index 2b0a8baf4f23..5ba93bf483f2 100644 --- a/src/test/compile-fail/unboxed-closures-unsafe-extern-fn.rs +++ b/src/test/compile-fail/unboxed-closures-unsafe-extern-fn.rs @@ -21,13 +21,11 @@ fn call_it_onceisize>(_: F, _: isize) -> isize { 0 } fn a() { let x = call_it(&square, 22); //~^ ERROR E0277 - //~| ERROR E0277 } fn b() { let y = call_it_mut(&mut square, 22); //~^ ERROR E0277 - //~| ERROR E0277 } fn c() { diff --git a/src/test/compile-fail/unboxed-closures-wrong-abi.rs b/src/test/compile-fail/unboxed-closures-wrong-abi.rs index f6ba25f43685..ff06f7c559b2 100644 --- a/src/test/compile-fail/unboxed-closures-wrong-abi.rs +++ b/src/test/compile-fail/unboxed-closures-wrong-abi.rs @@ -21,13 +21,11 @@ fn call_it_onceisize>(_: F, _: isize) -> isize { 0 } fn a() { let x = call_it(&square, 22); //~^ ERROR E0277 - //~| ERROR E0277 } fn b() { let y = call_it_mut(&mut square, 22); //~^ ERROR E0277 - //~| ERROR E0277 } fn c() { diff --git a/src/test/compile-fail/unboxed-closures-wrong-arg-type-extern-fn.rs b/src/test/compile-fail/unboxed-closures-wrong-arg-type-extern-fn.rs index 9d907ffc17f2..d77750d2a040 100644 --- a/src/test/compile-fail/unboxed-closures-wrong-arg-type-extern-fn.rs +++ b/src/test/compile-fail/unboxed-closures-wrong-arg-type-extern-fn.rs @@ -22,13 +22,11 @@ fn call_it_onceisize>(_: F, _: isize) -> isize { 0 } fn a() { let x = call_it(&square, 22); //~^ ERROR E0277 - //~| ERROR E0277 } fn b() { let y = call_it_mut(&mut square, 22); //~^ ERROR E0277 - //~| ERROR E0277 } fn c() { diff --git a/src/test/compile-fail/unsized6.rs b/src/test/compile-fail/unsized6.rs index 462d760a60ce..dec8699f46e3 100644 --- a/src/test/compile-fail/unsized6.rs +++ b/src/test/compile-fail/unsized6.rs @@ -12,15 +12,15 @@ trait T {} -fn f1(x: &X) { - let _: X; // <-- this is OK, no bindings created, no initializer. +fn f1(x: &X) { + let _: W; // <-- this is OK, no bindings created, no initializer. let _: (isize, (X, isize)); //~ERROR `X: std::marker::Sized` is not satisfie - let y: X; //~ERROR `X: std::marker::Sized` is not satisfied - let y: (isize, (X, usize)); + let y: Y; //~ERROR `Y: std::marker::Sized` is not satisfied + let y: (isize, (Z, usize)); //~ERROR `Z: std::marker::Sized` is not satisfied } -fn f2(x: &X) { +fn f2(x: &X) { let y: X; //~ERROR `X: std::marker::Sized` is not satisfied - let y: (isize, (X, isize)); //~ERROR `X: std::marker::Sized` is not satisfied + let y: (isize, (Y, isize)); //~ERROR `Y: std::marker::Sized` is not satisfied } fn f3(x1: Box, x2: Box, x3: Box) { diff --git a/src/test/ui/mismatched_types/E0281.stderr b/src/test/ui/mismatched_types/E0281.stderr index fab48e9a740a..3eb5c125789f 100644 --- a/src/test/ui/mismatched_types/E0281.stderr +++ b/src/test/ui/mismatched_types/E0281.stderr @@ -9,16 +9,5 @@ error[E0281]: type mismatch: `[closure@$DIR/E0281.rs:14:9: 14:24]` implements th | = note: required by `foo` -error[E0281]: type mismatch: `[closure@$DIR/E0281.rs:14:9: 14:24]` implements the trait `std::ops::FnOnce<(std::string::String,)>`, but the trait `std::ops::FnOnce<(usize,)>` is required - --> $DIR/E0281.rs:14:5 - | -14 | foo(|y: String| { }); - | ^^^ --------------- implements `std::ops::FnOnce<(std::string::String,)>` - | | - | requires `std::ops::FnOnce<(usize,)>` - | expected usize, found struct `std::string::String` - | - = note: required by `foo` - error: aborting due to previous error(s) diff --git a/src/test/ui/mismatched_types/binops.stderr b/src/test/ui/mismatched_types/binops.stderr index 1faf72cd760b..cebdc12f5684 100644 --- a/src/test/ui/mismatched_types/binops.stderr +++ b/src/test/ui/mismatched_types/binops.stderr @@ -30,14 +30,6 @@ error[E0277]: the trait bound `{integer}: std::ops::Div<&str>` is not satisfied | = help: the trait `std::ops::Div<&str>` is not implemented for `{integer}` -error[E0277]: the trait bound `{integer}: std::cmp::PartialEq` is not satisfied - --> $DIR/binops.rs:16:7 - | -16 | 5 < String::new(); - | ^ can't compare `{integer}` with `std::string::String` - | - = help: the trait `std::cmp::PartialEq` is not implemented for `{integer}` - error[E0277]: the trait bound `{integer}: std::cmp::PartialOrd` is not satisfied --> $DIR/binops.rs:16:7 | diff --git a/src/test/ui/mismatched_types/closure-arg-count.stderr b/src/test/ui/mismatched_types/closure-arg-count.stderr index cd16e5d70b68..85734dfac70d 100644 --- a/src/test/ui/mismatched_types/closure-arg-count.stderr +++ b/src/test/ui/mismatched_types/closure-arg-count.stderr @@ -6,22 +6,6 @@ error[E0593]: closure takes 0 arguments but 2 arguments are required | | | expected closure that takes 2 arguments -error[E0593]: closure takes 0 arguments but 2 arguments are required - --> $DIR/closure-arg-count.rs:12:15 - | -12 | [1, 2, 3].sort_by(|| panic!()); - | ^^^^^^^ ----------- takes 0 arguments - | | - | expected closure that takes 2 arguments - -error[E0593]: closure takes 1 argument but 2 arguments are required - --> $DIR/closure-arg-count.rs:13:15 - | -13 | [1, 2, 3].sort_by(|tuple| panic!()); - | ^^^^^^^ ---------------- takes 1 argument - | | - | expected closure that takes 2 arguments - error[E0593]: closure takes 1 argument but 2 arguments are required --> $DIR/closure-arg-count.rs:13:15 | @@ -47,13 +31,5 @@ error[E0593]: closure takes 1 argument but 2 arguments are required | | | expected closure that takes 2 arguments -error[E0593]: closure takes 1 argument but 2 arguments are required - --> $DIR/closure-arg-count.rs:14:15 - | -14 | [1, 2, 3].sort_by(|(tuple, tuple2)| panic!()); - | ^^^^^^^ -------------------------- takes 1 argument - | | - | expected closure that takes 2 arguments - error: aborting due to previous error(s) diff --git a/src/test/ui/mismatched_types/issue-36053-2.stderr b/src/test/ui/mismatched_types/issue-36053-2.stderr index 8b756814ced8..f818bd8bcb1b 100644 --- a/src/test/ui/mismatched_types/issue-36053-2.stderr +++ b/src/test/ui/mismatched_types/issue-36053-2.stderr @@ -17,14 +17,5 @@ error[E0281]: type mismatch: `[closure@$DIR/issue-36053-2.rs:17:39: 17:53]` impl | requires `for<'r> std::ops::FnMut<(&'r &str,)>` | expected &str, found str -error[E0281]: type mismatch: `[closure@$DIR/issue-36053-2.rs:17:39: 17:53]` implements the trait `for<'r> std::ops::FnOnce<(&'r str,)>`, but the trait `for<'r> std::ops::FnOnce<(&'r &str,)>` is required - --> $DIR/issue-36053-2.rs:17:32 - | -17 | once::<&str>("str").fuse().filter(|a: &str| true).count(); - | ^^^^^^ -------------- implements `for<'r> std::ops::FnOnce<(&'r str,)>` - | | - | requires `for<'r> std::ops::FnOnce<(&'r &str,)>` - | expected &str, found str - error: aborting due to previous error(s) diff --git a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs index 7400a27fb6bc..693a1585320e 100644 --- a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs +++ b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs @@ -24,7 +24,6 @@ pub fn main() { //~| NOTE implements let z = call_it(3, f); //~^ ERROR type mismatch - //~| ERROR type mismatch //~| NOTE expected isize, found usize //~| NOTE expected isize, found usize //~| NOTE requires diff --git a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr index c5bfb6e45e77..643c9b36dbd5 100644 --- a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr +++ b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr @@ -12,19 +12,5 @@ error[E0281]: type mismatch: `[closure@$DIR/unboxed-closures-vtable-mismatch.rs: | = note: required by `call_it` -error[E0281]: type mismatch: `[closure@$DIR/unboxed-closures-vtable-mismatch.rs:22:23: 22:73]` implements the trait `std::ops::FnOnce<(usize, isize)>`, but the trait `std::ops::FnOnce<(isize, isize)>` is required - --> $DIR/unboxed-closures-vtable-mismatch.rs:25:13 - | -22 | let f = to_fn_mut(|x: usize, y: isize| -> isize { (x as isize) + y }); - | -------------------------------------------------- implements `std::ops::FnOnce<(usize, isize)>` -... -25 | let z = call_it(3, f); - | ^^^^^^^ - | | - | requires `std::ops::FnOnce<(isize, isize)>` - | expected isize, found usize - | - = note: required by `call_it` - error: aborting due to previous error(s) diff --git a/src/test/ui/type-check/issue-40294.stderr b/src/test/ui/type-check/issue-40294.stderr index bf03e52369fe..cd474b14193f 100644 --- a/src/test/ui/type-check/issue-40294.stderr +++ b/src/test/ui/type-check/issue-40294.stderr @@ -1,4 +1,4 @@ -error[E0282]: type annotations needed +error[E0283]: type annotations required: cannot resolve `&'a T: Foo` --> $DIR/issue-40294.rs:15:1 | 15 | / fn foo<'a,'b,T>(x: &'a T, y: &'b T) @@ -8,7 +8,9 @@ error[E0282]: type annotations needed 19 | | x.foo(); 20 | | y.foo(); 21 | | } - | |_^ cannot infer type for `&'a T` + | |_^ + | + = note: required by `Foo` error: aborting due to previous error(s) From 2619636a1ac3c1104eae069c9f68108a8e5d8020 Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Wed, 14 Jun 2017 14:38:51 -0600 Subject: [PATCH 198/233] Correct note as to location of section. --- src/librustc/infer/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/infer/README.md b/src/librustc/infer/README.md index 68e64b8b7bfc..b4075f697309 100644 --- a/src/librustc/infer/README.md +++ b/src/librustc/infer/README.md @@ -236,4 +236,4 @@ yet, that's what we're trying to find! In our code, we opt to unify We make use of a trait-like implementation strategy to consolidate duplicated code between subtypes, GLB, and LUB computations. See the -section on "Type Combining" below for details. +section on "Type Combining" in combine.rs for more details. From 130b67c2965b9c1939af15eca0caf2035a1f5e58 Mon Sep 17 00:00:00 2001 From: est31 Date: Thu, 15 Jun 2017 00:19:42 +0200 Subject: [PATCH 199/233] Remove some more stubs --- .../unstable-book/src/language-features/abi-unadjusted.md | 6 ------ .../unstable-book/src/language-features/abi-vectorcall.md | 7 ------- .../src/language-features/allow-internal-unstable.md | 6 ------ .../language-features/omit-gdb-pretty-printer-section.md | 6 ------ .../unstable-book/src/language-features/prelude-import.md | 6 ------ .../src/language-features/rustc-diagnostic-macros.md | 6 ------ .../src/language-features/sanitizer-runtime.md | 6 ------ src/doc/unstable-book/src/language-features/staged-api.md | 6 ------ .../unstable-book/src/language-features/target-feature.md | 6 ------ .../src/language-features/unwind-attributes.md | 6 ------ src/doc/unstable-book/src/library-features/ascii-ctype.md | 5 ----- .../unstable-book/src/library-features/manually-drop.md | 0 src/doc/unstable-book/src/library-features/mpsc-select.md | 5 ----- src/doc/unstable-book/src/library-features/ord-max-min.md | 7 ------- 14 files changed, 78 deletions(-) delete mode 100644 src/doc/unstable-book/src/language-features/abi-unadjusted.md delete mode 100644 src/doc/unstable-book/src/language-features/abi-vectorcall.md delete mode 100644 src/doc/unstable-book/src/language-features/allow-internal-unstable.md delete mode 100644 src/doc/unstable-book/src/language-features/omit-gdb-pretty-printer-section.md delete mode 100644 src/doc/unstable-book/src/language-features/prelude-import.md delete mode 100644 src/doc/unstable-book/src/language-features/rustc-diagnostic-macros.md delete mode 100644 src/doc/unstable-book/src/language-features/sanitizer-runtime.md delete mode 100644 src/doc/unstable-book/src/language-features/staged-api.md delete mode 100644 src/doc/unstable-book/src/language-features/target-feature.md delete mode 100644 src/doc/unstable-book/src/language-features/unwind-attributes.md delete mode 100644 src/doc/unstable-book/src/library-features/ascii-ctype.md delete mode 100644 src/doc/unstable-book/src/library-features/manually-drop.md delete mode 100644 src/doc/unstable-book/src/library-features/mpsc-select.md delete mode 100644 src/doc/unstable-book/src/library-features/ord-max-min.md diff --git a/src/doc/unstable-book/src/language-features/abi-unadjusted.md b/src/doc/unstable-book/src/language-features/abi-unadjusted.md deleted file mode 100644 index 2e3113abdbf2..000000000000 --- a/src/doc/unstable-book/src/language-features/abi-unadjusted.md +++ /dev/null @@ -1,6 +0,0 @@ -# `abi_unadjusted` - -The tracking issue for this feature is: none. - ------------------------- - diff --git a/src/doc/unstable-book/src/language-features/abi-vectorcall.md b/src/doc/unstable-book/src/language-features/abi-vectorcall.md deleted file mode 100644 index 3e36b1569fd4..000000000000 --- a/src/doc/unstable-book/src/language-features/abi-vectorcall.md +++ /dev/null @@ -1,7 +0,0 @@ -# `abi_vectorcall` - -The tracking issue for this feature is: none. - ------------------------- - - diff --git a/src/doc/unstable-book/src/language-features/allow-internal-unstable.md b/src/doc/unstable-book/src/language-features/allow-internal-unstable.md deleted file mode 100644 index 74709ad5aeb4..000000000000 --- a/src/doc/unstable-book/src/language-features/allow-internal-unstable.md +++ /dev/null @@ -1,6 +0,0 @@ -# `allow_internal_unstable` - -The tracking issue for this feature is: None. - ------------------------- - diff --git a/src/doc/unstable-book/src/language-features/omit-gdb-pretty-printer-section.md b/src/doc/unstable-book/src/language-features/omit-gdb-pretty-printer-section.md deleted file mode 100644 index d8ac520fcb5e..000000000000 --- a/src/doc/unstable-book/src/language-features/omit-gdb-pretty-printer-section.md +++ /dev/null @@ -1,6 +0,0 @@ -# `omit_gdb_pretty_printer_section` - -The tracking issue for this feature is: None. - ------------------------- - diff --git a/src/doc/unstable-book/src/language-features/prelude-import.md b/src/doc/unstable-book/src/language-features/prelude-import.md deleted file mode 100644 index 75dae5cfb740..000000000000 --- a/src/doc/unstable-book/src/language-features/prelude-import.md +++ /dev/null @@ -1,6 +0,0 @@ -# `prelude_import` - -The tracking issue for this feature is: None. - ------------------------- - diff --git a/src/doc/unstable-book/src/language-features/rustc-diagnostic-macros.md b/src/doc/unstable-book/src/language-features/rustc-diagnostic-macros.md deleted file mode 100644 index 0df6ca12089e..000000000000 --- a/src/doc/unstable-book/src/language-features/rustc-diagnostic-macros.md +++ /dev/null @@ -1,6 +0,0 @@ -# `rustc_diagnostic_macros` - -The tracking issue for this feature is: None. - ------------------------- - diff --git a/src/doc/unstable-book/src/language-features/sanitizer-runtime.md b/src/doc/unstable-book/src/language-features/sanitizer-runtime.md deleted file mode 100644 index f19504de58e1..000000000000 --- a/src/doc/unstable-book/src/language-features/sanitizer-runtime.md +++ /dev/null @@ -1,6 +0,0 @@ -# `sanitizer_runtime` - -The tracking issue for this feature is: None. - ------------------------- - diff --git a/src/doc/unstable-book/src/language-features/staged-api.md b/src/doc/unstable-book/src/language-features/staged-api.md deleted file mode 100644 index 1409e570e887..000000000000 --- a/src/doc/unstable-book/src/language-features/staged-api.md +++ /dev/null @@ -1,6 +0,0 @@ -# `staged_api` - -The tracking issue for this feature is: None. - ------------------------- - diff --git a/src/doc/unstable-book/src/language-features/target-feature.md b/src/doc/unstable-book/src/language-features/target-feature.md deleted file mode 100644 index 85ab1ab39efe..000000000000 --- a/src/doc/unstable-book/src/language-features/target-feature.md +++ /dev/null @@ -1,6 +0,0 @@ -# `target_feature` - -The tracking issue for this feature is: None. - ------------------------- - diff --git a/src/doc/unstable-book/src/language-features/unwind-attributes.md b/src/doc/unstable-book/src/language-features/unwind-attributes.md deleted file mode 100644 index 0167a33b081a..000000000000 --- a/src/doc/unstable-book/src/language-features/unwind-attributes.md +++ /dev/null @@ -1,6 +0,0 @@ -# `unwind_attributes` - -The tracking issue for this feature is: None. - ------------------------- - diff --git a/src/doc/unstable-book/src/library-features/ascii-ctype.md b/src/doc/unstable-book/src/library-features/ascii-ctype.md deleted file mode 100644 index e253b4dcd9b5..000000000000 --- a/src/doc/unstable-book/src/library-features/ascii-ctype.md +++ /dev/null @@ -1,5 +0,0 @@ -# `ascii_ctype` - -The tracking issue for this feature is: [#39658] - -[#39658]: https://github.com/rust-lang/rust/issues/39658 diff --git a/src/doc/unstable-book/src/library-features/manually-drop.md b/src/doc/unstable-book/src/library-features/manually-drop.md deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/src/doc/unstable-book/src/library-features/mpsc-select.md b/src/doc/unstable-book/src/library-features/mpsc-select.md deleted file mode 100644 index 1405b6c5cb24..000000000000 --- a/src/doc/unstable-book/src/library-features/mpsc-select.md +++ /dev/null @@ -1,5 +0,0 @@ -# `mpsc_select` - -The tracking issue for this feature is: [#27800] - -[#27800]: https://github.com/rust-lang/rust/issues/27800 diff --git a/src/doc/unstable-book/src/library-features/ord-max-min.md b/src/doc/unstable-book/src/library-features/ord-max-min.md deleted file mode 100644 index 564cd1ac30b2..000000000000 --- a/src/doc/unstable-book/src/library-features/ord-max-min.md +++ /dev/null @@ -1,7 +0,0 @@ -# `ord-max-min` - -The tracking issue for this feature is: [#25663] - -[#25663]: https://github.com/rust-lang/rust/issues/25663 - ------------------------- From d0c1e6480c7d6e99118adf9f6aa2d25ac9625647 Mon Sep 17 00:00:00 2001 From: Aidan Hobson Sayers Date: Thu, 15 Jun 2017 00:19:21 +0100 Subject: [PATCH 200/233] Use --depth to speed up pristine submodule cloning In addition, remove all the unused cache stuff --- src/ci/init_repo.sh | 39 ++++----------------------------------- 1 file changed, 4 insertions(+), 35 deletions(-) diff --git a/src/ci/init_repo.sh b/src/ci/init_repo.sh index 282da009eac3..817ed8dd5543 100755 --- a/src/ci/init_repo.sh +++ b/src/ci/init_repo.sh @@ -22,9 +22,6 @@ REPO_DIR="$1" CACHE_DIR="$2" cache_src_dir="$CACHE_DIR/src" -# If the layout of the cache directory changes, bump the number here -# (and anywhere else this file is referenced) so the cache is wiped -cache_valid_file="$CACHE_DIR/cache_valid1" if [ ! -d "$REPO_DIR" -o ! -d "$REPO_DIR/.git" ]; then echo "Error: $REPO_DIR does not exist or is not a git repo" @@ -36,47 +33,19 @@ if [ ! -d "$CACHE_DIR" ]; then exit 1 fi -# Wipe the cache if it's not valid, or mark it as invalid while we update it -if [ ! -f "$cache_valid_file" ]; then - echo "Invalid cache, wiping ($cache_valid_file missing)" - rm -rf "$CACHE_DIR" - mkdir "$CACHE_DIR" -else - # Ignore errors while gathering information about the possible brokenness - # of the git repo since our gathered info will tell us something is wrong - set +o errexit - stat_lines=$(cd "$cache_src_dir" && git status --porcelain | wc -l) - stat_ec=$(cd "$cache_src_dir" && git status >/dev/null 2>&1; echo $?) - set -o errexit - if [ ! -d "$cache_src_dir/.git" -o $stat_lines != 0 -o $stat_ec != 0 ]; then - # Something is badly wrong - the cache valid file is here, but something - # about the git repo is fishy. Nuke it all, just in case - echo "WARNING: $cache_valid_file exists but bad repo: l:$stat_lines, ec:$stat_ec" - rm -rf "$CACHE_DIR" - mkdir "$CACHE_DIR" - else - echo "Valid cache ($cache_valid_file exists)" - rm "$cache_valid_file" - fi -fi +rm -rf "$CACHE_DIR" +mkdir "$CACHE_DIR" travis_fold start update_cache travis_time_start # Update the cache (a pristine copy of the rust source master) -if [ ! -d "$cache_src_dir/.git" ]; then - retry sh -c "rm -rf $cache_src_dir && mkdir -p $cache_src_dir && \ - git clone https://github.com/rust-lang/rust.git $cache_src_dir" -fi -retry sh -c "cd $cache_src_dir && git reset --hard && git pull" +retry sh -c "rm -rf $cache_src_dir && mkdir -p $cache_src_dir && \ + git clone --depth 1 https://github.com/rust-lang/rust.git $cache_src_dir" (cd $cache_src_dir && git rm src/llvm) retry sh -c "cd $cache_src_dir && \ git submodule deinit -f . && git submodule sync && git submodule update --init" -# Cache was updated without errors, mark it as valid -echo "Refreshed cache (touch $cache_valid_file)" -touch "$cache_valid_file" - travis_fold end update_cache travis_time_finish From 65288f4026b7cb0c269bdc43bbacfdc37ddae92f Mon Sep 17 00:00:00 2001 From: Wonwoo Choi Date: Thu, 15 Jun 2017 11:16:54 +0900 Subject: [PATCH 201/233] Remove struct_field_attributes from the Unstable Book --- src/doc/unstable-book/src/SUMMARY.md | 1 - .../src/language-features/struct-field-attributes.md | 10 ---------- 2 files changed, 11 deletions(-) delete mode 100644 src/doc/unstable-book/src/language-features/struct-field-attributes.md diff --git a/src/doc/unstable-book/src/SUMMARY.md b/src/doc/unstable-book/src/SUMMARY.md index 39922b7bbcfd..e49b27c1b863 100644 --- a/src/doc/unstable-book/src/SUMMARY.md +++ b/src/doc/unstable-book/src/SUMMARY.md @@ -87,7 +87,6 @@ - [start](language-features/start.md) - [static_nobundle](language-features/static-nobundle.md) - [stmt_expr_attributes](language-features/stmt-expr-attributes.md) - - [struct_field_attributes](language-features/struct-field-attributes.md) - [structural_match](language-features/structural-match.md) - [target_feature](language-features/target-feature.md) - [thread_local](language-features/thread-local.md) diff --git a/src/doc/unstable-book/src/language-features/struct-field-attributes.md b/src/doc/unstable-book/src/language-features/struct-field-attributes.md deleted file mode 100644 index 1a94562968d1..000000000000 --- a/src/doc/unstable-book/src/language-features/struct-field-attributes.md +++ /dev/null @@ -1,10 +0,0 @@ -# `struct_field_attributes` - -The tracking issue for this feature is: [#38814] - -[#38814]: https://github.com/rust-lang/rust/issues/38814 - ------------------------- - - - From 028b5f94e3aef435c626131e5b571272f2d3d52c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 13 Jun 2017 16:26:20 -0700 Subject: [PATCH 202/233] Report error for assignment in `if` condition For code like `if x = 3 {}`, output: ``` error[E0308]: mismatched types --> $DIR/issue-17283.rs:25:8 | 25 | if x = x { | ^^^^^ | | | help: did you mean to compare equality? `x == x` | expected bool, found () | = note: expected type `bool` found type `()` ``` --- src/librustc_typeck/check/demand.rs | 9 ++- src/librustc_typeck/check/mod.rs | 68 ++++++++++++++----- .../type-check}/issue-17283.rs | 18 ++--- src/test/ui/type-check/issue-17283.stderr | 50 ++++++++++++++ 4 files changed, 118 insertions(+), 27 deletions(-) rename src/test/{compile-fail => ui/type-check}/issue-17283.rs (76%) create mode 100644 src/test/ui/type-check/issue-17283.stderr diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 9ed50dd1e4d4..732b9be81a39 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -26,13 +26,20 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Requires that the two types unify, and prints an error message if // they don't. pub fn demand_suptype(&self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>) { + self.demand_suptype_diag(sp, expected, actual).map(|mut e| e.emit()); + } + + pub fn demand_suptype_diag(&self, sp: Span, + expected: Ty<'tcx>, + actual: Ty<'tcx>) -> Option> { let cause = &self.misc(sp); match self.at(cause, self.param_env).sup(expected, actual) { Ok(InferOk { obligations, value: () }) => { self.register_predicates(obligations); + None }, Err(e) => { - self.report_mismatched_types(&cause, expected, actual, e).emit(); + Some(self.report_mismatched_types(&cause, expected, actual, e)) } } } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index c12df083c30e..5bba79a176ee 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -232,6 +232,9 @@ pub enum Expectation<'tcx> { /// We know nothing about what type this expression should have. NoExpectation, + /// This expression is an `if` condition, it must resolve to `bool`. + ExpectIfCondition, + /// This expression should have the type given (or some subtype) ExpectHasType(Ty<'tcx>), @@ -310,9 +313,8 @@ impl<'a, 'gcx, 'tcx> Expectation<'tcx> { // no constraints yet present), just returns `None`. fn resolve(self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) -> Expectation<'tcx> { match self { - NoExpectation => { - NoExpectation - } + NoExpectation => NoExpectation, + ExpectIfCondition => ExpectIfCondition, ExpectCastableToType(t) => { ExpectCastableToType(fcx.resolve_type_vars_if_possible(&t)) } @@ -328,6 +330,7 @@ impl<'a, 'gcx, 'tcx> Expectation<'tcx> { fn to_option(self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) -> Option> { match self.resolve(fcx) { NoExpectation => None, + ExpectIfCondition => Some(fcx.tcx.types.bool), ExpectCastableToType(ty) | ExpectHasType(ty) | ExpectRvalueLikeUnsized(ty) => Some(ty), @@ -341,6 +344,7 @@ impl<'a, 'gcx, 'tcx> Expectation<'tcx> { fn only_has_type(self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) -> Option> { match self.resolve(fcx) { ExpectHasType(ty) => Some(ty), + ExpectIfCondition => Some(fcx.tcx.types.bool), _ => None } } @@ -2646,7 +2650,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { pub fn check_expr_has_type(&self, expr: &'gcx hir::Expr, expected: Ty<'tcx>) -> Ty<'tcx> { - let mut ty = self.check_expr_with_hint(expr, expected); + self.check_expr_expect_type(expr, ExpectHasType(expected)) + } + + fn check_expr_expect_type(&self, + expr: &'gcx hir::Expr, + expected: Expectation<'tcx>) -> Ty<'tcx> { + let expected_ty = expected.to_option(&self).unwrap_or(self.tcx.types.bool); + let mut ty = self.check_expr_with_expectation(expr, expected); // While we don't allow *arbitrary* coercions here, we *do* allow // coercions from ! to `expected`. @@ -2662,7 +2673,24 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ty = adj_ty; } - self.demand_suptype(expr.span, expected, ty); + if let Some(mut err) = self.demand_suptype_diag(expr.span, expected_ty, ty) { + // Add help to type error if this is an `if` condition with an assignment + match (expected, &expr.node) { + (ExpectIfCondition, &hir::ExprAssign(ref lhs, ref rhs)) => { + let msg = "did you mean to compare equality?"; + if let (Ok(left), Ok(right)) = ( + self.tcx.sess.codemap().span_to_snippet(lhs.span), + self.tcx.sess.codemap().span_to_snippet(rhs.span)) + { + err.span_suggestion(expr.span, msg, format!("{} == {}", left, right)); + } else { + err.help(msg); + } + } + _ => (), + } + err.emit(); + } ty } @@ -2837,7 +2865,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { opt_else_expr: Option<&'gcx hir::Expr>, sp: Span, expected: Expectation<'tcx>) -> Ty<'tcx> { - let cond_ty = self.check_expr_has_type(cond_expr, self.tcx.types.bool); + let cond_ty = self.check_expr_expect_type(cond_expr, ExpectIfCondition); let cond_diverges = self.diverges.get(); self.diverges.set(Diverges::Maybe); @@ -3637,19 +3665,25 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { hir::ExprAssign(ref lhs, ref rhs) => { let lhs_ty = self.check_expr_with_lvalue_pref(&lhs, PreferMutLvalue); - let tcx = self.tcx; - if !tcx.expr_is_lval(&lhs) { - struct_span_err!( - tcx.sess, expr.span, E0070, - "invalid left-hand side expression") - .span_label( - expr.span, - "left-hand of expression not valid") - .emit(); - } - let rhs_ty = self.check_expr_coercable_to_type(&rhs, lhs_ty); + match expected { + ExpectIfCondition => (), + _ => { + // Only check this if not in an `if` condition, as the + // mistyped comparison help is more appropriate. + if !self.tcx.expr_is_lval(&lhs) { + struct_span_err!( + self.tcx.sess, expr.span, E0070, + "invalid left-hand side expression") + .span_label( + expr.span, + "left-hand of expression not valid") + .emit(); + } + } + } + self.require_type_is_sized(lhs_ty, lhs.span, traits::AssignmentLhsSized); if lhs_ty.references_error() || rhs_ty.references_error() { diff --git a/src/test/compile-fail/issue-17283.rs b/src/test/ui/type-check/issue-17283.rs similarity index 76% rename from src/test/compile-fail/issue-17283.rs rename to src/test/ui/type-check/issue-17283.rs index 98208bcfdbde..f06888b8ec46 100644 --- a/src/test/compile-fail/issue-17283.rs +++ b/src/test/ui/type-check/issue-17283.rs @@ -24,25 +24,25 @@ fn main() { // `x { ... }` should not be interpreted as a struct literal here if x = x { //~^ ERROR mismatched types - //~| expected type `bool` - //~| found type `()` - //~| expected bool, found () + //~| HELP did you mean to compare equality? println!("{}", x); } // Explicit parentheses on the left should match behavior of above if (x = x) { //~^ ERROR mismatched types - //~| expected type `bool` - //~| found type `()` - //~| expected bool, found () + //~| HELP did you mean to compare equality? println!("{}", x); } // The struct literal interpretation is fine with explicit parentheses on the right if y = (Foo { foo: x }) { //~^ ERROR mismatched types - //~| expected type `bool` - //~| found type `()` - //~| expected bool, found () + //~| HELP did you mean to compare equality? + println!("{}", x); + } + // "invalid left-hand side expression" error is suppresed + if 3 = x { + //~^ ERROR mismatched types + //~| HELP did you mean to compare equality? println!("{}", x); } } diff --git a/src/test/ui/type-check/issue-17283.stderr b/src/test/ui/type-check/issue-17283.stderr new file mode 100644 index 000000000000..f258caecd300 --- /dev/null +++ b/src/test/ui/type-check/issue-17283.stderr @@ -0,0 +1,50 @@ +error[E0308]: mismatched types + --> $DIR/issue-17283.rs:25:8 + | +25 | if x = x { + | ^^^^^ + | | + | help: did you mean to compare equality? `x == x` + | expected bool, found () + | + = note: expected type `bool` + found type `()` + +error[E0308]: mismatched types + --> $DIR/issue-17283.rs:31:8 + | +31 | if (x = x) { + | ^^^^^^^ + | | + | help: did you mean to compare equality? `x == x` + | expected bool, found () + | + = note: expected type `bool` + found type `()` + +error[E0308]: mismatched types + --> $DIR/issue-17283.rs:37:8 + | +37 | if y = (Foo { foo: x }) { + | ^^^^^^^^^^^^^^^^^^^^ + | | + | help: did you mean to compare equality? `y == (Foo { foo: x })` + | expected bool, found () + | + = note: expected type `bool` + found type `()` + +error[E0308]: mismatched types + --> $DIR/issue-17283.rs:43:8 + | +43 | if 3 = x { + | ^^^^^ + | | + | help: did you mean to compare equality? `3 == x` + | expected bool, found () + | + = note: expected type `bool` + found type `()` + +error: aborting due to previous error(s) + From c98ca953b07c2afb8dd7ceab1215249e94c3025d Mon Sep 17 00:00:00 2001 From: Taylor Cramer Date: Wed, 14 Jun 2017 22:49:07 -0700 Subject: [PATCH 203/233] Switch CrateNum queries to DefId --- src/librustc/dep_graph/dep_node.rs | 1 - src/librustc/hir/def_id.rs | 2 + src/librustc/middle/dependency_format.rs | 14 +- src/librustc/ty/item_path.rs | 4 +- src/librustc/ty/maps.rs | 16 +-- src/librustc_metadata/cstore_impl.rs | 169 ++++++++++------------- src/librustc_save_analysis/lib.rs | 2 +- src/librustc_trans/back/symbol_export.rs | 4 +- 8 files changed, 96 insertions(+), 116 deletions(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 6c4c90585b3c..c987a37c420d 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -305,7 +305,6 @@ define_dep_nodes!( // Represents the metadata for a given HIR node, typically found // in an extern crate. MetaData(DefId), - MetaDataByCrateNum(CrateNum), // Represents some artifact that we save to disk. Note that these // do not have a def-id as part of their identifier. diff --git a/src/librustc/hir/def_id.rs b/src/librustc/hir/def_id.rs index ce2baa738975..95a27f065999 100644 --- a/src/librustc/hir/def_id.rs +++ b/src/librustc/hir/def_id.rs @@ -58,6 +58,8 @@ impl CrateNum { pub fn as_u32(&self) -> u32 { self.0 } + + pub fn as_def_id(&self) -> DefId { DefId { krate: *self, index: CRATE_DEF_INDEX } } } impl fmt::Display for CrateNum { diff --git a/src/librustc/middle/dependency_format.rs b/src/librustc/middle/dependency_format.rs index da217d7a1733..4e1f06cca06c 100644 --- a/src/librustc/middle/dependency_format.rs +++ b/src/librustc/middle/dependency_format.rs @@ -172,7 +172,7 @@ fn calculate_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, if src.dylib.is_some() { info!("adding dylib: {}", name); add_library(sess, cnum, RequireDynamic, &mut formats); - let deps = tcx.dylib_dependency_formats(cnum); + let deps = tcx.dylib_dependency_formats(cnum.as_def_id()); for &(depnum, style) in deps.iter() { info!("adding {:?}: {}", style, sess.cstore.crate_name(depnum)); @@ -215,9 +215,9 @@ fn calculate_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Things like allocators and panic runtimes may not have been activated // quite yet, so do so here. activate_injected_dep(sess.injected_allocator.get(), &mut ret, - &|cnum| tcx.is_allocator(cnum)); + &|cnum| tcx.is_allocator(cnum.as_def_id())); activate_injected_dep(sess.injected_panic_runtime.get(), &mut ret, - &|cnum| tcx.is_panic_runtime(cnum)); + &|cnum| tcx.is_panic_runtime(cnum.as_def_id())); // When dylib B links to dylib A, then when using B we must also link to A. // It could be the case, however, that the rlib for A is present (hence we @@ -296,9 +296,9 @@ fn attempt_static<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option(tcx: TyCtxt<'a, 'tcx, 'tcx>, list: &[Linkage]) { continue } let cnum = CrateNum::new(i + 1); - if tcx.is_allocator(cnum) { + if tcx.is_allocator(cnum.as_def_id()) { if let Some(prev) = allocator { let prev_name = sess.cstore.crate_name(prev); let cur_name = sess.cstore.crate_name(cnum); @@ -356,7 +356,7 @@ fn verify_ok<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, list: &[Linkage]) { allocator = Some(cnum); } - if tcx.is_panic_runtime(cnum) { + if tcx.is_panic_runtime(cnum.as_def_id()) { if let Some((prev, _)) = panic_runtime { let prev_name = sess.cstore.crate_name(prev); let cur_name = sess.cstore.crate_name(cnum); diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index e63fe42877fe..09a3bcd06138 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -100,7 +100,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // // Returns `None` for the local crate. if cnum != LOCAL_CRATE { - let opt_extern_crate = self.extern_crate(cnum); + let opt_extern_crate = self.extern_crate(cnum.as_def_id()); let opt_extern_crate = opt_extern_crate.and_then(|extern_crate| { if extern_crate.direct { Some(extern_crate.def_id) @@ -136,7 +136,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // If `cur_def` is a direct or injected extern crate, push the path to the crate // followed by the path to the item within the crate and return. if cur_def.index == CRATE_DEF_INDEX { - match *self.extern_crate(cur_def.krate) { + match *self.extern_crate(cur_def) { Some(ref extern_crate) if extern_crate.direct => { self.push_item_path(buffer, extern_crate.def_id); cur_path.iter().rev().map(|segment| buffer.push(&segment.as_str())).count(); diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs index 27713f728ac5..dccc0a8283a9 100644 --- a/src/librustc/ty/maps.rs +++ b/src/librustc/ty/maps.rs @@ -484,25 +484,25 @@ impl<'tcx> QueryDescription for queries::is_const_fn<'tcx> { } impl<'tcx> QueryDescription for queries::dylib_dependency_formats<'tcx> { - fn describe(_: TyCtxt, _: CrateNum) -> String { + fn describe(_: TyCtxt, _: DefId) -> String { "dylib dependency formats of crate".to_string() } } impl<'tcx> QueryDescription for queries::is_allocator<'tcx> { - fn describe(_: TyCtxt, _: CrateNum) -> String { + fn describe(_: TyCtxt, _: DefId) -> String { "checking if the crate is_allocator".to_string() } } impl<'tcx> QueryDescription for queries::is_panic_runtime<'tcx> { - fn describe(_: TyCtxt, _: CrateNum) -> String { + fn describe(_: TyCtxt, _: DefId) -> String { "checking if the crate is_panic_runtime".to_string() } } impl<'tcx> QueryDescription for queries::extern_crate<'tcx> { - fn describe(_: TyCtxt, _: CrateNum) -> String { + fn describe(_: TyCtxt, _: DefId) -> String { "getting crate's ExternCrateData".to_string() } } @@ -964,13 +964,13 @@ define_maps! { <'tcx> [] layout_raw: layout_dep_node(ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> Result<&'tcx Layout, LayoutError<'tcx>>, - [] dylib_dependency_formats: MetaDataByCrateNum(CrateNum) + [] dylib_dependency_formats: MetaData(DefId) -> Rc>, - [] is_allocator: MetaDataByCrateNum(CrateNum) -> bool, - [] is_panic_runtime: MetaDataByCrateNum(CrateNum) -> bool, + [] is_allocator: MetaData(DefId) -> bool, + [] is_panic_runtime: MetaData(DefId) -> bool, - [] extern_crate: MetaDataByCrateNum(CrateNum) -> Rc>, + [] extern_crate: MetaData(DefId) -> Rc>, } fn type_param_predicates((item_id, param_id): (DefId, DefId)) -> DepConstructor { diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 9522d9625c94..7e85c2779799 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -40,17 +40,10 @@ use rustc::hir::svh::Svh; use rustc::hir; macro_rules! provide { - (<$lt:tt> $tcx:ident, $def_id:ident, $cdata:ident, $cnum:ident, - ByDefId { - $($cdata_fn_name:ident => $cdata_fn_compute:block)* - } - ByCrateNum { - $($cnum_fn_name:ident => $cnum_fn_compute:block)* - } - )=> { + (<$lt:tt> $tcx:ident, $def_id:ident, $cdata:ident, $($name:ident => $compute:block)*) => { pub fn provide<$lt>(providers: &mut Providers<$lt>) { - $(fn $cdata_fn_name<'a, $lt:$lt>($tcx: TyCtxt<'a, $lt, $lt>, $def_id: DefId) - -> as + $(fn $name<'a, $lt:$lt>($tcx: TyCtxt<'a, $lt, $lt>, $def_id: DefId) + -> as DepTrackingMapConfig>::Value { assert!(!$def_id.is_local()); @@ -62,102 +55,88 @@ macro_rules! provide { let $cdata = $tcx.sess.cstore.crate_data_as_rc_any($def_id.krate); let $cdata = $cdata.downcast_ref::() .expect("CrateStore crated ata is not a CrateMetadata"); - $cdata_fn_compute - })* - - $(fn $cnum_fn_name<'a, $lt:$lt>($tcx: TyCtxt<'a, $lt, $lt>, $cnum: CrateNum) - -> as - DepTrackingMapConfig>::Value { - let $cdata = $tcx.sess.cstore.crate_data_as_rc_any($cnum); - let $cdata = $cdata.downcast_ref::() - .expect("CrateStore crated ata is not a CrateMetadata"); - $cnum_fn_compute + $compute })* *providers = Providers { - $($cdata_fn_name,)* - $($cnum_fn_name,)* + $($name,)* ..*providers }; } } } -provide! { <'tcx> tcx, def_id, cdata, cnum, - ByDefId { - type_of => { cdata.get_type(def_id.index, tcx) } - generics_of => { tcx.alloc_generics(cdata.get_generics(def_id.index)) } - predicates_of => { cdata.get_predicates(def_id.index, tcx) } - super_predicates_of => { cdata.get_super_predicates(def_id.index, tcx) } - trait_def => { - tcx.alloc_trait_def(cdata.get_trait_def(def_id.index)) - } - adt_def => { cdata.get_adt_def(def_id.index, tcx) } - adt_destructor => { - let _ = cdata; - tcx.calculate_dtor(def_id, &mut |_,_| Ok(())) - } - variances_of => { Rc::new(cdata.get_item_variances(def_id.index)) } - associated_item_def_ids => { - let mut result = vec![]; - cdata.each_child_of_item(def_id.index, - |child| result.push(child.def.def_id()), tcx.sess); - Rc::new(result) - } - associated_item => { cdata.get_associated_item(def_id.index) } - impl_trait_ref => { cdata.get_impl_trait(def_id.index, tcx) } - impl_polarity => { cdata.get_impl_polarity(def_id.index) } - coerce_unsized_info => { - cdata.get_coerce_unsized_info(def_id.index).unwrap_or_else(|| { - bug!("coerce_unsized_info: `{:?}` is missing its info", def_id); - }) - } - optimized_mir => { - let mir = cdata.maybe_get_optimized_mir(tcx, def_id.index).unwrap_or_else(|| { - bug!("get_optimized_mir: missing MIR for `{:?}`", def_id) - }); - - let mir = tcx.alloc_mir(mir); - - mir - } - mir_const_qualif => { cdata.mir_const_qualif(def_id.index) } - typeck_tables_of => { cdata.item_body_tables(def_id.index, tcx) } - closure_kind => { cdata.closure_kind(def_id.index) } - closure_type => { cdata.closure_ty(def_id.index, tcx) } - inherent_impls => { Rc::new(cdata.get_inherent_implementations_for_type(def_id.index)) } - is_const_fn => { cdata.is_const_fn(def_id.index) } - is_foreign_item => { cdata.is_foreign_item(def_id.index) } - is_default_impl => { cdata.is_default_impl(def_id.index) } - describe_def => { cdata.get_def(def_id.index) } - def_span => { cdata.get_span(def_id.index, &tcx.sess) } - stability => { cdata.get_stability(def_id.index) } - deprecation => { cdata.get_deprecation(def_id.index) } - item_attrs => { cdata.get_item_attrs(def_id.index, &tcx.dep_graph) } - // FIXME(#38501) We've skipped a `read` on the `HirBody` of - // a `fn` when encoding, so the dep-tracking wouldn't work. - // This is only used by rustdoc anyway, which shouldn't have - // incremental recompilation ever enabled. - fn_arg_names => { cdata.get_fn_arg_names(def_id.index) } - impl_parent => { cdata.get_parent_impl(def_id.index) } - trait_of_item => { cdata.get_trait_of_item(def_id.index) } - is_exported_symbol => { - let dep_node = cdata.metadata_dep_node(GlobalMetaDataKind::ExportedSymbols); - cdata.exported_symbols.get(&tcx.dep_graph, dep_node).contains(&def_id.index) - } - item_body_nested_bodies => { Rc::new(cdata.item_body_nested_bodies(def_id.index)) } - const_is_rvalue_promotable_to_static => { - cdata.const_is_rvalue_promotable_to_static(def_id.index) - } - is_mir_available => { cdata.is_item_mir_available(def_id.index) } +provide! { <'tcx> tcx, def_id, cdata, + type_of => { cdata.get_type(def_id.index, tcx) } + generics_of => { tcx.alloc_generics(cdata.get_generics(def_id.index)) } + predicates_of => { cdata.get_predicates(def_id.index, tcx) } + super_predicates_of => { cdata.get_super_predicates(def_id.index, tcx) } + trait_def => { + tcx.alloc_trait_def(cdata.get_trait_def(def_id.index)) } - - ByCrateNum { - dylib_dependency_formats => { Rc::new(cdata.get_dylib_dependency_formats(&tcx.dep_graph)) } - is_allocator => { cdata.is_allocator(&tcx.dep_graph) } - is_panic_runtime => { cdata.is_panic_runtime(&tcx.dep_graph) } - extern_crate => { Rc::new(cdata.extern_crate.get()) } + adt_def => { cdata.get_adt_def(def_id.index, tcx) } + adt_destructor => { + let _ = cdata; + tcx.calculate_dtor(def_id, &mut |_,_| Ok(())) } + variances_of => { Rc::new(cdata.get_item_variances(def_id.index)) } + associated_item_def_ids => { + let mut result = vec![]; + cdata.each_child_of_item(def_id.index, + |child| result.push(child.def.def_id()), tcx.sess); + Rc::new(result) + } + associated_item => { cdata.get_associated_item(def_id.index) } + impl_trait_ref => { cdata.get_impl_trait(def_id.index, tcx) } + impl_polarity => { cdata.get_impl_polarity(def_id.index) } + coerce_unsized_info => { + cdata.get_coerce_unsized_info(def_id.index).unwrap_or_else(|| { + bug!("coerce_unsized_info: `{:?}` is missing its info", def_id); + }) + } + optimized_mir => { + let mir = cdata.maybe_get_optimized_mir(tcx, def_id.index).unwrap_or_else(|| { + bug!("get_optimized_mir: missing MIR for `{:?}`", def_id) + }); + + let mir = tcx.alloc_mir(mir); + + mir + } + mir_const_qualif => { cdata.mir_const_qualif(def_id.index) } + typeck_tables_of => { cdata.item_body_tables(def_id.index, tcx) } + closure_kind => { cdata.closure_kind(def_id.index) } + closure_type => { cdata.closure_ty(def_id.index, tcx) } + inherent_impls => { Rc::new(cdata.get_inherent_implementations_for_type(def_id.index)) } + is_const_fn => { cdata.is_const_fn(def_id.index) } + is_foreign_item => { cdata.is_foreign_item(def_id.index) } + is_default_impl => { cdata.is_default_impl(def_id.index) } + describe_def => { cdata.get_def(def_id.index) } + def_span => { cdata.get_span(def_id.index, &tcx.sess) } + stability => { cdata.get_stability(def_id.index) } + deprecation => { cdata.get_deprecation(def_id.index) } + item_attrs => { cdata.get_item_attrs(def_id.index, &tcx.dep_graph) } + // FIXME(#38501) We've skipped a `read` on the `HirBody` of + // a `fn` when encoding, so the dep-tracking wouldn't work. + // This is only used by rustdoc anyway, which shouldn't have + // incremental recompilation ever enabled. + fn_arg_names => { cdata.get_fn_arg_names(def_id.index) } + impl_parent => { cdata.get_parent_impl(def_id.index) } + trait_of_item => { cdata.get_trait_of_item(def_id.index) } + is_exported_symbol => { + let dep_node = cdata.metadata_dep_node(GlobalMetaDataKind::ExportedSymbols); + cdata.exported_symbols.get(&tcx.dep_graph, dep_node).contains(&def_id.index) + } + item_body_nested_bodies => { Rc::new(cdata.item_body_nested_bodies(def_id.index)) } + const_is_rvalue_promotable_to_static => { + cdata.const_is_rvalue_promotable_to_static(def_id.index) + } + is_mir_available => { cdata.is_item_mir_available(def_id.index) } + + dylib_dependency_formats => { Rc::new(cdata.get_dylib_dependency_formats(&tcx.dep_graph)) } + is_allocator => { cdata.is_allocator(&tcx.dep_graph) } + is_panic_runtime => { cdata.is_panic_runtime(&tcx.dep_graph) } + extern_crate => { Rc::new(cdata.extern_crate.get()) } } pub fn provide_local<'tcx>(providers: &mut Providers<'tcx>) { diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 814a45ef636b..4ab2c1aa63c5 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -107,7 +107,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { let mut result = Vec::new(); for n in self.tcx.sess.cstore.crates() { - let span = match *self.tcx.extern_crate(n) { + let span = match *self.tcx.extern_crate(n.as_def_id()) { Some(ref c) => c.span, None => { debug!("Skipping crate {}, no data", n); diff --git a/src/librustc_trans/back/symbol_export.rs b/src/librustc_trans/back/symbol_export.rs index 8eb7ccd48220..b38dc1883892 100644 --- a/src/librustc_trans/back/symbol_export.rs +++ b/src/librustc_trans/back/symbol_export.rs @@ -92,8 +92,8 @@ impl ExportedSymbols { // Down below we'll hardwire all of the symbols to the `Rust` export // level instead. let special_runtime_crate = - scx.tcx().is_allocator(cnum) || - scx.tcx().is_panic_runtime(cnum) || + scx.tcx().is_allocator(cnum.as_def_id()) || + scx.tcx().is_panic_runtime(cnum.as_def_id()) || scx.sess().cstore.is_compiler_builtins(cnum); let crate_exports = scx From b6e9ed1e407b36270df9df08cdee67828efb5e6d Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 12 Jun 2017 19:02:09 +0200 Subject: [PATCH 204/233] Use new macro instead --- src/librustc_typeck/check/mod.rs | 6 +++--- src/librustc_typeck/diagnostics.rs | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index d428852d39e8..205ed515bd73 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3889,9 +3889,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { element_ty } None => { - let mut err = struct_span_err!(tcx.sess, expr.span, E0608, - "cannot index into a value of type `{}`", - base_t); + let mut err = type_error_struct!(tcx.sess, expr.span, base_t, E0608, + "cannot index into a value of type `{}`", + base_t); // Try to give some advice about indexing tuples. if let ty::TyTuple(..) = base_t.sty { let mut needs_note = true; diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 5342fb6cc878..2480650ad1be 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -4105,8 +4105,8 @@ Erroneous code example: 0u8[2]; // error: cannot index into a value of type `u8` ``` -To be able to index a value from a type, it needs to implement the -`std::ops::Index` trait. Example: +To be able to index into a type it needs to implement the `std::ops::Index` +trait. Example: ``` let v: Vec = vec![0, 1, 2, 3]; From 62c245281c9e988cf5eb7cffa15f0dd2ce3b54cf Mon Sep 17 00:00:00 2001 From: Ximin Luo Date: Thu, 15 Jun 2017 13:24:08 +0200 Subject: [PATCH 205/233] Ensure that disable-doc builds don't depend on doc targets --- src/bootstrap/step.rs | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/step.rs b/src/bootstrap/step.rs index 9e8b08a23b7e..ca829cc56683 100644 --- a/src/bootstrap/step.rs +++ b/src/bootstrap/step.rs @@ -1407,13 +1407,20 @@ mod tests { fn build(args: &[&str], extra_host: &[&str], extra_target: &[&str]) -> Build { + build_(args, extra_host, extra_target, true) + } + + fn build_(args: &[&str], + extra_host: &[&str], + extra_target: &[&str], + docs: bool) -> Build { let mut args = args.iter().map(|s| s.to_string()).collect::>(); args.push("--build".to_string()); args.push("A".to_string()); let flags = Flags::parse(&args); let mut config = Config::default(); - config.docs = true; + config.docs = docs; config.build = "A".to_string(); config.host = vec![config.build.clone()]; config.host.extend(extra_host.iter().map(|s| s.to_string())); @@ -1768,4 +1775,22 @@ mod tests { assert!(!plan.iter().any(|s| s.name.contains("tidy"))); assert!(plan.iter().any(|s| s.name.contains("valgrind"))); } + + #[test] + fn test_disable_docs() { + let build = build_(&["test"], &[], &[], false); + let rules = super::build_rules(&build); + let plan = rules.plan(); + println!("rules: {:#?}", plan); + assert!(!plan.iter().any(|s| { + s.name.contains("doc-") || s.name.contains("default:doc") + })); + // none of the dependencies should be a doc rule either + assert!(!plan.iter().any(|s| { + rules.rules[s.name].deps.iter().any(|dep| { + let dep = dep(&rules.sbuild.name(s.name)); + dep.name.contains("doc-") || dep.name.contains("default:doc") + }) + })); + } } From 13b1a80505c7497cddadfa4fbed93f0d69ddeca5 Mon Sep 17 00:00:00 2001 From: Ximin Luo Date: Thu, 15 Jun 2017 13:25:15 +0200 Subject: [PATCH 206/233] Only run check-linkchecker when actually building docs Otherwise the build fails, when running tests but not building docs, e.g.: https://buildd.debian.org/status/fetch.php?pkg=rustc&arch=ppc64el&ver=1.17.0%2Bdfsg2-3&stamp=1497403375&raw=0 --- src/bootstrap/step.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/step.rs b/src/bootstrap/step.rs index ca829cc56683..8c3662002671 100644 --- a/src/bootstrap/step.rs +++ b/src/bootstrap/step.rs @@ -463,7 +463,7 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { rules.test("check-linkchecker", "src/tools/linkchecker") .dep(|s| s.name("tool-linkchecker").stage(0)) .dep(|s| s.name("default:doc")) - .default(true) + .default(build.config.docs) .host(true) .run(move |s| check::linkcheck(build, s.target)); rules.test("check-cargotest", "src/tools/cargotest") From f720e972cfaadcd26a552953b1a876f1f0437ace Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 14 Jun 2017 18:15:13 +0200 Subject: [PATCH 207/233] Add E0618 --- src/librustc_typeck/check/callee.rs | 21 +++++++------- src/librustc_typeck/diagnostics.rs | 28 +++++++++++++++++++ src/test/compile-fail/E0618.rs | 20 +++++++++++++ .../compile-fail/empty-struct-unit-expr.rs | 4 +-- 4 files changed, 60 insertions(+), 13 deletions(-) create mode 100644 src/test/compile-fail/E0618.rs diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index d5ee66a2f0a0..385ed7eb0e38 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -15,7 +15,7 @@ use super::method::MethodCallee; use hir::def::Def; use hir::def_id::{DefId, LOCAL_CRATE}; use rustc::{infer, traits}; -use rustc::ty::{self, TyCtxt, LvaluePreference, Ty}; +use rustc::ty::{self, TyCtxt, TypeFoldable, LvaluePreference, Ty}; use rustc::ty::subst::Subst; use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow}; use syntax::abi; @@ -209,17 +209,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } } - let mut err = if let Some(path) = unit_variant { - let mut err = self.type_error_struct(call_expr.span, |_| { - format!("`{}` is being called, but it is not a function", path) - }, callee_ty); + let mut err = type_error_struct!(self.tcx.sess, call_expr.span, callee_ty, E0618, + "expected function, found `{}`", + if let Some(ref path) = unit_variant { + path.to_string() + } else { + callee_ty.to_string() + }); + if let Some(path) = unit_variant { err.help(&format!("did you mean to write `{}`?", path)); - err - } else { - self.type_error_struct(call_expr.span, |actual| { - format!("expected function, found `{}`", actual) - }, callee_ty) - }; + } if let hir::ExprCall(ref expr, _) = call_expr.node { let def = if let hir::ExprPath(ref qpath) = expr.node { diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 76c664d7997a..c1240be6d2b4 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -4173,6 +4173,34 @@ as possible. For better explanations, see The Rust Book: https://doc.rust-lang.org/book/ "##, +E0618: r##" +Attempted to call something which isn't a function nor a method. + +Erroneous code examples: + +```compile_fail,E0618 +enum X { + Entry, +} + +X::Entry(); // error: expected function, found `X::Entry` + +// Or even simpler: +let x = 0i32; +x(); // error: expected function, found `i32` +``` + +Only functions and methods can be called using `()`. Example: + +``` +// We declare a function: +fn i_am_a_function() {} + +// And we call it: +i_am_a_function(); +``` +"##, + } register_diagnostics! { diff --git a/src/test/compile-fail/E0618.rs b/src/test/compile-fail/E0618.rs new file mode 100644 index 000000000000..1ba2e8e2e561 --- /dev/null +++ b/src/test/compile-fail/E0618.rs @@ -0,0 +1,20 @@ +// 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. + +enum X { + Entry, +} + +fn main() { + X::Entry(); //~ ERROR expected function, found `X::Entry` [E0618] + //~| HELP did you mean to write `X::Entry`? + let x = 0i32; + x(); //~ ERROR expected function, found `i32` [E0618] +} diff --git a/src/test/compile-fail/empty-struct-unit-expr.rs b/src/test/compile-fail/empty-struct-unit-expr.rs index 273ce91a7c5b..9655007604de 100644 --- a/src/test/compile-fail/empty-struct-unit-expr.rs +++ b/src/test/compile-fail/empty-struct-unit-expr.rs @@ -24,10 +24,10 @@ enum E { fn main() { let e2 = Empty2(); //~ ERROR expected function, found `Empty2` let e4 = E::Empty4(); - //~^ ERROR `E::Empty4` is being called, but it is not a function + //~^ ERROR expected function, found `E::Empty4` [E0618] //~| HELP did you mean to write `E::Empty4`? let xe2 = XEmpty2(); //~ ERROR expected function, found `empty_struct::XEmpty2` let xe4 = XE::XEmpty4(); - //~^ ERROR `XE::XEmpty4` is being called, but it is not a function + //~^ ERROR expected function, found `XE::XEmpty4` [E0618] //~| HELP did you mean to write `XE::XEmpty4`? } From ad260ffc884477686e8f6f52c97a417bf99e2f19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 14 Jun 2017 20:42:24 -0700 Subject: [PATCH 208/233] Review comments - generate error instead of warning - remove `RewindPoint` and just keep a copy of `Parser` to rewind state. - `dont_parse_generics: bool` -> `parse_generics: bool` - remove `eat_lt` - move error handling code to separate method --- src/libsyntax/parse/parser.rs | 174 ++++++++---------- src/test/parse-fail/better-expected.rs | 2 +- src/test/parse-fail/bounds-type-where.rs | 2 +- src/test/parse-fail/closure-return-syntax.rs | 2 +- src/test/parse-fail/empty-impl-semicolon.rs | 2 +- src/test/parse-fail/multitrait.rs | 2 +- .../removed-syntax-closure-lifetime.rs | 2 +- .../parse-fail/removed-syntax-fixed-vec.rs | 2 +- .../parse-fail/removed-syntax-ptr-lifetime.rs | 2 +- src/test/ui/issue-22644.stderr | 6 +- 10 files changed, 85 insertions(+), 111 deletions(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index b3623fbe3ac1..3e62f6e33e09 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -150,7 +150,7 @@ fn maybe_append(mut lhs: Vec, rhs: Option>) lhs } -#[derive(PartialEq)] +#[derive(Clone, PartialEq)] enum PrevTokenKind { DocComment, Comma, @@ -162,6 +162,7 @@ enum PrevTokenKind { /* ident is handled by common.rs */ +#[derive(Clone)] pub struct Parser<'a> { pub sess: &'a ParseSess, /// the current token: @@ -441,15 +442,6 @@ fn dummy_arg(span: Span) -> Arg { Arg { ty: P(ty), pat: pat, id: ast::DUMMY_NODE_ID } } -struct RewindPoint { - token: token::Token, - span: Span, - meta_var_span: Option, - prev_span: Span, - token_cursor: TokenCursor, - expected_tokens: Vec, -} - impl<'a> Parser<'a> { pub fn new(sess: &'a ParseSess, tokens: TokenStream, @@ -798,13 +790,6 @@ impl<'a> Parser<'a> { } } - fn is_lt(&mut self) -> bool { - match self.token { - token::Lt | token::BinOp(token::Shl) => true, - _ => false, - } - } - /// Attempt to consume a `<`. If `<<` is seen, replace it with a single /// `<` and continue. If a `<` is not seen, return false. /// @@ -1743,7 +1728,7 @@ impl<'a> Parser<'a> { let segments = match mode { PathStyle::Type => { - self.parse_path_segments_without_colons(false)? + self.parse_path_segments_without_colons(true)? } PathStyle::Expr => { self.parse_path_segments_with_colons()? @@ -1764,14 +1749,14 @@ impl<'a> Parser<'a> { /// bounds are permitted and whether `::` must precede type parameter /// groups. pub fn parse_path(&mut self, mode: PathStyle) -> PResult<'a, ast::Path> { - self.parse_path_common(mode, false) - } - - pub fn parse_path_without_generics(&mut self, mode: PathStyle) -> PResult<'a, ast::Path> { self.parse_path_common(mode, true) } - fn parse_path_common(&mut self, mode: PathStyle, dont_parse_generics: bool) + pub fn parse_path_without_generics(&mut self, mode: PathStyle) -> PResult<'a, ast::Path> { + self.parse_path_common(mode, false) + } + + fn parse_path_common(&mut self, mode: PathStyle, parse_generics: bool) -> PResult<'a, ast::Path> { maybe_whole!(self, NtPath, |x| x); @@ -1784,7 +1769,7 @@ impl<'a> Parser<'a> { // A bound set is a set of type parameter bounds. let mut segments = match mode { PathStyle::Type => { - self.parse_path_segments_without_colons(dont_parse_generics)? + self.parse_path_segments_without_colons(parse_generics)? } PathStyle::Expr => { self.parse_path_segments_with_colons()? @@ -1829,7 +1814,7 @@ impl<'a> Parser<'a> { /// - `a::b::c` /// - `a::b::c(V) -> W` /// - `a::b::c(V)` - pub fn parse_path_segments_without_colons(&mut self, dont_parse_generics: bool) + pub fn parse_path_segments_without_colons(&mut self, parse_generics: bool) -> PResult<'a, Vec> { let mut segments = Vec::new(); @@ -1850,8 +1835,7 @@ impl<'a> Parser<'a> { } // Parse types, optionally. - let parameters = if self.is_lt() && !dont_parse_generics { - let _ = self.eat_lt(); + let parameters = if parse_generics && self.eat_lt() { let (lifetimes, types, bindings) = self.parse_generic_args()?; self.expect_gt()?; ast::AngleBracketedParameterData { @@ -2832,60 +2816,7 @@ impl<'a> Parser<'a> { if op == AssocOp::As { // Save the state of the parser before parsing type normally, in case there is a // LessThan comparison after this cast. - let rp = self.get_rewind_point(); - match self.parse_ty_no_plus() { - Ok(rhs) => { - lhs = self.mk_expr(lhs_span.to(rhs.span), - ExprKind::Cast(lhs, rhs), ThinVec::new()); - } - Err(mut err) => { - // Rewind to before attempting to parse the type with generics, to get - // arround #22644. - let rp_err = self.get_rewind_point(); - let sp = rp_err.span.clone(); - self.rewind(rp); - let lo = self.span; - let path = match self.parse_path_without_generics(PathStyle::Type) { - Ok(path) => { - // Successfully parsed the type leaving a `<` yet to parse - err.cancel(); - let codemap = self.sess.codemap(); - let suggestion_span = lhs_span.to(self.prev_span); - let suggestion = match codemap.span_to_snippet(suggestion_span) { - Ok(lstring) => format!("({})", lstring), - _ => format!("()") - }; - let warn_message = match codemap.span_to_snippet(self.prev_span) { - Ok(lstring) => format!("`{}`", lstring), - _ => "a type".to_string(), - }; - let msg = format!("`<` is interpreted as a start of generic \ - arguments for {}, not a comparison", - warn_message); - let mut warn = self.sess.span_diagnostic.struct_span_warn(sp, &msg); - warn.span_label(sp, "interpreted as generic argument"); - warn.span_label(self.span, "not interpreted as comparison"); - warn.span_suggestion(suggestion_span, - "if you want to compare the casted value \ - then write:", - suggestion); - warn.emit(); - path - } - Err(mut path_err) => { - // Still couldn't parse, return original error and parser state - path_err.cancel(); - self.rewind(rp_err); - return Err(err); - } - }; - let path = TyKind::Path(None, path); - let span = lo.to(self.prev_span); - let rhs = P(Ty { node: path, span: span, id: ast::DUMMY_NODE_ID }); - lhs = self.mk_expr(lhs_span.to(rhs.span), - ExprKind::Cast(lhs, rhs), ThinVec::new()); - } - }; + lhs = self.parse_assoc_op_as(lhs, lhs_span)?; continue } else if op == AssocOp::Colon { let rhs = self.parse_ty_no_plus()?; @@ -2983,6 +2914,67 @@ impl<'a> Parser<'a> { Ok(lhs) } + fn parse_assoc_op_as(&mut self, lhs: P, lhs_span: Span) -> PResult<'a, P> { + let rp = self.clone(); + match self.parse_ty_no_plus() { + Ok(rhs) => { + Ok(self.mk_expr(lhs_span.to(rhs.span), + ExprKind::Cast(lhs, rhs), + ThinVec::new())) + } + Err(mut err) => { + let rp_err = self.clone(); + let sp = rp_err.span.clone(); + + // Rewind to before attempting to parse the type with generics, to get + // arround #22644. + mem::replace(self, rp); + let lo = self.span; + match self.parse_path_without_generics(PathStyle::Type) { + Ok(path) => { + // Successfully parsed the type leaving a `<` yet to parse + err.cancel(); + let codemap = self.sess.codemap(); + let suggestion_span = lhs_span.to(self.prev_span); + let suggestion = match codemap.span_to_snippet(suggestion_span) { + Ok(lstring) => format!("({})", lstring), + _ => format!("( as )") + }; + let warn_message = match codemap.span_to_snippet(self.prev_span) { + Ok(lstring) => format!("`{}`", lstring), + _ => "a type".to_string(), + }; + let msg = format!("`<` is interpreted as a start of generic \ + arguments for {}, not a comparison", + warn_message); + let mut err = self.sess.span_diagnostic.struct_span_err(sp, &msg); + err.span_label(sp, "interpreted as generic argument"); + err.span_label(self.span, "not interpreted as comparison"); + err.span_suggestion(suggestion_span, + "if you want to compare the casted value then write:", + suggestion); + err.emit(); + + let path = TyKind::Path(None, path); + let span = lo.to(self.prev_span); + let rhs = P(Ty { node: path, span: span, id: ast::DUMMY_NODE_ID }); + // Letting the parser accept the recovered type to avoid further errors, + // but the code will still not compile due to the error emitted above. + Ok(self.mk_expr(lhs_span.to(rhs.span), + ExprKind::Cast(lhs, rhs), + ThinVec::new())) + } + Err(mut path_err) => { + // Still couldn't parse, return original error and parser state + path_err.cancel(); + mem::replace(self, rp_err); + Err(err) + } + } + } + } + } + /// Produce an error if comparison operators are chained (RFC #558). /// We only need to check lhs, not rhs, because all comparison ops /// have same precedence and are left-associative @@ -6264,24 +6256,4 @@ impl<'a> Parser<'a> { _ => Err(self.fatal("expected string literal")) } } - - fn get_rewind_point(&mut self) -> RewindPoint { - RewindPoint { - token: self.token.clone(), - span: self.span, - meta_var_span: self.meta_var_span, - prev_span: self.prev_span, - token_cursor: self.token_cursor.clone(), - expected_tokens: self.expected_tokens.clone(), - } - } - - fn rewind(&mut self, rp: RewindPoint) { - self.token = rp.token; - self.span = rp.span; - self.meta_var_span = rp.meta_var_span; - self.prev_span = rp.prev_span; - self.token_cursor = rp.token_cursor; - self.expected_tokens = rp.expected_tokens; - } } diff --git a/src/test/parse-fail/better-expected.rs b/src/test/parse-fail/better-expected.rs index d78ac3cb5ce9..b60201c251dc 100644 --- a/src/test/parse-fail/better-expected.rs +++ b/src/test/parse-fail/better-expected.rs @@ -11,5 +11,5 @@ // compile-flags: -Z parse-only fn main() { - let x: [isize 3]; //~ ERROR expected one of `!`, `(`, `+`, `::`, `;`, or `]`, found `3` + let x: [isize 3]; //~ ERROR expected one of `!`, `(`, `+`, `::`, `;`, `<`, or `]`, found `3` } diff --git a/src/test/parse-fail/bounds-type-where.rs b/src/test/parse-fail/bounds-type-where.rs index 103785495933..9dc5d8277446 100644 --- a/src/test/parse-fail/bounds-type-where.rs +++ b/src/test/parse-fail/bounds-type-where.rs @@ -18,6 +18,6 @@ type A where T: Trait + Trait = u8; // OK type A where = u8; // OK type A where T: Trait + = u8; // OK type A where T, = u8; -//~^ ERROR expected one of `!`, `(`, `+`, `::`, `:`, `==`, or `=`, found `,` +//~^ ERROR expected one of `!`, `(`, `+`, `::`, `:`, `<`, `==`, or `=`, found `,` fn main() {} diff --git a/src/test/parse-fail/closure-return-syntax.rs b/src/test/parse-fail/closure-return-syntax.rs index f3be750e2546..1da673591801 100644 --- a/src/test/parse-fail/closure-return-syntax.rs +++ b/src/test/parse-fail/closure-return-syntax.rs @@ -13,5 +13,5 @@ fn main() { let x = || -> i32 22; - //~^ ERROR expected one of `!`, `(`, `::`, or `{`, found `22` + //~^ ERROR expected one of `!`, `(`, `::`, `<`, or `{`, found `22` } diff --git a/src/test/parse-fail/empty-impl-semicolon.rs b/src/test/parse-fail/empty-impl-semicolon.rs index ef25e5d0fc2e..9939f1e36ea9 100644 --- a/src/test/parse-fail/empty-impl-semicolon.rs +++ b/src/test/parse-fail/empty-impl-semicolon.rs @@ -10,4 +10,4 @@ // compile-flags: -Z parse-only -impl Foo; //~ ERROR expected one of `!`, `(`, `+`, `::`, `for`, `where`, or `{`, found `;` +impl Foo; //~ ERROR expected one of `!`, `(`, `+`, `::`, `<`, `for`, `where`, or `{`, found `;` diff --git a/src/test/parse-fail/multitrait.rs b/src/test/parse-fail/multitrait.rs index d2be89d19ece..b7c9b1658846 100644 --- a/src/test/parse-fail/multitrait.rs +++ b/src/test/parse-fail/multitrait.rs @@ -15,7 +15,7 @@ struct S { } impl Cmp, ToString for S { -//~^ ERROR: expected one of `!`, `(`, `+`, `::`, `for`, `where`, or `{`, found `,` +//~^ ERROR: expected one of `!`, `(`, `+`, `::`, `<`, `for`, `where`, or `{`, found `,` fn eq(&&other: S) { false } fn to_string(&self) -> String { "hi".to_string() } } diff --git a/src/test/parse-fail/removed-syntax-closure-lifetime.rs b/src/test/parse-fail/removed-syntax-closure-lifetime.rs index 2dd2bd22d1a3..b305b1894a81 100644 --- a/src/test/parse-fail/removed-syntax-closure-lifetime.rs +++ b/src/test/parse-fail/removed-syntax-closure-lifetime.rs @@ -11,4 +11,4 @@ // compile-flags: -Z parse-only type closure = Box; -//~^ ERROR expected one of `!`, `(`, `+`, `,`, `::`, or `>`, found `/` +//~^ ERROR expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `/` diff --git a/src/test/parse-fail/removed-syntax-fixed-vec.rs b/src/test/parse-fail/removed-syntax-fixed-vec.rs index f943d5d50cac..0f34db088520 100644 --- a/src/test/parse-fail/removed-syntax-fixed-vec.rs +++ b/src/test/parse-fail/removed-syntax-fixed-vec.rs @@ -10,4 +10,4 @@ // compile-flags: -Z parse-only -type v = [isize * 3]; //~ ERROR expected one of `!`, `(`, `+`, `::`, `;`, or `]`, found `*` +type v = [isize * 3]; //~ ERROR expected one of `!`, `(`, `+`, `::`, `;`, `<`, or `]`, found `*` diff --git a/src/test/parse-fail/removed-syntax-ptr-lifetime.rs b/src/test/parse-fail/removed-syntax-ptr-lifetime.rs index 40f368e71054..b91ab8730b3d 100644 --- a/src/test/parse-fail/removed-syntax-ptr-lifetime.rs +++ b/src/test/parse-fail/removed-syntax-ptr-lifetime.rs @@ -10,4 +10,4 @@ // compile-flags: -Z parse-only -type bptr = &lifetime/isize; //~ ERROR expected one of `!`, `(`, `::`, or `;`, found `/` +type bptr = &lifetime/isize; //~ ERROR expected one of `!`, `(`, `::`, `;`, or `<`, found `/` diff --git a/src/test/ui/issue-22644.stderr b/src/test/ui/issue-22644.stderr index 1e7861755877..a22496357d99 100644 --- a/src/test/ui/issue-22644.stderr +++ b/src/test/ui/issue-22644.stderr @@ -1,4 +1,4 @@ -warning: `<` is interpreted as a start of generic arguments for `usize`, not a comparison +error: `<` is interpreted as a start of generic arguments for `usize`, not a comparison --> $DIR/issue-22644.rs:16:33 | 16 | println!("{}", a as usize < b); @@ -9,7 +9,7 @@ warning: `<` is interpreted as a start of generic arguments for `usize`, not a c help: if you want to compare the casted value then write: | println!("{}", (a as usize) < b); -warning: `<` is interpreted as a start of generic arguments for `usize`, not a comparison +error: `<` is interpreted as a start of generic arguments for `usize`, not a comparison --> $DIR/issue-22644.rs:17:33 | 17 | println!("{}", a as usize < 4); @@ -20,3 +20,5 @@ warning: `<` is interpreted as a start of generic arguments for `usize`, not a c help: if you want to compare the casted value then write: | println!("{}", (a as usize) < 4); +error: aborting due to previous error(s) + From 406eddf5e1e14b9356b332c0df987a1bdf0d2c7f Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Thu, 8 Jun 2017 17:18:05 +0300 Subject: [PATCH 209/233] Add a no-system-llvm compilecheck header --- src/bootstrap/check.rs | 3 +++ src/llvm | 2 +- src/test/codegen/alloc-optimisation.rs | 12 +++--------- src/tools/compiletest/src/common.rs | 3 +++ src/tools/compiletest/src/header.rs | 3 +++ src/tools/compiletest/src/main.rs | 2 ++ 6 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 385376333c1d..b45849972b07 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -245,6 +245,9 @@ pub fn compiletest(build: &Build, let llvm_config = build.llvm_config(target); let llvm_version = output(Command::new(&llvm_config).arg("--version")); cmd.arg("--llvm-version").arg(llvm_version); + if !build.is_rust_llvm(target) { + cmd.arg("--system-llvm"); + } cmd.args(&build.flags.cmd.test_args()); diff --git a/src/llvm b/src/llvm index 84c52ce9b75d..ee545e1d13e6 160000 --- a/src/llvm +++ b/src/llvm @@ -1 +1 @@ -Subproject commit 84c52ce9b75d841629e6f821b3794998fb0ddbd9 +Subproject commit ee545e1d13e6f2191572aebcadb7d1640ce45c65 diff --git a/src/test/codegen/alloc-optimisation.rs b/src/test/codegen/alloc-optimisation.rs index 3953f637cf7a..07dc1350714b 100644 --- a/src/test/codegen/alloc-optimisation.rs +++ b/src/test/codegen/alloc-optimisation.rs @@ -7,17 +7,11 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. +// +// no-system-llvm +// compile-flags: -O #![crate_type="lib"] -#[no_mangle] -pub fn alloc_zeroed_test(size: u8) { - // CHECK-LABEL: @alloc_zeroed_test - // CHECK-NEXT: start: - // CHECK-NEXT: ret void - let x = vec![0u8; size as usize]; - drop(x); -} - #[no_mangle] pub fn alloc_test(data: u32) { // CHECK-LABEL: @alloc_test diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 92f6f36d69d9..cc95e1b89305 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -166,6 +166,9 @@ pub struct Config { // Version of LLVM pub llvm_version: Option, + // Is LLVM a system LLVM + pub system_llvm: bool, + // Path to the android tools pub android_cross_path: PathBuf, diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index c503ca7d8cd1..aa33580b337c 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -166,6 +166,9 @@ impl EarlyProps { } fn ignore_llvm(config: &Config, line: &str) -> bool { + if config.system_llvm && line.starts_with("no-system-llvm") { + return true; + } if let Some(ref actual_version) = config.llvm_version { if line.starts_with("min-llvm-version") { let min_version = line.trim_right() diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index 1bb0b765f9f1..3dac580a5f4b 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -97,6 +97,7 @@ pub fn parse_config(args: Vec ) -> Config { optopt("", "gdb", "path to GDB to use for GDB debuginfo tests", "PATH"), optopt("", "lldb-version", "the version of LLDB used", "VERSION STRING"), optopt("", "llvm-version", "the version of LLVM used", "VERSION STRING"), + optflag("", "system-llvm", "is LLVM the system LLVM"), optopt("", "android-cross-path", "Android NDK standalone path", "PATH"), optopt("", "adb-path", "path to the android debugger", "PATH"), optopt("", "adb-test-dir", "path to tests for the android debugger", "PATH"), @@ -183,6 +184,7 @@ pub fn parse_config(args: Vec ) -> Config { gdb_native_rust: gdb_native_rust, lldb_version: extract_lldb_version(matches.opt_str("lldb-version")), llvm_version: matches.opt_str("llvm-version"), + system_llvm: matches.opt_present("system-llvm"), android_cross_path: opt_path(matches, "android-cross-path"), adb_path: opt_str2(matches.opt_str("adb-path")), adb_test_dir: opt_str2(matches.opt_str("adb-test-dir")), From 8074a88787de412a341e99ea16c88784ecf915a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 12 Jun 2017 15:54:04 -0700 Subject: [PATCH 210/233] Position span label correctly when it isn't last --- src/librustc_errors/emitter.rs | 7 ++++-- src/libsyntax/test_snippet.rs | 43 ++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index f820ea4c5e17..aa0fae508fde 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -445,8 +445,11 @@ impl EmitterWriter { && next.has_label()) // multiline start/end, move it to a new line || (annotation.has_label() // so as not to overlap the orizontal lines. && next.takes_space()) - || (annotation.takes_space() - && next.takes_space()) + || (annotation.takes_space() && next.takes_space()) + || (overlaps(next, annotation, l) + && next.end_col <= annotation.end_col + && next.has_label() + && p == 0) // Avoid #42595. { // This annotation needs a new line in the output. p += 1; diff --git a/src/libsyntax/test_snippet.rs b/src/libsyntax/test_snippet.rs index b3fa1e97376d..4fae2ff9814f 100644 --- a/src/libsyntax/test_snippet.rs +++ b/src/libsyntax/test_snippet.rs @@ -735,6 +735,49 @@ error: foo "#); } +#[test] +fn multiple_labels_secondary_without_message_3() { + test_harness(r#" +fn foo() { + a bc d +} +"#, + vec![ + SpanLabel { + start: Position { + string: "a", + count: 1, + }, + end: Position { + string: "b", + count: 1, + }, + label: "`a` is a good letter", + }, + SpanLabel { + start: Position { + string: "c", + count: 1, + }, + end: Position { + string: "d", + count: 1, + }, + label: "", + }, + ], + r#" +error: foo + --> test.rs:3:3 + | +3 | a bc d + | ^^^^---- + | | + | `a` is a good letter + +"#); +} + #[test] fn multiple_labels_without_message() { test_harness(r#" From ea149b8571d538fc8bb2117e46161d442aef48a4 Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Mon, 12 Jun 2017 20:07:54 +0300 Subject: [PATCH 211/233] Utf8Lossy type with chunks iterator and impl Display and Debug --- src/liballoc/string.rs | 127 ++++--------------- src/libstd_unicode/Cargo.toml | 4 + src/libstd_unicode/lib.rs | 3 + src/libstd_unicode/lossy.rs | 198 ++++++++++++++++++++++++++++++ src/libstd_unicode/tests/lib.rs | 15 +++ src/libstd_unicode/tests/lossy.rs | 91 ++++++++++++++ 6 files changed, 336 insertions(+), 102 deletions(-) create mode 100644 src/libstd_unicode/lossy.rs create mode 100644 src/libstd_unicode/tests/lib.rs create mode 100644 src/libstd_unicode/tests/lossy.rs diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index 1d98626e90b0..2cb81029f95e 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -61,8 +61,8 @@ use core::hash; use core::iter::{FromIterator, FusedIterator}; use core::ops::{self, Add, AddAssign, Index, IndexMut}; use core::ptr; -use core::str as core_str; use core::str::pattern::Pattern; +use std_unicode::lossy; use std_unicode::char::{decode_utf16, REPLACEMENT_CHARACTER}; use borrow::{Cow, ToOwned}; @@ -533,111 +533,34 @@ impl String { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn from_utf8_lossy<'a>(v: &'a [u8]) -> Cow<'a, str> { - let mut i; - match str::from_utf8(v) { - Ok(s) => return Cow::Borrowed(s), - Err(e) => i = e.valid_up_to(), + let mut iter = lossy::Utf8Lossy::from_bytes(v).chunks(); + + let (first_valid, first_broken) = if let Some(chunk) = iter.next() { + let lossy::Utf8LossyChunk { valid, broken } = chunk; + if valid.len() == v.len() { + debug_assert!(broken.is_empty()); + return Cow::Borrowed(valid); + } + (valid, broken) + } else { + return Cow::Borrowed(""); + }; + + const REPLACEMENT: &'static str = "\u{FFFD}"; + + let mut res = String::with_capacity(v.len()); + res.push_str(first_valid); + if !first_broken.is_empty() { + res.push_str(REPLACEMENT); } - const TAG_CONT_U8: u8 = 128; - const REPLACEMENT: &'static [u8] = b"\xEF\xBF\xBD"; // U+FFFD in UTF-8 - let total = v.len(); - fn unsafe_get(xs: &[u8], i: usize) -> u8 { - unsafe { *xs.get_unchecked(i) } - } - fn safe_get(xs: &[u8], i: usize, total: usize) -> u8 { - if i >= total { 0 } else { unsafe_get(xs, i) } - } - - let mut res = String::with_capacity(total); - - if i > 0 { - unsafe { res.as_mut_vec().extend_from_slice(&v[..i]) }; - } - - // subseqidx is the index of the first byte of the subsequence we're - // looking at. It's used to copy a bunch of contiguous good codepoints - // at once instead of copying them one by one. - let mut subseqidx = i; - - while i < total { - let i_ = i; - let byte = unsafe_get(v, i); - i += 1; - - macro_rules! error { () => ({ - unsafe { - if subseqidx != i_ { - res.as_mut_vec().extend_from_slice(&v[subseqidx..i_]); - } - subseqidx = i; - res.as_mut_vec().extend_from_slice(REPLACEMENT); - } - })} - - if byte < 128 { - // subseqidx handles this - } else { - let w = core_str::utf8_char_width(byte); - - match w { - 2 => { - if safe_get(v, i, total) & 192 != TAG_CONT_U8 { - error!(); - continue; - } - i += 1; - } - 3 => { - match (byte, safe_get(v, i, total)) { - (0xE0, 0xA0...0xBF) => (), - (0xE1...0xEC, 0x80...0xBF) => (), - (0xED, 0x80...0x9F) => (), - (0xEE...0xEF, 0x80...0xBF) => (), - _ => { - error!(); - continue; - } - } - i += 1; - if safe_get(v, i, total) & 192 != TAG_CONT_U8 { - error!(); - continue; - } - i += 1; - } - 4 => { - match (byte, safe_get(v, i, total)) { - (0xF0, 0x90...0xBF) => (), - (0xF1...0xF3, 0x80...0xBF) => (), - (0xF4, 0x80...0x8F) => (), - _ => { - error!(); - continue; - } - } - i += 1; - if safe_get(v, i, total) & 192 != TAG_CONT_U8 { - error!(); - continue; - } - i += 1; - if safe_get(v, i, total) & 192 != TAG_CONT_U8 { - error!(); - continue; - } - i += 1; - } - _ => { - error!(); - continue; - } - } + for lossy::Utf8LossyChunk { valid, broken } in iter { + res.push_str(valid); + if !broken.is_empty() { + res.push_str(REPLACEMENT); } } - if subseqidx < total { - unsafe { res.as_mut_vec().extend_from_slice(&v[subseqidx..total]) }; - } + Cow::Owned(res) } diff --git a/src/libstd_unicode/Cargo.toml b/src/libstd_unicode/Cargo.toml index 28fbd3c1aa94..b3346dbe2fb1 100644 --- a/src/libstd_unicode/Cargo.toml +++ b/src/libstd_unicode/Cargo.toml @@ -9,5 +9,9 @@ path = "lib.rs" test = false bench = false +[[test]] +name = "std_unicode_tests" +path = "tests/lib.rs" + [dependencies] core = { path = "../libcore" } diff --git a/src/libstd_unicode/lib.rs b/src/libstd_unicode/lib.rs index 19f2ad1c56f2..98624800b4c6 100644 --- a/src/libstd_unicode/lib.rs +++ b/src/libstd_unicode/lib.rs @@ -34,6 +34,8 @@ #![feature(char_escape_debug)] #![feature(core_char_ext)] +#![feature(str_internals)] +#![feature(core_intrinsics)] #![feature(decode_utf8)] #![feature(fused)] #![feature(fn_traits)] @@ -45,6 +47,7 @@ mod tables; mod u_str; pub mod char; +pub mod lossy; #[allow(deprecated)] pub mod str { diff --git a/src/libstd_unicode/lossy.rs b/src/libstd_unicode/lossy.rs new file mode 100644 index 000000000000..b914cbcf4b85 --- /dev/null +++ b/src/libstd_unicode/lossy.rs @@ -0,0 +1,198 @@ +// 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 core::str as core_str; +use core::fmt; +use core::fmt::Write; +use char; +use core::intrinsics; + + +/// Lossy UTF-8 string. +#[unstable(feature = "str_internals", issue = "0")] +pub struct Utf8Lossy { + bytes: [u8] +} + +impl Utf8Lossy { + pub fn from_str(s: &str) -> &Utf8Lossy { + Utf8Lossy::from_bytes(s.as_bytes()) + } + + pub fn from_bytes(bytes: &[u8]) -> &Utf8Lossy { + unsafe { intrinsics::transmute(bytes) } + } + + pub fn chunks(&self) -> Utf8LossyChunksIter { + Utf8LossyChunksIter { source: &self.bytes } + } +} + + +/// Iterator over lossy UTF-8 string +#[unstable(feature = "str_internals", issue = "0")] +pub struct Utf8LossyChunksIter<'a> { + source: &'a [u8], +} + +#[unstable(feature = "str_internals", issue = "0")] +#[derive(PartialEq, Eq, Debug)] +pub struct Utf8LossyChunk<'a> { + /// Sequence of valid chars. + /// Can be empty between broken UTF-8 chars. + pub valid: &'a str, + /// Single broken char, empty if none. + /// Empty iff iterator item is last. + pub broken: &'a [u8], +} + +impl<'a> Iterator for Utf8LossyChunksIter<'a> { + type Item = Utf8LossyChunk<'a>; + + fn next(&mut self) -> Option> { + if self.source.len() == 0 { + return None; + } + + const TAG_CONT_U8: u8 = 128; + fn unsafe_get(xs: &[u8], i: usize) -> u8 { + unsafe { *xs.get_unchecked(i) } + } + fn safe_get(xs: &[u8], i: usize) -> u8 { + if i >= xs.len() { 0 } else { unsafe_get(xs, i) } + } + + let mut i = 0; + while i < self.source.len() { + let i_ = i; + + let byte = unsafe_get(self.source, i); + i += 1; + + if byte < 128 { + + } else { + let w = core_str::utf8_char_width(byte); + + macro_rules! error { () => ({ + unsafe { + let r = Utf8LossyChunk { + valid: core_str::from_utf8_unchecked(&self.source[0..i_]), + broken: &self.source[i_..i], + }; + self.source = &self.source[i..]; + return Some(r); + } + })} + + match w { + 2 => { + if safe_get(self.source, i) & 192 != TAG_CONT_U8 { + error!(); + } + i += 1; + } + 3 => { + match (byte, safe_get(self.source, i)) { + (0xE0, 0xA0 ... 0xBF) => (), + (0xE1 ... 0xEC, 0x80 ... 0xBF) => (), + (0xED, 0x80 ... 0x9F) => (), + (0xEE ... 0xEF, 0x80 ... 0xBF) => (), + _ => { + error!(); + } + } + i += 1; + if safe_get(self.source, i) & 192 != TAG_CONT_U8 { + error!(); + } + i += 1; + } + 4 => { + match (byte, safe_get(self.source, i)) { + (0xF0, 0x90 ... 0xBF) => (), + (0xF1 ... 0xF3, 0x80 ... 0xBF) => (), + (0xF4, 0x80 ... 0x8F) => (), + _ => { + error!(); + } + } + i += 1; + if safe_get(self.source, i) & 192 != TAG_CONT_U8 { + error!(); + } + i += 1; + if safe_get(self.source, i) & 192 != TAG_CONT_U8 { + error!(); + } + i += 1; + } + _ => { + error!(); + } + } + } + } + + let r = Utf8LossyChunk { + valid: unsafe { core_str::from_utf8_unchecked(self.source) }, + broken: &[], + }; + self.source = &[]; + return Some(r); + } +} + + +impl fmt::Display for Utf8Lossy { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + for Utf8LossyChunk { valid, broken } in self.chunks() { + f.write_str(valid)?; + if !broken.is_empty() { + f.write_char(char::REPLACEMENT_CHARACTER)?; + } + } + Ok(()) + } +} + +impl fmt::Debug for Utf8Lossy { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_char('"')?; + + for Utf8LossyChunk { valid, broken } in self.chunks() { + + // Valid part. + // Here we partially parse UTF-8 again which is suboptimal. + { + let mut from = 0; + for (i, c) in valid.char_indices() { + let esc = c.escape_debug(); + // If char needs escaping, flush backlog so far and write, else skip + if esc.len() != 1 { + f.write_str(&valid[from..i])?; + for c in esc { + f.write_char(c)?; + } + from = i + c.len_utf8(); + } + } + f.write_str(&valid[from..])?; + } + + // Broken parts of string as hex escape. + for &b in broken { + write!(f, "\\x{:02x}", b)?; + } + } + + f.write_char('"') + } +} diff --git a/src/libstd_unicode/tests/lib.rs b/src/libstd_unicode/tests/lib.rs new file mode 100644 index 000000000000..9535ec18763e --- /dev/null +++ b/src/libstd_unicode/tests/lib.rs @@ -0,0 +1,15 @@ +// 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. + +#![feature(str_internals, unicode)] + +extern crate std_unicode; + +mod lossy; diff --git a/src/libstd_unicode/tests/lossy.rs b/src/libstd_unicode/tests/lossy.rs new file mode 100644 index 000000000000..e05d06685563 --- /dev/null +++ b/src/libstd_unicode/tests/lossy.rs @@ -0,0 +1,91 @@ +// 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 std_unicode::lossy::*; + +#[test] +fn chunks() { + let mut iter = Utf8Lossy::from_bytes(b"hello").chunks(); + assert_eq!(Some(Utf8LossyChunk { valid: "hello", broken: b"", }), iter.next()); + assert_eq!(None, iter.next()); + + let mut iter = Utf8Lossy::from_bytes("ศไทย中华Việt Nam".as_bytes()).chunks(); + assert_eq!(Some(Utf8LossyChunk { valid: "ศไทย中华Việt Nam", broken: b"", }), iter.next()); + assert_eq!(None, iter.next()); + + let mut iter = Utf8Lossy::from_bytes(b"Hello\xC2 There\xFF Goodbye").chunks(); + assert_eq!(Some(Utf8LossyChunk { valid: "Hello", broken: b"\xC2", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: " There", broken: b"\xFF", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: " Goodbye", broken: b"", }), iter.next()); + assert_eq!(None, iter.next()); + + let mut iter = Utf8Lossy::from_bytes(b"Hello\xC0\x80 There\xE6\x83 Goodbye").chunks(); + assert_eq!(Some(Utf8LossyChunk { valid: "Hello", broken: b"\xC0", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\x80", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: " There", broken: b"\xE6\x83", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: " Goodbye", broken: b"", }), iter.next()); + assert_eq!(None, iter.next()); + + let mut iter = Utf8Lossy::from_bytes(b"\xF5foo\xF5\x80bar").chunks(); + assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xF5", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "foo", broken: b"\xF5", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\x80", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "bar", broken: b"", }), iter.next()); + assert_eq!(None, iter.next()); + + let mut iter = Utf8Lossy::from_bytes(b"\xF1foo\xF1\x80bar\xF1\x80\x80baz").chunks(); + assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xF1", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "foo", broken: b"\xF1\x80", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "bar", broken: b"\xF1\x80\x80", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "baz", broken: b"", }), iter.next()); + assert_eq!(None, iter.next()); + + let mut iter = Utf8Lossy::from_bytes(b"\xF4foo\xF4\x80bar\xF4\xBFbaz").chunks(); + assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xF4", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "foo", broken: b"\xF4\x80", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "bar", broken: b"\xF4", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xBF", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "baz", broken: b"", }), iter.next()); + assert_eq!(None, iter.next()); + + let mut iter = Utf8Lossy::from_bytes(b"\xF0\x80\x80\x80foo\xF0\x90\x80\x80bar").chunks(); + assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xF0", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\x80", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\x80", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\x80", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "foo\u{10000}bar", broken: b"", }), iter.next()); + assert_eq!(None, iter.next()); + + // surrogates + let mut iter = Utf8Lossy::from_bytes(b"\xED\xA0\x80foo\xED\xBF\xBFbar").chunks(); + assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xED", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xA0", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\x80", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "foo", broken: b"\xED", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xBF", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xBF", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "bar", broken: b"", }), iter.next()); + assert_eq!(None, iter.next()); +} + +#[test] +fn display() { + assert_eq!( + "Hello\u{FFFD}\u{FFFD} There\u{FFFD} Goodbye", + &format!("{}", Utf8Lossy::from_bytes(b"Hello\xC0\x80 There\xE6\x83 Goodbye"))); +} + +#[test] +fn debug() { + assert_eq!( + "\"Hello\\xc0\\x80 There\\xe6\\x83 Goodbye\\u{10d4ea}\"", + &format!("{:?}", Utf8Lossy::from_bytes( + b"Hello\xC0\x80 There\xE6\x83 Goodbye\xf4\x8d\x93\xaa"))); +} From ac96fd77874bb7968b7d82bed5a410d3941bc4c8 Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Mon, 12 Jun 2017 22:21:53 +0300 Subject: [PATCH 212/233] Avoid allocations in Debug for os_str Fixes #38879 --- src/libstd/ffi/os_str.rs | 18 ++++++++----- src/libstd/path.rs | 8 +++--- src/libstd/sys/redox/os_str.rs | 27 ++++++++++++++----- src/libstd/sys/unix/os_str.rs | 27 ++++++++++++++----- src/libstd/sys/windows/os_str.rs | 26 +++++++++++++----- src/libstd/sys_common/wtf8.rs | 46 +++++++++++++++++++++++++++++--- 6 files changed, 117 insertions(+), 35 deletions(-) diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs index a5a1b5e5f091..f54d79c201f4 100644 --- a/src/libstd/ffi/os_str.rs +++ b/src/libstd/ffi/os_str.rs @@ -9,7 +9,7 @@ // except according to those terms. use borrow::{Borrow, Cow}; -use fmt::{self, Debug}; +use fmt; use mem; use ops; use cmp; @@ -312,8 +312,8 @@ impl Default for OsString { } #[stable(feature = "rust1", since = "1.0.0")] -impl Debug for OsString { - fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { +impl fmt::Debug for OsString { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(&**self, formatter) } } @@ -669,9 +669,15 @@ impl Hash for OsStr { } #[stable(feature = "rust1", since = "1.0.0")] -impl Debug for OsStr { - fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { - self.inner.fmt(formatter) +impl fmt::Debug for OsStr { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(&self.inner, formatter) + } +} + +impl OsStr { + pub(crate) fn display(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(&self.inner, formatter) } } diff --git a/src/libstd/path.rs b/src/libstd/path.rs index e128a4164d74..42a54ed6d754 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -2281,8 +2281,8 @@ impl AsRef for Path { #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Debug for Path { - fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { - self.inner.fmt(formatter) + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(&self.inner, formatter) } } @@ -2314,14 +2314,14 @@ pub struct Display<'a> { #[stable(feature = "rust1", since = "1.0.0")] impl<'a> fmt::Debug for Display<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Debug::fmt(&self.path.to_string_lossy(), f) + fmt::Debug::fmt(&self.path, f) } } #[stable(feature = "rust1", since = "1.0.0")] impl<'a> fmt::Display for Display<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Display::fmt(&self.path.to_string_lossy(), f) + self.path.inner.display(f) } } diff --git a/src/libstd/sys/redox/os_str.rs b/src/libstd/sys/redox/os_str.rs index c2bba07f68ce..c54286353a92 100644 --- a/src/libstd/sys/redox/os_str.rs +++ b/src/libstd/sys/redox/os_str.rs @@ -12,10 +12,11 @@ /// a `Vec`/`[u8]`. use borrow::Cow; -use fmt::{self, Debug}; +use fmt; use str; use mem; use sys_common::{AsInner, IntoInner}; +use std_unicode::lossy::Utf8Lossy; #[derive(Clone, Hash)] pub struct Buf { @@ -26,15 +27,27 @@ pub struct Slice { pub inner: [u8] } -impl Debug for Slice { - fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { - self.to_string_lossy().fmt(formatter) +impl fmt::Debug for Slice { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(&Utf8Lossy::from_bytes(&self.inner), formatter) } } -impl Debug for Buf { - fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { - self.as_slice().fmt(formatter) +impl fmt::Display for Slice { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(&Utf8Lossy::from_bytes(&self.inner), formatter) + } +} + +impl fmt::Debug for Buf { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(self.as_slice(), formatter) + } +} + +impl fmt::Display for Buf { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(self.as_slice(), formatter) } } diff --git a/src/libstd/sys/unix/os_str.rs b/src/libstd/sys/unix/os_str.rs index f5b942d3343d..777db17e3e16 100644 --- a/src/libstd/sys/unix/os_str.rs +++ b/src/libstd/sys/unix/os_str.rs @@ -12,10 +12,11 @@ /// a `Vec`/`[u8]`. use borrow::Cow; -use fmt::{self, Debug}; +use fmt; use str; use mem; use sys_common::{AsInner, IntoInner}; +use std_unicode::lossy::Utf8Lossy; #[derive(Clone, Hash)] pub struct Buf { @@ -26,15 +27,27 @@ pub struct Slice { pub inner: [u8] } -impl Debug for Slice { - fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { - self.to_string_lossy().fmt(formatter) +impl fmt::Debug for Slice { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(&Utf8Lossy::from_bytes(&self.inner), formatter) } } -impl Debug for Buf { - fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { - self.as_slice().fmt(formatter) +impl fmt::Display for Slice { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(&Utf8Lossy::from_bytes(&self.inner), formatter) + } +} + +impl fmt::Debug for Buf { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(self.as_slice(), formatter) + } +} + +impl fmt::Display for Buf { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(self.as_slice(), formatter) } } diff --git a/src/libstd/sys/windows/os_str.rs b/src/libstd/sys/windows/os_str.rs index f401e7b35c8d..3eb4582718b5 100644 --- a/src/libstd/sys/windows/os_str.rs +++ b/src/libstd/sys/windows/os_str.rs @@ -12,7 +12,7 @@ /// wrapper around the "WTF-8" encoding; see the `wtf8` module for more. use borrow::Cow; -use fmt::{self, Debug}; +use fmt; use sys_common::wtf8::{Wtf8, Wtf8Buf}; use mem; use sys_common::{AsInner, IntoInner}; @@ -34,9 +34,15 @@ impl AsInner for Buf { } } -impl Debug for Buf { - fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { - self.as_slice().fmt(formatter) +impl fmt::Debug for Buf { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(self.as_slice(), formatter) + } +} + +impl fmt::Display for Buf { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(self.as_slice(), formatter) } } @@ -44,9 +50,15 @@ pub struct Slice { pub inner: Wtf8 } -impl Debug for Slice { - fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { - self.inner.fmt(formatter) +impl fmt::Debug for Slice { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(&self.inner, formatter) + } +} + +impl fmt::Display for Slice { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(&self.inner, formatter) } } diff --git a/src/libstd/sys_common/wtf8.rs b/src/libstd/sys_common/wtf8.rs index df5e4ef1d886..4e4a6e77d124 100644 --- a/src/libstd/sys_common/wtf8.rs +++ b/src/libstd/sys_common/wtf8.rs @@ -39,7 +39,7 @@ use slice; use str; use sys_common::AsInner; -const UTF8_REPLACEMENT_CHARACTER: &'static [u8] = b"\xEF\xBF\xBD"; +const UTF8_REPLACEMENT_CHARACTER: &'static str = "\u{FFFD}"; /// A Unicode code point: from U+0000 to U+10FFFF. /// @@ -339,7 +339,7 @@ impl Wtf8Buf { Some((surrogate_pos, _)) => { pos = surrogate_pos + 3; self.bytes[surrogate_pos..pos] - .copy_from_slice(UTF8_REPLACEMENT_CHARACTER); + .copy_from_slice(UTF8_REPLACEMENT_CHARACTER.as_bytes()); }, None => return unsafe { String::from_utf8_unchecked(self.bytes) } } @@ -438,6 +438,30 @@ impl fmt::Debug for Wtf8 { } } +impl fmt::Display for Wtf8 { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + let wtf8_bytes = &self.bytes; + let mut pos = 0; + loop { + match self.next_surrogate(pos) { + Some((surrogate_pos, _)) => { + formatter.write_str(unsafe { + str::from_utf8_unchecked(&wtf8_bytes[pos .. surrogate_pos]) + })?; + formatter.write_str(UTF8_REPLACEMENT_CHARACTER)?; + pos = surrogate_pos + 3; + }, + None => { + formatter.write_str(unsafe { + str::from_utf8_unchecked(&wtf8_bytes[pos..]) + })?; + return Ok(()); + } + } + } + } +} + impl Wtf8 { /// Creates a WTF-8 slice from a UTF-8 `&str` slice. /// @@ -516,13 +540,13 @@ impl Wtf8 { let wtf8_bytes = &self.bytes; let mut utf8_bytes = Vec::with_capacity(self.len()); utf8_bytes.extend_from_slice(&wtf8_bytes[..surrogate_pos]); - utf8_bytes.extend_from_slice(UTF8_REPLACEMENT_CHARACTER); + utf8_bytes.extend_from_slice(UTF8_REPLACEMENT_CHARACTER.as_bytes()); let mut pos = surrogate_pos + 3; loop { match self.next_surrogate(pos) { Some((surrogate_pos, _)) => { utf8_bytes.extend_from_slice(&wtf8_bytes[pos .. surrogate_pos]); - utf8_bytes.extend_from_slice(UTF8_REPLACEMENT_CHARACTER); + utf8_bytes.extend_from_slice(UTF8_REPLACEMENT_CHARACTER.as_bytes()); pos = surrogate_pos + 3; }, None => { @@ -1200,6 +1224,20 @@ mod tests { assert_eq!(string.to_string_lossy(), expected); } + #[test] + fn wtf8_display() { + fn d(b: &[u8]) -> String { + format!("{}", &unsafe { Wtf8::from_bytes_unchecked(b) }) + } + + assert_eq!("", d("".as_bytes())); + assert_eq!("aé 💩", d("aé 💩".as_bytes())); + + let mut string = Wtf8Buf::from_str("aé 💩"); + string.push(CodePoint::from_u32(0xD800).unwrap()); + assert_eq!("aé 💩�", d(string.as_inner())); + } + #[test] fn wtf8_encode_wide() { let mut string = Wtf8Buf::from_str("aé "); From 0c26b5998d269f58c513fc55ebfdf873be02cc99 Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Mon, 12 Jun 2017 17:19:40 +0300 Subject: [PATCH 213/233] Fix condvar.wait(distant future) return immediately on OSX Fixes issue #37440: `pthread_cond_timedwait` on macOS Sierra seems to overflow `ts_sec` parameter and returns immediately. To work around this problem patch rounds timeout down to approximately 1000 years. Patch also fixes overflow when converting `u64` to `time_t`. --- src/libstd/sync/condvar.rs | 66 ++++++++++++++++++++++++++-------- src/libstd/sys/unix/condvar.rs | 34 +++++++++++++++--- 2 files changed, 81 insertions(+), 19 deletions(-) diff --git a/src/libstd/sync/condvar.rs b/src/libstd/sync/condvar.rs index c120a3045e4b..564021758176 100644 --- a/src/libstd/sync/condvar.rs +++ b/src/libstd/sync/condvar.rs @@ -480,9 +480,10 @@ impl Drop for Condvar { mod tests { use sync::mpsc::channel; use sync::{Condvar, Mutex, Arc}; + use sync::atomic::{AtomicBool, Ordering}; use thread; use time::Duration; - use u32; + use u64; #[test] fn smoke() { @@ -547,23 +548,58 @@ mod tests { #[test] #[cfg_attr(target_os = "emscripten", ignore)] - fn wait_timeout_ms() { + fn wait_timeout_wait() { let m = Arc::new(Mutex::new(())); - let m2 = m.clone(); let c = Arc::new(Condvar::new()); - let c2 = c.clone(); - let g = m.lock().unwrap(); - let (g, _no_timeout) = c.wait_timeout(g, Duration::from_millis(1)).unwrap(); - // spurious wakeups mean this isn't necessarily true - // assert!(!no_timeout); - let _t = thread::spawn(move || { - let _g = m2.lock().unwrap(); - c2.notify_one(); - }); - let (g, timeout_res) = c.wait_timeout(g, Duration::from_millis(u32::MAX as u64)).unwrap(); - assert!(!timeout_res.timed_out()); - drop(g); + loop { + let g = m.lock().unwrap(); + let (_g, no_timeout) = c.wait_timeout(g, Duration::from_millis(1)).unwrap(); + // spurious wakeups mean this isn't necessarily true + // so execute test again, if not timeout + if !no_timeout.timed_out() { + continue; + } + + break; + } + } + + #[test] + #[cfg_attr(target_os = "emscripten", ignore)] + fn wait_timeout_wake() { + let m = Arc::new(Mutex::new(())); + let c = Arc::new(Condvar::new()); + + loop { + let g = m.lock().unwrap(); + + let c2 = c.clone(); + let m2 = m.clone(); + + let notified = Arc::new(AtomicBool::new(false)); + let notified_copy = notified.clone(); + + let t = thread::spawn(move || { + let _g = m2.lock().unwrap(); + thread::sleep(Duration::from_millis(1)); + notified_copy.store(true, Ordering::SeqCst); + c2.notify_one(); + }); + let (g, timeout_res) = c.wait_timeout(g, Duration::from_millis(u64::MAX)).unwrap(); + assert!(!timeout_res.timed_out()); + // spurious wakeups mean this isn't necessarily true + // so execute test again, if not notified + if !notified.load(Ordering::SeqCst) { + t.join().unwrap(); + continue; + } + drop(g); + + t.join().unwrap(); + + break; + } } #[test] diff --git a/src/libstd/sys/unix/condvar.rs b/src/libstd/sys/unix/condvar.rs index 27b9f131d120..b9ea573b323d 100644 --- a/src/libstd/sys/unix/condvar.rs +++ b/src/libstd/sys/unix/condvar.rs @@ -23,6 +23,14 @@ const TIMESPEC_MAX: libc::timespec = libc::timespec { tv_nsec: 1_000_000_000 - 1, }; +fn saturating_cast_to_time_t(value: u64) -> libc::time_t { + if value > ::max_value() as u64 { + ::max_value() + } else { + value as libc::time_t + } +} + impl Condvar { pub const fn new() -> Condvar { // Might be moved and address is changing it is better to avoid @@ -79,8 +87,7 @@ impl Condvar { // Nanosecond calculations can't overflow because both values are below 1e9. let nsec = dur.subsec_nanos() as libc::c_long + now.tv_nsec as libc::c_long; - // FIXME: Casting u64 into time_t could truncate the value. - let sec = (dur.as_secs() as libc::time_t) + let sec = saturating_cast_to_time_t(dur.as_secs()) .checked_add((nsec / 1_000_000_000) as libc::time_t) .and_then(|s| s.checked_add(now.tv_sec)); let nsec = nsec % 1_000_000_000; @@ -100,10 +107,29 @@ impl Condvar { // https://github.com/llvm-mirror/libcxx/blob/release_35/src/condition_variable.cpp#L46 // https://github.com/llvm-mirror/libcxx/blob/release_35/include/__mutex_base#L367 #[cfg(any(target_os = "macos", target_os = "ios", target_os = "android"))] - pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool { + pub unsafe fn wait_timeout(&self, mutex: &Mutex, mut dur: Duration) -> bool { use ptr; use time::Instant; + // 1000 years + let max_dur = Duration::from_secs(1000 * 365 * 86400); + + if dur > max_dur { + // OSX implementation of `pthread_cond_timedwait` is buggy + // with super long durations. When duration is greater than + // 0x100_0000_0000_0000 seconds, `pthread_cond_timedwait` + // in macOS Sierra return error 316. + // + // This program demonstrates the issue: + // https://gist.github.com/stepancheg/198db4623a20aad2ad7cddb8fda4a63c + // + // To work around this issue, and possible bugs of other OSes, timeout + // is clamped to 1000 years, which is allowable per the API of `wait_timeout` + // because of spurious wakeups. + + dur = max_dur; + } + // First, figure out what time it currently is, in both system and // stable time. pthread_cond_timedwait uses system time, but we want to // report timeout based on stable time. @@ -116,7 +142,7 @@ impl Condvar { (sys_now.tv_usec * 1000) as libc::c_long; let extra = (nsec / 1_000_000_000) as libc::time_t; let nsec = nsec % 1_000_000_000; - let seconds = dur.as_secs() as libc::time_t; + let seconds = saturating_cast_to_time_t(dur.as_secs()); let timeout = sys_now.tv_sec.checked_add(extra).and_then(|s| { s.checked_add(seconds) From 8a2857e6449c1b90355223367fb4884adb0ba860 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 8 Jun 2017 14:45:15 +1200 Subject: [PATCH 214/233] Remove intermediate forms and some other refactoring --- src/librustc_save_analysis/data.rs | 421 -------- src/librustc_save_analysis/dump.rs | 40 - src/librustc_save_analysis/dump_visitor.rs | 998 ++++++++---------- src/librustc_save_analysis/external_data.rs | 748 ------------- src/librustc_save_analysis/json_api_dumper.rs | 310 +----- src/librustc_save_analysis/json_dumper.rs | 401 +------ src/librustc_save_analysis/lib.rs | 622 ++++++----- src/librustc_save_analysis/span_utils.rs | 127 +-- 8 files changed, 841 insertions(+), 2826 deletions(-) delete mode 100644 src/librustc_save_analysis/data.rs delete mode 100644 src/librustc_save_analysis/dump.rs delete mode 100644 src/librustc_save_analysis/external_data.rs diff --git a/src/librustc_save_analysis/data.rs b/src/librustc_save_analysis/data.rs deleted file mode 100644 index e15e3f6e79e2..000000000000 --- a/src/librustc_save_analysis/data.rs +++ /dev/null @@ -1,421 +0,0 @@ -// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Structs representing the analysis data from a crate. -//! -//! The `Dump` trait can be used together with `DumpVisitor` in order to -//! retrieve the data from a crate. - -use rustc::hir; -use rustc::hir::def_id::{CrateNum, DefId}; -use syntax::ast::{self, Attribute, NodeId}; -use syntax_pos::Span; - -use rls_data::{ExternalCrateData, Signature}; - -pub struct CrateData { - pub name: String, - pub number: u32, - pub span: Span, -} - -/// Data for any entity in the Rust language. The actual data contained varies -/// with the kind of entity being queried. See the nested structs for details. -#[derive(Debug)] -pub enum Data { - /// Data for Enums. - EnumData(EnumData), - /// Data for extern crates. - ExternCrateData(ExternCrateData), - /// Data about a function call. - FunctionCallData(FunctionCallData), - /// Data for all kinds of functions and methods. - FunctionData(FunctionData), - /// Data about a function ref. - FunctionRefData(FunctionRefData), - /// Data for impls. - ImplData(ImplData2), - /// Data for trait inheritance. - InheritanceData(InheritanceData), - /// Data about a macro declaration. - MacroData(MacroData), - /// Data about a macro use. - MacroUseData(MacroUseData), - /// Data about a method call. - MethodCallData(MethodCallData), - /// Data for method declarations (methods with a body are treated as functions). - MethodData(MethodData), - /// Data for modules. - ModData(ModData), - /// Data for a reference to a module. - ModRefData(ModRefData), - /// Data for a struct declaration. - StructData(StructData), - /// Data for a struct variant. - StructVariantDat(StructVariantData), - /// Data for a trait declaration. - TraitData(TraitData), - /// Data for a tuple variant. - TupleVariantData(TupleVariantData), - /// Data for a typedef. - TypeDefData(TypeDefData), - /// Data for a reference to a type or trait. - TypeRefData(TypeRefData), - /// Data for a use statement. - UseData(UseData), - /// Data for a global use statement. - UseGlobData(UseGlobData), - /// Data for local and global variables (consts and statics), and fields. - VariableData(VariableData), - /// Data for the use of some variable (e.g., the use of a local variable, which - /// will refere to that variables declaration). - VariableRefData(VariableRefData), -} - -#[derive(Eq, PartialEq, Clone, Copy, Debug)] -pub enum Visibility { - Public, - Restricted, - Inherited, -} - -impl<'a> From<&'a ast::Visibility> for Visibility { - fn from(v: &'a ast::Visibility) -> Visibility { - match *v { - ast::Visibility::Public => Visibility::Public, - ast::Visibility::Crate(_) => Visibility::Restricted, - ast::Visibility::Restricted { .. } => Visibility::Restricted, - ast::Visibility::Inherited => Visibility::Inherited, - } - } -} - -impl<'a> From<&'a hir::Visibility> for Visibility { - fn from(v: &'a hir::Visibility) -> Visibility { - match *v { - hir::Visibility::Public => Visibility::Public, - hir::Visibility::Crate => Visibility::Restricted, - hir::Visibility::Restricted { .. } => Visibility::Restricted, - hir::Visibility::Inherited => Visibility::Inherited, - } - } -} - -/// Data for the prelude of a crate. -#[derive(Debug)] -pub struct CratePreludeData { - pub crate_name: String, - pub crate_root: String, - pub external_crates: Vec, - pub span: Span, -} - -/// Data for enum declarations. -#[derive(Clone, Debug)] -pub struct EnumData { - pub id: NodeId, - pub name: String, - pub value: String, - pub qualname: String, - pub span: Span, - pub scope: NodeId, - pub variants: Vec, - pub visibility: Visibility, - pub docs: String, - pub sig: Option, - pub attributes: Vec, -} - -/// Data for extern crates. -#[derive(Debug)] -pub struct ExternCrateData { - pub id: NodeId, - pub name: String, - pub crate_num: CrateNum, - pub location: String, - pub span: Span, - pub scope: NodeId, -} - -/// Data about a function call. -#[derive(Debug)] -pub struct FunctionCallData { - pub span: Span, - pub scope: NodeId, - pub ref_id: DefId, -} - -/// Data for all kinds of functions and methods. -#[derive(Clone, Debug)] -pub struct FunctionData { - pub id: NodeId, - pub name: String, - pub qualname: String, - pub declaration: Option, - pub span: Span, - pub scope: NodeId, - pub value: String, - pub visibility: Visibility, - pub parent: Option, - pub docs: String, - pub sig: Option, - pub attributes: Vec, -} - -/// Data about a function call. -#[derive(Debug)] -pub struct FunctionRefData { - pub span: Span, - pub scope: NodeId, - pub ref_id: DefId, -} - -#[derive(Debug)] -pub struct ImplData { - pub id: NodeId, - pub span: Span, - pub scope: NodeId, - pub trait_ref: Option, - pub self_ref: Option, -} - -#[derive(Debug)] -// FIXME: this struct should not exist. However, removing it requires heavy -// refactoring of dump_visitor.rs. See PR 31838 for more info. -pub struct ImplData2 { - pub id: NodeId, - pub span: Span, - pub scope: NodeId, - // FIXME: I'm not really sure inline data is the best way to do this. Seems - // OK in this case, but generalising leads to returning chunks of AST, which - // feels wrong. - pub trait_ref: Option, - pub self_ref: Option, -} - -#[derive(Debug)] -pub struct InheritanceData { - pub span: Span, - pub base_id: DefId, - pub deriv_id: NodeId -} - -/// Data about a macro declaration. -#[derive(Debug)] -pub struct MacroData { - pub span: Span, - pub name: String, - pub qualname: String, - pub docs: String, -} - -/// Data about a macro use. -#[derive(Debug)] -pub struct MacroUseData { - pub span: Span, - pub name: String, - pub qualname: String, - // Because macro expansion happens before ref-ids are determined, - // we use the callee span to reference the associated macro definition. - pub callee_span: Span, - pub scope: NodeId, - pub imported: bool, -} - -/// Data about a method call. -#[derive(Debug)] -pub struct MethodCallData { - pub span: Span, - pub scope: NodeId, - pub ref_id: Option, - pub decl_id: Option, -} - -/// Data for method declarations (methods with a body are treated as functions). -#[derive(Clone, Debug)] -pub struct MethodData { - pub id: NodeId, - pub name: String, - pub qualname: String, - pub span: Span, - pub scope: NodeId, - pub value: String, - pub decl_id: Option, - pub parent: Option, - pub visibility: Visibility, - pub docs: String, - pub sig: Option, - pub attributes: Vec, -} - -/// Data for modules. -#[derive(Debug)] -pub struct ModData { - pub id: NodeId, - pub name: String, - pub qualname: String, - pub span: Span, - pub scope: NodeId, - pub filename: String, - pub items: Vec, - pub visibility: Visibility, - pub docs: String, - pub sig: Option, - pub attributes: Vec, -} - -/// Data for a reference to a module. -#[derive(Debug)] -pub struct ModRefData { - pub span: Span, - pub scope: NodeId, - pub ref_id: Option, - pub qualname: String -} - -#[derive(Debug)] -pub struct StructData { - pub span: Span, - pub name: String, - pub id: NodeId, - pub ctor_id: NodeId, - pub qualname: String, - pub scope: NodeId, - pub value: String, - pub fields: Vec, - pub visibility: Visibility, - pub docs: String, - pub sig: Option, - pub attributes: Vec, -} - -#[derive(Debug)] -pub struct StructVariantData { - pub span: Span, - pub name: String, - pub id: NodeId, - pub qualname: String, - pub type_value: String, - pub value: String, - pub scope: NodeId, - pub parent: Option, - pub docs: String, - pub sig: Option, - pub attributes: Vec, -} - -#[derive(Debug)] -pub struct TraitData { - pub span: Span, - pub id: NodeId, - pub name: String, - pub qualname: String, - pub scope: NodeId, - pub value: String, - pub items: Vec, - pub visibility: Visibility, - pub docs: String, - pub sig: Option, - pub attributes: Vec, -} - -#[derive(Debug)] -pub struct TupleVariantData { - pub span: Span, - pub id: NodeId, - pub name: String, - pub qualname: String, - pub type_value: String, - pub value: String, - pub scope: NodeId, - pub parent: Option, - pub docs: String, - pub sig: Option, - pub attributes: Vec, -} - -/// Data for a typedef. -#[derive(Debug)] -pub struct TypeDefData { - pub id: NodeId, - pub name: String, - pub span: Span, - pub qualname: String, - pub value: String, - pub visibility: Visibility, - pub parent: Option, - pub docs: String, - pub sig: Option, - pub attributes: Vec, -} - -/// Data for a reference to a type or trait. -#[derive(Clone, Debug)] -pub struct TypeRefData { - pub span: Span, - pub scope: NodeId, - pub ref_id: Option, - pub qualname: String, -} - -#[derive(Debug)] -pub struct UseData { - pub id: NodeId, - pub span: Span, - pub name: String, - pub mod_id: Option, - pub scope: NodeId, - pub visibility: Visibility, -} - -#[derive(Debug)] -pub struct UseGlobData { - pub id: NodeId, - pub span: Span, - pub names: Vec, - pub scope: NodeId, - pub visibility: Visibility, -} - -/// Data for local and global variables (consts and statics). -#[derive(Debug)] -pub struct VariableData { - pub id: NodeId, - pub kind: VariableKind, - pub name: String, - pub qualname: String, - pub span: Span, - pub scope: NodeId, - pub parent: Option, - pub value: String, - pub type_value: String, - pub visibility: Visibility, - pub docs: String, - pub sig: Option, - pub attributes: Vec, -} - -#[derive(Debug)] -pub enum VariableKind { - Static, - Const, - Local, - Field, -} - -/// Data for the use of some item (e.g., the use of a local variable, which -/// will refer to that variables declaration (by ref_id)). -#[derive(Debug)] -pub struct VariableRefData { - pub name: String, - pub span: Span, - pub scope: NodeId, - pub ref_id: DefId, -} diff --git a/src/librustc_save_analysis/dump.rs b/src/librustc_save_analysis/dump.rs deleted file mode 100644 index 795ff58e2060..000000000000 --- a/src/librustc_save_analysis/dump.rs +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use super::external_data::*; - -use rls_data::CratePreludeData; - -pub trait Dump { - fn crate_prelude(&mut self, _: CratePreludeData) {} - fn enum_data(&mut self, _: EnumData) {} - fn extern_crate(&mut self, _: ExternCrateData) {} - fn impl_data(&mut self, _: ImplData) {} - fn inheritance(&mut self, _: InheritanceData) {} - fn function(&mut self, _: FunctionData) {} - fn function_ref(&mut self, _: FunctionRefData) {} - fn function_call(&mut self, _: FunctionCallData) {} - fn method(&mut self, _: MethodData) {} - fn method_call(&mut self, _: MethodCallData) {} - fn macro_data(&mut self, _: MacroData) {} - fn macro_use(&mut self, _: MacroUseData) {} - fn mod_data(&mut self, _: ModData) {} - fn mod_ref(&mut self, _: ModRefData) {} - fn struct_data(&mut self, _: StructData) {} - fn struct_variant(&mut self, _: StructVariantData) {} - fn trait_data(&mut self, _: TraitData) {} - fn tuple_variant(&mut self, _: TupleVariantData) {} - fn type_ref(&mut self, _: TypeRefData) {} - fn typedef(&mut self, _: TypeDefData) {} - fn use_data(&mut self, _: UseData) {} - fn use_glob(&mut self, _: UseGlobData) {} - fn variable(&mut self, _: VariableData) {} - fn variable_ref(&mut self, _: VariableRefData) {} -} diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index ea346d99e31b..cc33d3db8eba 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -8,10 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Write the output of rustc's analysis to an implementor of Dump. The data is -//! primarily designed to be used as input to the DXR tool, specifically its -//! Rust plugin. It could also be used by IDEs or other code browsing, search, or -//! cross-referencing tools. +//! Write the output of rustc's analysis to an implementor of Dump. //! //! Dumping the analysis is implemented by walking the AST and getting a bunch of //! info out from all over the place. We use Def IDs to identify objects. The @@ -27,16 +24,12 @@ //! is used for recording the output in a format-agnostic way (see CsvDumper //! for an example). -use rustc::hir; -use rustc::hir::def::Def; -use rustc::hir::def_id::{DefId, LOCAL_CRATE}; -use rustc::hir::map::{Node, NodeItem}; +use rustc::hir::def::Def as HirDef; +use rustc::hir::def_id::DefId; +use rustc::hir::map::Node; use rustc::session::Session; -use rustc::ty::{self, TyCtxt, AssociatedItemContainer}; +use rustc::ty::{self, TyCtxt}; -use std::collections::HashSet; -use std::collections::hash_map::DefaultHasher; -use std::hash::*; use std::path::Path; use syntax::ast::{self, NodeId, PatKind, Attribute, CRATE_NODE_ID}; @@ -48,15 +41,12 @@ use syntax::ptr::P; use syntax::codemap::Spanned; use syntax_pos::*; -use {escape, generated_code, SaveContext, PathCollector, docs_for_attrs}; -use data::*; -use dump::Dump; -use external_data::{Lower, make_def_id}; -use recorder; +use {escape, generated_code, SaveContext, PathCollector, docs_for_attrs, lower_attributes, Dump}; use span_utils::SpanUtils; use sig; -use rls_data::ExternalCrateData; +use rls_data::{CratePreludeData, Import, ImportKind, SpanData, Ref, RefKind, + Def, DefKind, Relation, RelationKind}; macro_rules! down_cast_data { ($id:ident, $kind:ident, $sp:expr) => { @@ -82,8 +72,7 @@ pub struct DumpVisitor<'l, 'tcx: 'l, 'll, D: 'll> { // of macro use (callsite) spans. We store these to ensure // we only write one macro def per unique macro definition, and // one macro use per unique callsite span. - mac_defs: HashSet, - mac_uses: HashSet, + // mac_defs: HashSet, } impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { @@ -98,8 +87,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { dumper: dumper, span: span_utils.clone(), cur_scope: CRATE_NODE_ID, - mac_defs: HashSet::new(), - mac_uses: HashSet::new(), + // mac_defs: HashSet::new(), } } @@ -127,6 +115,10 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { } } + fn span_from_span(&self, span: Span) -> SpanData { + self.save_ctxt.span_from_span(span) + } + pub fn dump_crate_info(&mut self, name: &str, krate: &ast::Crate) { let source_file = self.tcx.sess.local_crate_source_file.as_ref(); let crate_root = source_file.map(|source_file| { @@ -137,25 +129,14 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { } }); - // Info about all the external crates referenced from this crate. - let external_crates = self.save_ctxt.get_external_crates().into_iter().map(|c| { - let lo_loc = self.span.sess.codemap().lookup_char_pos(c.span.lo); - ExternalCrateData { - name: c.name, - num: c.number, - file_name: SpanUtils::make_path_string(&lo_loc.file.name), - } - }).collect(); - - // The current crate. let data = CratePreludeData { crate_name: name.into(), crate_root: crate_root.unwrap_or("".to_owned()), - external_crates: external_crates, - span: krate.span, + external_crates: self.save_ctxt.get_external_crates(), + span: self.span_from_span(krate.span), }; - self.dumper.crate_prelude(data.lower(self.tcx)); + self.dumper.crate_prelude(data); } // Return all non-empty prefixes of a path. @@ -211,13 +192,13 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { fn write_sub_paths(&mut self, path: &ast::Path) { let sub_paths = self.process_path_prefixes(path); - for (span, qualname) in sub_paths { - self.dumper.mod_ref(ModRefData { - span: span, - qualname: qualname, - scope: self.cur_scope, - ref_id: None - }.lower(self.tcx)); + for (span, _) in sub_paths { + let span = self.span_from_span(span); + self.dumper.dump_ref(Ref { + kind: RefKind::Mod, + span, + ref_id: ::null_id(), + }); } } @@ -230,13 +211,13 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { return; } - for (span, qualname) in sub_paths.into_iter().take(len - 1) { - self.dumper.mod_ref(ModRefData { - span: span, - qualname: qualname, - scope: self.cur_scope, - ref_id: None - }.lower(self.tcx)); + for (span, _) in sub_paths.into_iter().take(len - 1) { + let span = self.span_from_span(span); + self.dumper.dump_ref(Ref { + kind: RefKind::Mod, + span, + ref_id: ::null_id(), + }); } } @@ -251,32 +232,32 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { let sub_paths = &sub_paths[.. (len-1)]; // write the trait part of the sub-path - let (ref span, ref qualname) = sub_paths[len-2]; - self.dumper.type_ref(TypeRefData { - ref_id: None, - span: *span, - qualname: qualname.to_owned(), - scope: CRATE_NODE_ID - }.lower(self.tcx)); + let (ref span, _) = sub_paths[len-2]; + let span = self.span_from_span(*span); + self.dumper.dump_ref(Ref { + kind: RefKind::Type, + ref_id: ::null_id(), + span, + }); // write the other sub-paths if len <= 2 { return; } let sub_paths = &sub_paths[..len-2]; - for &(ref span, ref qualname) in sub_paths { - self.dumper.mod_ref(ModRefData { - span: *span, - qualname: qualname.to_owned(), - scope: self.cur_scope, - ref_id: None - }.lower(self.tcx)); + for &(ref span, _) in sub_paths { + let span = self.span_from_span(*span); + self.dumper.dump_ref(Ref { + kind: RefKind::Mod, + span, + ref_id: ::null_id(), + }); } } fn lookup_def_id(&self, ref_id: NodeId) -> Option { match self.save_ctxt.get_path_def(ref_id) { - Def::PrimTy(..) | Def::SelfTy(..) | Def::Err => None, + HirDef::PrimTy(..) | HirDef::SelfTy(..) | HirDef::Err => None, def => Some(def.def_id()), } } @@ -285,67 +266,67 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { ref_id: NodeId, span: Span, sub_span: Option, - def_id: DefId, - scope: NodeId) { + def_id: DefId) { if self.span.filter_generated(sub_span, span) { return; } let def = self.save_ctxt.get_path_def(ref_id); match def { - Def::Mod(_) => { - self.dumper.mod_ref(ModRefData { - span: sub_span.expect("No span found for mod ref"), - ref_id: Some(def_id), - scope: scope, - qualname: String::new() - }.lower(self.tcx)); + HirDef::Mod(_) => { + let span = self.span_from_span(sub_span.expect("No span found for mod ref")); + self.dumper.dump_ref(Ref { + kind: RefKind::Mod, + span, + ref_id: ::id_from_def_id(def_id), + }); } - Def::Struct(..) | - Def::Variant(..) | - Def::Union(..) | - Def::Enum(..) | - Def::TyAlias(..) | - Def::Trait(_) => { - self.dumper.type_ref(TypeRefData { - span: sub_span.expect("No span found for type ref"), - ref_id: Some(def_id), - scope: scope, - qualname: String::new() - }.lower(self.tcx)); + HirDef::Struct(..) | + HirDef::Variant(..) | + HirDef::Union(..) | + HirDef::Enum(..) | + HirDef::TyAlias(..) | + HirDef::Trait(_) => { + let span = self.span_from_span(sub_span.expect("No span found for type ref")); + self.dumper.dump_ref(Ref { + kind: RefKind::Type, + span, + ref_id: ::id_from_def_id(def_id), + }); } - Def::Static(..) | - Def::Const(..) | - Def::StructCtor(..) | - Def::VariantCtor(..) => { - self.dumper.variable_ref(VariableRefData { - span: sub_span.expect("No span found for var ref"), - ref_id: def_id, - scope: scope, - name: String::new() - }.lower(self.tcx)); + HirDef::Static(..) | + HirDef::Const(..) | + HirDef::StructCtor(..) | + HirDef::VariantCtor(..) => { + let span = self.span_from_span(sub_span.expect("No span found for var ref")); + self.dumper.dump_ref(Ref { + kind: RefKind::Variable, + span, + ref_id: ::id_from_def_id(def_id), + }); } - Def::Fn(..) => { - self.dumper.function_ref(FunctionRefData { - span: sub_span.expect("No span found for fn ref"), - ref_id: def_id, - scope: scope - }.lower(self.tcx)); + HirDef::Fn(..) => { + let span = self.span_from_span(sub_span.expect("No span found for fn ref")); + self.dumper.dump_ref(Ref { + kind: RefKind::Function, + span, + ref_id: ::id_from_def_id(def_id), + }); } // With macros 2.0, we can legitimately get a ref to a macro, but // we don't handle it properly for now (FIXME). - Def::Macro(..) => {} - Def::Local(..) | - Def::Upvar(..) | - Def::SelfTy(..) | - Def::Label(_) | - Def::TyParam(..) | - Def::Method(..) | - Def::AssociatedTy(..) | - Def::AssociatedConst(..) | - Def::PrimTy(_) | - Def::GlobalAsm(_) | - Def::Err => { + HirDef::Macro(..) => {} + HirDef::Local(..) | + HirDef::Upvar(..) | + HirDef::SelfTy(..) | + HirDef::Label(_) | + HirDef::TyParam(..) | + HirDef::Method(..) | + HirDef::AssociatedTy(..) | + HirDef::AssociatedConst(..) | + HirDef::PrimTy(_) | + HirDef::GlobalAsm(_) | + HirDef::Err => { span_bug!(span, "process_def_kind for unexpected item: {:?}", def); @@ -368,21 +349,23 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { // variable name, but who knows?) let sub_span = span_utils.span_for_last_ident(p.span); if !self.span.filter_generated(sub_span, p.span) { - self.dumper.variable(VariableData { - id: id, - kind: VariableKind::Local, - span: sub_span.expect("No span found for variable"), + let id = ::id_from_node_id(id, &self.save_ctxt); + let span = self.span_from_span(sub_span.expect("No span found for variable")); + + self.dumper.dump_def(false, Def { + kind: DefKind::Local, + id, + span, name: path_to_string(p), qualname: format!("{}::{}", qualname, path_to_string(p)), - type_value: typ, - value: String::new(), - scope: CRATE_NODE_ID, + value: typ, parent: None, - visibility: Visibility::Inherited, + children: vec![], + decl_id: None, docs: String::new(), sig: None, - attributes: vec![], - }.lower(self.tcx)); + attributes:vec![], + }); } } } @@ -393,12 +376,11 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { body: Option<&'l ast::Block>, id: ast::NodeId, name: ast::Ident, - vis: Visibility, - attrs: &'l [Attribute], + vis: ast::Visibility, span: Span) { debug!("process_method: {}:{}", id, name); - if let Some(method_data) = self.save_ctxt.get_method_data(id, name.name, span) { + if let Some(mut method_data) = self.save_ctxt.get_method_data(id, name.name, span) { let sig_str = ::make_signature(&sig.decl, &sig.generics); if body.is_some() { @@ -407,61 +389,11 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { }); } - // If the method is defined in an impl, then try and find the corresponding - // method decl in a trait, and if there is one, make a decl_id for it. This - // requires looking up the impl, then the trait, then searching for a method - // with the right name. - if !self.span.filter_generated(Some(method_data.span), span) { - let container = - self.tcx.associated_item(self.tcx.hir.local_def_id(id)).container; - let mut trait_id; - let mut decl_id = None; - match container { - AssociatedItemContainer::ImplContainer(id) => { - trait_id = self.tcx.trait_id_of_impl(id); - - match trait_id { - Some(id) => { - for item in self.tcx.associated_items(id) { - if item.kind == ty::AssociatedKind::Method { - if item.name == name.name { - decl_id = Some(item.def_id); - break; - } - } - } - } - None => { - if let Some(NodeItem(item)) = self.tcx.hir.get_if_local(id) { - if let hir::ItemImpl(_, _, _, _, _, ref ty, _) = item.node { - trait_id = self.lookup_def_id(ty.id); - } - } - } - } - } - AssociatedItemContainer::TraitContainer(id) => { - trait_id = Some(id); - } - } - - self.dumper.method(MethodData { - id: method_data.id, - name: method_data.name, - span: method_data.span, - scope: method_data.scope, - qualname: method_data.qualname.clone(), - value: sig_str, - decl_id: decl_id, - parent: trait_id, - visibility: vis, - docs: docs_for_attrs(attrs), - sig: sig::method_signature(id, name, sig, &self.save_ctxt), - attributes: attrs.to_vec(), - }.lower(self.tcx)); - } - self.process_generic_params(&sig.generics, span, &method_data.qualname, id); + + method_data.value = sig_str; + method_data.sig = sig::method_signature(id, name, sig, &self.save_ctxt); + self.dumper.dump_def(vis == ast::Visibility::Public, method_data); } // walk arg and return types @@ -480,22 +412,17 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { } fn process_trait_ref(&mut self, trait_ref: &'l ast::TraitRef) { - let trait_ref_data = self.save_ctxt.get_trait_ref_data(trait_ref, self.cur_scope); + let trait_ref_data = self.save_ctxt.get_trait_ref_data(trait_ref); if let Some(trait_ref_data) = trait_ref_data { - if !self.span.filter_generated(Some(trait_ref_data.span), trait_ref.path.span) { - self.dumper.type_ref(trait_ref_data.lower(self.tcx)); - } + self.dumper.dump_ref(trait_ref_data); } - self.process_path(trait_ref.ref_id, &trait_ref.path, Some(recorder::TypeRef)); + self.process_path(trait_ref.ref_id, &trait_ref.path); } fn process_struct_field_def(&mut self, field: &ast::StructField, parent_id: NodeId) { let field_data = self.save_ctxt.get_field_data(field, parent_id); - if let Some(mut field_data) = field_data { - if !self.span.filter_generated(Some(field_data.span), field.span) { - field_data.value = String::new(); - self.dumper.variable(field_data.lower(self.tcx)); - } + if let Some(field_data) = field_data { + self.dumper.dump_def(field.vis == ast::Visibility::Public, field_data); } } @@ -519,18 +446,23 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { name, id); if !self.span.filter_generated(Some(param_ss), full_span) { - self.dumper.typedef(TypeDefData { - span: param_ss, - name: name, - id: param.id, - qualname: qualname, + let id = ::id_from_node_id(param.id, &self.save_ctxt); + let span = self.span_from_span(param_ss); + + self.dumper.dump_def(false, Def { + kind: DefKind::Type, + id, + span, + name, + qualname, value: String::new(), - visibility: Visibility::Inherited, parent: None, + children: vec![], + decl_id: None, docs: String::new(), sig: None, attributes: vec![], - }.lower(self.tcx)); + }); } } self.visit_generics(generics); @@ -542,13 +474,10 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { ty_params: &'l ast::Generics, body: &'l ast::Block) { if let Some(fn_data) = self.save_ctxt.get_item_data(item) { - down_cast_data!(fn_data, FunctionData, item.span); - if !self.span.filter_generated(Some(fn_data.span), item.span) { - self.dumper.function(fn_data.clone().lower(self.tcx)); - } - + down_cast_data!(fn_data, DefData, item.span); self.nest_tables(item.id, |v| v.process_formals(&decl.inputs, &fn_data.qualname)); self.process_generic_params(ty_params, item.span, &fn_data.qualname, item.id); + self.dumper.dump_def(item.vis == ast::Visibility::Public, fn_data); } for arg in &decl.inputs { @@ -567,10 +496,8 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { typ: &'l ast::Ty, expr: &'l ast::Expr) { if let Some(var_data) = self.save_ctxt.get_item_data(item) { - down_cast_data!(var_data, VariableData, item.span); - if !self.span.filter_generated(Some(var_data.span), item.span) { - self.dumper.variable(var_data.lower(self.tcx)); - } + down_cast_data!(var_data, DefData, item.span); + self.dumper.dump_def(item.vis == ast::Visibility::Public, var_data); } self.visit_ty(&typ); self.visit_expr(expr); @@ -583,29 +510,31 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { typ: &'l ast::Ty, expr: Option<&'l ast::Expr>, parent_id: DefId, - vis: Visibility, + vis: ast::Visibility, attrs: &'l [Attribute]) { let qualname = format!("::{}", self.tcx.node_path_str(id)); let sub_span = self.span.sub_span_after_keyword(span, keywords::Const); - let value = expr.map(|e| self.span.snippet(e.span)).unwrap_or(String::new()); if !self.span.filter_generated(sub_span, span) { - self.dumper.variable(VariableData { - span: sub_span.expect("No span found for variable"), - kind: VariableKind::Const, - id: id, + let sig = sig::assoc_const_signature(id, name, typ, expr, &self.save_ctxt); + let id = ::id_from_node_id(id, &self.save_ctxt); + let span = self.span_from_span(sub_span.expect("No span found for variable")); + + self.dumper.dump_def(vis == ast::Visibility::Public, Def { + kind: DefKind::Const, + id, + span, name: name.to_string(), - qualname: qualname, - value: value, - type_value: ty_to_string(&typ), - scope: self.cur_scope, - parent: Some(parent_id), - visibility: vis, + qualname, + value: ty_to_string(&typ), + parent: Some(::id_from_def_id(parent_id)), + children: vec![], + decl_id: None, docs: docs_for_attrs(attrs), - sig: sig::assoc_const_signature(id, name, typ, expr, &self.save_ctxt), - attributes: attrs.to_vec(), - }.lower(self.tcx)); + sig, + attributes: lower_attributes(attrs.to_owned(), &self.save_ctxt), + }); } // walk type and init value @@ -624,7 +553,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { let qualname = format!("::{}", self.tcx.node_path_str(item.id)); let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Struct); - let (val, fields) = + let (value, fields) = if let ast::ItemKind::Struct(ast::VariantData::Struct(ref fields, _), _) = item.node { let fields_str = fields.iter() @@ -633,26 +562,28 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { .unwrap_or(i.to_string())) .collect::>() .join(", "); - (format!("{} {{ {} }}", name, fields_str), fields.iter().map(|f| f.id).collect()) + (format!("{} {{ {} }}", name, fields_str), + fields.iter().map(|f| ::id_from_node_id(f.id, &self.save_ctxt)).collect()) } else { (String::new(), vec![]) }; if !self.span.filter_generated(sub_span, item.span) { - self.dumper.struct_data(StructData { - span: sub_span.expect("No span found for struct"), - id: item.id, - name: name, - ctor_id: def.id(), + let span = self.span_from_span(sub_span.expect("No span found for struct")); + self.dumper.dump_def(item.vis == ast::Visibility::Public, Def { + kind: DefKind::Struct, + id: ::id_from_node_id(item.id, &self.save_ctxt), + span, + name, qualname: qualname.clone(), - scope: self.cur_scope, - value: val, - fields: fields, - visibility: From::from(&item.vis), + value, + parent: None, + children: fields, + decl_id: None, docs: docs_for_attrs(&item.attrs), sig: sig::item_signature(item, &self.save_ctxt), - attributes: item.attrs.clone(), - }.lower(self.tcx)); + attributes: lower_attributes(item.attrs.clone(), &self.save_ctxt), + }); } for field in def.fields() { @@ -672,10 +603,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { None => return, Some(data) => data, }; - down_cast_data!(enum_data, EnumData, item.span); - if !self.span.filter_generated(Some(enum_data.span), item.span) { - self.dumper.enum_data(enum_data.clone().lower(self.tcx)); - } + down_cast_data!(enum_data, DefData, item.span); for variant in &enum_definition.variants { let name = variant.node.name.name.to_string(); @@ -692,48 +620,62 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { .unwrap_or(i.to_string())) .collect::>() .join(", "); - let val = format!("{}::{} {{ {} }}", enum_data.name, name, fields_str); + let value = format!("{}::{} {{ {} }}", enum_data.name, name, fields_str); if !self.span.filter_generated(sub_span, variant.span) { - self.dumper.struct_variant(StructVariantData { - span: sub_span.expect("No span found for struct variant"), - id: variant.node.data.id(), - name: name, - qualname: qualname, - type_value: enum_data.qualname.clone(), - value: val, - scope: enum_data.scope, - parent: Some(make_def_id(item.id, &self.tcx.hir)), + let span = self.span_from_span( + sub_span.expect("No span found for struct variant")); + let id = ::id_from_node_id(variant.node.data.id(), &self.save_ctxt); + let parent = Some(::id_from_node_id(item.id, &self.save_ctxt)); + + self.dumper.dump_def(item.vis == ast::Visibility::Public, Def { + kind: DefKind::Struct, + id, + span, + name, + qualname, + value, + parent, + children: vec![], + decl_id: None, docs: docs_for_attrs(&variant.node.attrs), sig: sig::variant_signature(variant, &self.save_ctxt), - attributes: variant.node.attrs.clone(), - }.lower(self.tcx)); + attributes: lower_attributes(variant.node.attrs.clone(), + &self.save_ctxt), + }); } } ref v => { let sub_span = self.span.span_for_first_ident(variant.span); - let mut val = format!("{}::{}", enum_data.name, name); + let mut value = format!("{}::{}", enum_data.name, name); if let &ast::VariantData::Tuple(ref fields, _) = v { - val.push('('); - val.push_str(&fields.iter() - .map(|f| ty_to_string(&f.ty)) - .collect::>() - .join(", ")); - val.push(')'); + value.push('('); + value.push_str(&fields.iter() + .map(|f| ty_to_string(&f.ty)) + .collect::>() + .join(", ")); + value.push(')'); } if !self.span.filter_generated(sub_span, variant.span) { - self.dumper.tuple_variant(TupleVariantData { - span: sub_span.expect("No span found for tuple variant"), - id: variant.node.data.id(), - name: name, - qualname: qualname, - type_value: enum_data.qualname.clone(), - value: val, - scope: enum_data.scope, - parent: Some(make_def_id(item.id, &self.tcx.hir)), + let span = + self.span_from_span(sub_span.expect("No span found for tuple variant")); + let id = ::id_from_node_id(variant.node.data.id(), &self.save_ctxt); + let parent = Some(::id_from_node_id(item.id, &self.save_ctxt)); + + self.dumper.dump_def(item.vis == ast::Visibility::Public, Def { + kind: DefKind::Tuple, + id, + span, + name, + qualname, + value, + parent, + children: vec![], + decl_id: None, docs: docs_for_attrs(&variant.node.attrs), sig: sig::variant_signature(variant, &self.save_ctxt), - attributes: variant.node.attrs.clone(), - }.lower(self.tcx)); + attributes: lower_attributes(variant.node.attrs.clone(), + &self.save_ctxt), + }); } } } @@ -744,7 +686,8 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { self.visit_ty(&field.ty); } } - self.process_generic_params(ty_params, item.span, &enum_data.qualname, enum_data.id); + self.process_generic_params(ty_params, item.span, &enum_data.qualname, item.id); + self.dumper.dump_def(item.vis == ast::Visibility::Public, enum_data); } fn process_impl(&mut self, @@ -754,25 +697,17 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { typ: &'l ast::Ty, impl_items: &'l [ast::ImplItem]) { if let Some(impl_data) = self.save_ctxt.get_item_data(item) { - down_cast_data!(impl_data, ImplData, item.span); - if !self.span.filter_generated(Some(impl_data.span), item.span) { - self.dumper.impl_data(ImplData { - id: impl_data.id, - span: impl_data.span, - scope: impl_data.scope, - trait_ref: impl_data.trait_ref.map(|d| d.ref_id.unwrap()), - self_ref: impl_data.self_ref.map(|d| d.ref_id.unwrap()) - }.lower(self.tcx)); - } + down_cast_data!(impl_data, RelationData, item.span); + self.dumper.dump_relation(impl_data); } self.visit_ty(&typ); if let &Some(ref trait_ref) = trait_ref { - self.process_path(trait_ref.ref_id, &trait_ref.path, Some(recorder::TypeRef)); + self.process_path(trait_ref.ref_id, &trait_ref.path); } self.process_generic_params(type_parameters, item.span, "", item.id); for impl_item in impl_items { let map = &self.tcx.hir; - self.process_impl_item(impl_item, make_def_id(item.id, map)); + self.process_impl_item(impl_item, map.local_def_id(item.id)); } } @@ -793,19 +728,24 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { } let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Trait); if !self.span.filter_generated(sub_span, item.span) { - self.dumper.trait_data(TraitData { - span: sub_span.expect("No span found for trait"), - id: item.id, - name: name, + let id = ::id_from_node_id(item.id, &self.save_ctxt); + let span = self.span_from_span(sub_span.expect("No span found for trait")); + let children = + methods.iter().map(|i| ::id_from_node_id(i.id, &self.save_ctxt)).collect(); + self.dumper.dump_def(item.vis == ast::Visibility::Public, Def { + kind: DefKind::Trait, + id, + span, + name, qualname: qualname.clone(), - scope: self.cur_scope, value: val, - items: methods.iter().map(|i| i.id).collect(), - visibility: From::from(&item.vis), + parent: None, + children, + decl_id: None, docs: docs_for_attrs(&item.attrs), sig: sig::item_signature(item, &self.save_ctxt), - attributes: item.attrs.clone(), - }.lower(self.tcx)); + attributes: lower_attributes(item.attrs.clone(), &self.save_ctxt), + }); } // super-traits @@ -823,21 +763,22 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { if let Some(id) = self.lookup_def_id(trait_ref.ref_id) { let sub_span = self.span.sub_span_for_type_name(trait_ref.path.span); if !self.span.filter_generated(sub_span, trait_ref.path.span) { - self.dumper.type_ref(TypeRefData { - span: sub_span.expect("No span found for trait ref"), - ref_id: Some(id), - scope: self.cur_scope, - qualname: String::new() - }.lower(self.tcx)); + let span = self.span_from_span(sub_span.expect("No span found for trait ref")); + self.dumper.dump_ref(Ref { + kind: RefKind::Type, + span, + ref_id: ::id_from_def_id(id), + }); } if !self.span.filter_generated(sub_span, trait_ref.path.span) { - let sub_span = sub_span.expect("No span for inheritance"); - self.dumper.inheritance(InheritanceData { + let sub_span = self.span_from_span(sub_span.expect("No span for inheritance")); + self.dumper.dump_relation(Relation { + kind: RelationKind::SuperTrait, span: sub_span, - base_id: id, - deriv_id: item.id - }.lower(self.tcx)); + from: ::id_from_def_id(id), + to: ::id_from_node_id(item.id, &self.save_ctxt), + }); } } } @@ -846,21 +787,19 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { self.process_generic_params(generics, item.span, &qualname, item.id); for method in methods { let map = &self.tcx.hir; - self.process_trait_item(method, make_def_id(item.id, map)) + self.process_trait_item(method, map.local_def_id(item.id)) } } // `item` is the module in question, represented as an item. fn process_mod(&mut self, item: &ast::Item) { if let Some(mod_data) = self.save_ctxt.get_item_data(item) { - down_cast_data!(mod_data, ModData, item.span); - if !self.span.filter_generated(Some(mod_data.span), item.span) { - self.dumper.mod_data(mod_data.lower(self.tcx)); - } + down_cast_data!(mod_data, DefData, item.span); + self.dumper.dump_def(item.vis == ast::Visibility::Public, mod_data); } } - fn process_path(&mut self, id: NodeId, path: &ast::Path, ref_kind: Option) { + fn process_path(&mut self, id: NodeId, path: &ast::Path) { let path_data = self.save_ctxt.get_path_data(id, path); if generated_code(path.span) && path_data.is_none() { return; @@ -873,81 +812,29 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { } }; - match path_data { - Data::VariableRefData(vrd) => { - // FIXME: this whole block duplicates the code in process_def_kind - if !self.span.filter_generated(Some(vrd.span), path.span) { - match ref_kind { - Some(recorder::TypeRef) => { - self.dumper.type_ref(TypeRefData { - span: vrd.span, - ref_id: Some(vrd.ref_id), - scope: vrd.scope, - qualname: String::new() - }.lower(self.tcx)); - } - Some(recorder::FnRef) => { - self.dumper.function_ref(FunctionRefData { - span: vrd.span, - ref_id: vrd.ref_id, - scope: vrd.scope - }.lower(self.tcx)); - } - Some(recorder::ModRef) => { - self.dumper.mod_ref( ModRefData { - span: vrd.span, - ref_id: Some(vrd.ref_id), - scope: vrd.scope, - qualname: String::new() - }.lower(self.tcx)); - } - Some(recorder::VarRef) | None - => self.dumper.variable_ref(vrd.lower(self.tcx)) - } - } - - } - Data::TypeRefData(trd) => { - if !self.span.filter_generated(Some(trd.span), path.span) { - self.dumper.type_ref(trd.lower(self.tcx)); - } - } - Data::MethodCallData(mcd) => { - if !self.span.filter_generated(Some(mcd.span), path.span) { - self.dumper.method_call(mcd.lower(self.tcx)); - } - } - Data::FunctionCallData(fcd) => { - if !self.span.filter_generated(Some(fcd.span), path.span) { - self.dumper.function_call(fcd.lower(self.tcx)); - } - } - _ => { - span_bug!(path.span, "Unexpected data: {:?}", path_data); - } - } + self.dumper.dump_ref(path_data); // Modules or types in the path prefix. match self.save_ctxt.get_path_def(id) { - Def::Method(did) => { + HirDef::Method(did) => { let ti = self.tcx.associated_item(did); if ti.kind == ty::AssociatedKind::Method && ti.method_has_self_argument { self.write_sub_path_trait_truncated(path); } } - Def::Fn(..) | - Def::Const(..) | - Def::Static(..) | - Def::StructCtor(..) | - Def::VariantCtor(..) | - Def::AssociatedConst(..) | - Def::Local(..) | - Def::Upvar(..) | - Def::Struct(..) | - Def::Union(..) | - Def::Variant(..) | - Def::TyAlias(..) | - Def::AssociatedTy(..) => self.write_sub_paths_truncated(path), + HirDef::Fn(..) | + HirDef::Const(..) | + HirDef::Static(..) | + HirDef::StructCtor(..) | + HirDef::VariantCtor(..) | + HirDef::AssociatedConst(..) | + HirDef::Local(..) | + HirDef::Upvar(..) | + HirDef::Struct(..) | + HirDef::Union(..) | + HirDef::Variant(..) | + HirDef::TyAlias(..) | + HirDef::AssociatedTy(..) => self.write_sub_paths_truncated(path), _ => {} } } @@ -961,20 +848,15 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { self.write_sub_paths_truncated(path); if let Some(struct_lit_data) = self.save_ctxt.get_expr_data(ex) { - down_cast_data!(struct_lit_data, TypeRefData, ex.span); - if !self.span.filter_generated(Some(struct_lit_data.span), ex.span) { - self.dumper.type_ref(struct_lit_data.lower(self.tcx)); + down_cast_data!(struct_lit_data, RefData, ex.span); + if !generated_code(ex.span) { + self.dumper.dump_ref(struct_lit_data); } - let scope = self.save_ctxt.enclosing_scope(ex.id); - for field in fields { if let Some(field_data) = self.save_ctxt - .get_field_ref_data(field, variant, scope) { - - if !self.span.filter_generated(Some(field_data.span), field.ident.span) { - self.dumper.variable_ref(field_data.lower(self.tcx)); - } + .get_field_ref_data(field, variant) { + self.dumper.dump_ref(field_data); } self.visit_expr(&field.expr) @@ -986,9 +868,9 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { fn process_method_call(&mut self, ex: &'l ast::Expr, args: &'l [P]) { if let Some(mcd) = self.save_ctxt.get_expr_data(ex) { - down_cast_data!(mcd, MethodCallData, ex.span); - if !self.span.filter_generated(Some(mcd.span), ex.span) { - self.dumper.method_call(mcd.lower(self.tcx)); + down_cast_data!(mcd, RefData, ex.span); + if !generated_code(ex.span) { + self.dumper.dump_ref(mcd); } } @@ -1013,12 +895,13 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { let sub_span = self.span.span_for_first_ident(span); if let Some(f) = variant.find_field_named(field.ident.name) { if !self.span.filter_generated(sub_span, span) { - self.dumper.variable_ref(VariableRefData { - span: sub_span.expect("No span fund for var ref"), - ref_id: f.did, - scope: self.cur_scope, - name: String::new() - }.lower(self.tcx)); + let span = + self.span_from_span(sub_span.expect("No span fund for var ref")); + self.dumper.dump_ref(Ref { + kind: RefKind::Variable, + span, + ref_id: ::id_from_def_id(f.did), + }); } } self.visit_pat(&field.pat); @@ -1036,7 +919,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { collector.visit_pat(&p); self.visit_pat(&p); - for &(id, ref p, immut, _) in &collector.collected_paths { + for &(id, ref p, immut) in &collector.collected_paths { let mut value = match immut { ast::Mutability::Immutable => value.to_string(), _ => String::new(), @@ -1058,21 +941,24 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { let sub_span = self.span.span_for_last_ident(p.span); // Rust uses the id of the pattern for var lookups, so we'll use it too. if !self.span.filter_generated(sub_span, p.span) { - self.dumper.variable(VariableData { - span: sub_span.expect("No span found for variable"), - kind: VariableKind::Local, - id: id, + let qualname = format!("{}${}", path_to_string(p), id); + let id = ::id_from_node_id(id, &self.save_ctxt); + let span = self.span_from_span(sub_span.expect("No span found for variable")); + + self.dumper.dump_def(false, Def { + kind: DefKind::Local, + id, + span, name: path_to_string(p), - qualname: format!("{}${}", path_to_string(p), id), - value: value, - type_value: typ, - scope: CRATE_NODE_ID, + qualname, + value: typ, parent: None, - visibility: Visibility::Inherited, + children: vec![], + decl_id: None, docs: String::new(), sig: None, - attributes: vec![], - }.lower(self.tcx)); + attributes:vec![], + }); } } } @@ -1084,46 +970,36 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { /// If the span is not macro-generated, do nothing, else use callee and /// callsite spans to record macro definition and use data, using the /// mac_uses and mac_defs sets to prevent multiples. - fn process_macro_use(&mut self, span: Span, id: NodeId) { - let data = match self.save_ctxt.get_macro_use_data(span, id) { + fn process_macro_use(&mut self, span: Span) { + let data = match self.save_ctxt.get_macro_use_data(span) { None => return, Some(data) => data, }; - let mut hasher = DefaultHasher::new(); - data.callee_span.hash(&mut hasher); - let hash = hasher.finish(); - let qualname = format!("{}::{}", data.name, hash); + + // FIXME write the macro def + // let mut hasher = DefaultHasher::new(); + // data.callee_span.hash(&mut hasher); + // let hash = hasher.finish(); + // let qualname = format!("{}::{}", data.name, hash); // Don't write macro definition for imported macros - if !self.mac_defs.contains(&data.callee_span) - && !data.imported { - self.mac_defs.insert(data.callee_span); - if let Some(sub_span) = self.span.span_for_macro_def_name(data.callee_span) { - self.dumper.macro_data(MacroData { - span: sub_span, - name: data.name.clone(), - qualname: qualname.clone(), - // FIXME where do macro docs come from? - docs: String::new(), - }.lower(self.tcx)); - } - } - if !self.mac_uses.contains(&data.span) { - self.mac_uses.insert(data.span); - if let Some(sub_span) = self.span.span_for_macro_use_name(data.span) { - self.dumper.macro_use(MacroUseData { - span: sub_span, - name: data.name, - qualname: qualname, - scope: data.scope, - callee_span: data.callee_span, - imported: data.imported, - }.lower(self.tcx)); - } - } + // if !self.mac_defs.contains(&data.callee_span) + // && !data.imported { + // self.mac_defs.insert(data.callee_span); + // if let Some(sub_span) = self.span.span_for_macro_def_name(data.callee_span) { + // self.dumper.macro_data(MacroData { + // span: sub_span, + // name: data.name.clone(), + // qualname: qualname.clone(), + // // FIXME where do macro docs come from? + // docs: String::new(), + // }.lower(self.tcx)); + // } + // } + self.dumper.macro_use(data); } fn process_trait_item(&mut self, trait_item: &'l ast::TraitItem, trait_id: DefId) { - self.process_macro_use(trait_item.span, trait_item.id); + self.process_macro_use(trait_item.span); match trait_item.node { ast::TraitItemKind::Const(ref ty, ref expr) => { self.process_assoc_const(trait_item.id, @@ -1132,7 +1008,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { &ty, expr.as_ref().map(|e| &**e), trait_id, - Visibility::Public, + ast::Visibility::Public, &trait_item.attrs); } ast::TraitItemKind::Method(ref sig, ref body) => { @@ -1140,8 +1016,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { body.as_ref().map(|x| &**x), trait_item.id, trait_item.ident, - Visibility::Public, - &trait_item.attrs, + ast::Visibility::Public, trait_item.span); } ast::TraitItemKind::Type(ref bounds, ref default_ty) => { @@ -1151,22 +1026,27 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { let sub_span = self.span.sub_span_after_keyword(trait_item.span, keywords::Type); if !self.span.filter_generated(sub_span, trait_item.span) { - self.dumper.typedef(TypeDefData { - span: sub_span.expect("No span found for assoc type"), - name: name, - id: trait_item.id, - qualname: qualname, + let span = self.span_from_span(sub_span.expect("No span found for assoc type")); + let id = ::id_from_node_id(trait_item.id, &self.save_ctxt); + + self.dumper.dump_def(true, Def { + kind: DefKind::Type, + id, + span, + name, + qualname, value: self.span.snippet(trait_item.span), - visibility: Visibility::Public, - parent: Some(trait_id), + parent: Some(::id_from_def_id(trait_id)), + children: vec![], + decl_id: None, docs: docs_for_attrs(&trait_item.attrs), sig: sig::assoc_type_signature(trait_item.id, trait_item.ident, Some(bounds), default_ty.as_ref().map(|ty| &**ty), &self.save_ctxt), - attributes: trait_item.attrs.clone(), - }.lower(self.tcx)); + attributes: lower_attributes(trait_item.attrs.clone(), &self.save_ctxt), + }); } if let &Some(ref default_ty) = default_ty { @@ -1178,7 +1058,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { } fn process_impl_item(&mut self, impl_item: &'l ast::ImplItem, impl_id: DefId) { - self.process_macro_use(impl_item.span, impl_item.id); + self.process_macro_use(impl_item.span); match impl_item.node { ast::ImplItemKind::Const(ref ty, ref expr) => { self.process_assoc_const(impl_item.id, @@ -1187,7 +1067,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { &ty, Some(expr), impl_id, - From::from(&impl_item.vis), + impl_item.vis.clone(), &impl_item.attrs); } ast::ImplItemKind::Method(ref sig, ref body) => { @@ -1195,8 +1075,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { Some(body), impl_item.id, impl_item.ident, - From::from(&impl_item.vis), - &impl_item.attrs, + impl_item.vis.clone(), impl_item.span); } ast::ImplItemKind::Type(ref ty) => { @@ -1220,25 +1099,30 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, let cm = self.tcx.sess.codemap(); let filename = cm.span_to_filename(span); - self.dumper.mod_data(ModData { - id: id, + let data_id = ::id_from_node_id(id, &self.save_ctxt); + let children = m.items.iter().map(|i| ::id_from_node_id(i.id, &self.save_ctxt)).collect(); + let span = self.span_from_span(span); + + self.dumper.dump_def(true, Def { + kind: DefKind::Mod, + id: data_id, name: String::new(), - qualname: qualname, - span: span, - scope: id, - filename: filename, - items: m.items.iter().map(|i| i.id).collect(), - visibility: Visibility::Public, + qualname, + span, + value: filename, + children, + parent: None, + decl_id: None, docs: docs_for_attrs(attrs), sig: None, - attributes: attrs.to_owned(), - }.lower(self.tcx)); + attributes: lower_attributes(attrs.to_owned(), &self.save_ctxt), + }); self.nest_scope(id, |v| visit::walk_mod(v, m)); } fn visit_item(&mut self, item: &'l ast::Item) { use syntax::ast::ItemKind::*; - self.process_macro_use(item.span, item.id); + self.process_macro_use(item.span); match item.node { Use(ref use_item) => { match use_item.node { @@ -1246,9 +1130,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, let sub_span = self.span.span_for_last_ident(path.span); let mod_id = match self.lookup_def_id(item.id) { Some(def_id) => { - let scope = self.cur_scope; - self.process_def_kind(item.id, path.span, sub_span, def_id, scope); - + self.process_def_kind(item.id, path.span, sub_span, def_id); Some(def_id) } None => None, @@ -1263,14 +1145,15 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, }; if !self.span.filter_generated(sub_span, path.span) { - self.dumper.use_data(UseData { - span: sub_span.expect("No span found for use"), - id: item.id, - mod_id: mod_id, + let span = + self.span_from_span(sub_span.expect("No span found for use")); + self.dumper.import(item.vis == ast::Visibility::Public, Import { + kind: ImportKind::Use, + ref_id: mod_id.map(|id| ::id_from_def_id(id)), + span, name: ident.to_string(), - scope: self.cur_scope, - visibility: From::from(&item.vis), - }.lower(self.tcx)); + value: String::new(), + }); } self.write_sub_paths_truncated(path); } @@ -1288,23 +1171,24 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, let sub_span = self.span .sub_span_of_token(item.span, token::BinOp(token::Star)); if !self.span.filter_generated(sub_span, item.span) { - self.dumper.use_glob(UseGlobData { - span: sub_span.expect("No span found for use glob"), - id: item.id, - names: names, - scope: self.cur_scope, - visibility: From::from(&item.vis), - }.lower(self.tcx)); + let span = + self.span_from_span(sub_span.expect("No span found for use glob")); + self.dumper.import(item.vis == ast::Visibility::Public, Import { + kind: ImportKind::GlobUse, + ref_id: None, + span, + name: "*".to_owned(), + value: names.join(", "), + }); } self.write_sub_paths(path); } ast::ViewPathList(ref path, ref list) => { for plid in list { - let scope = self.cur_scope; let id = plid.node.id; if let Some(def_id) = self.lookup_def_id(id) { let span = plid.span; - self.process_def_kind(id, span, Some(span), def_id, scope); + self.process_def_kind(id, span, Some(span), def_id); } } @@ -1312,26 +1196,19 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, } } } - ExternCrate(ref s) => { - let location = match *s { - Some(s) => s.to_string(), - None => item.ident.to_string(), - }; + ExternCrate(_) => { let alias_span = self.span.span_for_last_ident(item.span); - let cnum = match self.sess.cstore.extern_mod_stmt_cnum(item.id) { - Some(cnum) => cnum, - None => LOCAL_CRATE, - }; if !self.span.filter_generated(alias_span, item.span) { - self.dumper.extern_crate(ExternCrateData { - id: item.id, + let span = + self.span_from_span(alias_span.expect("No span found for extern crate")); + self.dumper.import(false, Import { + kind: ImportKind::ExternCrate, + ref_id: None, + span, name: item.ident.to_string(), - crate_num: cnum, - location: location, - span: alias_span.expect("No span found for extern crate"), - scope: self.cur_scope, - }.lower(self.tcx)); + value: String::new(), + }); } } Fn(ref decl, .., ref ty_params, ref body) => @@ -1360,18 +1237,23 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, let value = ty_to_string(&ty); let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Type); if !self.span.filter_generated(sub_span, item.span) { - self.dumper.typedef(TypeDefData { - span: sub_span.expect("No span found for typedef"), + let span = self.span_from_span(sub_span.expect("No span found for typedef")); + let id = ::id_from_node_id(item.id, &self.save_ctxt); + + self.dumper.dump_def(item.vis == ast::Visibility::Public, Def { + kind: DefKind::Type, + id, + span, name: item.ident.to_string(), - id: item.id, qualname: qualname.clone(), - value: value, - visibility: From::from(&item.vis), + value, parent: None, + children: vec![], + decl_id: None, docs: docs_for_attrs(&item.attrs), sig: sig::item_signature(item, &self.save_ctxt), - attributes: item.attrs.clone(), - }.lower(self.tcx)); + attributes: lower_attributes(item.attrs.clone(), &self.save_ctxt), + }); } self.visit_ty(&ty); @@ -1396,7 +1278,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, } fn visit_ty(&mut self, t: &'l ast::Ty) { - self.process_macro_use(t.span, t.id); + self.process_macro_use(t.span); match t.node { ast::TyKind::Path(_, ref path) => { if generated_code(t.span) { @@ -1405,12 +1287,12 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, if let Some(id) = self.lookup_def_id(t.id) { if let Some(sub_span) = self.span.sub_span_for_type_name(t.span) { - self.dumper.type_ref(TypeRefData { - span: sub_span, - ref_id: Some(id), - scope: self.cur_scope, - qualname: String::new() - }.lower(self.tcx)); + let span = self.span_from_span(sub_span); + self.dumper.dump_ref(Ref { + kind: RefKind::Type, + span, + ref_id: ::id_from_def_id(id), + }); } } @@ -1427,7 +1309,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, fn visit_expr(&mut self, ex: &'l ast::Expr) { debug!("visit_expr {:?}", ex.node); - self.process_macro_use(ex.span, ex.id); + self.process_macro_use(ex.span); match ex.node { ast::ExprKind::Struct(ref path, ref fields, ref base) => { let hir_expr = self.save_ctxt.tcx.hir.expect_expr(ex.id); @@ -1446,9 +1328,9 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, self.visit_expr(&sub_ex); if let Some(field_data) = self.save_ctxt.get_expr_data(ex) { - down_cast_data!(field_data, VariableRefData, ex.span); - if !self.span.filter_generated(Some(field_data.span), ex.span) { - self.dumper.variable_ref(field_data.lower(self.tcx)); + down_cast_data!(field_data, RefData, ex.span); + if !generated_code(ex.span) { + self.dumper.dump_ref(field_data); } } } @@ -1474,12 +1356,13 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, ty::TyAdt(def, _) => { let sub_span = self.span.sub_span_after_token(ex.span, token::Dot); if !self.span.filter_generated(sub_span, ex.span) { - self.dumper.variable_ref(VariableRefData { - span: sub_span.expect("No span found for var ref"), - ref_id: def.struct_variant().fields[idx.node].did, - scope: self.cur_scope, - name: String::new() - }.lower(self.tcx)); + let span = + self.span_from_span(sub_span.expect("No span found for var ref")); + self.dumper.dump_ref(Ref { + kind: RefKind::Variable, + span: span, + ref_id: ::id_from_def_id(def.struct_variant().fields[idx.node].did), + }); } } ty::TyTuple(..) => {} @@ -1540,7 +1423,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, } fn visit_pat(&mut self, p: &'l ast::Pat) { - self.process_macro_use(p.span, p.id); + self.process_macro_use(p.span); self.process_pat(p); } @@ -1556,9 +1439,9 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, let mut paths_to_process = vec![]; // process collected paths - for &(id, ref p, immut, ref_kind) in &collector.collected_paths { + for &(id, ref p, immut) in &collector.collected_paths { match self.save_ctxt.get_path_def(id) { - Def::Local(def_id) => { + HirDef::Local(def_id) => { let id = self.tcx.hir.as_local_node_id(def_id).unwrap(); let mut value = if immut == ast::Mutability::Immutable { self.span.snippet(p.span).to_string() @@ -1573,53 +1456,56 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, assert!(p.segments.len() == 1, "qualified path for local variable def in arm"); if !self.span.filter_generated(Some(p.span), p.span) { - self.dumper.variable(VariableData { - span: p.span, - kind: VariableKind::Local, - id: id, + let qualname = format!("{}${}", path_to_string(p), id); + let id = ::id_from_node_id(id, &self.save_ctxt); + let span = self.span_from_span(p.span); + + self.dumper.dump_def(false, Def { + kind: DefKind::Local, + id, + span, name: path_to_string(p), - qualname: format!("{}${}", path_to_string(p), id), - value: value, - type_value: typ, - scope: CRATE_NODE_ID, + qualname, + value: typ, parent: None, - visibility: Visibility::Inherited, + children: vec![], + decl_id: None, docs: String::new(), sig: None, - attributes: vec![], - }.lower(self.tcx)); + attributes:vec![], + }); } } - Def::StructCtor(..) | Def::VariantCtor(..) | - Def::Const(..) | Def::AssociatedConst(..) | - Def::Struct(..) | Def::Variant(..) | - Def::TyAlias(..) | Def::AssociatedTy(..) | - Def::SelfTy(..) => { - paths_to_process.push((id, p.clone(), Some(ref_kind))) + HirDef::StructCtor(..) | HirDef::VariantCtor(..) | + HirDef::Const(..) | HirDef::AssociatedConst(..) | + HirDef::Struct(..) | HirDef::Variant(..) | + HirDef::TyAlias(..) | HirDef::AssociatedTy(..) | + HirDef::SelfTy(..) => { + paths_to_process.push((id, p.clone())) } def => error!("unexpected definition kind when processing collected paths: {:?}", def), } } - for &(id, ref path, ref_kind) in &paths_to_process { - self.process_path(id, path, ref_kind); + for &(id, ref path) in &paths_to_process { + self.process_path(id, path); } walk_list!(self, visit_expr, &arm.guard); self.visit_expr(&arm.body); } fn visit_path(&mut self, p: &'l ast::Path, id: NodeId) { - self.process_path(id, p, None); + self.process_path(id, p); } fn visit_stmt(&mut self, s: &'l ast::Stmt) { - self.process_macro_use(s.span, s.id); + self.process_macro_use(s.span); visit::walk_stmt(self, s) } fn visit_local(&mut self, l: &'l ast::Local) { - self.process_macro_use(l.span, l.id); + self.process_macro_use(l.span); let value = l.init.as_ref().map(|i| self.span.snippet(i.span)).unwrap_or(String::new()); self.process_var_decl(&l.pat, value); @@ -1632,14 +1518,12 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, match item.node { ast::ForeignItemKind::Fn(ref decl, ref generics) => { if let Some(fn_data) = self.save_ctxt.get_extern_item_data(item) { - down_cast_data!(fn_data, FunctionData, item.span); - if !self.span.filter_generated(Some(fn_data.span), item.span) { - self.dumper.function(fn_data.clone().lower(self.tcx)); - } + down_cast_data!(fn_data, DefData, item.span); self.nest_tables(item.id, |v| v.process_formals(&decl.inputs, &fn_data.qualname)); self.process_generic_params(generics, item.span, &fn_data.qualname, item.id); + self.dumper.dump_def(item.vis == ast::Visibility::Public, fn_data); } for arg in &decl.inputs { @@ -1652,10 +1536,8 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, } ast::ForeignItemKind::Static(ref ty, _) => { if let Some(var_data) = self.save_ctxt.get_extern_item_data(item) { - down_cast_data!(var_data, VariableData, item.span); - if !self.span.filter_generated(Some(var_data.span), item.span) { - self.dumper.variable(var_data.lower(self.tcx)); - } + down_cast_data!(var_data, DefData, item.span); + self.dumper.dump_def(item.vis == ast::Visibility::Public, var_data); } self.visit_ty(ty); diff --git a/src/librustc_save_analysis/external_data.rs b/src/librustc_save_analysis/external_data.rs deleted file mode 100644 index 245a3bcc6179..000000000000 --- a/src/librustc_save_analysis/external_data.rs +++ /dev/null @@ -1,748 +0,0 @@ -// Copyright 2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use rustc::hir::def_id::{CrateNum, DefId, DefIndex}; -use rustc::hir::map::Map; -use rustc::ty::TyCtxt; -use syntax::ast::{self, NodeId}; -use syntax::codemap::CodeMap; -use syntax::print::pprust; -use syntax_pos::Span; - -use data::{self, Visibility}; - -use rls_data::{SpanData, CratePreludeData, Attribute, Signature}; -use rls_span::{Column, Row}; - -// FIXME: this should be pub(crate), but the current snapshot doesn't allow it yet -pub trait Lower { - type Target; - fn lower(self, tcx: TyCtxt) -> Self::Target; -} - -pub fn make_def_id(id: NodeId, map: &Map) -> DefId { - map.opt_local_def_id(id).unwrap_or(null_def_id()) -} - -pub fn null_def_id() -> DefId { - DefId { - krate: CrateNum::from_u32(u32::max_value()), - index: DefIndex::from_u32(u32::max_value()) - } -} - -pub fn span_from_span(span: Span, cm: &CodeMap) -> SpanData { - let start = cm.lookup_char_pos(span.lo); - let end = cm.lookup_char_pos(span.hi); - - SpanData { - file_name: start.file.name.clone().into(), - byte_start: span.lo.0, - byte_end: span.hi.0, - line_start: Row::new_one_indexed(start.line as u32), - line_end: Row::new_one_indexed(end.line as u32), - column_start: Column::new_one_indexed(start.col.0 as u32 + 1), - column_end: Column::new_one_indexed(end.col.0 as u32 + 1), - } -} - -impl Lower for Vec { - type Target = Vec; - - fn lower(self, tcx: TyCtxt) -> Vec { - self.into_iter() - // Only retain real attributes. Doc comments are lowered separately. - .filter(|attr| attr.path != "doc") - .map(|mut attr| { - // Remove the surrounding '#[..]' or '#![..]' of the pretty printed - // attribute. First normalize all inner attribute (#![..]) to outer - // ones (#[..]), then remove the two leading and the one trailing character. - attr.style = ast::AttrStyle::Outer; - let value = pprust::attribute_to_string(&attr); - // This str slicing works correctly, because the leading and trailing characters - // are in the ASCII range and thus exactly one byte each. - let value = value[2..value.len()-1].to_string(); - - Attribute { - value: value, - span: span_from_span(attr.span, tcx.sess.codemap()), - } - }).collect() - } -} - -impl Lower for data::CratePreludeData { - type Target = CratePreludeData; - - fn lower(self, tcx: TyCtxt) -> CratePreludeData { - CratePreludeData { - crate_name: self.crate_name, - crate_root: self.crate_root, - external_crates: self.external_crates, - span: span_from_span(self.span, tcx.sess.codemap()), - } - } -} - -/// Data for enum declarations. -#[derive(Clone, Debug)] -pub struct EnumData { - pub id: DefId, - pub value: String, - pub name: String, - pub qualname: String, - pub span: SpanData, - pub scope: DefId, - pub variants: Vec, - pub visibility: Visibility, - pub docs: String, - pub sig: Option, - pub attributes: Vec, -} - -impl Lower for data::EnumData { - type Target = EnumData; - - fn lower(self, tcx: TyCtxt) -> EnumData { - EnumData { - id: make_def_id(self.id, &tcx.hir), - name: self.name, - value: self.value, - qualname: self.qualname, - span: span_from_span(self.span, tcx.sess.codemap()), - scope: make_def_id(self.scope, &tcx.hir), - variants: self.variants.into_iter().map(|id| make_def_id(id, &tcx.hir)).collect(), - visibility: self.visibility, - docs: self.docs, - sig: self.sig, - attributes: self.attributes.lower(tcx), - } - } -} - -/// Data for extern crates. -#[derive(Debug)] -pub struct ExternCrateData { - pub id: DefId, - pub name: String, - pub crate_num: CrateNum, - pub location: String, - pub span: SpanData, - pub scope: DefId, -} - -impl Lower for data::ExternCrateData { - type Target = ExternCrateData; - - fn lower(self, tcx: TyCtxt) -> ExternCrateData { - ExternCrateData { - id: make_def_id(self.id, &tcx.hir), - name: self.name, - crate_num: self.crate_num, - location: self.location, - span: span_from_span(self.span, tcx.sess.codemap()), - scope: make_def_id(self.scope, &tcx.hir), - } - } -} - -/// Data about a function call. -#[derive(Debug)] -pub struct FunctionCallData { - pub span: SpanData, - pub scope: DefId, - pub ref_id: DefId, -} - -impl Lower for data::FunctionCallData { - type Target = FunctionCallData; - - fn lower(self, tcx: TyCtxt) -> FunctionCallData { - FunctionCallData { - span: span_from_span(self.span, tcx.sess.codemap()), - scope: make_def_id(self.scope, &tcx.hir), - ref_id: self.ref_id, - } - } -} - -/// Data for all kinds of functions and methods. -#[derive(Clone, Debug)] -pub struct FunctionData { - pub id: DefId, - pub name: String, - pub qualname: String, - pub declaration: Option, - pub span: SpanData, - pub scope: DefId, - pub value: String, - pub visibility: Visibility, - pub parent: Option, - pub docs: String, - pub sig: Option, - pub attributes: Vec, -} - -impl Lower for data::FunctionData { - type Target = FunctionData; - - fn lower(self, tcx: TyCtxt) -> FunctionData { - FunctionData { - id: make_def_id(self.id, &tcx.hir), - name: self.name, - qualname: self.qualname, - declaration: self.declaration, - span: span_from_span(self.span, tcx.sess.codemap()), - scope: make_def_id(self.scope, &tcx.hir), - value: self.value, - visibility: self.visibility, - parent: self.parent, - docs: self.docs, - sig: self.sig, - attributes: self.attributes.lower(tcx), - } - } -} - -/// Data about a function call. -#[derive(Debug)] -pub struct FunctionRefData { - pub span: SpanData, - pub scope: DefId, - pub ref_id: DefId, -} - -impl Lower for data::FunctionRefData { - type Target = FunctionRefData; - - fn lower(self, tcx: TyCtxt) -> FunctionRefData { - FunctionRefData { - span: span_from_span(self.span, tcx.sess.codemap()), - scope: make_def_id(self.scope, &tcx.hir), - ref_id: self.ref_id, - } - } -} -#[derive(Debug)] -pub struct ImplData { - pub id: DefId, - pub span: SpanData, - pub scope: DefId, - pub trait_ref: Option, - pub self_ref: Option, -} - -impl Lower for data::ImplData { - type Target = ImplData; - - fn lower(self, tcx: TyCtxt) -> ImplData { - ImplData { - id: make_def_id(self.id, &tcx.hir), - span: span_from_span(self.span, tcx.sess.codemap()), - scope: make_def_id(self.scope, &tcx.hir), - trait_ref: self.trait_ref, - self_ref: self.self_ref, - } - } -} - -#[derive(Debug)] -pub struct InheritanceData { - pub span: SpanData, - pub base_id: DefId, - pub deriv_id: DefId -} - -impl Lower for data::InheritanceData { - type Target = InheritanceData; - - fn lower(self, tcx: TyCtxt) -> InheritanceData { - InheritanceData { - span: span_from_span(self.span, tcx.sess.codemap()), - base_id: self.base_id, - deriv_id: make_def_id(self.deriv_id, &tcx.hir) - } - } -} - -/// Data about a macro declaration. -#[derive(Debug)] -pub struct MacroData { - pub span: SpanData, - pub name: String, - pub qualname: String, - pub docs: String, -} - -impl Lower for data::MacroData { - type Target = MacroData; - - fn lower(self, tcx: TyCtxt) -> MacroData { - MacroData { - span: span_from_span(self.span, tcx.sess.codemap()), - name: self.name, - qualname: self.qualname, - docs: self.docs, - } - } -} - -/// Data about a macro use. -#[derive(Debug)] -pub struct MacroUseData { - pub span: SpanData, - pub name: String, - pub qualname: String, - // Because macro expansion happens before ref-ids are determined, - // we use the callee span to reference the associated macro definition. - pub callee_span: SpanData, - pub scope: DefId, -} - -impl Lower for data::MacroUseData { - type Target = MacroUseData; - - fn lower(self, tcx: TyCtxt) -> MacroUseData { - MacroUseData { - span: span_from_span(self.span, tcx.sess.codemap()), - name: self.name, - qualname: self.qualname, - callee_span: span_from_span(self.callee_span, tcx.sess.codemap()), - scope: make_def_id(self.scope, &tcx.hir), - } - } -} - -/// Data about a method call. -#[derive(Debug)] -pub struct MethodCallData { - pub span: SpanData, - pub scope: DefId, - pub ref_id: Option, - pub decl_id: Option, -} - -impl Lower for data::MethodCallData { - type Target = MethodCallData; - - fn lower(self, tcx: TyCtxt) -> MethodCallData { - MethodCallData { - span: span_from_span(self.span, tcx.sess.codemap()), - scope: make_def_id(self.scope, &tcx.hir), - ref_id: self.ref_id, - decl_id: self.decl_id, - } - } -} - -/// Data for method declarations (methods with a body are treated as functions). -#[derive(Clone, Debug)] -pub struct MethodData { - pub id: DefId, - pub name: String, - pub qualname: String, - pub span: SpanData, - pub scope: DefId, - pub value: String, - pub decl_id: Option, - pub visibility: Visibility, - pub parent: Option, - pub docs: String, - pub sig: Option, - pub attributes: Vec, -} - -impl Lower for data::MethodData { - type Target = MethodData; - - fn lower(self, tcx: TyCtxt) -> MethodData { - MethodData { - span: span_from_span(self.span, tcx.sess.codemap()), - name: self.name, - scope: make_def_id(self.scope, &tcx.hir), - id: make_def_id(self.id, &tcx.hir), - qualname: self.qualname, - value: self.value, - decl_id: self.decl_id, - visibility: self.visibility, - parent: self.parent, - docs: self.docs, - sig: self.sig, - attributes: self.attributes.lower(tcx), - } - } -} - -/// Data for modules. -#[derive(Debug)] -pub struct ModData { - pub id: DefId, - pub name: String, - pub qualname: String, - pub span: SpanData, - pub scope: DefId, - pub filename: String, - pub items: Vec, - pub visibility: Visibility, - pub docs: String, - pub sig: Option, - pub attributes: Vec, -} - -impl Lower for data::ModData { - type Target = ModData; - - fn lower(self, tcx: TyCtxt) -> ModData { - ModData { - id: make_def_id(self.id, &tcx.hir), - name: self.name, - qualname: self.qualname, - span: span_from_span(self.span, tcx.sess.codemap()), - scope: make_def_id(self.scope, &tcx.hir), - filename: self.filename, - items: self.items.into_iter().map(|id| make_def_id(id, &tcx.hir)).collect(), - visibility: self.visibility, - docs: self.docs, - sig: self.sig, - attributes: self.attributes.lower(tcx), - } - } -} - -/// Data for a reference to a module. -#[derive(Debug)] -pub struct ModRefData { - pub span: SpanData, - pub scope: DefId, - pub ref_id: Option, - pub qualname: String -} - -impl Lower for data::ModRefData { - type Target = ModRefData; - - fn lower(self, tcx: TyCtxt) -> ModRefData { - ModRefData { - span: span_from_span(self.span, tcx.sess.codemap()), - scope: make_def_id(self.scope, &tcx.hir), - ref_id: self.ref_id, - qualname: self.qualname, - } - } -} - -#[derive(Debug)] -pub struct StructData { - pub span: SpanData, - pub name: String, - pub id: DefId, - pub ctor_id: DefId, - pub qualname: String, - pub scope: DefId, - pub value: String, - pub fields: Vec, - pub visibility: Visibility, - pub docs: String, - pub sig: Option, - pub attributes: Vec, -} - -impl Lower for data::StructData { - type Target = StructData; - - fn lower(self, tcx: TyCtxt) -> StructData { - StructData { - span: span_from_span(self.span, tcx.sess.codemap()), - name: self.name, - id: make_def_id(self.id, &tcx.hir), - ctor_id: make_def_id(self.ctor_id, &tcx.hir), - qualname: self.qualname, - scope: make_def_id(self.scope, &tcx.hir), - value: self.value, - fields: self.fields.into_iter().map(|id| make_def_id(id, &tcx.hir)).collect(), - visibility: self.visibility, - docs: self.docs, - sig: self.sig, - attributes: self.attributes.lower(tcx), - } - } -} - -#[derive(Debug)] -pub struct StructVariantData { - pub span: SpanData, - pub name: String, - pub id: DefId, - pub qualname: String, - pub type_value: String, - pub value: String, - pub scope: DefId, - pub parent: Option, - pub docs: String, - pub sig: Option, - pub attributes: Vec, -} - -impl Lower for data::StructVariantData { - type Target = StructVariantData; - - fn lower(self, tcx: TyCtxt) -> StructVariantData { - StructVariantData { - span: span_from_span(self.span, tcx.sess.codemap()), - name: self.name, - id: make_def_id(self.id, &tcx.hir), - qualname: self.qualname, - type_value: self.type_value, - value: self.value, - scope: make_def_id(self.scope, &tcx.hir), - parent: self.parent, - docs: self.docs, - sig: self.sig, - attributes: self.attributes.lower(tcx), - } - } -} - -#[derive(Debug)] -pub struct TraitData { - pub span: SpanData, - pub name: String, - pub id: DefId, - pub qualname: String, - pub scope: DefId, - pub value: String, - pub items: Vec, - pub visibility: Visibility, - pub docs: String, - pub sig: Option, - pub attributes: Vec, -} - -impl Lower for data::TraitData { - type Target = TraitData; - - fn lower(self, tcx: TyCtxt) -> TraitData { - TraitData { - span: span_from_span(self.span, tcx.sess.codemap()), - name: self.name, - id: make_def_id(self.id, &tcx.hir), - qualname: self.qualname, - scope: make_def_id(self.scope, &tcx.hir), - value: self.value, - items: self.items.into_iter().map(|id| make_def_id(id, &tcx.hir)).collect(), - visibility: self.visibility, - docs: self.docs, - sig: self.sig, - attributes: self.attributes.lower(tcx), - } - } -} - -#[derive(Debug)] -pub struct TupleVariantData { - pub span: SpanData, - pub id: DefId, - pub name: String, - pub qualname: String, - pub type_value: String, - pub value: String, - pub scope: DefId, - pub parent: Option, - pub docs: String, - pub sig: Option, - pub attributes: Vec, -} - -impl Lower for data::TupleVariantData { - type Target = TupleVariantData; - - fn lower(self, tcx: TyCtxt) -> TupleVariantData { - TupleVariantData { - span: span_from_span(self.span, tcx.sess.codemap()), - id: make_def_id(self.id, &tcx.hir), - name: self.name, - qualname: self.qualname, - type_value: self.type_value, - value: self.value, - scope: make_def_id(self.scope, &tcx.hir), - parent: self.parent, - docs: self.docs, - sig: self.sig, - attributes: self.attributes.lower(tcx), - } - } -} - -/// Data for a typedef. -#[derive(Debug)] -pub struct TypeDefData { - pub id: DefId, - pub name: String, - pub span: SpanData, - pub qualname: String, - pub value: String, - pub visibility: Visibility, - pub parent: Option, - pub docs: String, - pub sig: Option, - pub attributes: Vec, -} - -impl Lower for data::TypeDefData { - type Target = TypeDefData; - - fn lower(self, tcx: TyCtxt) -> TypeDefData { - TypeDefData { - id: make_def_id(self.id, &tcx.hir), - name: self.name, - span: span_from_span(self.span, tcx.sess.codemap()), - qualname: self.qualname, - value: self.value, - visibility: self.visibility, - parent: self.parent, - docs: self.docs, - sig: self.sig, - attributes: self.attributes.lower(tcx), - } - } -} - -/// Data for a reference to a type or trait. -#[derive(Clone, Debug)] -pub struct TypeRefData { - pub span: SpanData, - pub scope: DefId, - pub ref_id: Option, - pub qualname: String, -} - -impl Lower for data::TypeRefData { - type Target = TypeRefData; - - fn lower(self, tcx: TyCtxt) -> TypeRefData { - TypeRefData { - span: span_from_span(self.span, tcx.sess.codemap()), - scope: make_def_id(self.scope, &tcx.hir), - ref_id: self.ref_id, - qualname: self.qualname, - } - } -} - -#[derive(Debug)] -pub struct UseData { - pub id: DefId, - pub span: SpanData, - pub name: String, - pub mod_id: Option, - pub scope: DefId, - pub visibility: Visibility, -} - -impl Lower for data::UseData { - type Target = UseData; - - fn lower(self, tcx: TyCtxt) -> UseData { - UseData { - id: make_def_id(self.id, &tcx.hir), - span: span_from_span(self.span, tcx.sess.codemap()), - name: self.name, - mod_id: self.mod_id, - scope: make_def_id(self.scope, &tcx.hir), - visibility: self.visibility, - } - } -} - -#[derive(Debug)] -pub struct UseGlobData { - pub id: DefId, - pub span: SpanData, - pub names: Vec, - pub scope: DefId, - pub visibility: Visibility, -} - -impl Lower for data::UseGlobData { - type Target = UseGlobData; - - fn lower(self, tcx: TyCtxt) -> UseGlobData { - UseGlobData { - id: make_def_id(self.id, &tcx.hir), - span: span_from_span(self.span, tcx.sess.codemap()), - names: self.names, - scope: make_def_id(self.scope, &tcx.hir), - visibility: self.visibility, - } - } -} - -/// Data for local and global variables (consts and statics). -#[derive(Debug)] -pub struct VariableData { - pub id: DefId, - pub name: String, - pub kind: data::VariableKind, - pub qualname: String, - pub span: SpanData, - pub scope: DefId, - pub value: String, - pub type_value: String, - pub parent: Option, - pub visibility: Visibility, - pub docs: String, - pub sig: Option, - pub attributes: Vec, -} - -impl Lower for data::VariableData { - type Target = VariableData; - - fn lower(self, tcx: TyCtxt) -> VariableData { - VariableData { - id: make_def_id(self.id, &tcx.hir), - kind: self.kind, - name: self.name, - qualname: self.qualname, - span: span_from_span(self.span, tcx.sess.codemap()), - scope: make_def_id(self.scope, &tcx.hir), - value: self.value, - type_value: self.type_value, - parent: self.parent, - visibility: self.visibility, - docs: self.docs, - sig: self.sig, - attributes: self.attributes.lower(tcx), - } - } -} - -/// Data for the use of some item (e.g., the use of a local variable, which -/// will refer to that variables declaration (by ref_id)). -#[derive(Debug)] -pub struct VariableRefData { - pub name: String, - pub span: SpanData, - pub scope: DefId, - pub ref_id: DefId, -} - -impl Lower for data::VariableRefData { - type Target = VariableRefData; - - fn lower(self, tcx: TyCtxt) -> VariableRefData { - VariableRefData { - name: self.name, - span: span_from_span(self.span, tcx.sess.codemap()), - scope: make_def_id(self.scope, &tcx.hir), - ref_id: self.ref_id, - } - } -} diff --git a/src/librustc_save_analysis/json_api_dumper.rs b/src/librustc_save_analysis/json_api_dumper.rs index bddee6460ff9..4b2301fd7f80 100644 --- a/src/librustc_save_analysis/json_api_dumper.rs +++ b/src/librustc_save_analysis/json_api_dumper.rs @@ -12,12 +12,9 @@ use std::io::Write; use rustc_serialize::json::as_json; -use external_data::*; -use data::{VariableKind, Visibility}; -use dump::Dump; -use id_from_def_id; +use Dump; -use rls_data::{Analysis, Import, ImportKind, Def, DefKind, CratePreludeData, Format}; +use rls_data::{Analysis, Import, Def, CratePreludeData, Format, Relation}; // A dumper to dump a restricted set of JSON information, designed for use with @@ -47,306 +44,23 @@ impl<'b, W: Write> Drop for JsonApiDumper<'b, W> { } } -macro_rules! impl_fn { - ($fn_name: ident, $data_type: ident, $bucket: ident) => { - fn $fn_name(&mut self, data: $data_type) { - if let Some(datum) = data.into() { - self.result.$bucket.push(datum); - } - } - } -} - impl<'b, W: Write + 'b> Dump for JsonApiDumper<'b, W> { fn crate_prelude(&mut self, data: CratePreludeData) { self.result.prelude = Some(data) } - impl_fn!(use_data, UseData, imports); - impl_fn!(use_glob, UseGlobData, imports); - - impl_fn!(enum_data, EnumData, defs); - impl_fn!(tuple_variant, TupleVariantData, defs); - impl_fn!(struct_variant, StructVariantData, defs); - impl_fn!(struct_data, StructData, defs); - impl_fn!(trait_data, TraitData, defs); - impl_fn!(function, FunctionData, defs); - impl_fn!(method, MethodData, defs); - impl_fn!(macro_data, MacroData, defs); - impl_fn!(mod_data, ModData, defs); - impl_fn!(typedef, TypeDefData, defs); - impl_fn!(variable, VariableData, defs); - - fn impl_data(&mut self, data: ImplData) { - if data.self_ref.is_some() { - self.result.relations.push(data.into()); + fn dump_relation(&mut self, data: Relation) { + self.result.relations.push(data); + } + fn import(&mut self, public: bool, import: Import) { + if public { + self.result.imports.push(import); } } - fn inheritance(&mut self, data: InheritanceData) { - self.result.relations.push(data.into()); - } -} - -// FIXME methods. The defs have information about possible overriding and the -// refs have decl information (e.g., a trait method where we know the required -// method, but not the supplied method). In both cases, we are currently -// ignoring it. - -impl Into> for UseData { - fn into(self) -> Option { - match self.visibility { - Visibility::Public => Some(Import { - kind: ImportKind::Use, - ref_id: self.mod_id.map(|id| id_from_def_id(id)), - span: self.span, - name: self.name, - value: String::new(), - }), - _ => None, - } - } -} -impl Into> for UseGlobData { - fn into(self) -> Option { - match self.visibility { - Visibility::Public => Some(Import { - kind: ImportKind::GlobUse, - ref_id: None, - span: self.span, - name: "*".to_owned(), - value: self.names.join(", "), - }), - _ => None, - } - } -} - -impl Into> for EnumData { - fn into(self) -> Option { - match self.visibility { - Visibility::Public => Some(Def { - kind: DefKind::Enum, - id: id_from_def_id(self.id), - span: self.span, - name: self.name, - qualname: self.qualname, - value: self.value, - parent: None, - children: self.variants.into_iter().map(|id| id_from_def_id(id)).collect(), - decl_id: None, - docs: self.docs, - sig: self.sig, - attributes: vec![], - }), - _ => None, - } - } -} - -impl Into> for TupleVariantData { - fn into(self) -> Option { - Some(Def { - kind: DefKind::Tuple, - id: id_from_def_id(self.id), - span: self.span, - name: self.name, - qualname: self.qualname, - value: self.value, - parent: self.parent.map(|id| id_from_def_id(id)), - children: vec![], - decl_id: None, - docs: self.docs, - sig: self.sig, - attributes: vec![], - }) - } -} -impl Into> for StructVariantData { - fn into(self) -> Option { - Some(Def { - kind: DefKind::Struct, - id: id_from_def_id(self.id), - span: self.span, - name: self.name, - qualname: self.qualname, - value: self.value, - parent: self.parent.map(|id| id_from_def_id(id)), - children: vec![], - decl_id: None, - docs: self.docs, - sig: self.sig, - attributes: vec![], - }) - } -} -impl Into> for StructData { - fn into(self) -> Option { - match self.visibility { - Visibility::Public => Some(Def { - kind: DefKind::Struct, - id: id_from_def_id(self.id), - span: self.span, - name: self.name, - qualname: self.qualname, - value: self.value, - parent: None, - children: self.fields.into_iter().map(|id| id_from_def_id(id)).collect(), - decl_id: None, - docs: self.docs, - sig: self.sig, - attributes: vec![], - }), - _ => None, - } - } -} -impl Into> for TraitData { - fn into(self) -> Option { - match self.visibility { - Visibility::Public => Some(Def { - kind: DefKind::Trait, - id: id_from_def_id(self.id), - span: self.span, - name: self.name, - qualname: self.qualname, - value: self.value, - children: self.items.into_iter().map(|id| id_from_def_id(id)).collect(), - parent: None, - decl_id: None, - docs: self.docs, - sig: self.sig, - attributes: vec![], - }), - _ => None, - } - } -} -impl Into> for FunctionData { - fn into(self) -> Option { - match self.visibility { - Visibility::Public => Some(Def { - kind: DefKind::Function, - id: id_from_def_id(self.id), - span: self.span, - name: self.name, - qualname: self.qualname, - value: self.value, - children: vec![], - parent: self.parent.map(|id| id_from_def_id(id)), - decl_id: None, - docs: self.docs, - sig: self.sig, - attributes: vec![], - }), - _ => None, - } - } -} -impl Into> for MethodData { - fn into(self) -> Option { - match self.visibility { - Visibility::Public => Some(Def { - kind: DefKind::Method, - id: id_from_def_id(self.id), - span: self.span, - name: self.name, - qualname: self.qualname, - value: self.value, - children: vec![], - parent: self.parent.map(|id| id_from_def_id(id)), - decl_id: self.decl_id.map(|id| id_from_def_id(id)), - docs: self.docs, - sig: self.sig, - attributes: vec![], - }), - _ => None, - } - } -} -impl Into> for MacroData { - fn into(self) -> Option { - Some(Def { - kind: DefKind::Macro, - id: id_from_def_id(null_def_id()), - span: self.span, - name: self.name, - qualname: self.qualname, - value: String::new(), - children: vec![], - parent: None, - decl_id: None, - docs: self.docs, - sig: None, - attributes: vec![], - }) - } -} -impl Into> for ModData { - fn into(self) -> Option { - match self.visibility { - Visibility::Public => Some(Def { - kind: DefKind::Mod, - id: id_from_def_id(self.id), - span: self.span, - name: self.name, - qualname: self.qualname, - value: self.filename, - children: self.items.into_iter().map(|id| id_from_def_id(id)).collect(), - parent: None, - decl_id: None, - docs: self.docs, - sig: self.sig.map(|s| s.into()), - attributes: vec![], - }), - _ => None, - } - } -} -impl Into> for TypeDefData { - fn into(self) -> Option { - match self.visibility { - Visibility::Public => Some(Def { - kind: DefKind::Type, - id: id_from_def_id(self.id), - span: self.span, - name: self.name, - qualname: self.qualname, - value: self.value, - children: vec![], - parent: self.parent.map(|id| id_from_def_id(id)), - decl_id: None, - docs: String::new(), - sig: self.sig.map(|s| s.into()), - attributes: vec![], - }), - _ => None, - } - } -} - -impl Into> for VariableData { - fn into(self) -> Option { - match self.visibility { - Visibility::Public => Some(Def { - kind: match self.kind { - VariableKind::Static => DefKind::Static, - VariableKind::Const => DefKind::Const, - VariableKind::Local => { return None } - VariableKind::Field => DefKind::Field, - }, - id: id_from_def_id(self.id), - span: self.span, - name: self.name, - qualname: self.qualname, - value: self.value, - children: vec![], - parent: self.parent.map(|id| id_from_def_id(id)), - decl_id: None, - docs: self.docs, - sig: self.sig.map(|s| s.into()), - attributes: vec![], - }), - _ => None, + fn dump_def(&mut self, public: bool, mut data: Def) { + if public { + data.attributes = vec![]; + self.result.defs.push(data); } } } diff --git a/src/librustc_save_analysis/json_dumper.rs b/src/librustc_save_analysis/json_dumper.rs index 58df612c687c..9cd375e98558 100644 --- a/src/librustc_save_analysis/json_dumper.rs +++ b/src/librustc_save_analysis/json_dumper.rs @@ -12,14 +12,11 @@ use std::io::Write; use rustc_serialize::json::as_json; -use rls_data::{self, Id, Analysis, Import, ImportKind, Def, DefKind, Ref, RefKind, MacroRef, - Relation, RelationKind, CratePreludeData}; +use rls_data::{self, Analysis, Import, Def, DefKind, Ref, RefKind, MacroRef, + Relation, CratePreludeData}; use rls_span::{Column, Row}; -use external_data::*; -use data::VariableKind; -use dump::Dump; -use id_from_def_id; +use Dump; pub struct JsonDumper { result: Analysis, @@ -70,71 +67,35 @@ impl Drop for JsonDumper { } } -macro_rules! impl_fn { - ($fn_name: ident, $data_type: ident, $bucket: ident) => { - fn $fn_name(&mut self, data: $data_type) { - self.result.$bucket.push(data.into()); - } - } -} - impl<'b, O: DumpOutput + 'b> Dump for JsonDumper { fn crate_prelude(&mut self, data: CratePreludeData) { self.result.prelude = Some(data) } - impl_fn!(extern_crate, ExternCrateData, imports); - impl_fn!(use_data, UseData, imports); - impl_fn!(use_glob, UseGlobData, imports); + fn macro_use(&mut self, data: MacroRef) { + self.result.macro_refs.push(data); + } - impl_fn!(enum_data, EnumData, defs); - impl_fn!(tuple_variant, TupleVariantData, defs); - impl_fn!(struct_variant, StructVariantData, defs); - impl_fn!(struct_data, StructData, defs); - impl_fn!(trait_data, TraitData, defs); - impl_fn!(function, FunctionData, defs); - impl_fn!(method, MethodData, defs); - impl_fn!(macro_data, MacroData, defs); - impl_fn!(typedef, TypeDefData, defs); - impl_fn!(variable, VariableData, defs); + fn import(&mut self, _: bool, import: Import) { + self.result.imports.push(import); + } - impl_fn!(function_ref, FunctionRefData, refs); - impl_fn!(function_call, FunctionCallData, refs); - impl_fn!(method_call, MethodCallData, refs); - impl_fn!(mod_ref, ModRefData, refs); - impl_fn!(type_ref, TypeRefData, refs); - impl_fn!(variable_ref, VariableRefData, refs); - - impl_fn!(macro_use, MacroUseData, macro_refs); - - fn mod_data(&mut self, data: ModData) { - let id: Id = id_from_def_id(data.id); - let mut def = Def { - kind: DefKind::Mod, - id: id, - span: data.span.into(), - name: data.name, - qualname: data.qualname, - value: data.filename, - parent: None, - children: data.items.into_iter().map(|id| id_from_def_id(id)).collect(), - decl_id: None, - docs: data.docs, - sig: data.sig, - attributes: data.attributes.into_iter().map(|a| a.into()).collect(), - }; - if def.span.file_name.to_str().unwrap() != def.value { + fn dump_ref(&mut self, data: Ref) { + self.result.refs.push(data); + } + fn dump_def(&mut self, _: bool, mut data: Def) { + if data.kind == DefKind::Mod && data.span.file_name.to_str().unwrap() != data.value { // If the module is an out-of-line defintion, then we'll make the // defintion the first character in the module's file and turn the // the declaration into a reference to it. let rf = Ref { kind: RefKind::Mod, - span: def.span, - ref_id: id, + span: data.span, + ref_id: data.id, }; self.result.refs.push(rf); - def.span = rls_data::SpanData { - file_name: def.value.clone().into(), + data.span = rls_data::SpanData { + file_name: data.value.clone().into(), byte_start: 0, byte_end: 0, line_start: Row::new_one_indexed(1), @@ -143,330 +104,10 @@ impl<'b, O: DumpOutput + 'b> Dump for JsonDumper { column_end: Column::new_one_indexed(1), } } - - self.result.defs.push(def); + self.result.defs.push(data); } - fn impl_data(&mut self, data: ImplData) { - if data.self_ref.is_some() { - self.result.relations.push(data.into()); - } - } - fn inheritance(&mut self, data: InheritanceData) { - self.result.relations.push(data.into()); - } -} - -// FIXME do we want to change ExternalData to this mode? It will break DXR. -// FIXME methods. The defs have information about possible overriding and the -// refs have decl information (e.g., a trait method where we know the required -// method, but not the supplied method). In both cases, we are currently -// ignoring it. - -impl Into for ExternCrateData { - fn into(self) -> Import { - Import { - kind: ImportKind::ExternCrate, - ref_id: None, - span: self.span, - name: self.name, - value: String::new(), - } - } -} -impl Into for UseData { - fn into(self) -> Import { - Import { - kind: ImportKind::Use, - ref_id: self.mod_id.map(|id| id_from_def_id(id)), - span: self.span, - name: self.name, - value: String::new(), - } - } -} -impl Into for UseGlobData { - fn into(self) -> Import { - Import { - kind: ImportKind::GlobUse, - ref_id: None, - span: self.span, - name: "*".to_owned(), - value: self.names.join(", "), - } - } -} - -impl Into for EnumData { - fn into(self) -> Def { - Def { - kind: DefKind::Enum, - id: id_from_def_id(self.id), - span: self.span, - name: self.name, - qualname: self.qualname, - value: self.value, - parent: None, - children: self.variants.into_iter().map(|id| id_from_def_id(id)).collect(), - decl_id: None, - docs: self.docs, - sig: self.sig, - attributes: self.attributes, - } - } -} - -impl Into for TupleVariantData { - fn into(self) -> Def { - Def { - kind: DefKind::Tuple, - id: id_from_def_id(self.id), - span: self.span, - name: self.name, - qualname: self.qualname, - value: self.value, - parent: None, - children: vec![], - decl_id: None, - docs: self.docs, - sig: self.sig, - attributes: self.attributes, - } - } -} -impl Into for StructVariantData { - fn into(self) -> Def { - Def { - kind: DefKind::Struct, - id: id_from_def_id(self.id), - span: self.span, - name: self.name, - qualname: self.qualname, - value: self.value, - parent: None, - children: vec![], - decl_id: None, - docs: self.docs, - sig: self.sig, - attributes: self.attributes, - } - } -} -impl Into for StructData { - fn into(self) -> Def { - Def { - kind: DefKind::Struct, - id: id_from_def_id(self.id), - span: self.span, - name: self.name, - qualname: self.qualname, - value: self.value, - parent: None, - children: self.fields.into_iter().map(|id| id_from_def_id(id)).collect(), - decl_id: None, - docs: self.docs, - sig: self.sig, - attributes: self.attributes, - } - } -} -impl Into for TraitData { - fn into(self) -> Def { - Def { - kind: DefKind::Trait, - id: id_from_def_id(self.id), - span: self.span, - name: self.name, - qualname: self.qualname, - value: self.value, - parent: None, - children: self.items.into_iter().map(|id| id_from_def_id(id)).collect(), - decl_id: None, - docs: self.docs, - sig: self.sig, - attributes: self.attributes, - } - } -} -impl Into for FunctionData { - fn into(self) -> Def { - Def { - kind: DefKind::Function, - id: id_from_def_id(self.id), - span: self.span, - name: self.name, - qualname: self.qualname, - value: self.value, - parent: None, - children: vec![], - decl_id: None, - docs: self.docs, - sig: self.sig, - attributes: self.attributes, - } - } -} -impl Into for MethodData { - fn into(self) -> Def { - Def { - kind: DefKind::Method, - id: id_from_def_id(self.id), - span: self.span, - name: self.name, - qualname: self.qualname, - value: self.value, - parent: None, - children: vec![], - decl_id: self.decl_id.map(|id| id_from_def_id(id)), - docs: self.docs, - sig: self.sig, - attributes: self.attributes, - } - } -} -impl Into for MacroData { - fn into(self) -> Def { - Def { - kind: DefKind::Macro, - id: id_from_def_id(null_def_id()), - span: self.span, - name: self.name, - qualname: self.qualname, - value: String::new(), - parent: None, - children: vec![], - decl_id: None, - docs: self.docs, - sig: None, - attributes: vec![], - } - } -} -impl Into for TypeDefData { - fn into(self) -> Def { - Def { - kind: DefKind::Type, - id: id_from_def_id(self.id), - span: self.span, - name: self.name, - qualname: self.qualname, - value: self.value, - parent: None, - children: vec![], - decl_id: None, - docs: String::new(), - sig: self.sig, - attributes: self.attributes, - } - } -} -impl Into for VariableData { - fn into(self) -> Def { - Def { - kind: match self.kind { - VariableKind::Static => DefKind::Static, - VariableKind::Const => DefKind::Const, - VariableKind::Local => DefKind::Local, - VariableKind::Field => DefKind::Field, - }, - id: id_from_def_id(self.id), - span: self.span, - name: self.name, - qualname: self.qualname, - value: self.type_value, - parent: None, - children: vec![], - decl_id: None, - docs: self.docs, - sig: None, - attributes: self.attributes, - } - } -} - -impl Into for FunctionRefData { - fn into(self) -> Ref { - Ref { - kind: RefKind::Function, - span: self.span, - ref_id: id_from_def_id(self.ref_id), - } - } -} -impl Into for FunctionCallData { - fn into(self) -> Ref { - Ref { - kind: RefKind::Function, - span: self.span, - ref_id: id_from_def_id(self.ref_id), - } - } -} -impl Into for MethodCallData { - fn into(self) -> Ref { - Ref { - kind: RefKind::Function, - span: self.span, - ref_id: id_from_def_id(self.ref_id.or(self.decl_id).unwrap_or(null_def_id())), - } - } -} -impl Into for ModRefData { - fn into(self) -> Ref { - Ref { - kind: RefKind::Mod, - span: self.span, - ref_id: id_from_def_id(self.ref_id.unwrap_or(null_def_id())), - } - } -} -impl Into for TypeRefData { - fn into(self) -> Ref { - Ref { - kind: RefKind::Type, - span: self.span, - ref_id: id_from_def_id(self.ref_id.unwrap_or(null_def_id())), - } - } -} -impl Into for VariableRefData { - fn into(self) -> Ref { - Ref { - kind: RefKind::Variable, - span: self.span, - ref_id: id_from_def_id(self.ref_id), - } - } -} - -impl Into for MacroUseData { - fn into(self) -> MacroRef { - MacroRef { - span: self.span, - qualname: self.qualname, - callee_span: self.callee_span.into(), - } - } -} - -impl Into for ImplData { - fn into(self) -> Relation { - Relation { - span: self.span, - kind: RelationKind::Impl, - from: id_from_def_id(self.self_ref.unwrap_or(null_def_id())), - to: id_from_def_id(self.trait_ref.unwrap_or(null_def_id())), - } - } -} - -impl Into for InheritanceData { - fn into(self) -> Relation { - Relation { - span: self.span, - kind: RelationKind::SuperTrait, - from: id_from_def_id(self.base_id), - to: id_from_def_id(self.deriv_id), - } + fn dump_relation(&mut self, data: Relation) { + self.result.relations.push(data); } } diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index be879a01fb8f..0b2614ee83ca 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -37,17 +37,14 @@ extern crate rls_span; mod json_api_dumper; mod json_dumper; -mod data; -mod dump; mod dump_visitor; -pub mod external_data; #[macro_use] -pub mod span_utils; +mod span_utils; mod sig; use rustc::hir; -use rustc::hir::def::Def; -use rustc::hir::map::Node; +use rustc::hir::def::Def as HirDef; +use rustc::hir::map::{Node, NodeItem}; use rustc::hir::def_id::DefId; use rustc::session::config::CrateType::CrateTypeExecutable; use rustc::session::Session; @@ -61,32 +58,21 @@ use std::path::{Path, PathBuf}; use syntax::ast::{self, NodeId, PatKind, Attribute, CRATE_NODE_ID}; use syntax::parse::lexer::comments::strip_doc_comment_decoration; use syntax::parse::token; +use syntax::print::pprust; use syntax::symbol::keywords; use syntax::visit::{self, Visitor}; use syntax::print::pprust::{ty_to_string, arg_to_string}; use syntax::codemap::MacroAttribute; use syntax_pos::*; -pub use self::json_api_dumper::JsonApiDumper; -pub use self::json_dumper::JsonDumper; -pub use self::data::*; -pub use self::external_data::make_def_id; -pub use self::dump::Dump; -pub use self::dump_visitor::DumpVisitor; -use self::span_utils::SpanUtils; +pub use json_api_dumper::JsonApiDumper; +pub use json_dumper::JsonDumper; +use dump_visitor::DumpVisitor; +use span_utils::SpanUtils; -// FIXME this is legacy code and should be removed -pub mod recorder { - pub use self::Row::*; +use rls_data::{Ref, RefKind, SpanData, MacroRef, Def, DefKind, Relation, RelationKind, + ExternalCrateData, Import, CratePreludeData}; - #[derive(Copy, Clone, Debug, Eq, PartialEq)] - pub enum Row { - TypeRef, - ModRef, - VarRef, - FnRef, - } -} pub struct SaveContext<'l, 'tcx: 'l> { tcx: TyCtxt<'l, 'tcx, 'tcx>, @@ -95,13 +81,49 @@ pub struct SaveContext<'l, 'tcx: 'l> { span_utils: SpanUtils<'tcx>, } +#[derive(Debug)] +pub enum Data { + /// Data about a macro use. + MacroUseData(MacroRef), + RefData(Ref), + DefData(Def), + RelationData(Relation), +} + +pub trait Dump { + fn crate_prelude(&mut self, _: CratePreludeData); + fn macro_use(&mut self, _: MacroRef) {} + fn import(&mut self, _: bool, _: Import); + fn dump_ref(&mut self, _: Ref) {} + fn dump_def(&mut self, _: bool, _: Def); + fn dump_relation(&mut self, data: Relation); +} + macro_rules! option_try( ($e:expr) => (match $e { Some(e) => e, None => return None }) ); impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { + fn span_from_span(&self, span: Span) -> SpanData { + use rls_span::{Row, Column}; + + let cm = self.tcx.sess.codemap(); + let start = cm.lookup_char_pos(span.lo); + let end = cm.lookup_char_pos(span.hi); + + SpanData { + file_name: start.file.name.clone().into(), + byte_start: span.lo.0, + byte_end: span.hi.0, + line_start: Row::new_one_indexed(start.line as u32), + line_end: Row::new_one_indexed(end.line as u32), + column_start: Column::new_one_indexed(start.col.0 as u32 + 1), + column_end: Column::new_one_indexed(end.col.0 as u32 + 1), + } + } + // List external crates used by the current crate. - pub fn get_external_crates(&self) -> Vec { + pub fn get_external_crates(&self) -> Vec { let mut result = Vec::new(); for n in self.tcx.sess.cstore.crates() { @@ -112,10 +134,11 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { continue; } }; - result.push(CrateData { + let lo_loc = self.span_utils.sess.codemap().lookup_char_pos(span.lo); + result.push(ExternalCrateData { name: self.tcx.sess.cstore.crate_name(n).to_string(), - number: n.as_u32(), - span: span, + num: n.as_u32(), + file_name: SpanUtils::make_path_string(&lo_loc.file.name), }); } @@ -128,39 +151,43 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { ast::ForeignItemKind::Fn(ref decl, ref generics) => { let sub_span = self.span_utils.sub_span_after_keyword(item.span, keywords::Fn); filter!(self.span_utils, sub_span, item.span, None); - Some(Data::FunctionData(FunctionData { - id: item.id, + + Some(Data::DefData(Def { + kind: DefKind::Function, + id: id_from_node_id(item.id, self), + span: self.span_from_span(sub_span.unwrap()), name: item.ident.to_string(), - qualname: qualname, - declaration: None, - span: sub_span.unwrap(), - scope: self.enclosing_scope(item.id), + qualname, value: make_signature(decl, generics), - visibility: From::from(&item.vis), parent: None, + children: vec![], + decl_id: None, docs: docs_for_attrs(&item.attrs), sig: sig::foreign_item_signature(item, self), - attributes: item.attrs.clone(), + attributes: lower_attributes(item.attrs.clone(), self), })) } ast::ForeignItemKind::Static(ref ty, m) => { let keyword = if m { keywords::Mut } else { keywords::Static }; let sub_span = self.span_utils.sub_span_after_keyword(item.span, keyword); filter!(self.span_utils, sub_span, item.span, None); - Some(Data::VariableData(VariableData { - id: item.id, - kind: VariableKind::Static, + + let id = ::id_from_node_id(item.id, self); + let span = self.span_from_span(sub_span.unwrap()); + + Some(Data::DefData(Def { + kind: DefKind::Static, + id, + span, name: item.ident.to_string(), - qualname: qualname, - span: sub_span.unwrap(), - scope: self.enclosing_scope(item.id), + qualname, + value: ty_to_string(ty), parent: None, - value: String::new(), - type_value: ty_to_string(ty), - visibility: From::from(&item.vis), + children: vec![], + decl_id: None, docs: docs_for_attrs(&item.attrs), sig: sig::foreign_item_signature(item, self), - attributes: item.attrs.clone(), + attributes: lower_attributes(item.attrs.clone(), self), })) } } @@ -172,70 +199,71 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { let qualname = format!("::{}", self.tcx.node_path_str(item.id)); let sub_span = self.span_utils.sub_span_after_keyword(item.span, keywords::Fn); filter!(self.span_utils, sub_span, item.span, None); - - - Some(Data::FunctionData(FunctionData { - id: item.id, + Some(Data::DefData(Def { + kind: DefKind::Function, + id: id_from_node_id(item.id, self), + span: self.span_from_span(sub_span.unwrap()), name: item.ident.to_string(), - qualname: qualname, - declaration: None, - span: sub_span.unwrap(), - scope: self.enclosing_scope(item.id), + qualname, value: make_signature(decl, generics), - visibility: From::from(&item.vis), parent: None, + children: vec![], + decl_id: None, docs: docs_for_attrs(&item.attrs), sig: sig::item_signature(item, self), - attributes: item.attrs.clone(), + attributes: lower_attributes(item.attrs.clone(), self), })) } - ast::ItemKind::Static(ref typ, mt, ref expr) => { + ast::ItemKind::Static(ref typ, mt, _) => { let qualname = format!("::{}", self.tcx.node_path_str(item.id)); - // If the variable is immutable, save the initialising expression. - let (value, keyword) = match mt { - ast::Mutability::Mutable => (String::from(""), keywords::Mut), - ast::Mutability::Immutable => { - (self.span_utils.snippet(expr.span), keywords::Static) - }, + let keyword = match mt { + ast::Mutability::Mutable => keywords::Mut, + ast::Mutability::Immutable => keywords::Static, }; let sub_span = self.span_utils.sub_span_after_keyword(item.span, keyword); filter!(self.span_utils, sub_span, item.span, None); - Some(Data::VariableData(VariableData { - id: item.id, - kind: VariableKind::Static, + + let id = id_from_node_id(item.id, self); + let span = self.span_from_span(sub_span.unwrap()); + + Some(Data::DefData(Def { + kind: DefKind::Static, + id, + span, name: item.ident.to_string(), - qualname: qualname, - span: sub_span.unwrap(), - scope: self.enclosing_scope(item.id), + qualname, + value: ty_to_string(&typ), parent: None, - value: value, - type_value: ty_to_string(&typ), - visibility: From::from(&item.vis), + children: vec![], + decl_id: None, docs: docs_for_attrs(&item.attrs), sig: sig::item_signature(item, self), - attributes: item.attrs.clone(), + attributes: lower_attributes(item.attrs.clone(), self), })) } - ast::ItemKind::Const(ref typ, ref expr) => { + ast::ItemKind::Const(ref typ, _) => { let qualname = format!("::{}", self.tcx.node_path_str(item.id)); let sub_span = self.span_utils.sub_span_after_keyword(item.span, keywords::Const); filter!(self.span_utils, sub_span, item.span, None); - Some(Data::VariableData(VariableData { - id: item.id, - kind: VariableKind::Const, + + let id = id_from_node_id(item.id, self); + let span = self.span_from_span(sub_span.unwrap()); + + Some(Data::DefData(Def { + kind: DefKind::Const, + id, + span, name: item.ident.to_string(), - qualname: qualname, - span: sub_span.unwrap(), - scope: self.enclosing_scope(item.id), + qualname, + value: ty_to_string(typ), parent: None, - value: self.span_utils.snippet(expr.span), - type_value: ty_to_string(&typ), - visibility: From::from(&item.vis), + children: vec![], + decl_id: None, docs: docs_for_attrs(&item.attrs), sig: sig::item_signature(item, self), - attributes: item.attrs.clone(), + attributes: lower_attributes(item.attrs.clone(), self), })) } ast::ItemKind::Mod(ref m) => { @@ -247,18 +275,19 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { let sub_span = self.span_utils.sub_span_after_keyword(item.span, keywords::Mod); filter!(self.span_utils, sub_span, item.span, None); - Some(Data::ModData(ModData { - id: item.id, + Some(Data::DefData(Def { + kind: DefKind::Mod, + id: id_from_node_id(item.id, self), name: item.ident.to_string(), - qualname: qualname, - span: sub_span.unwrap(), - scope: self.enclosing_scope(item.id), - filename: filename, - items: m.items.iter().map(|i| i.id).collect(), - visibility: From::from(&item.vis), + qualname, + span: self.span_from_span(sub_span.unwrap()), + value: filename, + parent: None, + children: m.items.iter().map(|i| id_from_node_id(i.id, self)).collect(), + decl_id: None, docs: docs_for_attrs(&item.attrs), sig: sig::item_signature(item, self), - attributes: item.attrs.clone(), + attributes: lower_attributes(item.attrs.clone(), self), })) } ast::ItemKind::Enum(ref def, _) => { @@ -270,61 +299,47 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { .map(|v| v.node.name.to_string()) .collect::>() .join(", "); - let val = format!("{}::{{{}}}", name, variants_str); - Some(Data::EnumData(EnumData { - id: item.id, - name: name, - value: val, - span: sub_span.unwrap(), - qualname: qualname, - scope: self.enclosing_scope(item.id), - variants: def.variants.iter().map(|v| v.node.data.id()).collect(), - visibility: From::from(&item.vis), + let value = format!("{}::{{{}}}", name, variants_str); + Some(Data::DefData(Def { + kind: DefKind::Enum, + id: id_from_node_id(item.id, self), + span: self.span_from_span(sub_span.unwrap()), + name, + qualname, + value, + parent: None, + children: def.variants + .iter() + .map(|v| id_from_node_id(v.node.data.id(), self)) + .collect(), + decl_id: None, docs: docs_for_attrs(&item.attrs), sig: sig::item_signature(item, self), - attributes: item.attrs.clone(), + attributes: lower_attributes(item.attrs.to_owned(), self), })) } ast::ItemKind::Impl(.., ref trait_ref, ref typ, _) => { - let mut type_data = None; - let sub_span; - - let parent = self.enclosing_scope(item.id); - - match typ.node { + if let ast::TyKind::Path(None, ref path) = typ.node { // Common case impl for a struct or something basic. - ast::TyKind::Path(None, ref path) => { - if generated_code(path.span) { - return None; - } - sub_span = self.span_utils.sub_span_for_type_name(path.span); - type_data = self.lookup_ref_id(typ.id).map(|id| { - TypeRefData { - span: sub_span.unwrap(), - scope: parent, - ref_id: Some(id), - qualname: String::new() // FIXME: generate the real qualname - } - }); - } - _ => { - // Less useful case, impl for a compound type. - let span = typ.span; - sub_span = self.span_utils.sub_span_for_type_name(span).or(Some(span)); + if generated_code(path.span) { + return None; } + let sub_span = self.span_utils.sub_span_for_type_name(path.span); + filter!(self.span_utils, sub_span, typ.span, None); + + let type_data = self.lookup_ref_id(typ.id); + type_data.map(|type_data| Data::RelationData(Relation { + kind: RelationKind::Impl, + span: self.span_from_span(sub_span.unwrap()), + from: id_from_def_id(type_data), + to: trait_ref.as_ref() + .and_then(|t| self.lookup_ref_id(t.ref_id)) + .map(id_from_def_id) + .unwrap_or(null_id()), + })) + } else { + None } - - let trait_data = trait_ref.as_ref() - .and_then(|tr| self.get_trait_ref_data(tr, parent)); - - filter!(self.span_utils, sub_span, typ.span, None); - Some(Data::ImplData(ImplData2 { - id: item.id, - span: sub_span.unwrap(), - scope: parent, - trait_ref: trait_data, - self_ref: type_data, - })) } _ => { // FIXME @@ -336,7 +351,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { pub fn get_field_data(&self, field: &ast::StructField, scope: NodeId) - -> Option { + -> Option { if let Some(ident) = field.ident { let name = ident.to_string(); let qualname = format!("::{}::{}", self.tcx.node_path_str(scope), ident); @@ -345,20 +360,23 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { let def_id = self.tcx.hir.local_def_id(field.id); let typ = self.tcx.type_of(def_id).to_string(); - Some(VariableData { - id: field.id, - kind: VariableKind::Field, - name: name, - qualname: qualname, - span: sub_span.unwrap(), - scope: scope, - parent: Some(make_def_id(scope, &self.tcx.hir)), - value: "".to_owned(), - type_value: typ, - visibility: From::from(&field.vis), + + let id = id_from_node_id(field.id, self); + let span = self.span_from_span(sub_span.unwrap()); + + Some(Def { + kind: DefKind::Field, + id, + span, + name, + qualname, + value: typ, + parent: Some(id_from_node_id(scope, self)), + children: vec![], + decl_id: None, docs: docs_for_attrs(&field.attrs), sig: sig::field_signature(field, self), - attributes: field.attrs.clone(), + attributes: lower_attributes(field.attrs.clone(), self), }) } else { None @@ -371,10 +389,10 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { id: ast::NodeId, name: ast::Name, span: Span) - -> Option { + -> Option { // The qualname for a method is the trait name or name of the struct in an impl in // which the method is declared in, followed by the method's name. - let (qualname, parent_scope, decl_id, vis, docs, attributes) = + let (qualname, parent_scope, decl_id, docs, attributes) = match self.tcx.impl_of_method(self.tcx.hir.local_def_id(id)) { Some(impl_id) => match self.tcx.hir.get_if_local(impl_id) { Some(Node::NodeItem(item)) => { @@ -383,7 +401,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { let mut result = String::from("<"); result.push_str(&self.tcx.hir.node_to_pretty_string(ty.id)); - let trait_id = self.tcx.trait_id_of_impl(impl_id); + let mut trait_id = self.tcx.trait_id_of_impl(impl_id); let mut decl_id = None; if let Some(def_id) = trait_id { result.push_str(" as "); @@ -391,11 +409,16 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { self.tcx.associated_items(def_id) .find(|item| item.name == name) .map(|item| decl_id = Some(item.def_id)); + } else { + if let Some(NodeItem(item)) = self.tcx.hir.find(id) { + if let hir::ItemImpl(_, _, _, _, _, ref ty, _) = item.node { + trait_id = self.lookup_ref_id(ty.id); + } + } } result.push_str(">"); (result, trait_id, decl_id, - From::from(&item.vis), docs_for_attrs(&item.attrs), item.attrs.to_vec()) } @@ -421,7 +444,6 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { Some(Node::NodeItem(item)) => { (format!("::{}", self.tcx.item_path_str(def_id)), Some(def_id), None, - From::from(&item.vis), docs_for_attrs(&item.attrs), item.attrs.to_vec()) } @@ -449,27 +471,26 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { let sub_span = self.span_utils.sub_span_after_keyword(span, keywords::Fn); filter!(self.span_utils, sub_span, span, None); - Some(FunctionData { - id: id, + Some(Def { + kind: DefKind::Method, + id: id_from_node_id(id, self), + span: self.span_from_span(sub_span.unwrap()), name: name.to_string(), - qualname: qualname, - declaration: decl_id, - span: sub_span.unwrap(), - scope: self.enclosing_scope(id), + qualname, // FIXME you get better data here by using the visitor. value: String::new(), - visibility: vis, - parent: parent_scope, - docs: docs, + parent: parent_scope.map(|id| id_from_def_id(id)), + children: vec![], + decl_id: decl_id.map(|id| id_from_def_id(id)), + docs, sig: None, - attributes: attributes, + attributes: lower_attributes(attributes, self), }) } pub fn get_trait_ref_data(&self, - trait_ref: &ast::TraitRef, - parent: NodeId) - -> Option { + trait_ref: &ast::TraitRef) + -> Option { self.lookup_ref_id(trait_ref.ref_id).and_then(|def_id| { let span = trait_ref.path.span; if generated_code(span) { @@ -477,11 +498,11 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { } 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 { - span: sub_span.unwrap(), - scope: parent, - ref_id: Some(def_id), - qualname: String::new() // FIXME: generate the real qualname + let span = self.span_from_span(sub_span.unwrap()); + Some(Ref { + kind: RefKind::Type, + span, + ref_id: id_from_def_id(def_id), }) }) } @@ -507,11 +528,11 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { let f = def.struct_variant().field_named(ident.node.name); let sub_span = self.span_utils.span_for_last_ident(expr.span); filter!(self.span_utils, sub_span, expr.span, None); - return Some(Data::VariableRefData(VariableRefData { - name: ident.node.to_string(), - span: sub_span.unwrap(), - scope: self.enclosing_scope(expr.id), - ref_id: f.did, + let span = self.span_from_span(sub_span.unwrap()); + return Some(Data::RefData(Ref { + kind: RefKind::Variable, + span, + ref_id: id_from_def_id(f.did), })); } _ => { @@ -525,11 +546,11 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { ty::TyAdt(def, _) if !def.is_enum() => { let sub_span = self.span_utils.span_for_last_ident(path.span); filter!(self.span_utils, sub_span, path.span, None); - Some(Data::TypeRefData(TypeRefData { - span: sub_span.unwrap(), - scope: self.enclosing_scope(expr.id), - ref_id: Some(def.did), - qualname: String::new() // FIXME: generate the real qualname + let span = self.span_from_span(sub_span.unwrap()); + Some(Data::RefData(Ref { + kind: RefKind::Type, + span, + ref_id: id_from_def_id(def.did), })) } _ => { @@ -548,16 +569,15 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { }; let sub_span = self.span_utils.sub_span_for_meth_name(expr.span); filter!(self.span_utils, sub_span, expr.span, None); - let parent = self.enclosing_scope(expr.id); - Some(Data::MethodCallData(MethodCallData { - span: sub_span.unwrap(), - scope: parent, - ref_id: def_id, - decl_id: decl_id, + let span = self.span_from_span(sub_span.unwrap()); + Some(Data::RefData(Ref { + kind: RefKind::Function, + span, + ref_id: def_id.or(decl_id).map(|id| id_from_def_id(id)).unwrap_or(null_id()), })) } ast::ExprKind::Path(_, ref path) => { - self.get_path_data(expr.id, path) + self.get_path_data(expr.id, path).map(|d| Data::RefData(d)) } _ => { // FIXME @@ -566,7 +586,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { } } - pub fn get_path_def(&self, id: NodeId) -> Def { + pub fn get_path_def(&self, id: NodeId) -> HirDef { match self.tcx.hir.get(id) { Node::NodeTraitRef(tr) => tr.path.def, @@ -582,7 +602,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { } Node::NodeLocal(&hir::Pat { node: hir::PatKind::Binding(_, def_id, ..), .. }) => { - Def::Local(def_id) + HirDef::Local(def_id) } Node::NodeTy(ty) => { @@ -595,58 +615,58 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { for item in self.tcx.associated_items(proj.trait_ref.def_id) { if item.kind == ty::AssociatedKind::Type { if item.name == proj.item_name(self.tcx) { - return Def::AssociatedTy(item.def_id); + return HirDef::AssociatedTy(item.def_id); } } } } - Def::Err + HirDef::Err } } } else { - Def::Err + HirDef::Err } } - _ => Def::Err + _ => HirDef::Err } } - pub fn get_path_data(&self, id: NodeId, path: &ast::Path) -> Option { + pub fn get_path_data(&self, id: NodeId, path: &ast::Path) -> Option { let def = self.get_path_def(id); let sub_span = self.span_utils.span_for_last_ident(path.span); filter!(self.span_utils, sub_span, path.span, None); match def { - Def::Upvar(..) | - Def::Local(..) | - Def::Static(..) | - Def::Const(..) | - Def::AssociatedConst(..) | - Def::StructCtor(..) | - Def::VariantCtor(..) => { - Some(Data::VariableRefData(VariableRefData { - name: self.span_utils.snippet(sub_span.unwrap()), - span: sub_span.unwrap(), - scope: self.enclosing_scope(id), - ref_id: def.def_id(), - })) + HirDef::Upvar(..) | + HirDef::Local(..) | + HirDef::Static(..) | + HirDef::Const(..) | + HirDef::AssociatedConst(..) | + HirDef::StructCtor(..) | + HirDef::VariantCtor(..) => { + let span = self.span_from_span(sub_span.unwrap()); + Some(Ref { + kind: RefKind::Variable, + span, + ref_id: id_from_def_id(def.def_id()), + }) } - Def::Struct(def_id) | - Def::Variant(def_id, ..) | - Def::Union(def_id) | - Def::Enum(def_id) | - Def::TyAlias(def_id) | - Def::AssociatedTy(def_id) | - Def::Trait(def_id) | - Def::TyParam(def_id) => { - Some(Data::TypeRefData(TypeRefData { - span: sub_span.unwrap(), - ref_id: Some(def_id), - scope: self.enclosing_scope(id), - qualname: String::new() // FIXME: generate the real qualname - })) + HirDef::Struct(def_id) | + HirDef::Variant(def_id, ..) | + HirDef::Union(def_id) | + HirDef::Enum(def_id) | + HirDef::TyAlias(def_id) | + HirDef::AssociatedTy(def_id) | + HirDef::Trait(def_id) | + HirDef::TyParam(def_id) => { + let span = self.span_from_span(sub_span.unwrap()); + Some(Ref { + kind: RefKind::Type, + span, + ref_id: id_from_def_id(def_id), + }) } - Def::Method(decl_id) => { + HirDef::Method(decl_id) => { let sub_span = self.span_utils.sub_span_for_meth_name(path.span); filter!(self.span_utils, sub_span, path.span, None); let def_id = if decl_id.is_local() { @@ -657,60 +677,60 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { } else { None }; - Some(Data::MethodCallData(MethodCallData { - span: sub_span.unwrap(), - scope: self.enclosing_scope(id), - ref_id: def_id, - decl_id: Some(decl_id), - })) + let span = self.span_from_span(sub_span.unwrap()); + Some(Ref { + kind: RefKind::Function, + span, + ref_id: id_from_def_id(def_id.unwrap_or(decl_id)), + }) } - Def::Fn(def_id) => { - Some(Data::FunctionCallData(FunctionCallData { - ref_id: def_id, - span: sub_span.unwrap(), - scope: self.enclosing_scope(id), - })) + HirDef::Fn(def_id) => { + let span = self.span_from_span(sub_span.unwrap()); + Some(Ref { + kind: RefKind::Function, + span, + ref_id: id_from_def_id(def_id), + }) } - Def::Mod(def_id) => { - Some(Data::ModRefData(ModRefData { - ref_id: Some(def_id), - span: sub_span.unwrap(), - scope: self.enclosing_scope(id), - qualname: String::new() // FIXME: generate the real qualname - })) + HirDef::Mod(def_id) => { + let span = self.span_from_span(sub_span.unwrap()); + Some(Ref { + kind: RefKind::Mod, + span, + ref_id: id_from_def_id(def_id), + }) } - Def::PrimTy(..) | - Def::SelfTy(..) | - Def::Label(..) | - Def::Macro(..) | - Def::GlobalAsm(..) | - Def::Err => None, + HirDef::PrimTy(..) | + HirDef::SelfTy(..) | + HirDef::Label(..) | + HirDef::Macro(..) | + HirDef::GlobalAsm(..) | + HirDef::Err => None, } } pub fn get_field_ref_data(&self, field_ref: &ast::Field, - variant: &ty::VariantDef, - parent: NodeId) - -> Option { + variant: &ty::VariantDef) + -> Option { let f = variant.field_named(field_ref.ident.node.name); // We don't really need a sub-span here, but no harm done let sub_span = self.span_utils.span_for_last_ident(field_ref.ident.span); filter!(self.span_utils, sub_span, field_ref.ident.span, None); - Some(VariableRefData { - name: field_ref.ident.node.to_string(), - span: sub_span.unwrap(), - scope: parent, - ref_id: f.did, + let span = self.span_from_span(sub_span.unwrap()); + Some(Ref { + kind: RefKind::Variable, + span, + ref_id: id_from_def_id(f.did), }) } - /// Attempt to return MacroUseData for any AST node. + /// Attempt to return MacroRef for any AST node. /// /// For a given piece of AST defined by the supplied Span and NodeId, /// returns None if the node is not macro-generated or the span is malformed, - /// else uses the expansion callsite and callee to return some MacroUseData. - pub fn get_macro_use_data(&self, span: Span, id: NodeId) -> Option { + /// else uses the expansion callsite and callee to return some MacroRef. + pub fn get_macro_use_data(&self, span: Span) -> Option { if !generated_code(span) { return None; } @@ -718,6 +738,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { // nested expansions and ensure we only generate data for source-visible // macro uses. let callsite = span.source_callsite(); + let callsite_span = self.span_from_span(callsite); let callee = option_try!(span.source_callee()); let callee_span = option_try!(callee.span); @@ -731,34 +752,25 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { // when read in, and no longer correspond to the source. if let Some(mac) = self.tcx.sess.imported_macro_spans.borrow().get(&callee_span) { let &(ref mac_name, mac_span) = mac; - return Some(MacroUseData { - span: callsite, - name: mac_name.clone(), - callee_span: mac_span, - scope: self.enclosing_scope(id), - imported: true, - qualname: String::new()// FIXME: generate the real qualname - }); + let mac_span = self.span_from_span(mac_span); + return Some(MacroRef { + span: callsite_span, + qualname: mac_name.clone(), // FIXME: generate the real qualname + callee_span: mac_span, + }); } - Some(MacroUseData { - span: callsite, - name: callee.name().to_string(), - callee_span: callee_span, - scope: self.enclosing_scope(id), - imported: false, - qualname: String::new() // FIXME: generate the real qualname + let callee_span = self.span_from_span(callee_span); + Some(MacroRef { + span: callsite_span, + qualname: callee.name().to_string(), // FIXME: generate the real qualname + callee_span, }) } - pub fn get_data_for_id(&self, _id: &NodeId) -> Data { - // FIXME - bug!(); - } - fn lookup_ref_id(&self, ref_id: NodeId) -> Option { match self.get_path_def(ref_id) { - Def::PrimTy(_) | Def::SelfTy(..) | Def::Err => None, + HirDef::PrimTy(_) | HirDef::SelfTy(..) | HirDef::Err => None, def => Some(def.def_id()), } } @@ -800,7 +812,7 @@ fn make_signature(decl: &ast::FnDecl, generics: &ast::Generics) -> String { // An AST visitor for collecting paths from patterns. struct PathCollector { // The Row field identifies the kind of pattern. - collected_paths: Vec<(NodeId, ast::Path, ast::Mutability, recorder::Row)>, + collected_paths: Vec<(NodeId, ast::Path, ast::Mutability)>, } impl PathCollector { @@ -814,12 +826,12 @@ impl<'a> Visitor<'a> for PathCollector { match p.node { PatKind::Struct(ref path, ..) => { self.collected_paths.push((p.id, path.clone(), - ast::Mutability::Mutable, recorder::TypeRef)); + ast::Mutability::Mutable)); } PatKind::TupleStruct(ref path, ..) | PatKind::Path(_, ref path) => { self.collected_paths.push((p.id, path.clone(), - ast::Mutability::Mutable, recorder::VarRef)); + ast::Mutability::Mutable)); } PatKind::Ident(bm, ref path1, _) => { debug!("PathCollector, visit ident in pat {}: {:?} {:?}", @@ -835,7 +847,7 @@ impl<'a> Visitor<'a> for PathCollector { }; // collect path for either visit_local or visit_arm let path = ast::Path::from_ident(path1.span, path1.node); - self.collected_paths.push((p.id, path, immut, recorder::VarRef)); + self.collected_paths.push((p.id, path, immut)); } _ => {} } @@ -1032,6 +1044,34 @@ fn id_from_def_id(id: DefId) -> rls_data::Id { } fn id_from_node_id(id: NodeId, scx: &SaveContext) -> rls_data::Id { - let def_id = scx.tcx.hir.local_def_id(id); - id_from_def_id(def_id) + let def_id = scx.tcx.hir.opt_local_def_id(id); + def_id.map(|id| id_from_def_id(id)).unwrap_or_else(null_id) +} + +fn null_id() -> rls_data::Id { + rls_data::Id { + krate: u32::max_value(), + index: u32::max_value(), + } +} + +fn lower_attributes(attrs: Vec, scx: &SaveContext) -> Vec { + attrs.into_iter() + // Only retain real attributes. Doc comments are lowered separately. + .filter(|attr| attr.path != "doc") + .map(|mut attr| { + // Remove the surrounding '#[..]' or '#![..]' of the pretty printed + // attribute. First normalize all inner attribute (#![..]) to outer + // ones (#[..]), then remove the two leading and the one trailing character. + attr.style = ast::AttrStyle::Outer; + let value = pprust::attribute_to_string(&attr); + // This str slicing works correctly, because the leading and trailing characters + // are in the ASCII range and thus exactly one byte each. + let value = value[2..value.len()-1].to_string(); + + rls_data::Attribute { + value: value, + span: scx.span_from_span(attr.span), + } + }).collect() } diff --git a/src/librustc_save_analysis/span_utils.rs b/src/librustc_save_analysis/span_utils.rs index af3efb480908..77cde33e9620 100644 --- a/src/librustc_save_analysis/span_utils.rs +++ b/src/librustc_save_analysis/span_utils.rs @@ -20,7 +20,6 @@ use syntax::ast; use syntax::parse::lexer::{self, StringReader}; use syntax::parse::token::{self, Token}; use syntax::symbol::keywords; -use syntax::tokenstream::TokenTree; use syntax_pos::*; #[derive(Clone)] @@ -277,45 +276,6 @@ impl<'a> SpanUtils<'a> { } } - /// `span` must be the span for an item such as a function or struct. This - /// function returns the program text from the start of the span until the - /// end of the 'signature' part, that is up to, but not including an opening - /// brace or semicolon. - pub fn signature_string_for_span(&self, span: Span) -> String { - let mut toks = self.retokenise_span(span); - toks.real_token(); - let mut toks = toks.parse_all_token_trees().unwrap().trees(); - let mut prev = toks.next().unwrap(); - - let first_span = prev.span(); - let mut angle_count = 0; - for tok in toks { - if let TokenTree::Token(_, ref tok) = prev { - angle_count += match *tok { - token::Eof => { break; } - token::Lt => 1, - token::Gt => -1, - token::BinOp(token::Shl) => 2, - token::BinOp(token::Shr) => -2, - _ => 0, - }; - } - if angle_count > 0 { - prev = tok; - continue; - } - if let TokenTree::Token(_, token::Semi) = tok { - return self.snippet(first_span.to(prev.span())); - } else if let TokenTree::Delimited(_, ref d) = tok { - if d.delim == token::Brace { - return self.snippet(first_span.to(prev.span())); - } - } - prev = tok; - } - self.snippet(span) - } - pub fn sub_span_before_token(&self, span: Span, tok: Token) -> Option { let mut toks = self.retokenise_span(span); let mut prev = toks.real_token(); @@ -385,57 +345,44 @@ impl<'a> SpanUtils<'a> { self.spans_with_brackets(span, 1, number) } - pub fn report_span_err(&self, kind: &str, span: Span) { - let loc = self.sess.codemap().lookup_char_pos(span.lo); - info!("({}) Could not find sub_span in `{}` in {}, line {}", - kind, - self.snippet(span), - loc.file.name, - loc.line); - self.err_count.set(self.err_count.get() + 1); - if self.err_count.get() > 1000 { - bug!("span errors reached 1000, giving up"); - } - } + // // Return the name for a macro definition (identifier after first `!`) + // pub fn span_for_macro_def_name(&self, span: Span) -> Option { + // let mut toks = self.retokenise_span(span); + // loop { + // let ts = toks.real_token(); + // if ts.tok == token::Eof { + // return None; + // } + // if ts.tok == token::Not { + // let ts = toks.real_token(); + // if ts.tok.is_ident() { + // return Some(ts.sp); + // } else { + // return None; + // } + // } + // } + // } - // Return the name for a macro definition (identifier after first `!`) - pub fn span_for_macro_def_name(&self, span: Span) -> Option { - let mut toks = self.retokenise_span(span); - loop { - let ts = toks.real_token(); - if ts.tok == token::Eof { - return None; - } - if ts.tok == token::Not { - let ts = toks.real_token(); - if ts.tok.is_ident() { - return Some(ts.sp); - } else { - return None; - } - } - } - } - - // Return the name for a macro use (identifier before first `!`). - pub fn span_for_macro_use_name(&self, span:Span) -> Option { - let mut toks = self.retokenise_span(span); - let mut prev = toks.real_token(); - loop { - if prev.tok == token::Eof { - return None; - } - let ts = toks.real_token(); - if ts.tok == token::Not { - if prev.tok.is_ident() { - return Some(prev.sp); - } else { - return None; - } - } - prev = ts; - } - } + // // Return the name for a macro use (identifier before first `!`). + // pub fn span_for_macro_use_name(&self, span:Span) -> Option { + // let mut toks = self.retokenise_span(span); + // let mut prev = toks.real_token(); + // loop { + // if prev.tok == token::Eof { + // return None; + // } + // let ts = toks.real_token(); + // if ts.tok == token::Not { + // if prev.tok.is_ident() { + // return Some(prev.sp); + // } else { + // return None; + // } + // } + // prev = ts; + // } + // } /// Return true if the span is generated code, and /// it is not a subspan of the root callsite. From e6dd8692606fc966dac7315c56e9a24932bb951c Mon Sep 17 00:00:00 2001 From: Taylor Cramer Date: Thu, 15 Jun 2017 22:25:41 -0700 Subject: [PATCH 215/233] Divide up metadata into separate DepNodes --- src/librustc/dep_graph/dep_node.rs | 8 ++++++-- src/librustc/ty/maps.rs | 8 ++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index c987a37c420d..a2ff009a55d1 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -80,7 +80,7 @@ macro_rules! define_dep_nodes { ($( $variant:ident $(( $($tuple_arg:tt),* ))* $({ $($struct_arg_name:ident : $struct_arg_ty:ty),* })* - ),* + ,)* ) => ( #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] @@ -421,7 +421,11 @@ define_dep_nodes!( IsExportedSymbol(DefId), IsMirAvailable(DefId), ItemAttrs(DefId), - FnArgNames(DefId) + FnArgNames(DefId), + DylibDepFormats(DefId), + IsAllocator(DefId), + IsPanicRuntime(DefId), + ExternCrate(DefId), ); trait DepNodeParams<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> { diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs index dccc0a8283a9..524cf57472bc 100644 --- a/src/librustc/ty/maps.rs +++ b/src/librustc/ty/maps.rs @@ -964,13 +964,13 @@ define_maps! { <'tcx> [] layout_raw: layout_dep_node(ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> Result<&'tcx Layout, LayoutError<'tcx>>, - [] dylib_dependency_formats: MetaData(DefId) + [] dylib_dependency_formats: DylibDepFormats(DefId) -> Rc>, - [] is_allocator: MetaData(DefId) -> bool, - [] is_panic_runtime: MetaData(DefId) -> bool, + [] is_allocator: IsAllocator(DefId) -> bool, + [] is_panic_runtime: IsPanicRuntime(DefId) -> bool, - [] extern_crate: MetaData(DefId) -> Rc>, + [] extern_crate: ExternCrate(DefId) -> Rc>, } fn type_param_predicates((item_id, param_id): (DefId, DefId)) -> DepConstructor { From b34ac5dbdab8221a227238f2ec8089df3a2aa06d Mon Sep 17 00:00:00 2001 From: est31 Date: Wed, 14 Jun 2017 18:49:41 +0200 Subject: [PATCH 216/233] Fix cross compilation --- src/bootstrap/step.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/bootstrap/step.rs b/src/bootstrap/step.rs index 684a00ce7f16..b5422728db42 100644 --- a/src/bootstrap/step.rs +++ b/src/bootstrap/step.rs @@ -666,12 +666,7 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { .target(&build.config.build) .stage(0) }) - .dep(move |s| { - s.name("doc-unstable-book-gen") - .host(&build.config.build) - .target(&build.config.build) - .stage(0) - }) + .dep(move |s| s.name("doc-unstable-book-gen")) .default(build.config.docs) .run(move |s| doc::rustbook_src(build, s.target, @@ -693,8 +688,13 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { .host(true) .run(move |s| doc::error_index(build, s.target)); rules.doc("doc-unstable-book-gen", "src/tools/unstable-book-gen") - .dep(move |s| s.name("tool-unstable-book-gen").target(&build.config.build).stage(0)) - .dep(move |s| s.name("librustc-link")) + .dep(move |s| { + s.name("tool-unstable-book-gen") + .host(&build.config.build) + .target(&build.config.build) + .stage(0) + }) + .dep(move |s| s.name("libstd-link")) .default(build.config.docs) .host(true) .run(move |s| doc::unstable_book_gen(build, s.target)); From 73267374d4176ac1c5d685ff2bac36556cfa4730 Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Fri, 16 Jun 2017 07:44:09 -0600 Subject: [PATCH 217/233] Use custom cargo/rustc paths when parsing flags. --- src/bootstrap/flags.rs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index 56cbb4cecf2a..dc9dac736278 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -242,11 +242,18 @@ Arguments: let cwd = t!(env::current_dir()); let paths = matches.free[1..].iter().map(|p| cwd.join(p)).collect::>(); + let cfg_file = matches.opt_str("config").map(PathBuf::from).or_else(|| { + if fs::metadata("config.toml").is_ok() { + Some(PathBuf::from("config.toml")) + } else { + None + } + }); // All subcommands can have an optional "Available paths" section if matches.opt_present("verbose") { let flags = Flags::parse(&["build".to_string()]); - let mut config = Config::default(); + let mut config = Config::parse(&flags.build, cfg_file.clone()); config.build = flags.build.clone(); let mut build = Build::new(flags, config); metadata::build(&mut build); @@ -307,14 +314,6 @@ Arguments: }; - let cfg_file = matches.opt_str("config").map(PathBuf::from).or_else(|| { - if fs::metadata("config.toml").is_ok() { - Some(PathBuf::from("config.toml")) - } else { - None - } - }); - let mut stage = matches.opt_str("stage").map(|j| j.parse().unwrap()); if matches.opt_present("incremental") { From c6afde6c46d167c9c75389b887f1d2498aeef3e4 Mon Sep 17 00:00:00 2001 From: est31 Date: Fri, 16 Jun 2017 19:58:37 +0200 Subject: [PATCH 218/233] Introduce tidy lint to check for inconsistent tracking issues This commit * Refactors the collect_lib_features function to work in a non-checking mode (no bad pointer needed, and list of lang features). * Introduces checking whether unstable/stable tags for a given feature have inconsistent tracking issues. * Fixes such inconsistencies throughout the codebase. --- src/liballoc/rc.rs | 4 +- src/libcore/hash/mod.rs | 2 +- src/libcore/str/mod.rs | 2 +- src/libfmt_macros/lib.rs | 2 +- src/librustc_trans/lib.rs | 1 - src/libstd/lib.rs | 2 +- src/libstd/rand/mod.rs | 2 +- src/libstd_unicode/char.rs | 8 +-- src/tools/tidy/src/features.rs | 93 +++++++++++++++++-------- src/tools/tidy/src/unstable_book.rs | 2 +- src/tools/unstable-book-gen/src/main.rs | 3 +- 11 files changed, 78 insertions(+), 43 deletions(-) diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 1f3388ad2c28..21a56ff9899e 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -428,7 +428,7 @@ impl Rc { #[doc(hidden)] #[unstable(feature = "rustc_private", reason = "for internal use in rustc", - issue = "0")] + issue = "27812")] pub fn __from_str(value: &str) -> Rc { unsafe { // Allocate enough space for `RcBox`. @@ -453,7 +453,7 @@ impl Rc<[T]> { #[doc(hidden)] #[unstable(feature = "rustc_private", reason = "for internal use in rustc", - issue = "0")] + issue = "27812")] pub fn __from_array(value: Box<[T]>) -> Rc<[T]> { unsafe { let ptr: *mut RcBox<[T]> = diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs index f68361e85227..3b304f4c479a 100644 --- a/src/libcore/hash/mod.rs +++ b/src/libcore/hash/mod.rs @@ -99,7 +99,7 @@ use mem; #[allow(deprecated)] pub use self::sip::SipHasher; -#[unstable(feature = "sip_hash_13", issue = "29754")] +#[unstable(feature = "sip_hash_13", issue = "34767")] #[allow(deprecated)] pub use self::sip::{SipHasher13, SipHasher24}; diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index c374f4009744..624c3638df5c 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -2085,7 +2085,7 @@ pub trait StrExt { fn is_char_boundary(&self, index: usize) -> bool; #[stable(feature = "core", since = "1.6.0")] fn as_bytes(&self) -> &[u8]; - #[unstable(feature = "str_mut_extras", issue = "0")] + #[unstable(feature = "str_mut_extras", issue = "41119")] unsafe fn as_bytes_mut(&mut self) -> &mut [u8]; #[stable(feature = "core", since = "1.6.0")] fn find<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option; diff --git a/src/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs index 641a42b08188..967bfb6c9905 100644 --- a/src/libfmt_macros/lib.rs +++ b/src/libfmt_macros/lib.rs @@ -26,7 +26,7 @@ #![deny(warnings)] #![cfg_attr(stage0, feature(staged_api))] -#![feature(unicode)] +#![feature(rustc_private)] pub use self::Piece::*; pub use self::Position::*; diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index 71fb2e5fb202..4c7037c9ef2d 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -33,7 +33,6 @@ #![feature(quote)] #![feature(rustc_diagnostic_macros)] #![feature(slice_patterns)] -#![feature(unicode)] #![feature(conservative_impl_trait)] #![feature(command_envs)] diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index f307fbb7c003..105f4026ec84 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -484,7 +484,7 @@ pub mod rt; // but it may be stabilized long-term. As a result we're exposing a hidden, // unstable module so we can get our build working. #[doc(hidden)] -#[unstable(feature = "rand", issue = "0")] +#[unstable(feature = "rand", issue = "27703")] pub mod __rand { pub use rand::{thread_rng, ThreadRng, Rng}; } diff --git a/src/libstd/rand/mod.rs b/src/libstd/rand/mod.rs index 4f33d7263981..8da070e7a497 100644 --- a/src/libstd/rand/mod.rs +++ b/src/libstd/rand/mod.rs @@ -56,7 +56,7 @@ //! between the two sources. (Also note that, on some systems e.g. FreeBSD, both `/dev/random` //! and `/dev/urandom` may block once if the CSPRNG has not seeded yet.) -#![unstable(feature = "rand", issue = "0")] +#![unstable(feature = "rand", issue = "27703")] use cell::RefCell; use fmt; diff --git a/src/libstd_unicode/char.rs b/src/libstd_unicode/char.rs index 92e5369758b4..eb36cbe3b1f5 100644 --- a/src/libstd_unicode/char.rs +++ b/src/libstd_unicode/char.rs @@ -599,9 +599,9 @@ impl char { /// 'XID_Start' is a Unicode Derived Property specified in /// [UAX #31](http://unicode.org/reports/tr31/#NFKC_Modifications), /// mostly similar to `ID_Start` but modified for closure under `NFKx`. - #[unstable(feature = "unicode", + #[unstable(feature = "rustc_private", reason = "mainly needed for compiler internals", - issue = "0")] + issue = "27812")] #[inline] pub fn is_xid_start(self) -> bool { derived_property::XID_Start(self) @@ -613,9 +613,9 @@ impl char { /// 'XID_Continue' is a Unicode Derived Property specified in /// [UAX #31](http://unicode.org/reports/tr31/#NFKC_Modifications), /// mostly similar to 'ID_Continue' but modified for closure under NFKx. - #[unstable(feature = "unicode", + #[unstable(feature = "rustc_private", reason = "mainly needed for compiler internals", - issue = "0")] + issue = "27812")] #[inline] pub fn is_xid_continue(self) -> bool { derived_property::XID_Continue(self) diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs index 81db23ccceb5..722fc2b317eb 100644 --- a/src/tools/tidy/src/features.rs +++ b/src/tools/tidy/src/features.rs @@ -56,7 +56,7 @@ pub fn check(path: &Path, bad: &mut bool, quiet: bool) { let mut features = collect_lang_features(path); assert!(!features.is_empty()); - let lib_features = collect_lib_features(path, bad, &features); + let lib_features = get_and_check_lib_features(path, bad, &features); assert!(!lib_features.is_empty()); let mut contents = String::new(); @@ -217,10 +217,61 @@ pub fn collect_lang_features(base_src_path: &Path) -> Features { .collect() } -pub fn collect_lib_features(base_src_path: &Path, - bad: &mut bool, - features: &Features) -> Features { +pub fn collect_lib_features(base_src_path: &Path) -> Features { let mut lib_features = Features::new(); + map_lib_features(base_src_path, + &mut |res, _, _| { + match res { + Ok((name, feature)) => { + if lib_features.get(name).is_some() { + return; + } + lib_features.insert(name.to_owned(), feature); + }, + Err(_) => (), + } + }); + lib_features +} + +fn get_and_check_lib_features(base_src_path: &Path, + bad: &mut bool, + lang_features: &Features) -> Features { + let mut lib_features = Features::new(); + map_lib_features(base_src_path, + &mut |res, file, line| { + match res { + Ok((name, f)) => { + let mut err = |msg: &str| { + tidy_error!(bad, "{}:{}: {}", file.display(), line, msg); + }; + if lang_features.contains_key(name) { + err("duplicating a lang feature"); + } + if let Some(ref s) = lib_features.get(name) { + if s.level != f.level { + err("different stability level than before"); + } + if s.since != f.since { + err("different `since` than before"); + } + if s.tracking_issue != f.tracking_issue { + err("different `tracking_issue` than before"); + } + } + lib_features.insert(name.to_owned(), f); + }, + Err(msg) => { + tidy_error!(bad, "{}:{}: {}", file.display(), line, msg); + }, + } + + }); + lib_features +} + +fn map_lib_features(base_src_path: &Path, + mf: &mut FnMut(Result<(&str, Feature), &str>, &Path, usize)) { let mut contents = String::new(); super::walk(base_src_path, &mut |path| super::filter_dirs(path) || path.ends_with("src/test"), @@ -236,8 +287,11 @@ pub fn collect_lib_features(base_src_path: &Path, let mut becoming_feature: Option<(String, Feature)> = None; for (i, line) in contents.lines().enumerate() { - let mut err = |msg: &str| { - tidy_error!(bad, "{}:{}: {}", file.display(), i + 1, msg); + macro_rules! err { + ($msg:expr) => {{ + mf(Err($msg), file, i + 1); + continue; + }}; }; if let Some((ref name, ref mut f)) = becoming_feature { if f.tracking_issue.is_none() { @@ -245,7 +299,7 @@ pub fn collect_lib_features(base_src_path: &Path, .map(|s| s.parse().unwrap()); } if line.ends_with("]") { - lib_features.insert(name.to_owned(), f.clone()); + mf(Ok((name, f.clone())), file, i + 1); } else if !line.ends_with(",") && !line.ends_with("\\") { // We need to bail here because we might have missed the // end of a stability attribute above because the "]" @@ -254,7 +308,7 @@ pub fn collect_lib_features(base_src_path: &Path, // we continue parsing the file assuming the current stability // attribute has not ended, and ignoring possible feature // attributes in the process. - err("malformed stability attribute"); + err!("malformed stability attribute"); } else { continue; } @@ -269,33 +323,17 @@ pub fn collect_lib_features(base_src_path: &Path, }; let feature_name = match find_attr_val(line, "feature") { Some(name) => name, - None => { - err("malformed stability attribute"); - continue; - } + None => err!("malformed stability attribute"), }; let since = match find_attr_val(line, "since") { Some(name) => name, None if level == Status::Stable => { - err("malformed stability attribute"); - continue; + err!("malformed stability attribute"); } None => "None", }; let tracking_issue = find_attr_val(line, "issue").map(|s| s.parse().unwrap()); - if features.contains_key(feature_name) { - err("duplicating a lang feature"); - } - if let Some(ref s) = lib_features.get(feature_name) { - if s.level != level { - err("different stability level than before"); - } - if s.since != since { - err("different `since` than before"); - } - continue; - } let feature = Feature { level, since: since.to_owned(), @@ -303,11 +341,10 @@ pub fn collect_lib_features(base_src_path: &Path, tracking_issue, }; if line.contains("]") { - lib_features.insert(feature_name.to_owned(), feature); + mf(Ok((feature_name, feature)), file, i + 1); } else { becoming_feature = Some((feature_name.to_owned(), feature)); } } }); - lib_features } diff --git a/src/tools/tidy/src/unstable_book.rs b/src/tools/tidy/src/unstable_book.rs index fd3ffc685d9b..c8bfe42aa03d 100644 --- a/src/tools/tidy/src/unstable_book.rs +++ b/src/tools/tidy/src/unstable_book.rs @@ -87,7 +87,7 @@ pub fn check(path: &path::Path, bad: &mut bool) { // Library features let lang_features = collect_lang_features(path); - let lib_features = collect_lib_features(path, bad, &lang_features); + let lib_features = collect_lib_features(path); let unstable_lib_feature_names = collect_unstable_feature_names(&lib_features); let unstable_book_lib_features_section_file_names = diff --git a/src/tools/unstable-book-gen/src/main.rs b/src/tools/unstable-book-gen/src/main.rs index adec73d4a69b..71063968ff2c 100644 --- a/src/tools/unstable-book-gen/src/main.rs +++ b/src/tools/unstable-book-gen/src/main.rs @@ -129,8 +129,7 @@ fn main() { let dest_path = Path::new(&dest_path_str).join("src"); let lang_features = collect_lang_features(src_path); - let mut bad = false; - let lib_features = collect_lib_features(src_path, &mut bad, &lang_features); + let lib_features = collect_lib_features(src_path); let doc_src_path = src_path.join(PATH_STR); From da78b4d88e1ba4598428a92a6c8d5f9c399fede0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 16 Jun 2017 10:34:17 -0700 Subject: [PATCH 219/233] Review comments - exhaustive match - rename method to `check_expr_meets_expectation_or_error` - formatting - add `delay_span_bug` - add test --- src/librustc_typeck/check/_match.rs | 4 +-- src/librustc_typeck/check/demand.rs | 3 +- src/librustc_typeck/check/mod.rs | 31 ++++++++++--------- .../{issue-17283.rs => assignment-in-if.rs} | 4 +++ ...e-17283.stderr => assignment-in-if.stderr} | 17 +++++++--- 5 files changed, 38 insertions(+), 21 deletions(-) rename src/test/ui/type-check/{issue-17283.rs => assignment-in-if.rs} (93%) rename src/test/ui/type-check/{issue-17283.stderr => assignment-in-if.stderr} (73%) diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 33f0b0282d17..bdd8169b84fe 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -413,7 +413,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // discriminant. This is sort of a workaround, see note (*) in // `check_pat` for some details. discrim_ty = self.next_ty_var(TypeVariableOrigin::TypeInference(discrim.span)); - self.check_expr_has_type(discrim, discrim_ty); + self.check_expr_has_type_or_error(discrim, discrim_ty); }; // If the discriminant diverges, the match is pointless (e.g., @@ -480,7 +480,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { for (i, (arm, pats_diverge)) in arms.iter().zip(all_arm_pats_diverge).enumerate() { if let Some(ref e) = arm.guard { self.diverges.set(pats_diverge); - self.check_expr_has_type(e, tcx.types.bool); + self.check_expr_has_type_or_error(e, tcx.types.bool); } self.diverges.set(pats_diverge); diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 732b9be81a39..1b6f96cf6513 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -29,7 +29,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.demand_suptype_diag(sp, expected, actual).map(|mut e| e.emit()); } - pub fn demand_suptype_diag(&self, sp: Span, + pub fn demand_suptype_diag(&self, + sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>) -> Option> { let cause = &self.misc(sp); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 5bba79a176ee..d663d8f0d2b5 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -345,7 +345,7 @@ impl<'a, 'gcx, 'tcx> Expectation<'tcx> { match self.resolve(fcx) { ExpectHasType(ty) => Some(ty), ExpectIfCondition => Some(fcx.tcx.types.bool), - _ => None + NoExpectation | ExpectCastableToType(_) | ExpectRvalueLikeUnsized(_) => None, } } @@ -2647,15 +2647,15 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.demand_eqtype(expr.span, expected, ty); } - pub fn check_expr_has_type(&self, - expr: &'gcx hir::Expr, - expected: Ty<'tcx>) -> Ty<'tcx> { - self.check_expr_expect_type(expr, ExpectHasType(expected)) + pub fn check_expr_has_type_or_error(&self, + expr: &'gcx hir::Expr, + expected: Ty<'tcx>) -> Ty<'tcx> { + self.check_expr_meets_expectation_or_error(expr, ExpectHasType(expected)) } - fn check_expr_expect_type(&self, - expr: &'gcx hir::Expr, - expected: Expectation<'tcx>) -> Ty<'tcx> { + fn check_expr_meets_expectation_or_error(&self, + expr: &'gcx hir::Expr, + expected: Expectation<'tcx>) -> Ty<'tcx> { let expected_ty = expected.to_option(&self).unwrap_or(self.tcx.types.bool); let mut ty = self.check_expr_with_expectation(expr, expected); @@ -2865,7 +2865,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { opt_else_expr: Option<&'gcx hir::Expr>, sp: Span, expected: Expectation<'tcx>) -> Ty<'tcx> { - let cond_ty = self.check_expr_expect_type(cond_expr, ExpectIfCondition); + let cond_ty = self.check_expr_meets_expectation_or_error(cond_expr, ExpectIfCondition); let cond_diverges = self.diverges.get(); self.diverges.set(Diverges::Maybe); @@ -3352,7 +3352,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.check_expr_struct_fields(struct_ty, expected, expr.id, path_span, variant, fields, base_expr.is_none()); if let &Some(ref base_expr) = base_expr { - self.check_expr_has_type(base_expr, struct_ty); + self.check_expr_has_type_or_error(base_expr, struct_ty); match struct_ty.sty { ty::TyAdt(adt, substs) if adt.is_struct() => { let fru_field_types = adt.struct_variant().fields.iter().map(|f| { @@ -3668,7 +3668,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let rhs_ty = self.check_expr_coercable_to_type(&rhs, lhs_ty); match expected { - ExpectIfCondition => (), + ExpectIfCondition => { + self.tcx.sess.delay_span_bug(lhs.span, "invalid lhs expression in if;\ + expected error elsehwere"); + } _ => { // Only check this if not in an `if` condition, as the // mistyped comparison help is more appropriate. @@ -3704,7 +3707,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }; self.with_breakable_ctxt(expr.id, ctxt, || { - self.check_expr_has_type(&cond, tcx.types.bool); + self.check_expr_has_type_or_error(&cond, tcx.types.bool); let cond_diverging = self.diverges.get(); self.check_block_no_value(&body); @@ -3842,7 +3845,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } None => { let t: Ty = self.next_ty_var(TypeVariableOrigin::MiscVariable(element.span)); - let element_ty = self.check_expr_has_type(&element, t); + let element_ty = self.check_expr_has_type_or_error(&element, t); (element_ty, t) } }; @@ -4097,7 +4100,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } hir::StmtExpr(ref expr, _) => { // Check with expected type of () - self.check_expr_has_type(&expr, self.tcx.mk_nil()); + self.check_expr_has_type_or_error(&expr, self.tcx.mk_nil()); } hir::StmtSemi(ref expr, _) => { self.check_expr(&expr); diff --git a/src/test/ui/type-check/issue-17283.rs b/src/test/ui/type-check/assignment-in-if.rs similarity index 93% rename from src/test/ui/type-check/issue-17283.rs rename to src/test/ui/type-check/assignment-in-if.rs index f06888b8ec46..98dc55c66630 100644 --- a/src/test/ui/type-check/issue-17283.rs +++ b/src/test/ui/type-check/assignment-in-if.rs @@ -45,4 +45,8 @@ fn main() { //~| HELP did you mean to compare equality? println!("{}", x); } + if (if true { x = 4 } else { x = 5 }) { + //~^ ERROR mismatched types + println!("{}", x); + } } diff --git a/src/test/ui/type-check/issue-17283.stderr b/src/test/ui/type-check/assignment-in-if.stderr similarity index 73% rename from src/test/ui/type-check/issue-17283.stderr rename to src/test/ui/type-check/assignment-in-if.stderr index f258caecd300..294399992732 100644 --- a/src/test/ui/type-check/issue-17283.stderr +++ b/src/test/ui/type-check/assignment-in-if.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/issue-17283.rs:25:8 + --> $DIR/assignment-in-if.rs:25:8 | 25 | if x = x { | ^^^^^ @@ -11,7 +11,7 @@ error[E0308]: mismatched types found type `()` error[E0308]: mismatched types - --> $DIR/issue-17283.rs:31:8 + --> $DIR/assignment-in-if.rs:31:8 | 31 | if (x = x) { | ^^^^^^^ @@ -23,7 +23,7 @@ error[E0308]: mismatched types found type `()` error[E0308]: mismatched types - --> $DIR/issue-17283.rs:37:8 + --> $DIR/assignment-in-if.rs:37:8 | 37 | if y = (Foo { foo: x }) { | ^^^^^^^^^^^^^^^^^^^^ @@ -35,7 +35,7 @@ error[E0308]: mismatched types found type `()` error[E0308]: mismatched types - --> $DIR/issue-17283.rs:43:8 + --> $DIR/assignment-in-if.rs:43:8 | 43 | if 3 = x { | ^^^^^ @@ -46,5 +46,14 @@ error[E0308]: mismatched types = note: expected type `bool` found type `()` +error[E0308]: mismatched types + --> $DIR/assignment-in-if.rs:48:8 + | +48 | if (if true { x = 4 } else { x = 5 }) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected bool, found () + | + = note: expected type `bool` + found type `()` + error: aborting due to previous error(s) From a65d8d3d71d49ba87fd4e8bfb86b70ec7d2ad83f Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 14 Jun 2017 12:46:14 -0400 Subject: [PATCH 220/233] move `implied_bounds` into regionck --- src/librustc/middle/free_region.rs | 20 +--- src/librustc/ty/wf.rs | 128 --------------------- src/librustc_typeck/check/regionck.rs | 159 +++++++++++++++++++++++--- 3 files changed, 142 insertions(+), 165 deletions(-) diff --git a/src/librustc/middle/free_region.rs b/src/librustc/middle/free_region.rs index 6a21bdc19e09..de738fba30e9 100644 --- a/src/librustc/middle/free_region.rs +++ b/src/librustc/middle/free_region.rs @@ -18,7 +18,6 @@ use hir::def_id::DefId; use middle::region::RegionMaps; use ty::{self, Lift, TyCtxt, Region}; -use ty::wf::ImpliedBound; use rustc_data_structures::transitive_relation::TransitiveRelation; /// Combines a `RegionMaps` (which governs relationships between @@ -136,23 +135,6 @@ impl<'tcx> FreeRegionMap<'tcx> { self.relation.is_empty() } - pub fn relate_free_regions_from_implied_bounds(&mut self, - implied_bounds: &[ImpliedBound<'tcx>]) - { - debug!("relate_free_regions_from_implied_bounds()"); - for implied_bound in implied_bounds { - debug!("implied bound: {:?}", implied_bound); - match *implied_bound { - ImpliedBound::RegionSubRegion(a, b) => { - self.relate_regions(a, b); - } - ImpliedBound::RegionSubParam(..) | - ImpliedBound::RegionSubProjection(..) => { - } - } - } - } - pub fn relate_free_regions_from_predicates(&mut self, predicates: &[ty::Predicate<'tcx>]) { debug!("relate_free_regions_from_predicates(predicates={:?})", predicates); @@ -177,7 +159,7 @@ impl<'tcx> FreeRegionMap<'tcx> { // Record that `'sup:'sub`. Or, put another way, `'sub <= 'sup`. // (with the exception that `'static: 'x` is not notable) - fn relate_regions(&mut self, sub: Region<'tcx>, sup: Region<'tcx>) { + pub fn relate_regions(&mut self, sub: Region<'tcx>, sup: Region<'tcx>) { if (is_free(sub) || *sub == ty::ReStatic) && is_free(sup) { self.relation.add(sub, sup) } diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs index aa2c9802e547..2eb0acac4f7e 100644 --- a/src/librustc/ty/wf.rs +++ b/src/librustc/ty/wf.rs @@ -10,7 +10,6 @@ use hir::def_id::DefId; use infer::InferCtxt; -use ty::outlives::Component; use ty::subst::Substs; use traits; use ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable}; @@ -107,133 +106,6 @@ pub fn predicate_obligations<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, wf.normalize() } -/// Implied bounds are region relationships that we deduce -/// automatically. The idea is that (e.g.) a caller must check that a -/// function's argument types are well-formed immediately before -/// calling that fn, and hence the *callee* can assume that its -/// argument types are well-formed. This may imply certain relationships -/// between generic parameters. For example: -/// -/// fn foo<'a,T>(x: &'a T) -/// -/// can only be called with a `'a` and `T` such that `&'a T` is WF. -/// For `&'a T` to be WF, `T: 'a` must hold. So we can assume `T: 'a`. -#[derive(Debug)] -pub enum ImpliedBound<'tcx> { - RegionSubRegion(ty::Region<'tcx>, ty::Region<'tcx>), - RegionSubParam(ty::Region<'tcx>, ty::ParamTy), - RegionSubProjection(ty::Region<'tcx>, ty::ProjectionTy<'tcx>), -} - -/// Compute the implied bounds that a callee/impl can assume based on -/// the fact that caller/projector has ensured that `ty` is WF. See -/// the `ImpliedBound` type for more details. -pub fn implied_bounds<'a, 'gcx, 'tcx>( - infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, - param_env: ty::ParamEnv<'tcx>, - body_id: ast::NodeId, - ty: Ty<'tcx>, - span: Span) - -> Vec> -{ - // Sometimes when we ask what it takes for T: WF, we get back that - // U: WF is required; in that case, we push U onto this stack and - // process it next. Currently (at least) these resulting - // predicates are always guaranteed to be a subset of the original - // type, so we need not fear non-termination. - let mut wf_types = vec![ty]; - - let mut implied_bounds = vec![]; - - while let Some(ty) = wf_types.pop() { - // Compute the obligations for `ty` to be well-formed. If `ty` is - // an unresolved inference variable, just substituted an empty set - // -- because the return type here is going to be things we *add* - // to the environment, it's always ok for this set to be smaller - // than the ultimate set. (Note: normally there won't be - // unresolved inference variables here anyway, but there might be - // during typeck under some circumstances.) - let obligations = obligations(infcx, param_env, body_id, ty, span).unwrap_or(vec![]); - - // From the full set of obligations, just filter down to the - // region relationships. - implied_bounds.extend( - obligations - .into_iter() - .flat_map(|obligation| { - assert!(!obligation.has_escaping_regions()); - match obligation.predicate { - ty::Predicate::Trait(..) | - ty::Predicate::Equate(..) | - ty::Predicate::Subtype(..) | - ty::Predicate::Projection(..) | - ty::Predicate::ClosureKind(..) | - ty::Predicate::ObjectSafe(..) => - vec![], - - ty::Predicate::WellFormed(subty) => { - wf_types.push(subty); - vec![] - } - - ty::Predicate::RegionOutlives(ref data) => - match infcx.tcx.no_late_bound_regions(data) { - None => - vec![], - Some(ty::OutlivesPredicate(r_a, r_b)) => - vec![ImpliedBound::RegionSubRegion(r_b, r_a)], - }, - - ty::Predicate::TypeOutlives(ref data) => - match infcx.tcx.no_late_bound_regions(data) { - None => vec![], - Some(ty::OutlivesPredicate(ty_a, r_b)) => { - let ty_a = infcx.resolve_type_vars_if_possible(&ty_a); - let components = infcx.tcx.outlives_components(ty_a); - implied_bounds_from_components(r_b, components) - } - }, - }})); - } - - implied_bounds -} - -/// When we have an implied bound that `T: 'a`, we can further break -/// this down to determine what relationships would have to hold for -/// `T: 'a` to hold. We get to assume that the caller has validated -/// those relationships. -fn implied_bounds_from_components<'tcx>(sub_region: ty::Region<'tcx>, - sup_components: Vec>) - -> Vec> -{ - sup_components - .into_iter() - .flat_map(|component| { - match component { - Component::Region(r) => - vec![ImpliedBound::RegionSubRegion(sub_region, r)], - Component::Param(p) => - vec![ImpliedBound::RegionSubParam(sub_region, p)], - Component::Projection(p) => - vec![ImpliedBound::RegionSubProjection(sub_region, p)], - Component::EscapingProjection(_) => - // If the projection has escaping regions, don't - // try to infer any implied bounds even for its - // free components. This is conservative, because - // the caller will still have to prove that those - // free components outlive `sub_region`. But the - // idea is that the WAY that the caller proves - // that may change in the future and we want to - // give ourselves room to get smarter here. - vec![], - Component::UnresolvedInferenceVariable(..) => - vec![], - } - }) - .collect() -} - struct WfPredicates<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, param_env: ty::ParamEnv<'tcx>, diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 952321c946bf..bbcd0eadef75 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -94,7 +94,8 @@ use rustc::traits; use rustc::ty::{self, Ty, TypeFoldable}; use rustc::infer::{self, GenericKind, SubregionOrigin, VerifyBound}; use rustc::ty::adjustment; -use rustc::ty::wf::ImpliedBound; +use rustc::ty::outlives::Component; +use rustc::ty::wf; use std::mem; use std::ops::Deref; @@ -196,6 +197,24 @@ pub struct RegionCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { } +/// Implied bounds are region relationships that we deduce +/// automatically. The idea is that (e.g.) a caller must check that a +/// function's argument types are well-formed immediately before +/// calling that fn, and hence the *callee* can assume that its +/// argument types are well-formed. This may imply certain relationships +/// between generic parameters. For example: +/// +/// fn foo<'a,T>(x: &'a T) +/// +/// can only be called with a `'a` and `T` such that `&'a T` is WF. +/// For `&'a T` to be WF, `T: 'a` must hold. So we can assume `T: 'a`. +#[derive(Debug)] +enum ImpliedBound<'tcx> { + RegionSubRegion(ty::Region<'tcx>, ty::Region<'tcx>), + RegionSubParam(ty::Region<'tcx>, ty::ParamTy), + RegionSubProjection(ty::Region<'tcx>, ty::ProjectionTy<'tcx>), +} + impl<'a, 'gcx, 'tcx> Deref for RegionCtxt<'a, 'gcx, 'tcx> { type Target = FnCtxt<'a, 'gcx, 'tcx>; fn deref(&self) -> &Self::Target { @@ -386,11 +405,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { for &ty in fn_sig_tys { let ty = self.resolve_type(ty); debug!("relate_free_regions(t={:?})", ty); - let implied_bounds = - ty::wf::implied_bounds(self, self.fcx.param_env, body_id, ty, span); - - // Record any relations between free regions that we observe into the free-region-map. - self.free_region_map.relate_free_regions_from_implied_bounds(&implied_bounds); + let implied_bounds = self.implied_bounds(body_id, ty, span); // But also record other relationships, such as `T:'x`, // that don't go into the free-region-map but which we use @@ -410,16 +425,18 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { ImpliedBound::RegionSubProjection(r_a, projection_b) => { self.region_bound_pairs.push((r_a, GenericKind::Projection(projection_b))); } - ImpliedBound::RegionSubRegion(..) => { + ImpliedBound::RegionSubRegion(r_a, r_b) => { // In principle, we could record (and take // advantage of) every relationship here, but // we are also free not to -- it simply means // strictly less that we can successfully type - // check. (It may also be that we should - // revise our inference system to be more - // general and to make use of *every* - // relationship that arises here, but - // presently we do not.) + // check. Right now we only look for things + // relationships between free regions. (It may + // also be that we should revise our inference + // system to be more general and to make use + // of *every* relationship that arises here, + // but presently we do not.) + self.free_region_map.relate_regions(r_a, r_b); } } } @@ -428,6 +445,112 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { debug!("<< relate_free_regions"); } + /// Compute the implied bounds that a callee/impl can assume based on + /// the fact that caller/projector has ensured that `ty` is WF. See + /// the `ImpliedBound` type for more details. + fn implied_bounds(&mut self, body_id: ast::NodeId, ty: Ty<'tcx>, span: Span) + -> Vec> { + // Sometimes when we ask what it takes for T: WF, we get back that + // U: WF is required; in that case, we push U onto this stack and + // process it next. Currently (at least) these resulting + // predicates are always guaranteed to be a subset of the original + // type, so we need not fear non-termination. + let mut wf_types = vec![ty]; + + let mut implied_bounds = vec![]; + + while let Some(ty) = wf_types.pop() { + // Compute the obligations for `ty` to be well-formed. If `ty` is + // an unresolved inference variable, just substituted an empty set + // -- because the return type here is going to be things we *add* + // to the environment, it's always ok for this set to be smaller + // than the ultimate set. (Note: normally there won't be + // unresolved inference variables here anyway, but there might be + // during typeck under some circumstances.) + let obligations = + wf::obligations(self, self.fcx.param_env, body_id, ty, span) + .unwrap_or(vec![]); + + // From the full set of obligations, just filter down to the + // region relationships. + implied_bounds.extend( + obligations + .into_iter() + .flat_map(|obligation| { + assert!(!obligation.has_escaping_regions()); + match obligation.predicate { + ty::Predicate::Trait(..) | + ty::Predicate::Equate(..) | + ty::Predicate::Subtype(..) | + ty::Predicate::Projection(..) | + ty::Predicate::ClosureKind(..) | + ty::Predicate::ObjectSafe(..) => + vec![], + + ty::Predicate::WellFormed(subty) => { + wf_types.push(subty); + vec![] + } + + ty::Predicate::RegionOutlives(ref data) => + match self.tcx.no_late_bound_regions(data) { + None => + vec![], + Some(ty::OutlivesPredicate(r_a, r_b)) => + vec![ImpliedBound::RegionSubRegion(r_b, r_a)], + }, + + ty::Predicate::TypeOutlives(ref data) => + match self.tcx.no_late_bound_regions(data) { + None => vec![], + Some(ty::OutlivesPredicate(ty_a, r_b)) => { + let ty_a = self.resolve_type_vars_if_possible(&ty_a); + let components = self.tcx.outlives_components(ty_a); + self.implied_bounds_from_components(r_b, components) + } + }, + }})); + } + + implied_bounds + } + + /// When we have an implied bound that `T: 'a`, we can further break + /// this down to determine what relationships would have to hold for + /// `T: 'a` to hold. We get to assume that the caller has validated + /// those relationships. + fn implied_bounds_from_components(&self, + sub_region: ty::Region<'tcx>, + sup_components: Vec>) + -> Vec> + { + sup_components + .into_iter() + .flat_map(|component| { + match component { + Component::Region(r) => + vec![ImpliedBound::RegionSubRegion(sub_region, r)], + Component::Param(p) => + vec![ImpliedBound::RegionSubParam(sub_region, p)], + Component::Projection(p) => + vec![ImpliedBound::RegionSubProjection(sub_region, p)], + Component::EscapingProjection(_) => + // If the projection has escaping regions, don't + // try to infer any implied bounds even for its + // free components. This is conservative, because + // the caller will still have to prove that those + // free components outlive `sub_region`. But the + // idea is that the WAY that the caller proves + // that may change in the future and we want to + // give ourselves room to get smarter here. + vec![], + Component::UnresolvedInferenceVariable(..) => + vec![], + } + }) + .collect() + } + fn resolve_regions_and_report_errors(&self) { self.fcx.resolve_regions_and_report_errors(self.subject_def_id, &self.region_maps, @@ -1353,25 +1476,25 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { fn components_must_outlive(&self, origin: infer::SubregionOrigin<'tcx>, - components: Vec>, + components: Vec>, region: ty::Region<'tcx>) { for component in components { let origin = origin.clone(); match component { - ty::outlives::Component::Region(region1) => { + Component::Region(region1) => { self.sub_regions(origin, region, region1); } - ty::outlives::Component::Param(param_ty) => { + Component::Param(param_ty) => { self.param_ty_must_outlive(origin, region, param_ty); } - ty::outlives::Component::Projection(projection_ty) => { + Component::Projection(projection_ty) => { self.projection_must_outlive(origin, region, projection_ty); } - ty::outlives::Component::EscapingProjection(subcomponents) => { + Component::EscapingProjection(subcomponents) => { self.components_must_outlive(origin, subcomponents, region); } - ty::outlives::Component::UnresolvedInferenceVariable(v) => { + Component::UnresolvedInferenceVariable(v) => { // ignore this, we presume it will yield an error // later, since if a type variable is not resolved by // this point it never will be From 9fec4093df1b31a3d63100922136e7bfb53c0d26 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 14 Jun 2017 14:25:41 -0400 Subject: [PATCH 221/233] register the obligations from `wf::implied_bounds` Fixes #42552. Fixes #42545. --- src/librustc_typeck/check/mod.rs | 3 +- src/librustc_typeck/check/regionck.rs | 26 +++++++++++++++++ src/test/run-pass/issue-42552.rs | 40 +++++++++++++++++++++++++++ 3 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 src/test/run-pass/issue-42552.rs diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index b1d3292e04ca..44d85791f35c 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -614,7 +614,8 @@ impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> { .register_predicate_obligation(self, obligation); } - fn register_predicates(&self, obligations: Vec>) { + fn register_predicates(&self, obligations: I) + where I: IntoIterator> { for obligation in obligations { self.register_predicate(obligation); } diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index bbcd0eadef75..5e79237da69d 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -471,6 +471,32 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { wf::obligations(self, self.fcx.param_env, body_id, ty, span) .unwrap_or(vec![]); + // NB: All of these predicates *ought* to be easily proven + // true. In fact, their correctness is (mostly) implied by + // other parts of the program. However, in #42552, we had + // an annoying scenario where: + // + // - Some `T::Foo` gets normalized, resulting in a + // variable `_1` and a `T: Trait` constraint + // (not sure why it couldn't immediately get + // solved). This result of `_1` got cached. + // - These obligations were dropped on the floor here, + // rather than being registered. + // - Then later we would get a request to normalize + // `T::Foo` which would result in `_1` being used from + // the cache, but hence without the `T: Trait` + // constraint. As a result, `_1` never gets resolved, + // and we get an ICE (in dropck). + // + // Therefore, we register any predicates involving + // inference variables. We restrict ourselves to those + // involving inference variables both for efficiency and + // to avoids duplicate errors that otherwise show up. + self.fcx.register_predicates( + obligations.iter() + .filter(|o| o.predicate.has_infer_types()) + .cloned()); + // From the full set of obligations, just filter down to the // region relationships. implied_bounds.extend( diff --git a/src/test/run-pass/issue-42552.rs b/src/test/run-pass/issue-42552.rs new file mode 100644 index 000000000000..fd1265b7174f --- /dev/null +++ b/src/test/run-pass/issue-42552.rs @@ -0,0 +1,40 @@ +// 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. + +// Regression test for an obscure issue with the projection cache. + +fn into_iter(a: &I) -> Groups { + Groups { _a: a } +} + +pub struct Groups<'a, I: 'a> { + _a: &'a I, +} + +impl<'a, I: Iterator> Iterator for Groups<'a, I> { + type Item = Group<'a, I>; + fn next(&mut self) -> Option { + None + } +} + +pub struct Group<'a, I: Iterator + 'a> + where I::Item: 'a // <-- needed to trigger ICE! +{ + _phantom: &'a (), + _ice_trigger: I::Item, // <-- needed to trigger ICE! +} + + +fn main() { + let _ = into_iter(&[0].iter().map(|_| 0)).map(|grp| { + let _g = grp; + }); +} From ca52d8033896efaef095af18a134e92c8005dc6a Mon Sep 17 00:00:00 2001 From: Alexander Bulaev Date: Sat, 17 Jun 2017 13:51:36 +0300 Subject: [PATCH 222/233] Inline StrSearcher::haystack() --- src/libcore/str/pattern.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/libcore/str/pattern.rs b/src/libcore/str/pattern.rs index 4918e37eb35f..5a007285e487 100644 --- a/src/libcore/str/pattern.rs +++ b/src/libcore/str/pattern.rs @@ -618,7 +618,10 @@ impl<'a, 'b> StrSearcher<'a, 'b> { } unsafe impl<'a, 'b> Searcher<'a> for StrSearcher<'a, 'b> { - fn haystack(&self) -> &'a str { self.haystack } + #[inline] + fn haystack(&self) -> &'a str { + self.haystack + } #[inline] fn next(&mut self) -> SearchStep { From 1cede109d8afe64f4094638a823efacd71658dd3 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 14 Jun 2017 19:33:06 -0700 Subject: [PATCH 223/233] Update cargo/rls submodules and dependencies Brings in a few regression fixes on the Cargo side, updates the rls to work with the newer Cargo, and also updates other crates.io dependencies to pull in various bug fixes and such. --- src/Cargo.lock | 647 +++++++++++++++++++++++++----------------------- src/Cargo.toml | 2 +- src/tools/cargo | 2 +- src/tools/rls | 2 +- 4 files changed, 335 insertions(+), 318 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 9fae4b7e924c..e024081fd0f6 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -45,7 +45,7 @@ version = "0.0.0" dependencies = [ "build_helper 0.1.0", "core 0.0.0", - "gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.0.0", ] @@ -67,26 +67,36 @@ name = "arena" version = "0.0.0" [[package]] -name = "backtrace" -version = "0.3.0" +name = "atty" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "backtrace" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace-sys 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "backtrace-sys" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -114,12 +124,12 @@ name = "bootstrap" version = "0.0.0" dependencies = [ "build_helper 0.1.0", - "cmake 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -146,52 +156,53 @@ dependencies = [ [[package]] name = "cargo" -version = "0.20.0" -source = "git+https://github.com/rust-lang/cargo#2b32084293d8da63b48de56363a0f2e986ec3367" -replace = "cargo 0.20.0" +version = "0.21.0" +source = "git+https://github.com/rust-lang/cargo#50b1c24d146fa072db71f12005deed319ac5ba9a" +replace = "cargo 0.21.0" [[package]] name = "cargo" -version = "0.20.0" +version = "0.21.0" dependencies = [ "advapi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "cargotest 0.1.0", - "crates-io 0.9.0", + "crates-io 0.10.0", "crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "curl 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "docopt 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "docopt 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", - "fs2 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "fs2 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "git2 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "git2-curl 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "hamcrest 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "jobserver 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "hex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "jobserver 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", "libgit2-sys 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl 0.9.12 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)", "psapi-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "serde_ignored 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "shell-escape 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "tar 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "termcolor 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -200,21 +211,20 @@ name = "cargotest" version = "0.1.0" dependencies = [ "bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "cargo 0.20.0", + "cargo 0.21.0", "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", "git2 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "hamcrest 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "tar 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -224,31 +234,31 @@ version = "0.1.0" [[package]] name = "cfg-if" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "clap" -version = "2.19.3" +version = "2.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "strsim 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "term_size 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-segmentation 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", + "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "vec_map 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cmake" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -257,7 +267,7 @@ version = "0.0.0" dependencies = [ "build_helper 0.1.0", "core 0.0.0", - "gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -265,9 +275,9 @@ name = "compiletest" version = "0.0.0" dependencies = [ "diff 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -277,14 +287,14 @@ version = "0.0.0" [[package]] name = "crates-io" -version = "0.9.0" +version = "0.10.0" dependencies = [ "curl 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -297,23 +307,24 @@ name = "curl" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "curl-sys 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "curl-sys 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-probe 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.12 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "curl-sys" -version = "0.3.11" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "libz-sys 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.12 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", + "libz-sys 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -342,12 +353,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "docopt" -version = "0.7.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -361,7 +373,7 @@ name = "enum_primitive" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -369,17 +381,17 @@ name = "env_logger" version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "env_logger" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -387,7 +399,7 @@ name = "error-chain" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -399,7 +411,7 @@ name = "filetime" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -407,7 +419,7 @@ name = "flate" version = "0.0.0" dependencies = [ "build_helper 0.1.0", - "gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -415,7 +427,7 @@ name = "flate2" version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", "miniz-sys 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -430,28 +442,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "fs2" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "gcc" -version = "0.3.50" +version = "0.3.51" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "gdi32-sys" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "getopts" version = "0.0.0" @@ -467,11 +470,11 @@ version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", "libgit2-sys 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-probe 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.12 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -481,8 +484,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "curl 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "git2 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -499,7 +502,7 @@ name = "hamcrest" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "num 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -509,29 +512,34 @@ version = "0.25.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "pest 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "quick-error 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "hex" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "idna" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-bidi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-normalization 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-bidi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "installer" version = "0.0.0" dependencies = [ - "clap 2.19.3 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.24.2 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -549,13 +557,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "jobserver" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -573,10 +579,10 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -594,7 +600,7 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.22" +version = "0.2.24" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -602,13 +608,13 @@ name = "libgit2-sys" version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cmake 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", - "curl-sys 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", - "gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", + "curl-sys 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", "libssh2-sys 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libz-sys 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.12 (registry+https://github.com/rust-lang/crates.io-index)", + "libz-sys 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -617,21 +623,22 @@ name = "libssh2-sys" version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cmake 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "libz-sys 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.12 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", + "libz-sys 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libz-sys" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -640,22 +647,22 @@ version = "0.1.0" [[package]] name = "log" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "lzma-sys" -version = "0.1.4" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "matches" -version = "0.1.4" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -663,13 +670,13 @@ name = "mdbook" version = "0.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "clap 2.19.3 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.24.2 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "handlebars 0.25.3 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "open 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "pulldown-cmark 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -680,7 +687,7 @@ name = "memchr" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -688,7 +695,7 @@ name = "memchr" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -696,8 +703,8 @@ name = "miniz-sys" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -716,43 +723,43 @@ name = "net2" version = "0.2.29" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num" -version = "0.1.37" +version = "0.1.39" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-bigint 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "num-complex 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "num-bigint 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", + "num-complex 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", "num-integer 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", "num-iter 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)", - "num-rational 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "num-rational 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-bigint" -version = "0.1.37" +version = "0.1.39" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num-integer 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-complex" -version = "0.1.37" +version = "0.1.38" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -761,7 +768,7 @@ name = "num-integer" version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -770,31 +777,31 @@ version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num-integer 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-rational" -version = "0.1.36" +version = "0.1.38" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-bigint 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "num-bigint 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", "num-integer 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-traits" -version = "0.1.37" +version = "0.1.39" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "num_cpus" -version = "1.4.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -804,14 +811,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "openssl" -version = "0.9.12" +version = "0.9.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.12 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -821,14 +828,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "openssl-sys" -version = "0.9.12" +version = "0.9.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)", - "gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -857,6 +862,11 @@ dependencies = [ "unwind 0.0.0", ] +[[package]] +name = "percent-encoding" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "pest" version = "0.3.3" @@ -888,7 +898,7 @@ name = "profiler_builtins" version = "0.0.0" dependencies = [ "core 0.0.0", - "gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -934,16 +944,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "racer" -version = "2.0.6" +version = "2.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "clap 2.19.3 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.24.2 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "syntex_errors 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)", "syntex_syntax 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "typed-arena 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "typed-arena 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -958,7 +969,7 @@ name = "rand" version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -975,12 +986,12 @@ dependencies = [ [[package]] name = "regex" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -992,7 +1003,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "regex-syntax" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1007,22 +1018,22 @@ version = "0.1.0" name = "rls" version = "0.1.0" dependencies = [ - "cargo 0.20.0 (git+https://github.com/rust-lang/cargo)", + "cargo 0.21.0 (git+https://github.com/rust-lang/cargo)", "derive-new 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "languageserver-types 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "racer 2.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "racer 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "rls-analysis 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "rls-data 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rls-vfs 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rustfmt 0.9.0 (git+https://github.com/rust-lang-nursery/rustfmt?branch=libsyntax)", - "serde 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rustfmt-nightly 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1032,7 +1043,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "derive-new 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "rls-data 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1062,8 +1073,8 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1071,7 +1082,7 @@ name = "rls-vfs" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "racer 2.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "racer 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1079,7 +1090,7 @@ dependencies = [ name = "rustbook" version = "0.1.0" dependencies = [ - "clap 2.19.3 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.24.2 (registry+https://github.com/rust-lang/crates.io-index)", "mdbook 0.0.21 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1090,7 +1101,7 @@ dependencies = [ "arena 0.0.0", "fmt_macros 0.0.0", "graphviz 0.0.0", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_back 0.0.0", "rustc_bitflags 0.0.0", @@ -1127,7 +1138,7 @@ version = "0.0.0" dependencies = [ "alloc_system 0.0.0", "build_helper 0.1.0", - "cmake 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -1135,7 +1146,7 @@ dependencies = [ name = "rustc_back" version = "0.0.0" dependencies = [ - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "serialize 0.0.0", "syntax 0.0.0", ] @@ -1149,7 +1160,7 @@ name = "rustc_borrowck" version = "0.0.0" dependencies = [ "graphviz 0.0.0", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", @@ -1163,7 +1174,7 @@ name = "rustc_const_eval" version = "0.0.0" dependencies = [ "arena 0.0.0", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_back 0.0.0", "rustc_const_math 0.0.0", @@ -1185,7 +1196,7 @@ dependencies = [ name = "rustc_data_structures" version = "0.0.0" dependencies = [ - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "serialize 0.0.0", ] @@ -1194,9 +1205,9 @@ name = "rustc_driver" version = "0.0.0" dependencies = [ "arena 0.0.0", - "env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "graphviz 0.0.0", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "proc_macro_plugin 0.0.0", "rustc 0.0.0", "rustc_back 0.0.0", @@ -1234,7 +1245,7 @@ name = "rustc_incremental" version = "0.0.0" dependencies = [ "graphviz 0.0.0", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_data_structures 0.0.0", "serialize 0.0.0", @@ -1246,7 +1257,7 @@ dependencies = [ name = "rustc_lint" version = "0.0.0" dependencies = [ - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_back 0.0.0", "rustc_const_eval 0.0.0", @@ -1259,7 +1270,7 @@ name = "rustc_llvm" version = "0.0.0" dependencies = [ "build_helper 0.1.0", - "gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_bitflags 0.0.0", ] @@ -1269,7 +1280,7 @@ version = "0.0.0" dependencies = [ "alloc_system 0.0.0", "build_helper 0.1.0", - "cmake 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -1278,7 +1289,7 @@ name = "rustc_metadata" version = "0.0.0" dependencies = [ "flate 0.0.0", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "proc_macro 0.0.0", "rustc 0.0.0", @@ -1297,7 +1308,7 @@ name = "rustc_mir" version = "0.0.0" dependencies = [ "graphviz 0.0.0", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_bitflags 0.0.0", "rustc_const_eval 0.0.0", @@ -1313,7 +1324,7 @@ version = "0.0.0" dependencies = [ "alloc_system 0.0.0", "build_helper 0.1.0", - "cmake 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -1321,7 +1332,7 @@ dependencies = [ name = "rustc_passes" version = "0.0.0" dependencies = [ - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_const_eval 0.0.0", "rustc_const_math 0.0.0", @@ -1360,7 +1371,7 @@ name = "rustc_resolve" version = "0.0.0" dependencies = [ "arena 0.0.0", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_errors 0.0.0", "syntax 0.0.0", @@ -1371,7 +1382,7 @@ dependencies = [ name = "rustc_save_analysis" version = "0.0.0" dependencies = [ - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "rls-data 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", @@ -1386,8 +1397,8 @@ name = "rustc_trans" version = "0.0.0" dependencies = [ "flate 0.0.0", - "gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_back 0.0.0", @@ -1409,7 +1420,7 @@ version = "0.0.0" dependencies = [ "alloc_system 0.0.0", "build_helper 0.1.0", - "cmake 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -1419,7 +1430,7 @@ version = "0.0.0" dependencies = [ "arena 0.0.0", "fmt_macros 0.0.0", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_back 0.0.0", "rustc_const_math 0.0.0", @@ -1436,9 +1447,9 @@ version = "0.0.0" dependencies = [ "arena 0.0.0", "build_helper 0.1.0", - "env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "pulldown-cmark 0.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_back 0.0.0", @@ -1456,19 +1467,19 @@ dependencies = [ ] [[package]] -name = "rustfmt" -version = "0.9.0" -source = "git+https://github.com/rust-lang-nursery/rustfmt?branch=libsyntax#6c1de7694782d9f710b2f00b1f650f266a99b384" +name = "rustfmt-nightly" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "diff 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "strings 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1497,7 +1508,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1512,22 +1523,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.6" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.6" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive_internals 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive_internals 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_derive_internals" -version = "0.15.0" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1539,7 +1550,7 @@ name = "serde_ignored" version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1549,7 +1560,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1560,8 +1571,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1588,7 +1599,7 @@ dependencies = [ "build_helper 0.1.0", "compiler_builtins 0.0.0", "core 0.0.0", - "gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.0.0", "panic_abort 0.0.0", "panic_unwind 0.0.0", @@ -1614,14 +1625,9 @@ name = "strings" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "strsim" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "strsim" version = "0.6.0" @@ -1659,7 +1665,7 @@ name = "syntax" version = "0.0.0" dependencies = [ "bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", "serialize 0.0.0", @@ -1671,7 +1677,7 @@ name = "syntax_ext" version = "0.0.0" dependencies = [ "fmt_macros 0.0.0", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "proc_macro 0.0.0", "rustc_errors 0.0.0", "syntax 0.0.0", @@ -1690,8 +1696,8 @@ name = "syntex_errors" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", "syntex_pos 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1712,8 +1718,8 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", "syntex_errors 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)", "syntex_pos 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1727,7 +1733,7 @@ version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", "xattr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1754,14 +1760,22 @@ dependencies = [ [[package]] name = "term_size" -version = "0.2.3" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "termcolor" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "wincolor 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "test" version = "0.0.0" @@ -1776,7 +1790,7 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1785,7 +1799,7 @@ version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1838,30 +1852,25 @@ name = "toml" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "typed-arena" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "unicode-bidi" -version = "0.2.5" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "unicode-normalization" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "unicode-segmentation" -version = "0.1.3" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1901,11 +1910,12 @@ dependencies = [ [[package]] name = "url" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "idna 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "idna 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "percent-encoding 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1913,17 +1923,8 @@ name = "url_serde" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "user32-sys" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1936,9 +1937,14 @@ name = "utf8-ranges" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "vcpkg" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "vec_map" -version = "0.6.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1966,6 +1972,15 @@ name = "winapi-build" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "wincolor" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ws2_32-sys" version = "0.2.1" @@ -1980,7 +1995,7 @@ name = "xattr" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1988,7 +2003,7 @@ name = "xz2" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lzma-sys 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "lzma-sys 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2001,73 +2016,75 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ca972c2ea5f742bfce5687b9aef75506a764f61d37f8f649047846a9686ddb66" "checksum aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699" "checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6" -"checksum backtrace 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f551bc2ddd53aea015d453ef0b635af89444afa5ed2405dd0b2062ad5d600d80" -"checksum backtrace-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d192fd129132fbc97497c1f2ec2c2c5174e376b95f535199ef4fe0a293d33842" +"checksum atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d912da0db7fa85514874458ca3651fe2cddace8d0b0505571dbdcd41ab490159" +"checksum backtrace 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "72f9b4182546f4b04ebc4ab7f84948953a118bd6021a1b6a6c909e3e94f6be76" +"checksum backtrace-sys 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3a0d842ea781ce92be2bf78a9b38883948542749640b8378b3b2f03d1fd9f1ff" "checksum bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4f67931368edf3a9a51d29886d245f1c3db2f1ef0dcc9e35ff70341b78c10d23" "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" "checksum bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1370e9fc2a6ae53aea8b7a5110edbd08836ed87c88736dfabccade1c2b44bff4" "checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" "checksum bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f382711e76b9de6c744cc00d0497baba02fb00a787f088c879f01d09468e32" -"checksum cargo 0.20.0 (git+https://github.com/rust-lang/cargo)" = "" -"checksum cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de1e760d7b6535af4241fca8bd8adf68e2e7edacc6b29f5d399050c5e48cf88c" -"checksum clap 2.19.3 (registry+https://github.com/rust-lang/crates.io-index)" = "95b78f3fe0fc94c13c731714363260e04b557a637166f33a4570d3189d642374" -"checksum cmake 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)" = "92278eb79412c8f75cfc89e707a1bb3a6490b68f7f2e78d15c774f30fe701122" +"checksum cargo 0.21.0 (git+https://github.com/rust-lang/cargo)" = "" +"checksum cfg-if 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d0c47d456a36ebf0536a6705c83c1cbbcb9255fbc1d905a6ded104f479268a29" +"checksum clap 2.24.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6b8f69e518f967224e628896b54e41ff6acfb4dcfefc5076325c36525dac900f" +"checksum cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b8ebbb35d3dc9cd09497168f33de1acb79b265d350ab0ac34133b98f8509af1f" "checksum crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0c5ea215664ca264da8a9d9c3be80d2eaf30923c259d03e870388eb927508f97" "checksum curl 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c90e1240ef340dd4027ade439e5c7c2064dd9dc652682117bd50d1486a3add7b" -"checksum curl-sys 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "23e7e544dc5e1ba42c4a4a678bd47985e84b9c3f4d3404c29700622a029db9c3" +"checksum curl-sys 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)" = "f00c8ba847fb0730c293069b4d1203dc01bf3c2e1f90b4e55f426ed8f4a1eeac" "checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850" "checksum derive-new 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "41be6ca3b99e0c0483fb2389685448f650459c3ecbe4e18d7705d8010ec4ab8e" "checksum diff 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0a515461b6c8c08419850ced27bc29e86166dcdcde8fbe76f8b1f0589bb49472" -"checksum docopt 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ab32ea6e284d87987066f21a9e809a73c14720571ef34516f0890b3d355ccfd8" +"checksum docopt 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "63e408eee8a772c5c61f62353992e3ebf51ef5c832dd04d986b3dc7d48c5b440" "checksum dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80c8b71fd71146990a9742fc06dcbbde19161a267e0ad4e572c35162f4578c90" "checksum enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be4551092f4d519593039259a9ed8daedf0da12e5109c5280338073eaeb81180" "checksum env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "15abd780e45b3ea4f76b4e9a26ff4843258dd8a3eed2775a0e7368c2e7936c2f" -"checksum env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e3856f1697098606fc6cb97a93de88ca3f3bc35bb878c725920e6e82ecf05e83" +"checksum env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3ddf21e73e016298f5cb37d6ef8e8da8e39f91f9ec8b0df44b7deb16a9f8cd5b" "checksum error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9435d864e017c3c6afeac1654189b06cdb491cf2ff73dbf0d73b0f292f42ff8" "checksum filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "5363ab8e4139b8568a6237db5248646e5a8a2f89bd5ccb02092182b11fd3e922" "checksum flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)" = "36df0166e856739905cd3d7e0b210fe818592211a008862599845e012d8d304c" "checksum foreign-types 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e4056b9bd47f8ac5ba12be771f77a0dae796d1bbaaf5fd0b9c2d38b69b8a29d" -"checksum fs2 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "34edaee07555859dc13ca387e6ae05686bb4d0364c95d649b6dab959511f4baf" -"checksum gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)" = "5f837c392f2ea61cb1576eac188653df828c861b7137d74ea4a5caa89621f9e6" -"checksum gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0912515a8ff24ba900422ecda800b52f4016a56251922d397c576bf92c690518" +"checksum fs2 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9ab76cfd2aaa59b7bf6688ad9ba15bbae64bff97f04ea02144cfd3443e5c2866" +"checksum gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)" = "120d07f202dcc3f72859422563522b66fe6463a4c513df062874daad05f85f0a" "checksum getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9047cfbd08a437050b363d35ef160452c5fe8ea5187ae0a624708c91581d685" "checksum git2 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "aa01936ac96555c083c0e8553f672616274408d9d3fc5b8696603fbf63ff43ee" "checksum git2-curl 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "68676bc784bf0bef83278898929bf64a251e87c0340723d0b93fa096c9c5bf8e" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" "checksum hamcrest 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bf088f042a467089e9baa4972f57f9247e42a0cc549ba264c7a04fbb8ecb89d4" "checksum handlebars 0.25.3 (registry+https://github.com/rust-lang/crates.io-index)" = "15bdf598fc3c2de40c6b340213028301c0d225eea55a2294e6cc148074e557a1" -"checksum idna 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6ac85ec3f80c8e4e99d9325521337e14ec7555c458a14e377d189659a427f375" +"checksum hex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d6a22814455d41612f41161581c2883c0c6a1c41852729b17d5ed88f01e153aa" +"checksum idna 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2233d4940b1f19f0418c158509cd7396b8d70a5db5705ce410914dc8fa603b37" "checksum itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2f404fbc66fd9aac13e998248505e7ecb2ad8e44ab6388684c5fb11c6c251c" -"checksum jobserver 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c43fc6e4066b2adf0539c854daa1d926d7f23e6926e019850d34b8ae46391b2e" +"checksum jobserver 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4e28adc987f6d0521ef66ad60b055968107b164b3bb3cf3dc8474e0a380474a6" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum languageserver-types 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97c2985bfcbbcb0189cfa25e1c10c1ac7111df2b6214b652c690127aefdf4e5b" "checksum lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3b37545ab726dd833ec6420aaba8231c5b320814b9029ad585555d2a03e94fbf" -"checksum libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)" = "babb8281da88cba992fa1f4ddec7d63ed96280a1a53ec9b919fd37b53d71e502" +"checksum libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)" = "38f5c2b18a287cf78b4097db62e20f43cace381dc76ae5c0a3073067f78b7ddc" "checksum libgit2-sys 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "df18a822100352d9863b302faf6f8f25c0e77f0e60feb40e5dbe1238b7f13b1d" "checksum libssh2-sys 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0db4ec23611747ef772db1c4d650f8bd762f07b461727ec998f953c614024b75" -"checksum libz-sys 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e5ee912a45d686d393d5ac87fac15ba0ba18daae14e8e7543c63ebf7fb7e970c" -"checksum log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "5141eca02775a762cc6cd564d8d2c50f67c0ea3a372cbf1c51592b3e029e10ad" -"checksum lzma-sys 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "fedff6a5cbb24494ec6ee4784e9ac5c187161fede04c7767d49bf87544013afa" -"checksum matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "efd7622e3022e1a6eaa602c4cea8912254e5582c9c692e9167714182244801b1" +"checksum libz-sys 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "e70195f655a44af531ad7135b1ec2a0a82522b451fe09730fbb25674a85996e7" +"checksum log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b" +"checksum lzma-sys 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "013fa6506eb7d26040c46dab9ecb7ccb4e2896b5bf24a9d65932501ea9f67af8" +"checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376" "checksum mdbook 0.0.21 (registry+https://github.com/rust-lang/crates.io-index)" = "f1e2e9d848514dcfad4195788d0d42ae5153a477c191d75d5b84fab10f222fbd" "checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20" "checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4" "checksum miniz-sys 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "28eaee17666671fa872e567547e8428e83308ebe5808cdf6a0e28397dbe2c726" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" "checksum net2 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)" = "bc01404e7568680f1259aa5729539f221cb1e6d047a0d9053cab4be8a73b5d67" -"checksum num 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "98b15ba84e910ea7a1973bccd3df7b31ae282bf9d8bd2897779950c9b8303d40" -"checksum num-bigint 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "ba6d838b16e56da1b6c383d065ff1ec3c7d7797f65a3e8f6ba7092fd87820bac" -"checksum num-complex 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "148eb324ca772230853418731ffdf13531738b50f89b30692a01fcdcb0a64677" +"checksum num 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "2c3a3dc9f30bf824141521b30c908a859ab190b76e20435fcd89f35eb6583887" +"checksum num-bigint 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "6361748d02e5291c72a422dc8ed4d8464a80cb1e618971f6fffe6d52d97e3286" +"checksum num-complex 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)" = "412dfc143c56579aa6a22c574e38ddbf724522f1280ae2b257498cccff3fb6af" "checksum num-integer 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)" = "ef1a4bf6f9174aa5783a9b4cc892cacd11aebad6c69ad027a0b65c6ca5f8aa37" "checksum num-iter 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)" = "f7d1891bd7b936f12349b7d1403761c8a0b85a18b148e9da4429d5d102c1a41e" -"checksum num-rational 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "c2dc5ea04020a8f18318ae485c751f8cfa1c0e69dcf465c29ddaaa64a313cc44" -"checksum num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "e1cbfa3781f3fe73dc05321bed52a06d2d491eaa764c52335cf4399f046ece99" -"checksum num_cpus 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca313f1862c7ec3e0dfe8ace9fa91b1d9cb5c84ace3d00f5ec4216238e93c167" +"checksum num-rational 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)" = "33c881e104a26e1accc09449374c095ff2312c8e0c27fab7bbefe16eac7c776d" +"checksum num-traits 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "1708c0628602a98b52fad936cf3edb9a107af06e52e49fdf0707e884456a6af6" +"checksum num_cpus 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6e416ba127a4bb3ff398cb19546a8d0414f73352efe2857f4060d36f5fe5983a" "checksum open 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3478ed1686bd1300c8a981a940abc92b06fac9cbef747f4c668d4e032ff7b842" -"checksum openssl 0.9.12 (registry+https://github.com/rust-lang/crates.io-index)" = "bb5d1663b73d10c6a3eda53e2e9d0346f822394e7b858d7257718f65f61dfbe2" +"checksum openssl 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)" = "11ba043cb65fc9af71a431b8a36ffe8686cd4751cdf70a473ec1d01066ac7e41" "checksum openssl-probe 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d98df0270d404ccd3c050a41d579c52d1db15375168bb3471e04ec0f5f378daf" -"checksum openssl-sys 0.9.12 (registry+https://github.com/rust-lang/crates.io-index)" = "3a5886d87d3e2a0d890bf62dc8944f5e3769a405f7e1e9ef6e517e47fd7a0897" +"checksum openssl-sys 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)" = "236c718c2e2c2b58a546d86ffea5194400bb15dbe01ca85325ffd357b03cf66c" "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" +"checksum percent-encoding 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de154f638187706bde41d9b4738748933d64e6b37bdbffc0b47a97d16a6ae356" "checksum pest 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0a6dda33d67c26f0aac90d324ab2eb7239c819fc7b2552fe9faa4fe88441edc8" "checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903" "checksum psapi-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "abcd5d1a07d360e29727f757a9decb3ce8bc6e0efa8969cfaad669a8317a2478" @@ -2076,12 +2093,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum quick-error 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c36987d4978eb1be2e422b1e0423a557923a5c3e7e6f31d5699e9aafaefa469" "checksum quote 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4c5cf478fe1006dbcc72567121d23dbdae5f1632386068c5c86ff4f645628504" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" -"checksum racer 2.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b0d72b3afd67882adfca61d609fafb8d7aa5f9e814f12c32fcc6e171995920e8" +"checksum racer 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "edf2dfc188373ef96168bec3646a0415c5c21111c6144c0c36104fc720587ecd" "checksum rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "022e0636ec2519ddae48154b028864bdce4eaf7d35226ab8e65c611be97b189d" "checksum regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)" = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f" -"checksum regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4278c17d0f6d62dfef0ab00028feb45bd7d2102843f80763474eeb1be8a10c01" +"checksum regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1731164734096285ec2a5ec7fea5248ae2f5485b3feeb0115af4fda2183b2d1b" "checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957" -"checksum regex-syntax 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9191b1f57603095f105d317e375d19b1c9c5c3185ea9633a99a6dcbed04457" +"checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db" "checksum rls-analysis 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8d77d58e8933752142b5b92e3f8ba6d6f1630be6da5627c492268a43f79ffbda" "checksum rls-data 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "374a8fad31cc0681a7bfd8a04079dd4afd0e981d34e18a171b1a467445bdf51e" "checksum rls-data 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9e2087477364c34faca86c2476765deb1185dbae3c598cfb1eb040f3a74d22b5" @@ -2089,22 +2106,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rls-vfs 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ace07060dd154731b39254864245cbdd33c8f5f64fe1f630a089c72e2468f854" "checksum rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3058a43ada2c2d0b92b3ae38007a2d0fa5e9db971be260e0171408a4ff471c95" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" -"checksum rustfmt 0.9.0 (git+https://github.com/rust-lang-nursery/rustfmt?branch=libsyntax)" = "" +"checksum rustfmt-nightly 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "277deb9c0ee9c4788ee94faef5988fa334179cd7363bf281a2cae027edbbc8bf" "checksum same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d931a44fdaa43b8637009e7632a02adc4f2b2e0733c08caa4cf00e8da4a117a7" "checksum scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f417c22df063e9450888a7561788e9bd46d3bb3c1466435b4eccb903807f147d" "checksum semver 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3fdd61b85a0fa777f7fb7c454b9189b2941b110d1385ce84d7f76efdf1606a85" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" "checksum serde 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)" = "34b623917345a631dc9608d5194cc206b3fe6c3554cd1c75b937e55e285254af" -"checksum serde 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "38a3db3a5757f68069aba764b793823ea9fb9717c42c016f8903f8add50f508a" -"checksum serde_derive 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e46ef71ee001a4279a4513e79a6ebbb59da3a4987bf77a6df2e5534cd6f21d82" -"checksum serde_derive_internals 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "021c338d22c7e30f957a6ab7e388cb6098499dda9fd4ba1661ee074ca7a180d1" +"checksum serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c2f530d36fb84ec48fb7146936881f026cdbf4892028835fd9398475f82c1bb4" +"checksum serde_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "10552fad5500771f3902d0c5ba187c5881942b811b7ba0d8fbbfbf84d80806d3" +"checksum serde_derive_internals 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)" = "37aee4e0da52d801acfbc0cc219eb1eda7142112339726e427926a6f6ee65d3a" "checksum serde_ignored 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c10e798e4405d7dcec3658989e35ee6706f730a9ed7c1184d5ebd84317e82f46" "checksum serde_json 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ad8bcf487be7d2e15d3d543f04312de991d631cfe1b43ea0ade69e6a8a5b16a1" "checksum serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "48b04779552e92037212c3615370f6bd57a40ebba7f20e554ff9f55e41a69a7b" "checksum shell-escape 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "dd5cc96481d54583947bfe88bf30c23d53f883c6cd0145368b69989d97b84ef8" "checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b" "checksum strings 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "da75d8bf2c4d210d63dd09581a041b036001f9f6e03d9b151dbff810fb7ba26a" -"checksum strsim 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "67f84c44fbb2f91db7fef94554e6b2ac05909c9c0b0bc23bb98d3a1aebfe7f7c" "checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694" "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" "checksum syn 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6ae6fb0dcc9bd85f89a1a4adc0df2fd90c90c98849d61433983dd7a9df6363f7" @@ -2115,7 +2131,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum tar 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "281285b717926caa919ad905ef89c63d75805c7d89437fb873100925a53f2b1b" "checksum tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "87974a6f5c1dfb344d733055601650059a3363de2a6104819293baff662132d6" "checksum term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d168af3930b369cfe245132550579d47dfd873d69470755a19c2c6568dbbd989" -"checksum term_size 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "07b6c1ac5b3fffd75073276bca1ceed01f67a28537097a2a9539e116e50fb21a" +"checksum term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2b6b55df3198cc93372e85dd2ed817f0e38ce8cc0f22eb32391bfad9c4bf209" +"checksum termcolor 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9a5193a56b8d82014662c4b933dea6bec851daf018a2b01722e007daaf5f9dca" "checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03" "checksum thread-id 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8df7875b676fddfadffd96deea3b1124e5ede707d4884248931077518cf1f773" "checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5" @@ -2124,25 +2141,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum toml 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "736b60249cb25337bc196faa43ee12c705e426f3d55c214d73a4e7be06f92cb4" "checksum toml 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bd86ad9ebee246fdedd610e0f6d0587b754a3d81438db930a244d0480ed7878f" "checksum toml 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4cc5dbfb20a481e64b99eb7ae280859ec76730c7191570ba5edaa962394edb0a" -"checksum typed-arena 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8e2f9dc90da4f9d66ffc9ad3ead2c7d57582a26f4a3292d2ce7011bd29965100" -"checksum unicode-bidi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d3a078ebdd62c0e71a709c3d53d2af693fe09fe93fbff8344aebe289b78f9032" -"checksum unicode-normalization 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e28fa37426fceeb5cf8f41ee273faa7c82c47dc8fba5853402841e665fcd86ff" -"checksum unicode-segmentation 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c3bc443ded17b11305ffffe6b37e2076f328a5a8cb6aa877b1b98f77699e98b5" +"checksum typed-arena 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5934776c3ac1bea4a9d56620d6bf2d483b20d394e49581db40f187e1118ff667" +"checksum unicode-bidi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a6a2c4e3710edd365cd7e78383153ed739fa31af19f9172f72d3575060f5a43a" +"checksum unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "51ccda9ef9efa3f7ef5d91e8f9b83bbe6955f9bf86aec89d5cce2c874625920f" "checksum unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a8083c594e02b8ae1654ae26f0ade5158b119bd88ad0e8227a5d8fcd72407946" "checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f" "checksum unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "36dff09cafb4ec7c8cf0023eb0b686cb6ce65499116a12201c9e11840ca01beb" "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" "checksum unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f2ae5ddb18e1c92664717616dd9549dde73f539f01bd7b77c2edb2446bdff91" -"checksum url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f5ba8a749fb4479b043733416c244fa9d1d3af3d7c23804944651c8a448cb87e" +"checksum url 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a69a2e36a5e5ed3f3063c8c64a3b028c4d50d689fa6c862abd7cfe65f882595c" "checksum url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "74e7d099f1ee52f823d4bdd60c93c3602043c728f5db3b97bdb548467f7bddea" -"checksum user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ef4711d107b21b410a3a974b1204d9accc8b10dad75d8324b5d755de1617d47" "checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f" "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" -"checksum vec_map 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cac5efe5cb0fa14ec2f84f83c701c562ee63f6dcc680861b21d65c682adfb05f" +"checksum vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9e0a7d8bed3178a8fb112199d466eeca9ed09a14ba8ad67718179b4fd5487d0b" +"checksum vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887b5b631c2ad01628bbbaa7dd4c869f80d3186688f8d0b6f58774fbe324988c" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" "checksum walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "bb08f9e670fab86099470b97cd2b252d6527f0b3cc1401acdb595ffc9dd288ff" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" +"checksum wincolor 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "99c2af1426e2166e6f66d88b09b2a4d63afce06875f149174e386f2f1ee9779b" "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" "checksum xattr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "5f04de8a1346489a2f9e9bd8526b73d135ec554227b17568456e86aa35b6f3fc" "checksum xz2 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e9510bdf100731599107c61f77daf46713a69a568f75458999c1f9dbf6ba25b0" diff --git a/src/Cargo.toml b/src/Cargo.toml index 8efa484287a1..9cf6297d463b 100644 --- a/src/Cargo.toml +++ b/src/Cargo.toml @@ -37,4 +37,4 @@ debug = false debug-assertions = false [replace] -"https://github.com/rust-lang/cargo#0.20.0" = { path = "tools/cargo" } +"https://github.com/rust-lang/cargo#0.21.0" = { path = "tools/cargo" } diff --git a/src/tools/cargo b/src/tools/cargo index bbfe9b3a9d64..50b1c24d146f 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit bbfe9b3a9d64aa8698b18cbb3803b3fa00ee3f44 +Subproject commit 50b1c24d146fa072db71f12005deed319ac5ba9a diff --git a/src/tools/rls b/src/tools/rls index 0d0f3baad02d..e53e2f8d5b7f 160000 --- a/src/tools/rls +++ b/src/tools/rls @@ -1 +1 @@ -Subproject commit 0d0f3baad02d65d96befbb90e77bf8a326dd14f5 +Subproject commit e53e2f8d5b7f7751dd478fff68c1dbe7247cb096 From 723772fc556506d5357273e7f84b677e7c62bc96 Mon Sep 17 00:00:00 2001 From: ubsan Date: Sat, 17 Jun 2017 13:14:26 -0700 Subject: [PATCH 224/233] Add `_` to the list of keywords also, make sure the keyword table is correctly spaced --- src/doc/grammar.md | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/doc/grammar.md b/src/doc/grammar.md index 12daa24e857f..78432b6a9659 100644 --- a/src/doc/grammar.md +++ b/src/doc/grammar.md @@ -154,19 +154,19 @@ token : simple_token | ident | literal | symbol | whitespace token ;

-| | | | | | -|----------|----------|----------|----------|---------| -| abstract | alignof | as | become | box | -| break | const | continue | crate | do | -| else | enum | extern | false | final | -| fn | for | if | impl | in | -| let | loop | macro | match | mod | -| move | mut | offsetof | override | priv | -| proc | pub | pure | ref | return | -| Self | self | sizeof | static | struct | -| super | trait | true | type | typeof | -| unsafe | unsized | use | virtual | where | -| while | yield | | | | +| | | | | | +|----------|----------|----------|----------|----------| +| _ | abstract | alignof | as | become | +| box | break | const | continue | crate | +| do | else | enum | extern | false | +| final | fn | for | if | impl | +| in | let | loop | macro | match | +| mod | move | mut | offsetof | override | +| priv | proc | pub | pure | ref | +| return | Self | self | sizeof | static | +| struct | super | trait | true | type | +| typeof | unsafe | unsized | use | virtual | +| where | while | yield | | | Each of these keywords has special meaning in its grammar, and all of them are From 6484258f1749499d3e51685df867b3d460a7f0be Mon Sep 17 00:00:00 2001 From: Murarth Date: Sat, 17 Jun 2017 12:01:18 -0700 Subject: [PATCH 225/233] Reintroduce deprecated `collections` crate --- src/Cargo.lock | 9 +++ src/bootstrap/dist.rs | 1 + src/bootstrap/doc.rs | 2 +- src/doc/unstable-book/src/SUMMARY.md | 1 + .../src/library-features/collections.md | 5 ++ src/libcollections/Cargo.toml | 12 ++++ src/libcollections/lib.rs | 72 +++++++++++++++++++ src/libstd/Cargo.toml | 1 + 8 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 src/doc/unstable-book/src/library-features/collections.md create mode 100644 src/libcollections/Cargo.toml create mode 100644 src/libcollections/lib.rs diff --git a/src/Cargo.lock b/src/Cargo.lock index 9fae4b7e924c..efcd5645d336 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -251,6 +251,14 @@ dependencies = [ "gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "collections" +version = "0.0.0" +dependencies = [ + "alloc 0.0.0", + "core 0.0.0", +] + [[package]] name = "compiler_builtins" version = "0.0.0" @@ -1586,6 +1594,7 @@ dependencies = [ "alloc_jemalloc 0.0.0", "alloc_system 0.0.0", "build_helper 0.1.0", + "collections 0.0.0", "compiler_builtins 0.0.0", "core 0.0.0", "gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 4d58620ca648..f92e6f50eb3e 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -550,6 +550,7 @@ pub fn rust_src(build: &Build) { "src/liballoc_jemalloc", "src/liballoc_system", "src/libbacktrace", + "src/libcollections", "src/libcompiler_builtins", "src/libcore", "src/liblibc", diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 23a38f6a8969..30f631ca2df6 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -254,7 +254,7 @@ pub fn std(build: &Build, stage: u32, target: &str) { // for which docs must be built. if !build.config.compiler_docs { cargo.arg("--no-deps"); - for krate in &["alloc", "core", "std", "std_unicode"] { + for krate in &["alloc", "collections", "core", "std", "std_unicode"] { cargo.arg("-p").arg(krate); // Create all crate output directories first to make sure rustdoc uses // relative links. diff --git a/src/doc/unstable-book/src/SUMMARY.md b/src/doc/unstable-book/src/SUMMARY.md index d8f742735a8d..d7c368292115 100644 --- a/src/doc/unstable-book/src/SUMMARY.md +++ b/src/doc/unstable-book/src/SUMMARY.md @@ -108,6 +108,7 @@ - [char_escape_debug](library-features/char-escape-debug.md) - [coerce_unsized](library-features/coerce-unsized.md) - [collection_placement](library-features/collection-placement.md) + - [collections](library-features/collections.md) - [collections_range](library-features/collections-range.md) - [command_envs](library-features/command-envs.md) - [compiler_builtins_lib](library-features/compiler-builtins-lib.md) diff --git a/src/doc/unstable-book/src/library-features/collections.md b/src/doc/unstable-book/src/library-features/collections.md new file mode 100644 index 000000000000..5c937833c9e2 --- /dev/null +++ b/src/doc/unstable-book/src/library-features/collections.md @@ -0,0 +1,5 @@ +# `collections` + +This feature is internal to the Rust compiler and is not intended for general use. + +------------------------ diff --git a/src/libcollections/Cargo.toml b/src/libcollections/Cargo.toml new file mode 100644 index 000000000000..800e36161d24 --- /dev/null +++ b/src/libcollections/Cargo.toml @@ -0,0 +1,12 @@ +[package] +authors = ["The Rust Project Developers"] +name = "collections" +version = "0.0.0" + +[lib] +name = "collections" +path = "lib.rs" + +[dependencies] +alloc = { path = "../liballoc" } +core = { path = "../libcore" } diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs new file mode 100644 index 000000000000..de5d6df328cb --- /dev/null +++ b/src/libcollections/lib.rs @@ -0,0 +1,72 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_name = "collections"] +#![crate_type = "rlib"] +#![allow(unused_attributes)] +#![unstable(feature = "collections", + reason = "this library is unlikely to be stabilized in its current \ + form or name", + issue = "27783")] +#![rustc_deprecated(since = "1.20.0", + reason = "collections moved to `alloc`")] +#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", + html_favicon_url = "https://doc.rust-lang.org/favicon.ico", + html_root_url = "https://doc.rust-lang.org/nightly/", + issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/", + test(no_crate_inject, attr(allow(unused_variables), deny(warnings))))] +#![no_std] +#![needs_allocator] +#![deny(warnings)] + +#![feature(alloc)] +#![feature(collections_range)] +#![feature(macro_reexport)] +#![feature(needs_allocator)] +#![feature(staged_api)] + +//! Collection types +//! +//! See [`std::collections`](../std/collections/index.html) for a detailed +//! discussion of collections in Rust. + +#[macro_reexport(vec, format)] +extern crate alloc; + +pub use alloc::Bound; + +pub use alloc::binary_heap; +pub use alloc::borrow; +pub use alloc::fmt; +pub use alloc::linked_list; +pub use alloc::range; +pub use alloc::slice; +pub use alloc::str; +pub use alloc::string; +pub use alloc::vec; +pub use alloc::vec_deque; + +pub use alloc::btree_map; +pub use alloc::btree_set; + +#[doc(no_inline)] +pub use alloc::binary_heap::BinaryHeap; +#[doc(no_inline)] +pub use alloc::btree_map::BTreeMap; +#[doc(no_inline)] +pub use alloc::btree_set::BTreeSet; +#[doc(no_inline)] +pub use alloc::linked_list::LinkedList; +#[doc(no_inline)] +pub use alloc::vec_deque::VecDeque; +#[doc(no_inline)] +pub use alloc::string::String; +#[doc(no_inline)] +pub use alloc::vec::Vec; diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index f93af4c19201..b516cbd08ca0 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -15,6 +15,7 @@ alloc_jemalloc = { path = "../liballoc_jemalloc", optional = true } alloc_system = { path = "../liballoc_system" } panic_unwind = { path = "../libpanic_unwind", optional = true } panic_abort = { path = "../libpanic_abort" } +collections = { path = "../libcollections" } core = { path = "../libcore" } libc = { path = "../rustc/libc_shim" } rand = { path = "../librand" } From abebe8afde343a3eed5a62eaa8162b76d291f526 Mon Sep 17 00:00:00 2001 From: Wonwoo Choi Date: Sun, 18 Jun 2017 16:07:26 +0900 Subject: [PATCH 226/233] Use T as the subpattern type of Box The subpattern type of boxes being nil does not make sense because of box patterns. They should have their inner type as the subpattern type. --- src/librustc_const_eval/_match.rs | 35 ++++++++++++++++++------------- src/test/run-pass/issue-42679.rs | 31 +++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 15 deletions(-) create mode 100644 src/test/run-pass/issue-42679.rs diff --git a/src/librustc_const_eval/_match.rs b/src/librustc_const_eval/_match.rs index c1dc5f5f7a2b..98d90188312d 100644 --- a/src/librustc_const_eval/_match.rs +++ b/src/librustc_const_eval/_match.rs @@ -774,21 +774,26 @@ fn constructor_sub_pattern_tys<'a, 'tcx: 'a>(cx: &MatchCheckCtxt<'a, 'tcx>, }, ty::TyRef(_, ref ty_and_mut) => vec![ty_and_mut.ty], ty::TyAdt(adt, substs) => { - adt.variants[ctor.variant_index_for_adt(adt)].fields.iter().map(|field| { - let is_visible = adt.is_enum() - || field.vis.is_accessible_from(cx.module, cx.tcx); - if is_visible { - field.ty(cx.tcx, substs) - } else { - // Treat all non-visible fields as nil. They - // can't appear in any other pattern from - // this match (because they are private), - // so their type does not matter - but - // we don't want to know they are - // uninhabited. - cx.tcx.mk_nil() - } - }).collect() + if adt.is_box() { + // Use T as the sub pattern type of Box. + vec![substs[0].as_type().unwrap()] + } else { + adt.variants[ctor.variant_index_for_adt(adt)].fields.iter().map(|field| { + let is_visible = adt.is_enum() + || field.vis.is_accessible_from(cx.module, cx.tcx); + if is_visible { + field.ty(cx.tcx, substs) + } else { + // Treat all non-visible fields as nil. They + // can't appear in any other pattern from + // this match (because they are private), + // so their type does not matter - but + // we don't want to know they are + // uninhabited. + cx.tcx.mk_nil() + } + }).collect() + } } _ => vec![], } diff --git a/src/test/run-pass/issue-42679.rs b/src/test/run-pass/issue-42679.rs new file mode 100644 index 000000000000..312835225edf --- /dev/null +++ b/src/test/run-pass/issue-42679.rs @@ -0,0 +1,31 @@ +// 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. + +#![feature(box_syntax)] +#![feature(box_patterns)] + +#[derive(Debug, PartialEq)] +enum Test { + Foo(usize), + Bar(isize), +} + +fn main() { + let a = box Test::Foo(10); + let b = box Test::Bar(-20); + match (a, b) { + (_, box Test::Foo(_)) => unreachable!(), + (box Test::Foo(x), b) => { + assert_eq!(x, 10); + assert_eq!(b, box Test::Bar(-20)); + }, + _ => unreachable!(), + } +} From a5403d09f5fedd4cdc263e8108e7b455931f74da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Malo=20Jaffr=C3=A9?= Date: Sun, 18 Jun 2017 14:30:33 +0200 Subject: [PATCH 227/233] Add test for #24889 Fixes #24889. r? @Mark-Simulacrum. --- .../ui/coercion-missing-tail-expected-type.rs | 4 ++++ .../coercion-missing-tail-expected-type.stderr | 17 +++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/src/test/ui/coercion-missing-tail-expected-type.rs b/src/test/ui/coercion-missing-tail-expected-type.rs index 489ad817ea8b..15ce79a054f2 100644 --- a/src/test/ui/coercion-missing-tail-expected-type.rs +++ b/src/test/ui/coercion-missing-tail-expected-type.rs @@ -14,6 +14,10 @@ fn plus_one(x: i32) -> i32 { x + 1; } +fn foo() -> Result { + Ok(1); +} + fn main() { let x = plus_one(5); println!("X = {}", x); diff --git a/src/test/ui/coercion-missing-tail-expected-type.stderr b/src/test/ui/coercion-missing-tail-expected-type.stderr index 28a99e58eca8..e96bc425e0b4 100644 --- a/src/test/ui/coercion-missing-tail-expected-type.stderr +++ b/src/test/ui/coercion-missing-tail-expected-type.stderr @@ -15,5 +15,22 @@ help: consider removing this semicolon: 14 | x + 1; | ^ +error[E0308]: mismatched types + --> $DIR/coercion-missing-tail-expected-type.rs:17:29 + | +17 | fn foo() -> Result { + | _____________________________^ +18 | | Ok(1); +19 | | } + | |_^ expected enum `std::result::Result`, found () + | + = note: expected type `std::result::Result` + found type `()` +help: consider removing this semicolon: + --> $DIR/coercion-missing-tail-expected-type.rs:18:10 + | +18 | Ok(1); + | ^ + error: aborting due to previous error(s) From 09219d6a49357ae8dbfedae35fff20e6ffb6f738 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Sun, 18 Jun 2017 18:57:39 +0300 Subject: [PATCH 228/233] collector: apply param substs to closures cast to fn items Fixes #42718. --- src/librustc_trans/collector.rs | 4 ++++ src/test/run-pass/closure-to-fn-coercion.rs | 7 +++++++ 2 files changed, 11 insertions(+) diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs index da74ed88eaf8..d723cf325718 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans/collector.rs @@ -493,6 +493,8 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { } mir::Rvalue::Cast(mir::CastKind::ClosureFnPointer, ref operand, _) => { let source_ty = operand.ty(self.mir, self.scx.tcx()); + let source_ty = self.scx.tcx().trans_apply_param_substs(self.param_substs, + &source_ty); match source_ty.sty { ty::TyClosure(def_id, substs) => { let instance = monomorphize::resolve_closure( @@ -543,6 +545,8 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { block: mir::BasicBlock, kind: &mir::TerminatorKind<'tcx>, location: Location) { + debug!("visiting terminator {:?} @ {:?}", kind, location); + let tcx = self.scx.tcx(); match *kind { mir::TerminatorKind::Call { ref func, .. } => { diff --git a/src/test/run-pass/closure-to-fn-coercion.rs b/src/test/run-pass/closure-to-fn-coercion.rs index 7fb26bdc9360..343209143cc2 100644 --- a/src/test/run-pass/closure-to-fn-coercion.rs +++ b/src/test/run-pass/closure-to-fn-coercion.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::mem; + const FOO: fn(u8) -> u8 = |v: u8| { v }; const BAR: [fn(&mut u32); 5] = [ @@ -21,6 +23,10 @@ fn func_specific() -> (fn() -> u32) { || return 42 } +fn generic(_: T) -> fn() -> usize { + || mem::size_of::() +} + fn main() { // Items assert_eq!(func_specific()(), 42); @@ -34,4 +40,5 @@ fn main() { assert_eq!({ BAR[2](&mut a); a }, 3); assert_eq!({ BAR[3](&mut a); a }, 6); assert_eq!({ BAR[4](&mut a); a }, 10); + assert_eq!(generic(0i8)(), 1); } From 8723f287726073b43d3946838d930ce108d52988 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Sun, 18 Jun 2017 16:58:54 +0100 Subject: [PATCH 229/233] rustc: Check if def_path_hash_to_def_id is populated before accessing it. Without this patch, there is an ICE when running rustc with RUST_LOG=debug. This patch updates extract_def_id to check if the map has been populated before accessing it. This fixes the problem, but maybe we do not need to compute the incremental hashes maps in the first place when we are not in incremental mode? --- src/librustc/dep_graph/dep_node.rs | 10 +++++----- src/test/run-pass/rustc-rust-log.rs | 13 +++++++++++++ 2 files changed, 18 insertions(+), 5 deletions(-) create mode 100644 src/test/run-pass/rustc-rust-log.rs diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index b061663148d4..92efeb7fd862 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -257,11 +257,11 @@ macro_rules! define_dep_nodes { pub fn extract_def_id(&self, tcx: TyCtxt) -> Option { if self.kind.can_reconstruct_query_key() { let def_path_hash = DefPathHash(self.hash); - tcx.def_path_hash_to_def_id - .as_ref() - .unwrap() - .get(&def_path_hash) - .cloned() + if let Some(ref def_path_map) = tcx.def_path_hash_to_def_id.as_ref() { + def_path_map.get(&def_path_hash).cloned() + } else { + None + } } else { None } diff --git a/src/test/run-pass/rustc-rust-log.rs b/src/test/run-pass/rustc-rust-log.rs new file mode 100644 index 000000000000..629387d4cb11 --- /dev/null +++ b/src/test/run-pass/rustc-rust-log.rs @@ -0,0 +1,13 @@ +// 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. + +// rustc-env:RUST_LOG=debug + +fn main() {} From 5fe89e8eb1f0d9c4fbd8995bfe4e9a4e7926d4bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Malo=20Jaffr=C3=A9?= Date: Sun, 18 Jun 2017 18:18:08 +0200 Subject: [PATCH 230/233] Add tests for various issues Fixes #11740. Fixes #19601. Fixes #22603 Fixes #22789. Fixes #26614. r? @Mark-Simulacrum. --- src/test/compile-fail/issue-11740.rs | 38 ++++++++++++++++++++++++++++ src/test/compile-fail/issue-19601.rs | 19 ++++++++++++++ src/test/compile-fail/issue-22603.rs | 23 +++++++++++++++++ src/test/compile-fail/issue-22789.rs | 17 +++++++++++++ src/test/compile-fail/issue-26614.rs | 27 ++++++++++++++++++++ 5 files changed, 124 insertions(+) create mode 100644 src/test/compile-fail/issue-11740.rs create mode 100644 src/test/compile-fail/issue-19601.rs create mode 100644 src/test/compile-fail/issue-22603.rs create mode 100644 src/test/compile-fail/issue-22789.rs create mode 100644 src/test/compile-fail/issue-26614.rs diff --git a/src/test/compile-fail/issue-11740.rs b/src/test/compile-fail/issue-11740.rs new file mode 100644 index 000000000000..0bda06be9e8c --- /dev/null +++ b/src/test/compile-fail/issue-11740.rs @@ -0,0 +1,38 @@ +// 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. + +#![feature(rustc_attrs)] +#![allow(warnings)] + +struct Attr { + name: String, + value: String, +} + +struct Element { + attrs: Vec>, +} + +impl Element { + pub unsafe fn get_attr<'a>(&'a self, name: &str) { + self.attrs + .iter() + .find(|attr| { + let attr: &&Box = std::mem::transmute(attr); + true + }); + } +} + +#[rustc_error] +fn main() { //~ ERROR compilation successful + let element = Element { attrs: Vec::new() }; + let _ = unsafe { element.get_attr("foo") }; +} diff --git a/src/test/compile-fail/issue-19601.rs b/src/test/compile-fail/issue-19601.rs new file mode 100644 index 000000000000..02b4932cea8c --- /dev/null +++ b/src/test/compile-fail/issue-19601.rs @@ -0,0 +1,19 @@ +// 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. + +#![feature(rustc_attrs)] +#![allow(warnings)] + +trait A {} +struct B where B: A> { t: T } + +#[rustc_error] +fn main() { //~ ERROR compilation successful +} diff --git a/src/test/compile-fail/issue-22603.rs b/src/test/compile-fail/issue-22603.rs new file mode 100644 index 000000000000..d08f916b870c --- /dev/null +++ b/src/test/compile-fail/issue-22603.rs @@ -0,0 +1,23 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(unboxed_closures, fn_traits, rustc_attrs)] + +struct Foo; + +impl FnOnce<(A,)> for Foo { + type Output = (); + extern "rust-call" fn call_once(self, (_,): (A,)) { + } +} +#[rustc_error] +fn main() { //~ ERROR compilation successful + println!("{:?}", Foo("bar")); +} diff --git a/src/test/compile-fail/issue-22789.rs b/src/test/compile-fail/issue-22789.rs new file mode 100644 index 000000000000..cba1c367bb9b --- /dev/null +++ b/src/test/compile-fail/issue-22789.rs @@ -0,0 +1,17 @@ +// 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. + +#![feature(unboxed_closures, fn_traits, rustc_attrs)] + +#[rustc_error] +fn main() { //~ ERROR compilation successful + let k = |x: i32| { x + 1 }; + Fn::call(&k, (0,)); +} diff --git a/src/test/compile-fail/issue-26614.rs b/src/test/compile-fail/issue-26614.rs new file mode 100644 index 000000000000..c128fb3b4795 --- /dev/null +++ b/src/test/compile-fail/issue-26614.rs @@ -0,0 +1,27 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(rustc_attrs)] +#![allow(warnings)] + +trait Mirror { + type It; +} + +impl Mirror for T { + type It = Self; +} + + +#[rustc_error] +fn main() { //~ ERROR compilation successful + let c: ::It = 5; + const CCCC: ::It = 5; +} From 9f6fb8e88f5983d882deb85c7820021a014d11b9 Mon Sep 17 00:00:00 2001 From: est31 Date: Sat, 17 Jun 2017 21:40:22 +0200 Subject: [PATCH 231/233] Remove SUMMARY.md of the unstable book as its autogenerated Its being autogenerated now, as of PR #42612. It seems I forgot to remove it. --- src/doc/unstable-book/src/SUMMARY.md | 225 --------------------------- 1 file changed, 225 deletions(-) delete mode 100644 src/doc/unstable-book/src/SUMMARY.md diff --git a/src/doc/unstable-book/src/SUMMARY.md b/src/doc/unstable-book/src/SUMMARY.md deleted file mode 100644 index d7c368292115..000000000000 --- a/src/doc/unstable-book/src/SUMMARY.md +++ /dev/null @@ -1,225 +0,0 @@ -[The Unstable Book](the-unstable-book.md) - -- [Compiler flags](compiler-flags.md) - - [linker_flavor](compiler-flags/linker-flavor.md) - - [profile](compiler-flags/profile.md) - - [remap_path_prefix](compiler-flags/remap-path-prefix.md) -- [Language features](language-features.md) - - [abi_msp430_interrupt](language-features/abi-msp430-interrupt.md) - - [abi_ptx](language-features/abi-ptx.md) - - [abi_sysv64](language-features/abi-sysv64.md) - - [abi_thiscall](language-features/abi-thiscall.md) - - [abi_unadjusted](language-features/abi-unadjusted.md) - - [abi_vectorcall](language-features/abi-vectorcall.md) - - [abi_x86_interrupt](language-features/abi-x86-interrupt.md) - - [advanced_slice_patterns](language-features/advanced-slice-patterns.md) - - [allocator](language-features/allocator.md) - - [allow_internal_unstable](language-features/allow-internal-unstable.md) - - [asm](language-features/asm.md) - - [associated_consts](language-features/associated-consts.md) - - [associated_type_defaults](language-features/associated-type-defaults.md) - - [attr_literals](language-features/attr-literals.md) - - [box_patterns](language-features/box-patterns.md) - - [box_syntax](language-features/box-syntax.md) - - [catch_expr](language-features/catch-expr.md) - - [cfg_target_feature](language-features/cfg-target-feature.md) - - [cfg_target_has_atomic](language-features/cfg-target-has-atomic.md) - - [cfg_target_thread_local](language-features/cfg-target-thread-local.md) - - [cfg_target_vendor](language-features/cfg-target-vendor.md) - - [compiler_builtins](language-features/compiler-builtins.md) - - [concat_idents](language-features/concat-idents.md) - - [conservative_impl_trait](language-features/conservative-impl-trait.md) - - [const_fn](language-features/const-fn.md) - - [const_indexing](language-features/const-indexing.md) - - [custom_attribute](language-features/custom-attribute.md) - - [custom_derive](language-features/custom-derive.md) - - [default_type_parameter_fallback](language-features/default-type-parameter-fallback.md) - - [drop_types_in_const](language-features/drop-types-in-const.md) - - [dropck_eyepatch](language-features/dropck-eyepatch.md) - - [dropck_parametricity](language-features/dropck-parametricity.md) - - [exclusive_range_pattern](language-features/exclusive-range-pattern.md) - - [fundamental](language-features/fundamental.md) - - [generic_param_attrs](language-features/generic-param-attrs.md) - - [global_asm](language-features/global_asm.md) - - [i128_type](language-features/i128-type.md) - - [inclusive_range_syntax](language-features/inclusive-range-syntax.md) - - [intrinsics](language-features/intrinsics.md) - - [lang_items](language-features/lang-items.md) - - [link_args](language-features/link-args.md) - - [link_cfg](language-features/link-cfg.md) - - [link_llvm_intrinsics](language-features/link-llvm-intrinsics.md) - - [linkage](language-features/linkage.md) - - [log_syntax](language-features/log-syntax.md) - - [macro_reexport](language-features/macro-reexport.md) - - [macro_vis_matcher](language-features/macro-vis-matcher.md) - - [main](language-features/main.md) - - [naked_functions](language-features/naked-functions.md) - - [needs_allocator](language-features/needs-allocator.md) - - [needs_panic_runtime](language-features/needs-panic-runtime.md) - - [never_type](language-features/never-type.md) - - [no_core](language-features/no-core.md) - - [no_debug](language-features/no-debug.md) - - [non_ascii_idents](language-features/non-ascii-idents.md) - - [omit_gdb_pretty_printer_section](language-features/omit-gdb-pretty-printer-section.md) - - [on_unimplemented](language-features/on-unimplemented.md) - - [optin_builtin_traits](language-features/optin-builtin-traits.md) - - [overlapping_marker_traits](language-features/overlapping-marker-traits.md) - - [panic_runtime](language-features/panic-runtime.md) - - [placement_in_syntax](language-features/placement-in-syntax.md) - - [platform_intrinsics](language-features/platform-intrinsics.md) - - [plugin](language-features/plugin.md) - - [plugin_registrar](language-features/plugin-registrar.md) - - [prelude_import](language-features/prelude-import.md) - - [proc_macro](language-features/proc-macro.md) - - [profiler_runtime](language-features/profiler-runtime.md) - - [quote](language-features/quote.md) - - [repr_align](language-features/repr-align.md) - - [repr_simd](language-features/repr-simd.md) - - [rustc_attrs](language-features/rustc-attrs.md) - - [rustc_diagnostic_macros](language-features/rustc-diagnostic-macros.md) - - [rvalue_static_promotion](language-features/rvalue-static-promotion.md) - - [sanitizer_runtime](language-features/sanitizer-runtime.md) - - [simd](language-features/simd.md) - - [simd_ffi](language-features/simd-ffi.md) - - [slice_patterns](language-features/slice-patterns.md) - - [specialization](language-features/specialization.md) - - [staged_api](language-features/staged-api.md) - - [start](language-features/start.md) - - [static_nobundle](language-features/static-nobundle.md) - - [stmt_expr_attributes](language-features/stmt-expr-attributes.md) - - [structural_match](language-features/structural-match.md) - - [target_feature](language-features/target-feature.md) - - [thread_local](language-features/thread-local.md) - - [trace_macros](language-features/trace-macros.md) - - [type_ascription](language-features/type-ascription.md) - - [unboxed_closures](language-features/unboxed-closures.md) - - [untagged_unions](language-features/untagged-unions.md) - - [unwind_attributes](language-features/unwind-attributes.md) - - [use_extern_macros](language-features/use-extern-macros.md) - - [used](language-features/used.md) -- [Library Features](library-features.md) - - [alloc_jemalloc](library-features/alloc-jemalloc.md) - - [alloc_system](library-features/alloc-system.md) - - [alloc](library-features/alloc.md) - - [as_c_str](library-features/as-c-str.md) - - [ascii_ctype](library-features/ascii-ctype.md) - - [box_heap](library-features/box-heap.md) - - [c_void_variant](library-features/c-void-variant.md) - - [char_escape_debug](library-features/char-escape-debug.md) - - [coerce_unsized](library-features/coerce-unsized.md) - - [collection_placement](library-features/collection-placement.md) - - [collections](library-features/collections.md) - - [collections_range](library-features/collections-range.md) - - [command_envs](library-features/command-envs.md) - - [compiler_builtins_lib](library-features/compiler-builtins-lib.md) - - [compiler_fences](library-features/compiler-fences.md) - - [concat_idents_macro](library-features/concat-idents-macro.md) - - [core_char_ext](library-features/core-char-ext.md) - - [core_float](library-features/core-float.md) - - [core_intrinsics](library-features/core-intrinsics.md) - - [core_panic](library-features/core-panic.md) - - [core_private_bignum](library-features/core-private-bignum.md) - - [core_private_diy_float](library-features/core-private-diy-float.md) - - [core_slice_ext](library-features/core-slice-ext.md) - - [core_str_ext](library-features/core-str-ext.md) - - [dec2flt](library-features/dec2flt.md) - - [decode_utf8](library-features/decode-utf8.md) - - [derive_clone_copy](library-features/derive-clone-copy.md) - - [derive_eq](library-features/derive-eq.md) - - [discriminant_value](library-features/discriminant-value.md) - - [error_type_id](library-features/error-type-id.md) - - [exact_size_is_empty](library-features/exact-size-is-empty.md) - - [fd](library-features/fd.md) - - [fd_read](library-features/fd-read.md) - - [fixed_size_array](library-features/fixed-size-array.md) - - [float_bits_conv](library-features/float-bits-conv.md) - - [flt2dec](library-features/flt2dec.md) - - [fmt_flags_align](library-features/fmt-flags-align.md) - - [fmt_internals](library-features/fmt-internals.md) - - [fn_traits](library-features/fn-traits.md) - - [fnbox](library-features/fnbox.md) - - [from_utf8_error_as_bytes](library-features/from_utf8_error_as_bytes.md) - - [fused](library-features/fused.md) - - [future_atomic_orderings](library-features/future-atomic-orderings.md) - - [get_type_id](library-features/get-type-id.md) - - [heap_api](library-features/heap-api.md) - - [hint_core_should_pause](library-features/hint-core-should-pause.md) - - [i128](library-features/i128.md) - - [inclusive_range](library-features/inclusive-range.md) - - [integer_atomics](library-features/integer-atomics.md) - - [into_boxed_c_str](library-features/into-boxed-c-str.md) - - [into_boxed_os_str](library-features/into-boxed-os-str.md) - - [into_boxed_path](library-features/into-boxed-path.md) - - [io_error_internals](library-features/io-error-internals.md) - - [io](library-features/io.md) - - [ip](library-features/ip.md) - - [iter_rfind](library-features/iter-rfind.md) - - [iterator_step_by](library-features/iterator-step-by.md) - - [libstd_io_internals](library-features/libstd-io-internals.md) - - [libstd_sys_internals](library-features/libstd-sys-internals.md) - - [libstd_thread_internals](library-features/libstd-thread-internals.md) - - [linked_list_extras](library-features/linked-list-extras.md) - - [lookup_host](library-features/lookup-host.md) - - [manually_drop](library-features/manually-drop.md) - - [more_io_inner_methods](library-features/more-io-inner-methods.md) - - [mpsc_select](library-features/mpsc-select.md) - - [n16](library-features/n16.md) - - [never_type_impls](library-features/never-type-impls.md) - - [nonzero](library-features/nonzero.md) - - [ord_max_min](library-features/ord-max-min.md) - - [offset_to](library-features/offset-to.md) - - [once_poison](library-features/once-poison.md) - - [oom](library-features/oom.md) - - [option_entry](library-features/option-entry.md) - - [osstring_shrink_to_fit](library-features/osstring-shrink-to-fit.md) - - [panic_abort](library-features/panic-abort.md) - - [panic_unwind](library-features/panic-unwind.md) - - [pattern](library-features/pattern.md) - - [placement_in](library-features/placement-in.md) - - [placement_new_protocol](library-features/placement-new-protocol.md) - - [print_internals](library-features/print-internals.md) - - [proc_macro_internals](library-features/proc-macro-internals.md) - - [profiler_runtime_lib](library-features/sanitizer-runtime-lib.md) - - [question_mark_carrier](library-features/question-mark-carrier.md) - - [rand](library-features/rand.md) - - [range_contains](library-features/range-contains.md) - - [raw](library-features/raw.md) - - [reverse_cmp_key](library-features/reverse-cmp-key.md) - - [rt](library-features/rt.md) - - [rustc_private](library-features/rustc-private.md) - - [sanitizer_runtime_lib](library-features/sanitizer-runtime-lib.md) - - [set_stdio](library-features/set-stdio.md) - - [shared](library-features/shared.md) - - [sip_hash_13](library-features/sip-hash-13.md) - - [slice_concat_ext](library-features/slice-concat-ext.md) - - [slice_get_slice](library-features/slice-get-slice.md) - - [slice_rotate](library-features/slice-rotate.md) - - [slice_rsplit](library-features/slice-rsplit.md) - - [sort_internals](library-features/sort-internals.md) - - [sort_unstable](library-features/sort-unstable.md) - - [splice](library-features/splice.md) - - [step_by](library-features/step-by.md) - - [step_trait](library-features/step-trait.md) - - [str_checked_slicing](library-features/str-checked-slicing.md) - - [str_escape](library-features/str-escape.md) - - [str_internals](library-features/str-internals.md) - - [str_box_extras](library-features/str-box-extras.md) - - [str_mut_extras](library-features/str-mut-extras.md) - - [test](library-features/test.md) - - [thread_id](library-features/thread-id.md) - - [thread_local_internals](library-features/thread-local-internals.md) - - [thread_local_state](library-features/thread-local-state.md) - - [toowned_clone_into](library-features/toowned-clone-into.md) - - [trusted_len](library-features/trusted-len.md) - - [try_from](library-features/try-from.md) - - [try_trait](library-features/try-trait.md) - - [unicode](library-features/unicode.md) - - [unique](library-features/unique.md) - - [unsize](library-features/unsize.md) - - [utf8_error_error_len](library-features/utf8-error-error-len.md) - - [vec_resize_default](library-features/vec-resize-default.md) - - [vec_remove_item](library-features/vec-remove-item.md) - - [windows_c](library-features/windows-c.md) - - [windows_handle](library-features/windows-handle.md) - - [windows_net](library-features/windows-net.md) - - [windows_stdio](library-features/windows-stdio.md) From 696085faeef883bce7201ecf5ef95e8f11ad1f77 Mon Sep 17 00:00:00 2001 From: est31 Date: Sat, 17 Jun 2017 21:54:09 +0200 Subject: [PATCH 232/233] Sort entries of SUMMARY.md alphabetically --- src/tools/tidy/src/unstable_book.rs | 10 +++++----- src/tools/unstable-book-gen/src/main.rs | 18 +++++++++--------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/tools/tidy/src/unstable_book.rs b/src/tools/tidy/src/unstable_book.rs index c8bfe42aa03d..ff032b14ad1d 100644 --- a/src/tools/tidy/src/unstable_book.rs +++ b/src/tools/tidy/src/unstable_book.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::collections::HashSet; +use std::collections::BTreeSet; use std::fs; use std::path; use features::{collect_lang_features, collect_lib_features, Features, Status}; @@ -45,7 +45,7 @@ fn dir_entry_is_file(dir_entry: &fs::DirEntry) -> bool { } /// Retrieve names of all unstable features -pub fn collect_unstable_feature_names(features: &Features) -> HashSet { +pub fn collect_unstable_feature_names(features: &Features) -> BTreeSet { features .iter() .filter(|&(_, ref f)| f.level == Status::Unstable) @@ -53,7 +53,7 @@ pub fn collect_unstable_feature_names(features: &Features) -> HashSet { .collect() } -pub fn collect_unstable_book_section_file_names(dir: &path::Path) -> HashSet { +pub fn collect_unstable_book_section_file_names(dir: &path::Path) -> BTreeSet { fs::read_dir(dir) .expect("could not read directory") .into_iter() @@ -69,7 +69,7 @@ pub fn collect_unstable_book_section_file_names(dir: &path::Path) -> HashSet HashSet { + -> BTreeSet { collect_unstable_book_section_file_names(&unstable_book_lang_features_path(base_src_path)) } @@ -78,7 +78,7 @@ fn collect_unstable_book_lang_features_section_file_names(base_src_path: &path:: /// * hyphens replaced by underscores /// * the markdown suffix ('.md') removed fn collect_unstable_book_lib_features_section_file_names(base_src_path: &path::Path) - -> HashSet { + -> BTreeSet { collect_unstable_book_section_file_names(&unstable_book_lib_features_path(base_src_path)) } diff --git a/src/tools/unstable-book-gen/src/main.rs b/src/tools/unstable-book-gen/src/main.rs index 71063968ff2c..5c2bd1e3e087 100644 --- a/src/tools/unstable-book-gen/src/main.rs +++ b/src/tools/unstable-book-gen/src/main.rs @@ -17,7 +17,7 @@ extern crate tidy; use tidy::features::{Feature, Features, collect_lib_features, collect_lang_features}; use tidy::unstable_book::{collect_unstable_feature_names, collect_unstable_book_section_file_names, PATH_STR, LANG_FEATURES_DIR, LIB_FEATURES_DIR}; -use std::collections::HashSet; +use std::collections::BTreeSet; use std::io::Write; use std::fs::{self, File}; use std::env; @@ -48,9 +48,9 @@ fn generate_stub_no_issue(path: &Path, name: &str) { name = name))); } -fn hset_to_summary_str(hset: HashSet, dir: &str +fn set_to_summary_str(set: &BTreeSet, dir: &str ) -> String { - hset + set .iter() .map(|ref n| format!(" - [{}]({}/{}.md)", n, @@ -63,16 +63,16 @@ fn generate_summary(path: &Path, lang_features: &Features, lib_features: &Featur let compiler_flags = collect_unstable_book_section_file_names( &path.join("compiler-flags")); - let compiler_flags_str = hset_to_summary_str(compiler_flags, - "compiler-flags"); + let compiler_flags_str = set_to_summary_str(&compiler_flags, + "compiler-flags"); let unstable_lang_features = collect_unstable_feature_names(&lang_features); let unstable_lib_features = collect_unstable_feature_names(&lib_features); - let lang_features_str = hset_to_summary_str(unstable_lang_features, - LANG_FEATURES_DIR); - let lib_features_str = hset_to_summary_str(unstable_lib_features, - LIB_FEATURES_DIR); + let lang_features_str = set_to_summary_str(&unstable_lang_features, + LANG_FEATURES_DIR); + let lib_features_str = set_to_summary_str(&unstable_lib_features, + LIB_FEATURES_DIR); let mut file = t!(File::create(&path.join("SUMMARY.md"))); t!(file.write_fmt(format_args!(include_str!("SUMMARY.md"), From 207951b1699e426829296721adf668117294a580 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Sun, 18 Jun 2017 19:01:34 +0300 Subject: [PATCH 233/233] Backport fixes to LLVM 4.0 ARM codegen bugs So ARM had quite a few codegen bugs on LLVM 4.0 which are fixed on LLVM trunk. This backports 5 of them: r297871 - ARM: avoid clobbering register in v6 jump-table expansion. - fixes rust-lang/rust#42248 r294949 - [Thumb-1] TBB generation: spot redefinitions of index r295816 - [ARM] Fix constant islands pass. r300870 - [Thumb-1] Fix corner cases for compressed jump tables r302650 - [IfConversion] Add missing check in IfConversion/canFallThroughTo - unblocks rust-lang/rust#39409 --- src/llvm | 2 +- src/rustllvm/llvm-rebuild-trigger | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/llvm b/src/llvm index ee545e1d13e6..5415ff0264c1 160000 --- a/src/llvm +++ b/src/llvm @@ -1 +1 @@ -Subproject commit ee545e1d13e6f2191572aebcadb7d1640ce45c65 +Subproject commit 5415ff0264c134152cca65ae8f5d50b356d61162 diff --git a/src/rustllvm/llvm-rebuild-trigger b/src/rustllvm/llvm-rebuild-trigger index b2746bb6e68a..792b496f1dbe 100644 --- a/src/rustllvm/llvm-rebuild-trigger +++ b/src/rustllvm/llvm-rebuild-trigger @@ -1,4 +1,4 @@ # If this file is modified, then llvm will be (optionally) cleaned and then rebuilt. # The actual contents of this file do not matter, but to trigger a change on the # build bots then the contents should be changed so git updates the mtime. -2017-06-03 +2017-06-18